| /* |
| * 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.util.Stack; |
| import java.net.URL; |
| import java.net.MalformedURLException; |
| import org.apache.jasper.JspCompilationContext; |
| |
| /** |
| * Mark represents a point in the JSP input. |
| * |
| * @author Anil K. Vijendran |
| */ |
| final class Mark { |
| |
| // position within current stream |
| int cursor, line, col; |
| |
| // directory of file for current stream |
| String baseDir; |
| |
| // current stream |
| char[] stream = null; |
| |
| // fileid of current stream |
| private int fileId; |
| |
| // name of the current file |
| private String fileName; |
| |
| /* |
| * stack of stream and stream state of streams that have included |
| * current stream |
| */ |
| private Stack includeStack = null; |
| |
| // encoding of current file |
| private String encoding = null; |
| |
| // reader that owns this mark (so we can look up fileid's) |
| private JspReader reader; |
| |
| private JspCompilationContext ctxt; |
| |
| /** |
| * Constructor |
| * |
| * @param reader JspReader this mark belongs to |
| * @param inStream current stream for this mark |
| * @param fileId id of requested jsp file |
| * @param name JSP file name |
| * @param inBaseDir base directory of requested jsp file |
| * @param inEncoding encoding of current file |
| */ |
| Mark(JspReader reader, char[] inStream, int fileId, String name, |
| String inBaseDir, String inEncoding) { |
| |
| this.reader = reader; |
| this.ctxt = reader.getJspCompilationContext(); |
| this.stream = inStream; |
| this.cursor = 0; |
| this.line = 1; |
| this.col = 1; |
| this.fileId = fileId; |
| this.fileName = name; |
| this.baseDir = inBaseDir; |
| this.encoding = inEncoding; |
| this.includeStack = new Stack(); |
| } |
| |
| |
| /** |
| * Constructor |
| */ |
| Mark(Mark other) { |
| |
| this.reader = other.reader; |
| this.ctxt = other.reader.getJspCompilationContext(); |
| this.stream = other.stream; |
| this.fileId = other.fileId; |
| this.fileName = other.fileName; |
| this.cursor = other.cursor; |
| this.line = other.line; |
| this.col = other.col; |
| this.baseDir = other.baseDir; |
| this.encoding = other.encoding; |
| |
| // clone includeStack without cloning contents |
| includeStack = new Stack(); |
| for ( int i=0; i < other.includeStack.size(); i++ ) { |
| includeStack.addElement( other.includeStack.elementAt(i) ); |
| } |
| } |
| |
| |
| /** |
| * Constructor |
| */ |
| Mark(JspCompilationContext ctxt, String filename, int line, int col) { |
| |
| this.reader = null; |
| this.ctxt = ctxt; |
| this.stream = null; |
| this.cursor = 0; |
| this.line = line; |
| this.col = col; |
| this.fileId = -1; |
| this.fileName = filename; |
| this.baseDir = "le-basedir"; |
| this.encoding = "le-endocing"; |
| this.includeStack = null; |
| } |
| |
| |
| /** |
| * Sets this mark's state to a new stream. |
| * It will store the current stream in it's includeStack. |
| * |
| * @param inStream new stream for mark |
| * @param inFileId id of new file from which stream comes from |
| * @param inBaseDir directory of file |
| * @param inEncoding encoding of new file |
| */ |
| public void pushStream(char[] inStream, int inFileId, String name, |
| String inBaseDir, String inEncoding) |
| { |
| // store current state in stack |
| includeStack.push(new IncludeState(cursor, line, col, fileId, |
| fileName, baseDir, |
| encoding, stream) ); |
| |
| // set new variables |
| cursor = 0; |
| line = 1; |
| col = 1; |
| fileId = inFileId; |
| fileName = name; |
| baseDir = inBaseDir; |
| encoding = inEncoding; |
| stream = inStream; |
| } |
| |
| |
| /** |
| * Restores this mark's state to a previously stored stream. |
| * @return The previous Mark instance when the stream was pushed, or null |
| * if there is no previous stream |
| */ |
| public Mark popStream() { |
| // make sure we have something to pop |
| if ( includeStack.size() <= 0 ) { |
| return null; |
| } |
| |
| // get previous state in stack |
| IncludeState state = (IncludeState) includeStack.pop( ); |
| |
| // set new variables |
| cursor = state.cursor; |
| line = state.line; |
| col = state.col; |
| fileId = state.fileId; |
| fileName = state.fileName; |
| baseDir = state.baseDir; |
| stream = state.stream; |
| return this; |
| } |
| |
| |
| // -------------------- Locator interface -------------------- |
| |
| public int getLineNumber() { |
| return line; |
| } |
| |
| public int getColumnNumber() { |
| return col; |
| } |
| |
| public String getSystemId() { |
| return getFile(); |
| } |
| |
| public String getPublicId() { |
| return null; |
| } |
| |
| public String toString() { |
| return getFile()+"("+line+","+col+")"; |
| } |
| |
| public String getFile() { |
| return this.fileName; |
| } |
| |
| /** |
| * Gets the URL of the resource with which this Mark is associated |
| * |
| * @return URL of the resource with which this Mark is associated |
| * |
| * @exception MalformedURLException if the resource pathname is incorrect |
| */ |
| public URL getURL() throws MalformedURLException { |
| return ctxt.getResource(getFile()); |
| } |
| |
| public String toShortString() { |
| return "("+line+","+col+")"; |
| } |
| |
| public boolean equals(Object other) { |
| if (other instanceof Mark) { |
| Mark m = (Mark) other; |
| return this.reader == m.reader && this.fileId == m.fileId |
| && this.cursor == m.cursor && this.line == m.line |
| && this.col == m.col; |
| } |
| return false; |
| } |
| |
| /** |
| * @return true if this Mark is greather than the <code>other</code> |
| * Mark, false otherwise. |
| */ |
| public boolean isGreater(Mark other) { |
| |
| boolean greater = false; |
| |
| if (this.line > other.line) { |
| greater = true; |
| } else if (this.line == other.line && this.col > other.col) { |
| greater = true; |
| } |
| |
| return greater; |
| } |
| |
| /** |
| * Keep track of parser before parsing an included file. |
| * This class keeps track of the parser before we switch to parsing an |
| * included file. In other words, it's the parser's continuation to be |
| * reinstalled after the included file parsing is done. |
| */ |
| class IncludeState { |
| int cursor, line, col; |
| int fileId; |
| String fileName; |
| String baseDir; |
| String encoding; |
| char[] stream = null; |
| |
| IncludeState(int inCursor, int inLine, int inCol, int inFileId, |
| String name, String inBaseDir, String inEncoding, |
| char[] inStream) { |
| cursor = inCursor; |
| line = inLine; |
| col = inCol; |
| fileId = inFileId; |
| fileName = name; |
| baseDir = inBaseDir; |
| encoding = inEncoding; |
| stream = inStream; |
| } |
| } |
| |
| } |
| |