You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2009/09/28 02:43:39 UTC
svn commit: r819435 [12/23] - in
/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper:
./ compiler/ compiler/tagplugin/ el/ runtime/ security/ servlet/
tagplugins/ tagplugins/jstl/ tagplugins/jstl/core/ util/ xmlparser/
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ParserController.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ParserController.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ParserController.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ParserController.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,638 @@
+/*
+ * 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.jasper.compiler;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.Stack;
+import java.util.jar.JarFile;
+
+import org.apache.jasper.JasperException;
+import org.apache.jasper.JspCompilationContext;
+import org.apache.jasper.xmlparser.XMLEncodingDetector;
+import org.xml.sax.Attributes;
+
+/**
+ * Controller for the parsing of a JSP page.
+ * <p>
+ * The same ParserController instance is used for a JSP page and any JSP
+ * segments included by it (via an include directive), where each segment may
+ * be provided in standard or XML syntax. This class selects and invokes the
+ * appropriate parser for the JSP page and its included segments.
+ *
+ * @author Pierre Delisle
+ * @author Jan Luehe
+ */
+class ParserController implements TagConstants {
+
+ private static final String CHARSET = "charset=";
+
+ private JspCompilationContext ctxt;
+ private Compiler compiler;
+ private ErrorDispatcher err;
+
+ /*
+ * Indicates the syntax (XML or standard) of the file being processed
+ */
+ private boolean isXml;
+
+ /*
+ * A stack to keep track of the 'current base directory'
+ * for include directives that refer to relative paths.
+ */
+ private Stack baseDirStack = new Stack();
+
+ private boolean isEncodingSpecifiedInProlog;
+ private boolean isBomPresent;
+ private int skip;
+
+ private String sourceEnc;
+
+ private boolean isDefaultPageEncoding;
+ private boolean isTagFile;
+ private boolean directiveOnly;
+
+ /*
+ * Constructor
+ */
+ public ParserController(JspCompilationContext ctxt, Compiler compiler) {
+ this.ctxt = ctxt;
+ this.compiler = compiler;
+ this.err = compiler.getErrorDispatcher();
+ }
+
+ public JspCompilationContext getJspCompilationContext () {
+ return ctxt;
+ }
+
+ public Compiler getCompiler () {
+ return compiler;
+ }
+
+ /**
+ * Parses a JSP page or tag file. This is invoked by the compiler.
+ *
+ * @param inFileName The path to the JSP page or tag file to be parsed.
+ */
+ public Node.Nodes parse(String inFileName)
+ throws FileNotFoundException, JasperException, IOException {
+ // If we're parsing a packaged tag file or a resource included by it
+ // (using an include directive), ctxt.getTagFileJar() returns the
+ // JAR file from which to read the tag file or included resource,
+ // respectively.
+ isTagFile = ctxt.isTagFile();
+ directiveOnly = false;
+ return doParse(inFileName, null, ctxt.getTagFileJarUrl());
+ }
+
+ /**
+ * Parses the directives of a JSP page or tag file. This is invoked by the
+ * compiler.
+ *
+ * @param inFileName The path to the JSP page or tag file to be parsed.
+ */
+ public Node.Nodes parseDirectives(String inFileName)
+ throws FileNotFoundException, JasperException, IOException {
+ // If we're parsing a packaged tag file or a resource included by it
+ // (using an include directive), ctxt.getTagFileJar() returns the
+ // JAR file from which to read the tag file or included resource,
+ // respectively.
+ isTagFile = ctxt.isTagFile();
+ directiveOnly = true;
+ return doParse(inFileName, null, ctxt.getTagFileJarUrl());
+ }
+
+
+ /**
+ * Processes an include directive with the given path.
+ *
+ * @param inFileName The path to the resource to be included.
+ * @param parent The parent node of the include directive.
+ * @param jarFile The JAR file from which to read the included resource,
+ * or null of the included resource is to be read from the filesystem
+ */
+ public Node.Nodes parse(String inFileName, Node parent,
+ URL jarFileUrl)
+ throws FileNotFoundException, JasperException, IOException {
+ // For files that are statically included, isTagfile and directiveOnly
+ // remain unchanged.
+ return doParse(inFileName, parent, jarFileUrl);
+ }
+
+ /**
+ * Extracts tag file directive information from the tag file with the
+ * given name.
+ *
+ * This is invoked by the compiler
+ *
+ * @param inFileName The name of the tag file to be parsed.
+ * @deprecated Use {@link #parseTagFileDirectives(String, URL)}
+ * See https://issues.apache.org/bugzilla/show_bug.cgi?id=46471
+ */
+ public Node.Nodes parseTagFileDirectives(String inFileName)
+ throws FileNotFoundException, JasperException, IOException {
+ return parseTagFileDirectives(
+ inFileName, ctxt.getTagFileJarUrl(inFileName));
+ }
+
+ /**
+ * Extracts tag file directive information from the given tag file.
+ *
+ * This is invoked by the compiler
+ *
+ * @param inFileName The name of the tag file to be parsed.
+ * @param tagFileJarUrl The location of the tag file.
+ */
+ public Node.Nodes parseTagFileDirectives(String inFileName,
+ URL tagFileJarUrl)
+ throws FileNotFoundException, JasperException, IOException {
+ boolean isTagFileSave = isTagFile;
+ boolean directiveOnlySave = directiveOnly;
+ isTagFile = true;
+ directiveOnly = true;
+ Node.Nodes page = doParse(inFileName, null, tagFileJarUrl);
+ directiveOnly = directiveOnlySave;
+ isTagFile = isTagFileSave;
+ return page;
+ }
+
+ /**
+ * Parses the JSP page or tag file with the given path name.
+ *
+ * @param inFileName The name of the JSP page or tag file to be parsed.
+ * @param parent The parent node (non-null when processing an include
+ * directive)
+ * @param isTagFile true if file to be parsed is tag file, and false if it
+ * is a regular JSP page
+ * @param directivesOnly true if the file to be parsed is a tag file and
+ * we are only interested in the directives needed for constructing a
+ * TagFileInfo.
+ * @param jarFile The JAR file from which to read the JSP page or tag file,
+ * or null if the JSP page or tag file is to be read from the filesystem
+ */
+ private Node.Nodes doParse(String inFileName,
+ Node parent,
+ URL jarFileUrl)
+ throws FileNotFoundException, JasperException, IOException {
+
+ Node.Nodes parsedPage = null;
+ isEncodingSpecifiedInProlog = false;
+ isBomPresent = false;
+ isDefaultPageEncoding = false;
+
+ JarFile jarFile = getJarFile(jarFileUrl);
+ String absFileName = resolveFileName(inFileName);
+ String jspConfigPageEnc = getJspConfigPageEncoding(absFileName);
+
+ // Figure out what type of JSP document and encoding type we are
+ // dealing with
+ determineSyntaxAndEncoding(absFileName, jarFile, jspConfigPageEnc);
+
+ if (parent != null) {
+ // Included resource, add to dependent list
+ if (jarFile == null) {
+ compiler.getPageInfo().addDependant(absFileName);
+ } else {
+ compiler.getPageInfo().addDependant(
+ jarFileUrl.toExternalForm() + absFileName.substring(1));
+ }
+ }
+
+ if ((isXml && isEncodingSpecifiedInProlog) || isBomPresent) {
+ /*
+ * Make sure the encoding explicitly specified in the XML
+ * prolog (if any) matches that in the JSP config element
+ * (if any), treating "UTF-16", "UTF-16BE", and "UTF-16LE" as
+ * identical.
+ */
+ if (jspConfigPageEnc != null && !jspConfigPageEnc.equals(sourceEnc)
+ && (!jspConfigPageEnc.startsWith("UTF-16")
+ || !sourceEnc.startsWith("UTF-16"))) {
+ err.jspError("jsp.error.prolog_config_encoding_mismatch",
+ sourceEnc, jspConfigPageEnc);
+ }
+ }
+
+ // Dispatch to the appropriate parser
+ if (isXml) {
+ // JSP document (XML syntax)
+ // InputStream for jspx page is created and properly closed in
+ // JspDocumentParser.
+ parsedPage = JspDocumentParser.parse(this, absFileName,
+ jarFile, parent,
+ isTagFile, directiveOnly,
+ sourceEnc,
+ jspConfigPageEnc,
+ isEncodingSpecifiedInProlog,
+ isBomPresent);
+ } else {
+ // Standard syntax
+ InputStreamReader inStreamReader = null;
+ try {
+ inStreamReader = JspUtil.getReader(absFileName, sourceEnc,
+ jarFile, ctxt, err, skip);
+ JspReader jspReader = new JspReader(ctxt, absFileName,
+ sourceEnc, inStreamReader,
+ err);
+ parsedPage = Parser.parse(this, jspReader, parent, isTagFile,
+ directiveOnly, jarFileUrl,
+ sourceEnc, jspConfigPageEnc,
+ isDefaultPageEncoding, isBomPresent);
+ } finally {
+ if (inStreamReader != null) {
+ try {
+ inStreamReader.close();
+ } catch (Exception any) {
+ }
+ }
+ }
+ }
+
+ if (jarFile != null) {
+ try {
+ jarFile.close();
+ } catch (Throwable t) {}
+ }
+
+ baseDirStack.pop();
+
+ return parsedPage;
+ }
+
+ /*
+ * Checks to see if the given URI is matched by a URL pattern specified in
+ * a jsp-property-group in web.xml, and if so, returns the value of the
+ * <page-encoding> element.
+ *
+ * @param absFileName The URI to match
+ *
+ * @return The value of the <page-encoding> attribute of the
+ * jsp-property-group with matching URL pattern
+ */
+ private String getJspConfigPageEncoding(String absFileName)
+ throws JasperException {
+
+ JspConfig jspConfig = ctxt.getOptions().getJspConfig();
+ JspConfig.JspProperty jspProperty
+ = jspConfig.findJspProperty(absFileName);
+ return jspProperty.getPageEncoding();
+ }
+
+ /**
+ * Determines the syntax (standard or XML) and page encoding properties
+ * for the given file, and stores them in the 'isXml' and 'sourceEnc'
+ * instance variables, respectively.
+ */
+ private void determineSyntaxAndEncoding(String absFileName,
+ JarFile jarFile,
+ String jspConfigPageEnc)
+ throws JasperException, IOException {
+
+ isXml = false;
+
+ /*
+ * 'true' if the syntax (XML or standard) of the file is given
+ * from external information: either via a JSP configuration element,
+ * the ".jspx" suffix, or the enclosing file (for included resources)
+ */
+ boolean isExternal = false;
+
+ /*
+ * Indicates whether we need to revert from temporary usage of
+ * "ISO-8859-1" back to "UTF-8"
+ */
+ boolean revert = false;
+
+ JspConfig jspConfig = ctxt.getOptions().getJspConfig();
+ JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(
+ absFileName);
+ if (jspProperty.isXml() != null) {
+ // If <is-xml> is specified in a <jsp-property-group>, it is used.
+ isXml = JspUtil.booleanValue(jspProperty.isXml());
+ isExternal = true;
+ } else if (absFileName.endsWith(".jspx")
+ || absFileName.endsWith(".tagx")) {
+ isXml = true;
+ isExternal = true;
+ }
+
+ if (isExternal && !isXml) {
+ // JSP (standard) syntax. Use encoding specified in jsp-config
+ // if provided.
+ sourceEnc = jspConfigPageEnc;
+ if (sourceEnc != null) {
+ return;
+ }
+ // We don't know the encoding, so use BOM to determine it
+ sourceEnc = "ISO-8859-1";
+ } else {
+ // XML syntax or unknown, (auto)detect encoding ...
+ Object[] ret = XMLEncodingDetector.getEncoding(absFileName,
+ jarFile, ctxt, err);
+ sourceEnc = (String) ret[0];
+ if (((Boolean) ret[1]).booleanValue()) {
+ isEncodingSpecifiedInProlog = true;
+ }
+ if (((Boolean) ret[2]).booleanValue()) {
+ isBomPresent = true;
+ }
+ skip = ((Integer) ret[3]).intValue();
+
+ if (!isXml && sourceEnc.equals("UTF-8")) {
+ /*
+ * We don't know if we're dealing with XML or standard syntax.
+ * Therefore, we need to check to see if the page contains
+ * a <jsp:root> element.
+ *
+ * We need to be careful, because the page may be encoded in
+ * ISO-8859-1 (or something entirely different), and may
+ * contain byte sequences that will cause a UTF-8 converter to
+ * throw exceptions.
+ *
+ * It is safe to use a source encoding of ISO-8859-1 in this
+ * case, as there are no invalid byte sequences in ISO-8859-1,
+ * and the byte/character sequences we're looking for (i.e.,
+ * <jsp:root>) are identical in either encoding (both UTF-8
+ * and ISO-8859-1 are extensions of ASCII).
+ */
+ sourceEnc = "ISO-8859-1";
+ revert = true;
+ }
+ }
+
+ if (isXml) {
+ // (This implies 'isExternal' is TRUE.)
+ // We know we're dealing with a JSP document (via JSP config or
+ // ".jspx" suffix), so we're done.
+ return;
+ }
+
+ /*
+ * At this point, 'isExternal' or 'isXml' is FALSE.
+ * Search for jsp:root action, in order to determine if we're dealing
+ * with XML or standard syntax (unless we already know what we're
+ * dealing with, i.e., when 'isExternal' is TRUE and 'isXml' is FALSE).
+ * No check for XML prolog, since nothing prevents a page from
+ * outputting XML and still using JSP syntax (in this case, the
+ * XML prolog is treated as template text).
+ */
+ JspReader jspReader = null;
+ try {
+ jspReader = new JspReader(ctxt, absFileName, sourceEnc, jarFile,
+ err);
+ } catch (FileNotFoundException ex) {
+ throw new JasperException(ex);
+ }
+ jspReader.setSingleFile(true);
+ Mark startMark = jspReader.mark();
+ if (!isExternal) {
+ jspReader.reset(startMark);
+ if (hasJspRoot(jspReader)) {
+ if (revert) {
+ sourceEnc = "UTF-8";
+ }
+ isXml = true;
+ return;
+ } else {
+ if (revert && isBomPresent) {
+ sourceEnc = "UTF-8";
+ }
+ isXml = false;
+ }
+ }
+
+ /*
+ * At this point, we know we're dealing with JSP syntax.
+ * If an XML prolog is provided, it's treated as template text.
+ * Determine the page encoding from the page directive, unless it's
+ * specified via JSP config.
+ */
+ if (!isBomPresent) {
+ sourceEnc = jspConfigPageEnc;
+ if (sourceEnc == null) {
+ sourceEnc = getPageEncodingForJspSyntax(jspReader, startMark);
+ if (sourceEnc == null) {
+ // Default to "ISO-8859-1" per JSP spec
+ sourceEnc = "ISO-8859-1";
+ isDefaultPageEncoding = true;
+ }
+ }
+ }
+
+ }
+
+ /*
+ * Determines page source encoding for page or tag file in JSP syntax,
+ * by reading (in this order) the value of the 'pageEncoding' page
+ * directive attribute, or the charset value of the 'contentType' page
+ * directive attribute.
+ *
+ * @return The page encoding, or null if not found
+ */
+ private String getPageEncodingForJspSyntax(JspReader jspReader,
+ Mark startMark)
+ throws JasperException {
+
+ String encoding = null;
+ String saveEncoding = null;
+
+ jspReader.reset(startMark);
+
+ /*
+ * Determine page encoding from directive of the form <%@ page %>,
+ * <%@ tag %>, <jsp:directive.page > or <jsp:directive.tag >.
+ */
+ while (true) {
+ if (jspReader.skipUntil("<") == null) {
+ break;
+ }
+ // If this is a comment, skip until its end
+ if (jspReader.matches("%--")) {
+ if (jspReader.skipUntil("--%>") == null) {
+ // error will be caught in Parser
+ break;
+ }
+ continue;
+ }
+ boolean isDirective = jspReader.matches("%@");
+ if (isDirective) {
+ jspReader.skipSpaces();
+ }
+ else {
+ isDirective = jspReader.matches("jsp:directive.");
+ }
+ if (!isDirective) {
+ continue;
+ }
+
+ // compare for "tag ", so we don't match "taglib"
+ if (jspReader.matches("tag ") || jspReader.matches("page")) {
+
+ jspReader.skipSpaces();
+ Attributes attrs = Parser.parseAttributes(this, jspReader);
+ encoding = getPageEncodingFromDirective(attrs, "pageEncoding");
+ if (encoding != null) {
+ break;
+ }
+ encoding = getPageEncodingFromDirective(attrs, "contentType");
+ if (encoding != null) {
+ saveEncoding = encoding;
+ }
+ }
+ }
+
+ if (encoding == null) {
+ encoding = saveEncoding;
+ }
+
+ return encoding;
+ }
+
+ /*
+ * Scans the given attributes for the attribute with the given name,
+ * which is either 'pageEncoding' or 'contentType', and returns the
+ * specified page encoding.
+ *
+ * In the case of 'contentType', the page encoding is taken from the
+ * content type's 'charset' component.
+ *
+ * @param attrs The page directive attributes
+ * @param attrName The name of the attribute to search for (either
+ * 'pageEncoding' or 'contentType')
+ *
+ * @return The page encoding, or null
+ */
+ private String getPageEncodingFromDirective(Attributes attrs,
+ String attrName) {
+ String value = attrs.getValue(attrName);
+ if (attrName.equals("pageEncoding")) {
+ return value;
+ }
+
+ // attrName = contentType
+ String contentType = value;
+ String encoding = null;
+ if (contentType != null) {
+ int loc = contentType.indexOf(CHARSET);
+ if (loc != -1) {
+ encoding = contentType.substring(loc + CHARSET.length());
+ }
+ }
+
+ return encoding;
+ }
+
+ /*
+ * Resolve the name of the file and update baseDirStack() to keep track of
+ * the current base directory for each included file.
+ * The 'root' file is always an 'absolute' path, so no need to put an
+ * initial value in the baseDirStack.
+ */
+ private String resolveFileName(String inFileName) {
+ String fileName = inFileName.replace('\\', '/');
+ boolean isAbsolute = fileName.startsWith("/");
+ fileName = isAbsolute ? fileName
+ : (String) baseDirStack.peek() + fileName;
+ String baseDir =
+ fileName.substring(0, fileName.lastIndexOf("/") + 1);
+ baseDirStack.push(baseDir);
+ return fileName;
+ }
+
+ /*
+ * Checks to see if the given page contains, as its first element, a <root>
+ * element whose prefix is bound to the JSP namespace, as in:
+ *
+ * <wombat:root xmlns:wombat="http://java.sun.com/JSP/Page" version="1.2">
+ * ...
+ * </wombat:root>
+ *
+ * @param reader The reader for this page
+ *
+ * @return true if this page contains a root element whose prefix is bound
+ * to the JSP namespace, and false otherwise
+ */
+ private boolean hasJspRoot(JspReader reader) throws JasperException {
+
+ // <prefix>:root must be the first element
+ Mark start = null;
+ while ((start = reader.skipUntil("<")) != null) {
+ int c = reader.nextChar();
+ if (c != '!' && c != '?') break;
+ }
+ if (start == null) {
+ return false;
+ }
+ Mark stop = reader.skipUntil(":root");
+ if (stop == null) {
+ return false;
+ }
+ // call substring to get rid of leading '<'
+ String prefix = reader.getText(start, stop).substring(1);
+
+ start = stop;
+ stop = reader.skipUntil(">");
+ if (stop == null) {
+ return false;
+ }
+
+ // Determine namespace associated with <root> element's prefix
+ String root = reader.getText(start, stop);
+ String xmlnsDecl = "xmlns:" + prefix;
+ int index = root.indexOf(xmlnsDecl);
+ if (index == -1) {
+ return false;
+ }
+ index += xmlnsDecl.length();
+ while (index < root.length()
+ && Character.isWhitespace(root.charAt(index))) {
+ index++;
+ }
+ if (index < root.length() && root.charAt(index) == '=') {
+ index++;
+ while (index < root.length()
+ && Character.isWhitespace(root.charAt(index))) {
+ index++;
+ }
+ if (index < root.length() && root.charAt(index++) == '"'
+ && root.regionMatches(index, JSP_URI, 0,
+ JSP_URI.length())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private JarFile getJarFile(URL jarFileUrl) throws IOException {
+ JarFile jarFile = null;
+
+ if (jarFileUrl != null) {
+ JarURLConnection conn = (JarURLConnection) jarFileUrl.openConnection();
+ conn.setUseCaches(false);
+ conn.connect();
+ jarFile = conn.getJarFile();
+ }
+
+ return jarFile;
+ }
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ScriptingVariabler.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ScriptingVariabler.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ScriptingVariabler.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ScriptingVariabler.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,148 @@
+/*
+ * 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.jasper.compiler;
+
+import java.util.*;
+import javax.servlet.jsp.tagext.*;
+import org.apache.jasper.JasperException;
+
+/**
+ * Class responsible for determining the scripting variables that every
+ * custom action needs to declare.
+ *
+ * @author Jan Luehe
+ */
+class ScriptingVariabler {
+
+ private static final Integer MAX_SCOPE = new Integer(Integer.MAX_VALUE);
+
+ /*
+ * Assigns an identifier (of type integer) to every custom tag, in order
+ * to help identify, for every custom tag, the scripting variables that it
+ * needs to declare.
+ */
+ static class CustomTagCounter extends Node.Visitor {
+
+ private int count;
+ private Node.CustomTag parent;
+
+ public void visit(Node.CustomTag n) throws JasperException {
+ n.setCustomTagParent(parent);
+ Node.CustomTag tmpParent = parent;
+ parent = n;
+ visitBody(n);
+ parent = tmpParent;
+ n.setNumCount(new Integer(count++));
+ }
+ }
+
+ /*
+ * For every custom tag, determines the scripting variables it needs to
+ * declare.
+ */
+ static class ScriptingVariableVisitor extends Node.Visitor {
+
+ private ErrorDispatcher err;
+ private Hashtable scriptVars;
+
+ public ScriptingVariableVisitor(ErrorDispatcher err) {
+ this.err = err;
+ scriptVars = new Hashtable();
+ }
+
+ public void visit(Node.CustomTag n) throws JasperException {
+ setScriptingVars(n, VariableInfo.AT_BEGIN);
+ setScriptingVars(n, VariableInfo.NESTED);
+ visitBody(n);
+ setScriptingVars(n, VariableInfo.AT_END);
+ }
+
+ private void setScriptingVars(Node.CustomTag n, int scope)
+ throws JasperException {
+
+ TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
+ VariableInfo[] varInfos = n.getVariableInfos();
+ if (tagVarInfos.length == 0 && varInfos.length == 0) {
+ return;
+ }
+
+ Vector vec = new Vector();
+
+ Integer ownRange = null;
+ if (scope == VariableInfo.AT_BEGIN
+ || scope == VariableInfo.AT_END) {
+ Node.CustomTag parent = n.getCustomTagParent();
+ if (parent == null)
+ ownRange = MAX_SCOPE;
+ else
+ ownRange = parent.getNumCount();
+ } else {
+ // NESTED
+ ownRange = n.getNumCount();
+ }
+
+ if (varInfos.length > 0) {
+ for (int i=0; i<varInfos.length; i++) {
+ if (varInfos[i].getScope() != scope
+ || !varInfos[i].getDeclare()) {
+ continue;
+ }
+ String varName = varInfos[i].getVarName();
+
+ Integer currentRange = (Integer) scriptVars.get(varName);
+ if (currentRange == null
+ || ownRange.compareTo(currentRange) > 0) {
+ scriptVars.put(varName, ownRange);
+ vec.add(varInfos[i]);
+ }
+ }
+ } else {
+ for (int i=0; i<tagVarInfos.length; i++) {
+ if (tagVarInfos[i].getScope() != scope
+ || !tagVarInfos[i].getDeclare()) {
+ continue;
+ }
+ String varName = tagVarInfos[i].getNameGiven();
+ if (varName == null) {
+ varName = n.getTagData().getAttributeString(
+ tagVarInfos[i].getNameFromAttribute());
+ if (varName == null) {
+ err.jspError(n, "jsp.error.scripting.variable.missing_name",
+ tagVarInfos[i].getNameFromAttribute());
+ }
+ }
+
+ Integer currentRange = (Integer) scriptVars.get(varName);
+ if (currentRange == null
+ || ownRange.compareTo(currentRange) > 0) {
+ scriptVars.put(varName, ownRange);
+ vec.add(tagVarInfos[i]);
+ }
+ }
+ }
+
+ n.setScriptingVars(vec, scope);
+ }
+ }
+
+ public static void set(Node.Nodes page, ErrorDispatcher err)
+ throws JasperException {
+ page.visit(new CustomTagCounter());
+ page.visit(new ScriptingVariableVisitor(err));
+ }
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ServletWriter.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ServletWriter.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ServletWriter.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ServletWriter.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,176 @@
+/*
+ * 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.jasper.compiler;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * This is what is used to generate servlets.
+ *
+ * @author Anil K. Vijendran
+ * @author Kin-man Chung
+ */
+public class ServletWriter {
+ public static int TAB_WIDTH = 2;
+ public static String SPACES = " ";
+
+ // Current indent level:
+ private int indent = 0;
+ private int virtual_indent = 0;
+
+ // The sink writer:
+ PrintWriter writer;
+
+ // servlet line numbers start from 1
+ private int javaLine = 1;
+
+
+ public ServletWriter(PrintWriter writer) {
+ this.writer = writer;
+ }
+
+ public void close() throws IOException {
+ writer.close();
+ }
+
+
+ // -------------------- Access informations --------------------
+
+ public int getJavaLine() {
+ return javaLine;
+ }
+
+
+ // -------------------- Formatting --------------------
+
+ public void pushIndent() {
+ virtual_indent += TAB_WIDTH;
+ if (virtual_indent >= 0 && virtual_indent <= SPACES.length())
+ indent = virtual_indent;
+ }
+
+ public void popIndent() {
+ virtual_indent -= TAB_WIDTH;
+ if (virtual_indent >= 0 && virtual_indent <= SPACES.length())
+ indent = virtual_indent;
+ }
+
+ /**
+ * Print a standard comment for echo outputed chunk.
+ * @param start The starting position of the JSP chunk being processed.
+ * @param stop The ending position of the JSP chunk being processed.
+ */
+ public void printComment(Mark start, Mark stop, char[] chars) {
+ if (start != null && stop != null) {
+ println("// from="+start);
+ println("// to="+stop);
+ }
+
+ if (chars != null)
+ for(int i = 0; i < chars.length;) {
+ printin();
+ print("// ");
+ while (chars[i] != '\n' && i < chars.length)
+ writer.print(chars[i++]);
+ }
+ }
+
+ /**
+ * Prints the given string followed by '\n'
+ */
+ public void println(String s) {
+ javaLine++;
+ writer.println(s);
+ }
+
+ /**
+ * Prints a '\n'
+ */
+ public void println() {
+ javaLine++;
+ writer.println("");
+ }
+
+ /**
+ * Prints the current indention
+ */
+ public void printin() {
+ writer.print(SPACES.substring(0, indent));
+ }
+
+ /**
+ * Prints the current indention, followed by the given string
+ */
+ public void printin(String s) {
+ writer.print(SPACES.substring(0, indent));
+ writer.print(s);
+ }
+
+ /**
+ * Prints the current indention, and then the string, and a '\n'.
+ */
+ public void printil(String s) {
+ javaLine++;
+ writer.print(SPACES.substring(0, indent));
+ writer.println(s);
+ }
+
+ /**
+ * Prints the given char.
+ *
+ * Use println() to print a '\n'.
+ */
+ public void print(char c) {
+ writer.print(c);
+ }
+
+ /**
+ * Prints the given int.
+ */
+ public void print(int i) {
+ writer.print(i);
+ }
+
+ /**
+ * Prints the given string.
+ *
+ * The string must not contain any '\n', otherwise the line count will be
+ * off.
+ */
+ public void print(String s) {
+ writer.print(s);
+ }
+
+ /**
+ * Prints the given string.
+ *
+ * If the string spans multiple lines, the line count will be adjusted
+ * accordingly.
+ */
+ public void printMultiLn(String s) {
+ int index = 0;
+
+ // look for hidden newlines inside strings
+ while ((index=s.indexOf('\n',index)) > -1 ) {
+ javaLine++;
+ index++;
+ }
+
+ writer.print(s);
+ }
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapGenerator.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapGenerator.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapGenerator.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapGenerator.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,171 @@
+/*
+ * 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.jasper.compiler;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Represents a source map (SMAP), which serves to associate lines
+ * of the input JSP file(s) to lines in the generated servlet in the
+ * final .class file, according to the JSR-045 spec.
+ *
+ * @author Shawn Bayern
+ */
+public class SmapGenerator {
+
+ //*********************************************************************
+ // Overview
+
+ /*
+ * The SMAP syntax is reasonably straightforward. The purpose of this
+ * class is currently twofold:
+ * - to provide a simple but low-level Java interface to build
+ * a logical SMAP
+ * - to serialize this logical SMAP for eventual inclusion directly
+ * into a .class file.
+ */
+
+
+ //*********************************************************************
+ // Private state
+
+ private String outputFileName;
+ private String defaultStratum = "Java";
+ private List strata = new ArrayList();
+ private List embedded = new ArrayList();
+ private boolean doEmbedded = true;
+
+ //*********************************************************************
+ // Methods for adding mapping data
+
+ /**
+ * Sets the filename (without path information) for the generated
+ * source file. E.g., "foo$jsp.java".
+ */
+ public synchronized void setOutputFileName(String x) {
+ outputFileName = x;
+ }
+
+ /**
+ * Adds the given SmapStratum object, representing a Stratum with
+ * logically associated FileSection and LineSection blocks, to
+ * the current SmapGenerator. If <tt>default</tt> is true, this
+ * stratum is made the default stratum, overriding any previously
+ * set default.
+ *
+ * @param stratum the SmapStratum object to add
+ * @param defaultStratum if <tt>true</tt>, this SmapStratum is considered
+ * to represent the default SMAP stratum unless
+ * overwritten
+ */
+ public synchronized void addStratum(SmapStratum stratum,
+ boolean defaultStratum) {
+ strata.add(stratum);
+ if (defaultStratum)
+ this.defaultStratum = stratum.getStratumName();
+ }
+
+ /**
+ * Adds the given string as an embedded SMAP with the given stratum name.
+ *
+ * @param smap the SMAP to embed
+ * @param stratumName the name of the stratum output by the compilation
+ * that produced the <tt>smap</tt> to be embedded
+ */
+ public synchronized void addSmap(String smap, String stratumName) {
+ embedded.add("*O " + stratumName + "\n"
+ + smap
+ + "*C " + stratumName + "\n");
+ }
+
+ /**
+ * Instructs the SmapGenerator whether to actually print any embedded
+ * SMAPs or not. Intended for situations without an SMAP resolver.
+ *
+ * @param status If <tt>false</tt>, ignore any embedded SMAPs.
+ */
+ public void setDoEmbedded(boolean status) {
+ doEmbedded = status;
+ }
+
+ //*********************************************************************
+ // Methods for serializing the logical SMAP
+
+ public synchronized String getString() {
+ // check state and initialize buffer
+ if (outputFileName == null)
+ throw new IllegalStateException();
+ StringBuffer out = new StringBuffer();
+
+ // start the SMAP
+ out.append("SMAP\n");
+ out.append(outputFileName + '\n');
+ out.append(defaultStratum + '\n');
+
+ // include embedded SMAPs
+ if (doEmbedded) {
+ int nEmbedded = embedded.size();
+ for (int i = 0; i < nEmbedded; i++) {
+ out.append(embedded.get(i));
+ }
+ }
+
+ // print our StratumSections, FileSections, and LineSections
+ int nStrata = strata.size();
+ for (int i = 0; i < nStrata; i++) {
+ SmapStratum s = (SmapStratum) strata.get(i);
+ out.append(s.getString());
+ }
+
+ // end the SMAP
+ out.append("*E\n");
+
+ return out.toString();
+ }
+
+ public String toString() { return getString(); }
+
+ //*********************************************************************
+ // For testing (and as an example of use)...
+
+ public static void main(String args[]) {
+ SmapGenerator g = new SmapGenerator();
+ g.setOutputFileName("foo.java");
+ SmapStratum s = new SmapStratum("JSP");
+ s.addFile("foo.jsp");
+ s.addFile("bar.jsp", "/foo/foo/bar.jsp");
+ s.addLineData(1, "foo.jsp", 1, 1, 1);
+ s.addLineData(2, "foo.jsp", 1, 6, 1);
+ s.addLineData(3, "foo.jsp", 2, 10, 5);
+ s.addLineData(20, "bar.jsp", 1, 30, 1);
+ g.addStratum(s, true);
+ System.out.print(g);
+
+ System.out.println("---");
+
+ SmapGenerator embedded = new SmapGenerator();
+ embedded.setOutputFileName("blargh.tier2");
+ s = new SmapStratum("Tier2");
+ s.addFile("1.tier2");
+ s.addLineData(1, "1.tier2", 1, 1, 1);
+ embedded.addStratum(s, true);
+ g.addSmap(embedded.toString(), "JSP");
+ System.out.println(g);
+ }
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapStratum.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapStratum.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapStratum.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapStratum.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,336 @@
+/*
+ * 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.jasper.compiler;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Represents the line and file mappings associated with a JSR-045
+ * "stratum".
+ *
+ * @author Jayson Falkner
+ * @author Shawn Bayern
+ */
+public class SmapStratum {
+
+ //*********************************************************************
+ // Class for storing LineInfo data
+
+ /**
+ * Represents a single LineSection in an SMAP, associated with
+ * a particular stratum.
+ */
+ public static class LineInfo {
+ private int inputStartLine = -1;
+ private int outputStartLine = -1;
+ private int lineFileID = 0;
+ private int inputLineCount = 1;
+ private int outputLineIncrement = 1;
+ private boolean lineFileIDSet = false;
+
+ /** Sets InputStartLine. */
+ public void setInputStartLine(int inputStartLine) {
+ if (inputStartLine < 0)
+ throw new IllegalArgumentException("" + inputStartLine);
+ this.inputStartLine = inputStartLine;
+ }
+
+ /** Sets OutputStartLine. */
+ public void setOutputStartLine(int outputStartLine) {
+ if (outputStartLine < 0)
+ throw new IllegalArgumentException("" + outputStartLine);
+ this.outputStartLine = outputStartLine;
+ }
+
+ /**
+ * Sets lineFileID. Should be called only when different from
+ * that of prior LineInfo object (in any given context) or 0
+ * if the current LineInfo has no (logical) predecessor.
+ * <tt>LineInfo</tt> will print this file number no matter what.
+ */
+ public void setLineFileID(int lineFileID) {
+ if (lineFileID < 0)
+ throw new IllegalArgumentException("" + lineFileID);
+ this.lineFileID = lineFileID;
+ this.lineFileIDSet = true;
+ }
+
+ /** Sets InputLineCount. */
+ public void setInputLineCount(int inputLineCount) {
+ if (inputLineCount < 0)
+ throw new IllegalArgumentException("" + inputLineCount);
+ this.inputLineCount = inputLineCount;
+ }
+
+ /** Sets OutputLineIncrement. */
+ public void setOutputLineIncrement(int outputLineIncrement) {
+ if (outputLineIncrement < 0)
+ throw new IllegalArgumentException("" + outputLineIncrement);
+ this.outputLineIncrement = outputLineIncrement;
+ }
+
+ /**
+ * Retrieves the current LineInfo as a String, print all values
+ * only when appropriate (but LineInfoID if and only if it's been
+ * specified, as its necessity is sensitive to context).
+ */
+ public String getString() {
+ if (inputStartLine == -1 || outputStartLine == -1)
+ throw new IllegalStateException();
+ StringBuffer out = new StringBuffer();
+ out.append(inputStartLine);
+ if (lineFileIDSet)
+ out.append("#" + lineFileID);
+ if (inputLineCount != 1)
+ out.append("," + inputLineCount);
+ out.append(":" + outputStartLine);
+ if (outputLineIncrement != 1)
+ out.append("," + outputLineIncrement);
+ out.append('\n');
+ return out.toString();
+ }
+
+ public String toString() {
+ return getString();
+ }
+ }
+
+ //*********************************************************************
+ // Private state
+
+ private String stratumName;
+ private List fileNameList;
+ private List filePathList;
+ private List lineData;
+ private int lastFileID;
+
+ //*********************************************************************
+ // Constructor
+
+ /**
+ * Constructs a new SmapStratum object for the given stratum name
+ * (e.g., JSP).
+ *
+ * @param stratumName the name of the stratum (e.g., JSP)
+ */
+ public SmapStratum(String stratumName) {
+ this.stratumName = stratumName;
+ fileNameList = new ArrayList();
+ filePathList = new ArrayList();
+ lineData = new ArrayList();
+ lastFileID = 0;
+ }
+
+ //*********************************************************************
+ // Methods to add mapping information
+
+ /**
+ * Adds record of a new file, by filename.
+ *
+ * @param filename the filename to add, unqualified by path.
+ */
+ public void addFile(String filename) {
+ addFile(filename, filename);
+ }
+
+ /**
+ * Adds record of a new file, by filename and path. The path
+ * may be relative to a source compilation path.
+ *
+ * @param filename the filename to add, unqualified by path
+ * @param filePath the path for the filename, potentially relative
+ * to a source compilation path
+ */
+ public void addFile(String filename, String filePath) {
+ int pathIndex = filePathList.indexOf(filePath);
+ if (pathIndex == -1) {
+ fileNameList.add(filename);
+ filePathList.add(filePath);
+ }
+ }
+
+ /**
+ * Combines consecutive LineInfos wherever possible
+ */
+ public void optimizeLineSection() {
+
+/* Some debugging code
+ for (int i = 0; i < lineData.size(); i++) {
+ LineInfo li = (LineInfo)lineData.get(i);
+ System.out.print(li.toString());
+ }
+*/
+ //Incorporate each LineInfo into the previous LineInfo's
+ //outputLineIncrement, if possible
+ int i = 0;
+ while (i < lineData.size() - 1) {
+ LineInfo li = (LineInfo)lineData.get(i);
+ LineInfo liNext = (LineInfo)lineData.get(i + 1);
+ if (!liNext.lineFileIDSet
+ && liNext.inputStartLine == li.inputStartLine
+ && liNext.inputLineCount == 1
+ && li.inputLineCount == 1
+ && liNext.outputStartLine
+ == li.outputStartLine
+ + li.inputLineCount * li.outputLineIncrement) {
+ li.setOutputLineIncrement(
+ liNext.outputStartLine
+ - li.outputStartLine
+ + liNext.outputLineIncrement);
+ lineData.remove(i + 1);
+ } else {
+ i++;
+ }
+ }
+
+ //Incorporate each LineInfo into the previous LineInfo's
+ //inputLineCount, if possible
+ i = 0;
+ while (i < lineData.size() - 1) {
+ LineInfo li = (LineInfo)lineData.get(i);
+ LineInfo liNext = (LineInfo)lineData.get(i + 1);
+ if (!liNext.lineFileIDSet
+ && liNext.inputStartLine == li.inputStartLine + li.inputLineCount
+ && liNext.outputLineIncrement == li.outputLineIncrement
+ && liNext.outputStartLine
+ == li.outputStartLine
+ + li.inputLineCount * li.outputLineIncrement) {
+ li.setInputLineCount(li.inputLineCount + liNext.inputLineCount);
+ lineData.remove(i + 1);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ /**
+ * Adds complete information about a simple line mapping. Specify
+ * all the fields in this method; the back-end machinery takes care
+ * of printing only those that are necessary in the final SMAP.
+ * (My view is that fields are optional primarily for spatial efficiency,
+ * not for programmer convenience. Could always add utility methods
+ * later.)
+ *
+ * @param inputStartLine starting line in the source file
+ * (SMAP <tt>InputStartLine</tt>)
+ * @param inputFileName the filepath (or name) from which the input comes
+ * (yields SMAP <tt>LineFileID</tt>) Use unqualified names
+ * carefully, and only when they uniquely identify a file.
+ * @param inputLineCount the number of lines in the input to map
+ * (SMAP <tt>LineFileCount</tt>)
+ * @param outputStartLine starting line in the output file
+ * (SMAP <tt>OutputStartLine</tt>)
+ * @param outputLineIncrement number of output lines to map to each
+ * input line (SMAP <tt>OutputLineIncrement</tt>). <i>Given the
+ * fact that the name starts with "output", I continuously have
+ * the subconscious urge to call this field
+ * <tt>OutputLineExcrement</tt>.</i>
+ */
+ public void addLineData(
+ int inputStartLine,
+ String inputFileName,
+ int inputLineCount,
+ int outputStartLine,
+ int outputLineIncrement) {
+ // check the input - what are you doing here??
+ int fileIndex = filePathList.indexOf(inputFileName);
+ if (fileIndex == -1) // still
+ throw new IllegalArgumentException(
+ "inputFileName: " + inputFileName);
+
+ //Jasper incorrectly SMAPs certain Nodes, giving them an
+ //outputStartLine of 0. This can cause a fatal error in
+ //optimizeLineSection, making it impossible for Jasper to
+ //compile the JSP. Until we can fix the underlying
+ //SMAPping problem, we simply ignore the flawed SMAP entries.
+ if (outputStartLine == 0)
+ return;
+
+ // build the LineInfo
+ LineInfo li = new LineInfo();
+ li.setInputStartLine(inputStartLine);
+ li.setInputLineCount(inputLineCount);
+ li.setOutputStartLine(outputStartLine);
+ li.setOutputLineIncrement(outputLineIncrement);
+ if (fileIndex != lastFileID)
+ li.setLineFileID(fileIndex);
+ lastFileID = fileIndex;
+
+ // save it
+ lineData.add(li);
+ }
+
+ //*********************************************************************
+ // Methods to retrieve information
+
+ /**
+ * Returns the name of the stratum.
+ */
+ public String getStratumName() {
+ return stratumName;
+ }
+
+ /**
+ * Returns the given stratum as a String: a StratumSection,
+ * followed by at least one FileSection and at least one LineSection.
+ */
+ public String getString() {
+ // check state and initialize buffer
+ if (fileNameList.size() == 0 || lineData.size() == 0)
+ return null;
+
+ StringBuffer out = new StringBuffer();
+
+ // print StratumSection
+ out.append("*S " + stratumName + "\n");
+
+ // print FileSection
+ out.append("*F\n");
+ int bound = fileNameList.size();
+ for (int i = 0; i < bound; i++) {
+ if (filePathList.get(i) != null) {
+ out.append("+ " + i + " " + fileNameList.get(i) + "\n");
+ // Source paths must be relative, not absolute, so we
+ // remove the leading "/", if one exists.
+ String filePath = (String)filePathList.get(i);
+ if (filePath.startsWith("/")) {
+ filePath = filePath.substring(1);
+ }
+ out.append(filePath + "\n");
+ } else {
+ out.append(i + " " + fileNameList.get(i) + "\n");
+ }
+ }
+
+ // print LineSection
+ out.append("*L\n");
+ bound = lineData.size();
+ for (int i = 0; i < bound; i++) {
+ LineInfo li = (LineInfo)lineData.get(i);
+ out.append(li.getString());
+ }
+
+ return out.toString();
+ }
+
+ public String toString() {
+ return getString();
+ }
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapUtil.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapUtil.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapUtil.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/SmapUtil.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,729 @@
+/*
+ * 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.jasper.compiler;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.jasper.JasperException;
+import org.apache.jasper.JspCompilationContext;
+
+/**
+ * Contains static utilities for generating SMAP data based on the
+ * current version of Jasper.
+ *
+ * @author Jayson Falkner
+ * @author Shawn Bayern
+ * @author Robert Field (inner SDEInstaller class)
+ * @author Mark Roth
+ * @author Kin-man Chung
+ */
+public class SmapUtil {
+
+ private org.apache.juli.logging.Log log=
+ org.apache.juli.logging.LogFactory.getLog( SmapUtil.class );
+
+ //*********************************************************************
+ // Constants
+
+ public static final String SMAP_ENCODING = "UTF-8";
+
+ //*********************************************************************
+ // Public entry points
+
+ /**
+ * Generates an appropriate SMAP representing the current compilation
+ * context. (JSR-045.)
+ *
+ * @param ctxt Current compilation context
+ * @param pageNodes The current JSP page
+ * @return a SMAP for the page
+ */
+ public static String[] generateSmap(
+ JspCompilationContext ctxt,
+ Node.Nodes pageNodes)
+ throws IOException {
+
+ // Scan the nodes for presence of Jasper generated inner classes
+ PreScanVisitor psVisitor = new PreScanVisitor();
+ try {
+ pageNodes.visit(psVisitor);
+ } catch (JasperException ex) {
+ }
+ HashMap map = psVisitor.getMap();
+
+ // set up our SMAP generator
+ SmapGenerator g = new SmapGenerator();
+
+ /** Disable reading of input SMAP because:
+ 1. There is a bug here: getRealPath() is null if .jsp is in a jar
+ Bugzilla 14660.
+ 2. Mappings from other sources into .jsp files are not supported.
+ TODO: fix 1. if 2. is not true.
+ // determine if we have an input SMAP
+ String smapPath = inputSmapPath(ctxt.getRealPath(ctxt.getJspFile()));
+ File inputSmap = new File(smapPath);
+ if (inputSmap.exists()) {
+ byte[] embeddedSmap = null;
+ byte[] subSmap = SDEInstaller.readWhole(inputSmap);
+ String subSmapString = new String(subSmap, SMAP_ENCODING);
+ g.addSmap(subSmapString, "JSP");
+ }
+ **/
+
+ // now, assemble info about our own stratum (JSP) using JspLineMap
+ SmapStratum s = new SmapStratum("JSP");
+
+ g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
+
+ // Map out Node.Nodes
+ evaluateNodes(pageNodes, s, map, ctxt.getOptions().getMappedFile());
+ s.optimizeLineSection();
+ g.addStratum(s, true);
+
+ if (ctxt.getOptions().isSmapDumped()) {
+ File outSmap = new File(ctxt.getClassFileName() + ".smap");
+ PrintWriter so =
+ new PrintWriter(
+ new OutputStreamWriter(
+ new FileOutputStream(outSmap),
+ SMAP_ENCODING));
+ so.print(g.getString());
+ so.close();
+ }
+
+ String classFileName = ctxt.getClassFileName();
+ int innerClassCount = map.size();
+ String [] smapInfo = new String[2 + innerClassCount*2];
+ smapInfo[0] = classFileName;
+ smapInfo[1] = g.getString();
+
+ int count = 2;
+ Iterator iter = map.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String innerClass = (String) entry.getKey();
+ s = (SmapStratum) entry.getValue();
+ s.optimizeLineSection();
+ g = new SmapGenerator();
+ g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
+ g.addStratum(s, true);
+
+ String innerClassFileName =
+ classFileName.substring(0, classFileName.indexOf(".class")) +
+ '$' + innerClass + ".class";
+ if (ctxt.getOptions().isSmapDumped()) {
+ File outSmap = new File(innerClassFileName + ".smap");
+ PrintWriter so =
+ new PrintWriter(
+ new OutputStreamWriter(
+ new FileOutputStream(outSmap),
+ SMAP_ENCODING));
+ so.print(g.getString());
+ so.close();
+ }
+ smapInfo[count] = innerClassFileName;
+ smapInfo[count+1] = g.getString();
+ count += 2;
+ }
+
+ return smapInfo;
+ }
+
+ public static void installSmap(String[] smap)
+ throws IOException {
+ if (smap == null) {
+ return;
+ }
+
+ for (int i = 0; i < smap.length; i += 2) {
+ File outServlet = new File(smap[i]);
+ SDEInstaller.install(outServlet, smap[i+1].getBytes());
+ }
+ }
+
+ //*********************************************************************
+ // Private utilities
+
+ /**
+ * Returns an unqualified version of the given file path.
+ */
+ private static String unqualify(String path) {
+ path = path.replace('\\', '/');
+ return path.substring(path.lastIndexOf('/') + 1);
+ }
+
+ /**
+ * Returns a file path corresponding to a potential SMAP input
+ * for the given compilation input (JSP file).
+ */
+ private static String inputSmapPath(String path) {
+ return path.substring(0, path.lastIndexOf('.') + 1) + "smap";
+ }
+
+ //*********************************************************************
+ // Installation logic (from Robert Field, JSR-045 spec lead)
+ private static class SDEInstaller {
+
+ private org.apache.juli.logging.Log log=
+ org.apache.juli.logging.LogFactory.getLog( SDEInstaller.class );
+
+ static final String nameSDE = "SourceDebugExtension";
+
+ byte[] orig;
+ byte[] sdeAttr;
+ byte[] gen;
+
+ int origPos = 0;
+ int genPos = 0;
+
+ int sdeIndex;
+
+ public static void main(String[] args) throws IOException {
+ if (args.length == 2) {
+ install(new File(args[0]), new File(args[1]));
+ } else if (args.length == 3) {
+ install(
+ new File(args[0]),
+ new File(args[1]),
+ new File(args[2]));
+ } else {
+ System.err.println(
+ "Usage: <command> <input class file> "
+ + "<attribute file> <output class file name>\n"
+ + "<command> <input/output class file> <attribute file>");
+ }
+ }
+
+ static void install(File inClassFile, File attrFile, File outClassFile)
+ throws IOException {
+ new SDEInstaller(inClassFile, attrFile, outClassFile);
+ }
+
+ static void install(File inOutClassFile, File attrFile)
+ throws IOException {
+ File tmpFile = new File(inOutClassFile.getPath() + "tmp");
+ new SDEInstaller(inOutClassFile, attrFile, tmpFile);
+ if (!inOutClassFile.delete()) {
+ throw new IOException("inOutClassFile.delete() failed");
+ }
+ if (!tmpFile.renameTo(inOutClassFile)) {
+ throw new IOException("tmpFile.renameTo(inOutClassFile) failed");
+ }
+ }
+
+ static void install(File classFile, byte[] smap) throws IOException {
+ File tmpFile = new File(classFile.getPath() + "tmp");
+ new SDEInstaller(classFile, smap, tmpFile);
+ if (!classFile.delete()) {
+ throw new IOException("classFile.delete() failed");
+ }
+ if (!tmpFile.renameTo(classFile)) {
+ throw new IOException("tmpFile.renameTo(classFile) failed");
+ }
+ }
+
+ SDEInstaller(File inClassFile, byte[] sdeAttr, File outClassFile)
+ throws IOException {
+ if (!inClassFile.exists()) {
+ throw new FileNotFoundException("no such file: " + inClassFile);
+ }
+
+ this.sdeAttr = sdeAttr;
+ // get the bytes
+ orig = readWhole(inClassFile);
+ gen = new byte[orig.length + sdeAttr.length + 100];
+
+ // do it
+ addSDE();
+
+ // write result
+ FileOutputStream outStream = new FileOutputStream(outClassFile);
+ outStream.write(gen, 0, genPos);
+ outStream.close();
+ }
+
+ SDEInstaller(File inClassFile, File attrFile, File outClassFile)
+ throws IOException {
+ this(inClassFile, readWhole(attrFile), outClassFile);
+ }
+
+ static byte[] readWhole(File input) throws IOException {
+ FileInputStream inStream = new FileInputStream(input);
+ int len = (int)input.length();
+ byte[] bytes = new byte[len];
+ if (inStream.read(bytes, 0, len) != len) {
+ throw new IOException("expected size: " + len);
+ }
+ inStream.close();
+ return bytes;
+ }
+
+ void addSDE() throws UnsupportedEncodingException, IOException {
+ int i;
+ copy(4 + 2 + 2); // magic min/maj version
+ int constantPoolCountPos = genPos;
+ int constantPoolCount = readU2();
+ if (log.isDebugEnabled())
+ log.debug("constant pool count: " + constantPoolCount);
+ writeU2(constantPoolCount);
+
+ // copy old constant pool return index of SDE symbol, if found
+ sdeIndex = copyConstantPool(constantPoolCount);
+ if (sdeIndex < 0) {
+ // if "SourceDebugExtension" symbol not there add it
+ writeUtf8ForSDE();
+
+ // increment the countantPoolCount
+ sdeIndex = constantPoolCount;
+ ++constantPoolCount;
+ randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
+
+ if (log.isDebugEnabled())
+ log.debug("SourceDebugExtension not found, installed at: " + sdeIndex);
+ } else {
+ if (log.isDebugEnabled())
+ log.debug("SourceDebugExtension found at: " + sdeIndex);
+ }
+ copy(2 + 2 + 2); // access, this, super
+ int interfaceCount = readU2();
+ writeU2(interfaceCount);
+ if (log.isDebugEnabled())
+ log.debug("interfaceCount: " + interfaceCount);
+ copy(interfaceCount * 2);
+ copyMembers(); // fields
+ copyMembers(); // methods
+ int attrCountPos = genPos;
+ int attrCount = readU2();
+ writeU2(attrCount);
+ if (log.isDebugEnabled())
+ log.debug("class attrCount: " + attrCount);
+ // copy the class attributes, return true if SDE attr found (not copied)
+ if (!copyAttrs(attrCount)) {
+ // we will be adding SDE and it isn't already counted
+ ++attrCount;
+ randomAccessWriteU2(attrCountPos, attrCount);
+ if (log.isDebugEnabled())
+ log.debug("class attrCount incremented");
+ }
+ writeAttrForSDE(sdeIndex);
+ }
+
+ void copyMembers() {
+ int count = readU2();
+ writeU2(count);
+ if (log.isDebugEnabled())
+ log.debug("members count: " + count);
+ for (int i = 0; i < count; ++i) {
+ copy(6); // access, name, descriptor
+ int attrCount = readU2();
+ writeU2(attrCount);
+ if (log.isDebugEnabled())
+ log.debug("member attr count: " + attrCount);
+ copyAttrs(attrCount);
+ }
+ }
+
+ boolean copyAttrs(int attrCount) {
+ boolean sdeFound = false;
+ for (int i = 0; i < attrCount; ++i) {
+ int nameIndex = readU2();
+ // don't write old SDE
+ if (nameIndex == sdeIndex) {
+ sdeFound = true;
+ if (log.isDebugEnabled())
+ log.debug("SDE attr found");
+ } else {
+ writeU2(nameIndex); // name
+ int len = readU4();
+ writeU4(len);
+ copy(len);
+ if (log.isDebugEnabled())
+ log.debug("attr len: " + len);
+ }
+ }
+ return sdeFound;
+ }
+
+ void writeAttrForSDE(int index) {
+ writeU2(index);
+ writeU4(sdeAttr.length);
+ for (int i = 0; i < sdeAttr.length; ++i) {
+ writeU1(sdeAttr[i]);
+ }
+ }
+
+ void randomAccessWriteU2(int pos, int val) {
+ int savePos = genPos;
+ genPos = pos;
+ writeU2(val);
+ genPos = savePos;
+ }
+
+ int readU1() {
+ return ((int)orig[origPos++]) & 0xFF;
+ }
+
+ int readU2() {
+ int res = readU1();
+ return (res << 8) + readU1();
+ }
+
+ int readU4() {
+ int res = readU2();
+ return (res << 16) + readU2();
+ }
+
+ void writeU1(int val) {
+ gen[genPos++] = (byte)val;
+ }
+
+ void writeU2(int val) {
+ writeU1(val >> 8);
+ writeU1(val & 0xFF);
+ }
+
+ void writeU4(int val) {
+ writeU2(val >> 16);
+ writeU2(val & 0xFFFF);
+ }
+
+ void copy(int count) {
+ for (int i = 0; i < count; ++i) {
+ gen[genPos++] = orig[origPos++];
+ }
+ }
+
+ byte[] readBytes(int count) {
+ byte[] bytes = new byte[count];
+ for (int i = 0; i < count; ++i) {
+ bytes[i] = orig[origPos++];
+ }
+ return bytes;
+ }
+
+ void writeBytes(byte[] bytes) {
+ for (int i = 0; i < bytes.length; ++i) {
+ gen[genPos++] = bytes[i];
+ }
+ }
+
+ int copyConstantPool(int constantPoolCount)
+ throws UnsupportedEncodingException, IOException {
+ int sdeIndex = -1;
+ // copy const pool index zero not in class file
+ for (int i = 1; i < constantPoolCount; ++i) {
+ int tag = readU1();
+ writeU1(tag);
+ switch (tag) {
+ case 7 : // Class
+ case 8 : // String
+ if (log.isDebugEnabled())
+ log.debug(i + " copying 2 bytes");
+ copy(2);
+ break;
+ case 9 : // Field
+ case 10 : // Method
+ case 11 : // InterfaceMethod
+ case 3 : // Integer
+ case 4 : // Float
+ case 12 : // NameAndType
+ if (log.isDebugEnabled())
+ log.debug(i + " copying 4 bytes");
+ copy(4);
+ break;
+ case 5 : // Long
+ case 6 : // Double
+ if (log.isDebugEnabled())
+ log.debug(i + " copying 8 bytes");
+ copy(8);
+ i++;
+ break;
+ case 1 : // Utf8
+ int len = readU2();
+ writeU2(len);
+ byte[] utf8 = readBytes(len);
+ String str = new String(utf8, "UTF-8");
+ if (log.isDebugEnabled())
+ log.debug(i + " read class attr -- '" + str + "'");
+ if (str.equals(nameSDE)) {
+ sdeIndex = i;
+ }
+ writeBytes(utf8);
+ break;
+ default :
+ throw new IOException("unexpected tag: " + tag);
+ }
+ }
+ return sdeIndex;
+ }
+
+ void writeUtf8ForSDE() {
+ int len = nameSDE.length();
+ writeU1(1); // Utf8 tag
+ writeU2(len);
+ for (int i = 0; i < len; ++i) {
+ writeU1(nameSDE.charAt(i));
+ }
+ }
+ }
+
+ public static void evaluateNodes(
+ Node.Nodes nodes,
+ SmapStratum s,
+ HashMap innerClassMap,
+ boolean breakAtLF) {
+ try {
+ nodes.visit(new SmapGenVisitor(s, breakAtLF, innerClassMap));
+ } catch (JasperException ex) {
+ }
+ }
+
+ static class SmapGenVisitor extends Node.Visitor {
+
+ private SmapStratum smap;
+ private boolean breakAtLF;
+ private HashMap innerClassMap;
+
+ SmapGenVisitor(SmapStratum s, boolean breakAtLF, HashMap map) {
+ this.smap = s;
+ this.breakAtLF = breakAtLF;
+ this.innerClassMap = map;
+ }
+
+ public void visitBody(Node n) throws JasperException {
+ SmapStratum smapSave = smap;
+ String innerClass = n.getInnerClassName();
+ if (innerClass != null) {
+ this.smap = (SmapStratum) innerClassMap.get(innerClass);
+ }
+ super.visitBody(n);
+ smap = smapSave;
+ }
+
+ public void visit(Node.Declaration n) throws JasperException {
+ doSmapText(n);
+ }
+
+ public void visit(Node.Expression n) throws JasperException {
+ doSmapText(n);
+ }
+
+ public void visit(Node.Scriptlet n) throws JasperException {
+ doSmapText(n);
+ }
+
+ public void visit(Node.IncludeAction n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.ForwardAction n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.GetProperty n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.SetProperty n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.UseBean n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.PlugIn n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.CustomTag n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.UninterpretedTag n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.JspElement n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.JspText n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.NamedAttribute n) throws JasperException {
+ visitBody(n);
+ }
+
+ public void visit(Node.JspBody n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.InvokeAction n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.DoBodyAction n) throws JasperException {
+ doSmap(n);
+ visitBody(n);
+ }
+
+ public void visit(Node.ELExpression n) throws JasperException {
+ doSmap(n);
+ }
+
+ public void visit(Node.TemplateText n) throws JasperException {
+ Mark mark = n.getStart();
+ if (mark == null) {
+ return;
+ }
+
+ //Add the file information
+ String fileName = mark.getFile();
+ smap.addFile(unqualify(fileName), fileName);
+
+ //Add a LineInfo that corresponds to the beginning of this node
+ int iInputStartLine = mark.getLineNumber();
+ int iOutputStartLine = n.getBeginJavaLine();
+ int iOutputLineIncrement = breakAtLF? 1: 0;
+ smap.addLineData(iInputStartLine, fileName, 1, iOutputStartLine,
+ iOutputLineIncrement);
+
+ // Output additional mappings in the text
+ java.util.ArrayList extraSmap = n.getExtraSmap();
+
+ if (extraSmap != null) {
+ for (int i = 0; i < extraSmap.size(); i++) {
+ iOutputStartLine += iOutputLineIncrement;
+ smap.addLineData(
+ iInputStartLine+((Integer)extraSmap.get(i)).intValue(),
+ fileName,
+ 1,
+ iOutputStartLine,
+ iOutputLineIncrement);
+ }
+ }
+ }
+
+ private void doSmap(
+ Node n,
+ int inLineCount,
+ int outIncrement,
+ int skippedLines) {
+ Mark mark = n.getStart();
+ if (mark == null) {
+ return;
+ }
+
+ String unqualifiedName = unqualify(mark.getFile());
+ smap.addFile(unqualifiedName, mark.getFile());
+ smap.addLineData(
+ mark.getLineNumber() + skippedLines,
+ mark.getFile(),
+ inLineCount - skippedLines,
+ n.getBeginJavaLine() + skippedLines,
+ outIncrement);
+ }
+
+ private void doSmap(Node n) {
+ doSmap(n, 1, n.getEndJavaLine() - n.getBeginJavaLine(), 0);
+ }
+
+ private void doSmapText(Node n) {
+ String text = n.getText();
+ int index = 0;
+ int next = 0;
+ int lineCount = 1;
+ int skippedLines = 0;
+ boolean slashStarSeen = false;
+ boolean beginning = true;
+
+ // Count lines inside text, but skipping comment lines at the
+ // beginning of the text.
+ while ((next = text.indexOf('\n', index)) > -1) {
+ if (beginning) {
+ String line = text.substring(index, next).trim();
+ if (!slashStarSeen && line.startsWith("/*")) {
+ slashStarSeen = true;
+ }
+ if (slashStarSeen) {
+ skippedLines++;
+ int endIndex = line.indexOf("*/");
+ if (endIndex >= 0) {
+ // End of /* */ comment
+ slashStarSeen = false;
+ if (endIndex < line.length() - 2) {
+ // Some executable code after comment
+ skippedLines--;
+ beginning = false;
+ }
+ }
+ } else if (line.length() == 0 || line.startsWith("//")) {
+ skippedLines++;
+ } else {
+ beginning = false;
+ }
+ }
+ lineCount++;
+ index = next + 1;
+ }
+
+ doSmap(n, lineCount, 1, skippedLines);
+ }
+ }
+
+ private static class PreScanVisitor extends Node.Visitor {
+
+ HashMap map = new HashMap();
+
+ public void doVisit(Node n) {
+ String inner = n.getInnerClassName();
+ if (inner != null && !map.containsKey(inner)) {
+ map.put(inner, new SmapStratum("JSP"));
+ }
+ }
+
+ HashMap getMap() {
+ return map;
+ }
+ }
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagConstants.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagConstants.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagConstants.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagConstants.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.jasper.compiler;
+
+public interface TagConstants {
+
+ public static final String JSP_URI = "http://java.sun.com/JSP/Page";
+
+ public static final String DIRECTIVE_ACTION = "directive.";
+
+ public static final String ROOT_ACTION = "root";
+ public static final String JSP_ROOT_ACTION = "jsp:root";
+
+ public static final String PAGE_DIRECTIVE_ACTION = "directive.page";
+ public static final String JSP_PAGE_DIRECTIVE_ACTION = "jsp:directive.page";
+
+ public static final String INCLUDE_DIRECTIVE_ACTION = "directive.include";
+ public static final String JSP_INCLUDE_DIRECTIVE_ACTION = "jsp:directive.include";
+
+ public static final String DECLARATION_ACTION = "declaration";
+ public static final String JSP_DECLARATION_ACTION = "jsp:declaration";
+
+ public static final String SCRIPTLET_ACTION = "scriptlet";
+ public static final String JSP_SCRIPTLET_ACTION = "jsp:scriptlet";
+
+ public static final String EXPRESSION_ACTION = "expression";
+ public static final String JSP_EXPRESSION_ACTION = "jsp:expression";
+
+ public static final String USE_BEAN_ACTION = "useBean";
+ public static final String JSP_USE_BEAN_ACTION = "jsp:useBean";
+
+ public static final String SET_PROPERTY_ACTION = "setProperty";
+ public static final String JSP_SET_PROPERTY_ACTION = "jsp:setProperty";
+
+ public static final String GET_PROPERTY_ACTION = "getProperty";
+ public static final String JSP_GET_PROPERTY_ACTION = "jsp:getProperty";
+
+ public static final String INCLUDE_ACTION = "include";
+ public static final String JSP_INCLUDE_ACTION = "jsp:include";
+
+ public static final String FORWARD_ACTION = "forward";
+ public static final String JSP_FORWARD_ACTION = "jsp:forward";
+
+ public static final String PARAM_ACTION = "param";
+ public static final String JSP_PARAM_ACTION = "jsp:param";
+
+ public static final String PARAMS_ACTION = "params";
+ public static final String JSP_PARAMS_ACTION = "jsp:params";
+
+ public static final String PLUGIN_ACTION = "plugin";
+ public static final String JSP_PLUGIN_ACTION = "jsp:plugin";
+
+ public static final String FALLBACK_ACTION = "fallback";
+ public static final String JSP_FALLBACK_ACTION = "jsp:fallback";
+
+ public static final String TEXT_ACTION = "text";
+ public static final String JSP_TEXT_ACTION = "jsp:text";
+ public static final String JSP_TEXT_ACTION_END = "</jsp:text>";
+
+ public static final String ATTRIBUTE_ACTION = "attribute";
+ public static final String JSP_ATTRIBUTE_ACTION = "jsp:attribute";
+
+ public static final String BODY_ACTION = "body";
+ public static final String JSP_BODY_ACTION = "jsp:body";
+
+ public static final String ELEMENT_ACTION = "element";
+ public static final String JSP_ELEMENT_ACTION = "jsp:element";
+
+ public static final String OUTPUT_ACTION = "output";
+ public static final String JSP_OUTPUT_ACTION = "jsp:output";
+
+ public static final String TAGLIB_DIRECTIVE_ACTION = "taglib";
+ public static final String JSP_TAGLIB_DIRECTIVE_ACTION = "jsp:taglib";
+
+ /*
+ * Tag Files
+ */
+ public static final String INVOKE_ACTION = "invoke";
+ public static final String JSP_INVOKE_ACTION = "jsp:invoke";
+
+ public static final String DOBODY_ACTION = "doBody";
+ public static final String JSP_DOBODY_ACTION = "jsp:doBody";
+
+ /*
+ * Tag File Directives
+ */
+ public static final String TAG_DIRECTIVE_ACTION = "directive.tag";
+ public static final String JSP_TAG_DIRECTIVE_ACTION = "jsp:directive.tag";
+
+ public static final String ATTRIBUTE_DIRECTIVE_ACTION = "directive.attribute";
+ public static final String JSP_ATTRIBUTE_DIRECTIVE_ACTION = "jsp:directive.attribute";
+
+ public static final String VARIABLE_DIRECTIVE_ACTION = "directive.variable";
+ public static final String JSP_VARIABLE_DIRECTIVE_ACTION = "jsp:directive.variable";
+
+ /*
+ * Directive attributes
+ */
+ public static final String URN_JSPTAGDIR = "urn:jsptagdir:";
+ public static final String URN_JSPTLD = "urn:jsptld:";
+}