📄 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"); 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. * @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 = "8859_1"; // 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; 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 { ch = nextChar(); if (Character.toLowerCase((char) ch) != string.charAt(i++)) { reset(mark); return false; } } while (i < string.length()); reset(mark); return true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -