|
What this is
Other links
The source code
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.compiler;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Vector;
import org.apache.jasper.Constants;
import org.apache.jasper.JspCompilationContext;
import org.apache.tomcat.util.log.Log;
/**
* 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;
Log loghelper = Log.getLog("JASPER_LOG", "JspReader");
// 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 = "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);
try {
CharArrayWriter caw = new CharArrayWriter();
while (!stop.equals(mark()))
caw.write(nextChar());
caw.close();
reset(oldstart);
return caw.toCharArray();
} catch( Exception ex ) {
ex.printStackTrace();
throw new ParseException( ex.toString() );
}
}
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 {
ch = nextChar();
if (Character.toLowerCase((char) ch) != string.charAt(i++)) {
reset(mark);
return false;
}
} while (i < string.length());
reset(mark);
return true;
}
public boolean matches(String string) throws ParseException {
Mark mark = mark();
int ch = 0;
int i = 0;
do {
ch = nextChar();
if (((char) ch) != string.charAt(i++)) {
reset(mark);
return false;
}
} while (i < string.length());
reset(mark);
return true;
}
public void advance(int n) throws ParseException {
while (--n >= 0)
nextChar();
}
public int skipSpaces() throws ParseException {
int i = 0;
while (isSpace()) {
i++;
nextChar();
}
return i;
}
/**
* Skip until the given string is matched in the stream.
* When returned, the context is positioned past the end of the match.
* @param s The String to match.
* @return A non-null
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.