/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.sling.scripting.jsp.jasper.compiler; import java.util.Stack; import java.net.URL; import java.net.MalformedURLException; import org.apache.sling.scripting.jsp.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; } } }