📄 jspreader.java
字号:
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Stack;
import org.apache.jasper.Constants;
import org.apache.jasper.JspCompilationContext;
import org.apache.tomcat.logging.*;
/**
* JspReader is an input buffer for the JSP parser. It should allow
* unlimited lookahead and pushback. It also has a bunch of parsing
* utility methods for understanding htmlesque thingies.
*
* @author Anil K. Vijendran
* @author Anselm Baird-Smith
* @author Harish Prabandham
* @author Rajiv Mordani
* @author Mandar Raje
*/
public class JspReader {
protected Mark current = null;
String master = null;
Vector sourceFiles = new Vector();
int currFileId = 0;
int size = 0;
private JspCompilationContext context;
LogHelper loghelper = new LogHelper("JASPER_LOG", "JspReader");
/*
* Default encoding used. The JspReader is created with the
* "top file" encoding. This is then the encoding used for the
* included files (same translation unit).
*/
private String encoding = null;
public String getFile(int fileid) {
return (String) sourceFiles.elementAt(fileid);
}
/**
* Register a new source file.
* This method is used to implement file inclusion. Each included file
* gets a uniq identifier (which is the index in the array of source files).
* @return The index of the now registered file.
*/
protected int registerSourceFile(String file) {
if (sourceFiles.contains(file))
return -1;
sourceFiles.addElement(file);
this.size++;
return sourceFiles.size() - 1;
}
/**
* Unregister the source file.
* This method is used to implement file inclusion. Each included file
* gets a uniq identifier (which is the index in the array of source files).
* @return The index of the now registered file.
*/
protected int unregisterSourceFile(String file) {
if (!sourceFiles.contains(file))
return -1;
sourceFiles.removeElement(file);
this.size--;
return sourceFiles.size() - 1;
}
/**
* Push a new file onto the stack.
* The name of the file is resolved to a fully qualified filename.
* @param name The name of the file.
*/
public void pushFile(String name)
throws ParseException, FileNotFoundException
{
pushFile(name, this.encoding);
}
/**
* Push a new file onto the stack.
* The name of the file is resolved to a fully qualified filename.
* @param name The name of the file.
* @param encoding The optional encoding for the file.
*/
public void pushFile(String name, String encoding)
throws ParseException, FileNotFoundException
{
String parent = master == null ?
null : master.substring(0, master.lastIndexOf("/") + 1);
boolean isAbsolute = name.startsWith("/");
if (parent == null || isAbsolute) {
master = name;
pushFile(new File(name), encoding);
} else {
master = parent + name;
pushFile(new File(master), encoding);
}
}
/**
* Push a new file to be parsed onto the stack.
* @param inputFile The fully qualified path of the file.
* @param encoding Optional encoding to read the file.
*/
private void pushFile(File file, String encoding)
throws ParseException, FileNotFoundException
{
// Default encoding if needed:
if (encoding == null) {
encoding = this.encoding;
// XXX - longer term, this should really be:
// System.getProperty("file.encoding", "8859_1");
// but this doesn't work right now, so we stick with ASCII
}
// Register the file, and read its content:
String longName = (context == null)
? file.getAbsolutePath()
: context.getRealPath(file.toString());
if (longName == null)
throw new FileNotFoundException(file.toString());
int fileid = registerSourceFile(longName);
if (fileid == -1)
throw new ParseException(Constants.getString("jsp.error.file.already.registered",
new Object[] {
file
}));
currFileId = fileid;
InputStreamReader reader = null;
try {
if (context == null)
reader = new InputStreamReader(new FileInputStream(file),
encoding);
else {
String fileName = context.getRealPath(file.toString());
InputStream in = context.getResourceAsStream(file.toString());
if (in == null)
throw new FileNotFoundException(fileName);
try {
reader = new InputStreamReader(in, encoding);
} catch (Throwable ex) {
throw new FileNotFoundException(fileName + ": "+ ex.getMessage());
}
}
CharArrayWriter caw = new CharArrayWriter();
char buf[] = new char[1024];
for (int i = 0 ; (i = reader.read(buf)) != -1 ; )
caw.write(buf, 0, i);
caw.close();
if (current == null) {
current = new Mark( this, caw.toCharArray(), fileid, getFile(fileid),
master, encoding );
} else {
current.pushStream( caw.toCharArray(), fileid, getFile(fileid),
master, encoding );
}
} catch (FileNotFoundException fnfe) {
throw fnfe;
} catch (Throwable ex) {
loghelper.log("Exception parsing file " + file, ex);
// Pop state being constructed:
popFile();
throw new ParseException(Constants.getString("jsp.error.file.cannot.read",
new Object[] { file }));
} finally {
if ( reader != null ) {
try { reader.close(); } catch (Exception any) {}
}
}
}
public boolean popFile() throws ParseException {
// Is stack created ? (will happen if the Jsp file we'r looking at is
// missing.
if (current == null)
return false;
// Restore parser state:
//size--;
if (currFileId < 0) {
throw new ParseException(
Constants.getString("jsp.error.no.more.content"));
}
String fName = getFile(currFileId);
currFileId = unregisterSourceFile(fName);
if (currFileId < -1)
throw new ParseException
(Constants.getString("jsp.error.file.not.registered",
new Object[] {fName}));
boolean r = current.popStream();
if (r)
master = current.baseDir;
return r;
}
protected JspReader(String file, JspCompilationContext ctx, String encoding)
throws ParseException, FileNotFoundException
{
this.context = ctx;
this.encoding = encoding;
if (this.encoding == null) this.encoding = "ISO-8859-1";
pushFile(file, encoding);
}
public static JspReader createJspReader(String file, JspCompilationContext ctx, String encoding)
throws ParseException, FileNotFoundException
{
return new JspReader(file, ctx, encoding);
}
public boolean hasMoreInput() throws ParseException {
if (current.cursor >= current.stream.length) {
while (popFile()) {
if (current.cursor < current.stream.length) return true;
}
return false;
}
return true;
}
public int nextChar() throws ParseException {
if (!hasMoreInput())
return -1;
int ch = current.stream[current.cursor];
current.cursor++;
if (ch == '\n') {
current.line++;
current.col = 0;
} else {
current.col++;
}
return ch;
}
/**
* Gets Content until the next potential JSP element. Because all elements
* begin with a '<' we can just move until we see the next one.
*/
String nextContent() {
int cur_cursor = current.cursor;
int len = current.stream.length;
char ch;
if (peekChar() == '\n') {
current.line++;
current.col = 0;
}
else current.col++;
// pure obsfuscated genius!
while ((++current.cursor < len) &&
((ch = current.stream[current.cursor]) != '<')) {
if (ch == '\n') {
current.line++;
current.col = 0;
} else {
current.col++;
}
}
return new String(current.stream, cur_cursor, current.cursor-cur_cursor);
}
char[] getChars(Mark start, Mark stop) throws ParseException {
Mark oldstart = mark();
reset(start);
CharArrayWriter caw = new CharArrayWriter();
while (!stop.equals(mark()))
caw.write(nextChar());
caw.close();
reset(oldstart);
return caw.toCharArray();
}
public int peekChar() {
return current.stream[current.cursor];
}
public Mark mark() {
return new Mark(current);
}
public void reset(Mark mark) {
current = new Mark(mark);
}
public boolean matchesIgnoreCase(String string) throws ParseException {
Mark mark = mark();
int ch = 0;
int i = 0;
do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -