Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageDataImpl.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageDataImpl.java?rev=800614&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageDataImpl.java (added) +++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageDataImpl.java Mon Aug 3 23:16:50 2009 @@ -0,0 +1,711 @@ +/* + * 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.struts2.jasper.compiler; + +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.CharArrayWriter; +import java.io.UnsupportedEncodingException; +import java.util.ListIterator; +import javax.servlet.jsp.tagext.PageData; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; +import org.apache.struts2.jasper.JasperException; + +/** + * An implementation of <tt>javax.servlet.jsp.tagext.PageData</tt> which + * builds the XML view of a given page. + * + * The XML view is built in two passes: + * + * During the first pass, the FirstPassVisitor collects the attributes of the + * top-level jsp:root and those of the jsp:root elements of any included + * pages, and adds them to the jsp:root element of the XML view. + * In addition, any taglib directives are converted into xmlns: attributes and + * added to the jsp:root element of the XML view. + * This pass ignores any nodes other than JspRoot and TaglibDirective. + * + * During the second pass, the SecondPassVisitor produces the XML view, using + * the combined jsp:root attributes determined in the first pass and any + * remaining pages nodes (this pass ignores any JspRoot and TaglibDirective + * nodes). + * + * @author Jan Luehe + */ +class PageDataImpl extends PageData implements TagConstants { + + private static final String JSP_VERSION = "2.0"; + private static final String CDATA_START_SECTION = "<![CDATA[\n"; + private static final String CDATA_END_SECTION = "]]>\n"; + + // string buffer used to build XML view + private StringBuffer buf; + + /** + * Constructor. + * + * @param page the page nodes from which to generate the XML view + */ + public PageDataImpl(Node.Nodes page, Compiler compiler) + throws JasperException { + + // First pass + FirstPassVisitor firstPass = new FirstPassVisitor(page.getRoot(), + compiler.getPageInfo()); + page.visit(firstPass); + + // Second pass + buf = new StringBuffer(); + SecondPassVisitor secondPass + = new SecondPassVisitor(page.getRoot(), buf, compiler, + firstPass.getJspIdPrefix()); + page.visit(secondPass); + } + + /** + * Returns the input stream of the XML view. + * + * @return the input stream of the XML view + */ + public InputStream getInputStream() { + // Turn StringBuffer into InputStream + try { + return new ByteArrayInputStream(buf.toString().getBytes("UTF-8")); + } catch (UnsupportedEncodingException uee) { + // should never happen + throw new RuntimeException(uee.toString()); + } + } + + /* + * First-pass Visitor for JspRoot nodes (representing jsp:root elements) + * and TablibDirective nodes, ignoring any other nodes. + * + * The purpose of this Visitor is to collect the attributes of the + * top-level jsp:root and those of the jsp:root elements of any included + * pages, and add them to the jsp:root element of the XML view. + * In addition, this Visitor converts any taglib directives into xmlns: + * attributes and adds them to the jsp:root element of the XML view. + */ + static class FirstPassVisitor + extends Node.Visitor implements TagConstants { + + private Node.Root root; + private AttributesImpl rootAttrs; + private PageInfo pageInfo; + + // Prefix for the 'id' attribute + private String jspIdPrefix; + + /* + * Constructor + */ + public FirstPassVisitor(Node.Root root, PageInfo pageInfo) { + this.root = root; + this.pageInfo = pageInfo; + this.rootAttrs = new AttributesImpl(); + this.rootAttrs.addAttribute("", "", "version", "CDATA", + JSP_VERSION); + this.jspIdPrefix = "jsp"; + } + + public void visit(Node.Root n) throws JasperException { + visitBody(n); + if (n == root) { + /* + * Top-level page. + * + * Add + * xmlns:jsp="http://java.sun.com/JSP/Page" + * attribute only if not already present. + */ + if (!JSP_URI.equals(rootAttrs.getValue("xmlns:jsp"))) { + rootAttrs.addAttribute("", "", "xmlns:jsp", "CDATA", + JSP_URI); + } + + if (pageInfo.isJspPrefixHijacked()) { + /* + * 'jsp' prefix has been hijacked, that is, bound to a + * namespace other than the JSP namespace. This means that + * when adding an 'id' attribute to each element, we can't + * use the 'jsp' prefix. Therefore, create a new prefix + * (one that is unique across the translation unit) for use + * by the 'id' attribute, and bind it to the JSP namespace + */ + jspIdPrefix += "jsp"; + while (pageInfo.containsPrefix(jspIdPrefix)) { + jspIdPrefix += "jsp"; + } + rootAttrs.addAttribute("", "", "xmlns:" + jspIdPrefix, + "CDATA", JSP_URI); + } + + root.setAttributes(rootAttrs); + } + } + + public void visit(Node.JspRoot n) throws JasperException { + addAttributes(n.getTaglibAttributes()); + addAttributes(n.getNonTaglibXmlnsAttributes()); + addAttributes(n.getAttributes()); + + visitBody(n); + } + + /* + * Converts taglib directive into "xmlns:..." attribute of jsp:root + * element. + */ + public void visit(Node.TaglibDirective n) throws JasperException { + Attributes attrs = n.getAttributes(); + if (attrs != null) { + String qName = "xmlns:" + attrs.getValue("prefix"); + /* + * According to javadocs of org.xml.sax.helpers.AttributesImpl, + * the addAttribute method does not check to see if the + * specified attribute is already contained in the list: This + * is the application's responsibility! + */ + if (rootAttrs.getIndex(qName) == -1) { + String location = attrs.getValue("uri"); + if (location != null) { + if (location.startsWith("/")) { + location = URN_JSPTLD + location; + } + rootAttrs.addAttribute("", "", qName, "CDATA", + location); + } else { + location = attrs.getValue("tagdir"); + rootAttrs.addAttribute("", "", qName, "CDATA", + URN_JSPTAGDIR + location); + } + } + } + } + + public String getJspIdPrefix() { + return jspIdPrefix; + } + + private void addAttributes(Attributes attrs) { + if (attrs != null) { + int len = attrs.getLength(); + + for (int i=0; i<len; i++) { + String qName = attrs.getQName(i); + if ("version".equals(qName)) { + continue; + } + + // Bugzilla 35252: http://issues.apache.org/bugzilla/show_bug.cgi?id=35252 + if(rootAttrs.getIndex(qName) == -1) { + rootAttrs.addAttribute(attrs.getURI(i), + attrs.getLocalName(i), + qName, + attrs.getType(i), + attrs.getValue(i)); + } + } + } + } + } + + + /* + * Second-pass Visitor responsible for producing XML view and assigning + * each element a unique jsp:id attribute. + */ + static class SecondPassVisitor extends Node.Visitor + implements TagConstants { + + private Node.Root root; + private StringBuffer buf; + private Compiler compiler; + private String jspIdPrefix; + private boolean resetDefaultNS = false; + + // Current value of jsp:id attribute + private int jspId; + + /* + * Constructor + */ + public SecondPassVisitor(Node.Root root, StringBuffer buf, + Compiler compiler, String jspIdPrefix) { + this.root = root; + this.buf = buf; + this.compiler = compiler; + this.jspIdPrefix = jspIdPrefix; + } + + /* + * Visits root node. + */ + public void visit(Node.Root n) throws JasperException { + if (n == this.root) { + // top-level page + appendXmlProlog(); + appendTag(n); + } else { + boolean resetDefaultNSSave = resetDefaultNS; + if (n.isXmlSyntax()) { + resetDefaultNS = true; + } + visitBody(n); + resetDefaultNS = resetDefaultNSSave; + } + } + + /* + * Visits jsp:root element of JSP page in XML syntax. + * + * Any nested jsp:root elements (from pages included via an + * include directive) are ignored. + */ + public void visit(Node.JspRoot n) throws JasperException { + visitBody(n); + } + + public void visit(Node.PageDirective n) throws JasperException { + appendPageDirective(n); + } + + public void visit(Node.IncludeDirective n) throws JasperException { + // expand in place + visitBody(n); + } + + public void visit(Node.Comment n) throws JasperException { + // Comments are ignored in XML view + } + + public void visit(Node.Declaration n) throws JasperException { + appendTag(n); + } + + public void visit(Node.Expression n) throws JasperException { + appendTag(n); + } + + public void visit(Node.Scriptlet n) throws JasperException { + appendTag(n); + } + + public void visit(Node.JspElement n) throws JasperException { + appendTag(n); + } + + public void visit(Node.ELExpression n) throws JasperException { + if (!n.getRoot().isXmlSyntax()) { + buf.append("<").append(JSP_TEXT_ACTION); + buf.append(" "); + buf.append(jspIdPrefix); + buf.append(":id=\""); + buf.append(jspId++).append("\">"); + } + buf.append("${"); + buf.append(JspUtil.escapeXml(n.getText())); + buf.append("}"); + if (!n.getRoot().isXmlSyntax()) { + buf.append(JSP_TEXT_ACTION_END); + } + buf.append("\n"); + } + + public void visit(Node.IncludeAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.ForwardAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.GetProperty n) throws JasperException { + appendTag(n); + } + + public void visit(Node.SetProperty n) throws JasperException { + appendTag(n); + } + + public void visit(Node.ParamAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.ParamsAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.FallBackAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.UseBean n) throws JasperException { + appendTag(n); + } + + public void visit(Node.PlugIn n) throws JasperException { + appendTag(n); + } + + public void visit(Node.NamedAttribute n) throws JasperException { + appendTag(n); + } + + public void visit(Node.JspBody n) throws JasperException { + appendTag(n); + } + + public void visit(Node.CustomTag n) throws JasperException { + boolean resetDefaultNSSave = resetDefaultNS; + appendTag(n, resetDefaultNS); + resetDefaultNS = resetDefaultNSSave; + } + + public void visit(Node.UninterpretedTag n) throws JasperException { + boolean resetDefaultNSSave = resetDefaultNS; + appendTag(n, resetDefaultNS); + resetDefaultNS = resetDefaultNSSave; + } + + public void visit(Node.JspText n) throws JasperException { + appendTag(n); + } + + public void visit(Node.DoBodyAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.InvokeAction n) throws JasperException { + appendTag(n); + } + + public void visit(Node.TagDirective n) throws JasperException { + appendTagDirective(n); + } + + public void visit(Node.AttributeDirective n) throws JasperException { + appendTag(n); + } + + public void visit(Node.VariableDirective n) throws JasperException { + appendTag(n); + } + + public void visit(Node.TemplateText n) throws JasperException { + /* + * If the template text came from a JSP page written in JSP syntax, + * create a jsp:text element for it (JSP 5.3.2). + */ + appendText(n.getText(), !n.getRoot().isXmlSyntax()); + } + + /* + * Appends the given tag, including its body, to the XML view. + */ + private void appendTag(Node n) throws JasperException { + appendTag(n, false); + } + + /* + * Appends the given tag, including its body, to the XML view, + * and optionally reset default namespace to "", if none specified. + */ + private void appendTag(Node n, boolean addDefaultNS) + throws JasperException { + + Node.Nodes body = n.getBody(); + String text = n.getText(); + + buf.append("<").append(n.getQName()); + buf.append("\n"); + + printAttributes(n, addDefaultNS); + buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); + buf.append(jspId++).append("\"\n"); + + if (ROOT_ACTION.equals(n.getLocalName()) || body != null + || text != null) { + buf.append(">\n"); + if (ROOT_ACTION.equals(n.getLocalName())) { + if (compiler.getCompilationContext().isTagFile()) { + appendTagDirective(); + } else { + appendPageDirective(); + } + } + if (body != null) { + body.visit(this); + } else { + appendText(text, false); + } + buf.append("</" + n.getQName() + ">\n"); + } else { + buf.append("/>\n"); + } + } + + /* + * Appends the page directive with the given attributes to the XML + * view. + * + * Since the import attribute of the page directive is the only page + * attribute that is allowed to appear multiple times within the same + * document, and since XML allows only single-value attributes, + * the values of multiple import attributes must be combined into one, + * separated by comma. + * + * If the given page directive contains just 'contentType' and/or + * 'pageEncoding' attributes, we ignore it, as we've already appended + * a page directive containing just these two attributes. + */ + private void appendPageDirective(Node.PageDirective n) { + boolean append = false; + Attributes attrs = n.getAttributes(); + int len = (attrs == null) ? 0 : attrs.getLength(); + for (int i=0; i<len; i++) { + String attrName = attrs.getQName(i); + if (!"pageEncoding".equals(attrName) + && !"contentType".equals(attrName)) { + append = true; + break; + } + } + if (!append) { + return; + } + + buf.append("<").append(n.getQName()); + buf.append("\n"); + + // append jsp:id + buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); + buf.append(jspId++).append("\"\n"); + + // append remaining attributes + for (int i=0; i<len; i++) { + String attrName = attrs.getQName(i); + if ("import".equals(attrName) || "contentType".equals(attrName) + || "pageEncoding".equals(attrName)) { + /* + * Page directive's 'import' attribute is considered + * further down, and its 'pageEncoding' and 'contentType' + * attributes are ignored, since we've already appended + * a new page directive containing just these two + * attributes + */ + continue; + } + String value = attrs.getValue(i); + buf.append(" ").append(attrName).append("=\""); + buf.append(JspUtil.getExprInXml(value)).append("\"\n"); + } + if (n.getImports().size() > 0) { + // Concatenate names of imported classes/packages + boolean first = true; + ListIterator iter = n.getImports().listIterator(); + while (iter.hasNext()) { + if (first) { + first = false; + buf.append(" import=\""); + } else { + buf.append(","); + } + buf.append(JspUtil.getExprInXml((String) iter.next())); + } + buf.append("\"\n"); + } + buf.append("/>\n"); + } + + /* + * Appends a page directive with 'pageEncoding' and 'contentType' + * attributes. + * + * The value of the 'pageEncoding' attribute is hard-coded + * to UTF-8, whereas the value of the 'contentType' attribute, which + * is identical to what the container will pass to + * ServletResponse.setContentType(), is derived from the pageInfo. + */ + private void appendPageDirective() { + buf.append("<").append(JSP_PAGE_DIRECTIVE_ACTION); + buf.append("\n"); + + // append jsp:id + buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); + buf.append(jspId++).append("\"\n"); + buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n"); + buf.append(" ").append("contentType").append("=\""); + buf.append(compiler.getPageInfo().getContentType()).append("\"\n"); + buf.append("/>\n"); + } + + /* + * Appends the tag directive with the given attributes to the XML + * view. + * + * If the given tag directive contains just a 'pageEncoding' + * attributes, we ignore it, as we've already appended + * a tag directive containing just this attributes. + */ + private void appendTagDirective(Node.TagDirective n) + throws JasperException { + + boolean append = false; + Attributes attrs = n.getAttributes(); + int len = (attrs == null) ? 0 : attrs.getLength(); + for (int i=0; i<len; i++) { + String attrName = attrs.getQName(i); + if (!"pageEncoding".equals(attrName)) { + append = true; + break; + } + } + if (!append) { + return; + } + + appendTag(n); + } + + /* + * Appends a tag directive containing a single 'pageEncoding' + * attribute whose value is hard-coded to UTF-8. + */ + private void appendTagDirective() { + buf.append("<").append(JSP_TAG_DIRECTIVE_ACTION); + buf.append("\n"); + + // append jsp:id + buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); + buf.append(jspId++).append("\"\n"); + buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n"); + buf.append("/>\n"); + } + + private void appendText(String text, boolean createJspTextElement) { + if (createJspTextElement) { + buf.append("<").append(JSP_TEXT_ACTION); + buf.append("\n"); + + // append jsp:id + buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); + buf.append(jspId++).append("\"\n"); + buf.append(">\n"); + + appendCDATA(text); + buf.append(JSP_TEXT_ACTION_END); + buf.append("\n"); + } else { + appendCDATA(text); + } + } + + /* + * Appends the given text as a CDATA section to the XML view, unless + * the text has already been marked as CDATA. + */ + private void appendCDATA(String text) { + buf.append(CDATA_START_SECTION); + buf.append(escapeCDATA(text)); + buf.append(CDATA_END_SECTION); + } + + /* + * Escapes any occurrences of "]]>" (by replacing them with "]]>") + * within the given text, so it can be included in a CDATA section. + */ + private String escapeCDATA(String text) { + if( text==null ) return ""; + int len = text.length(); + CharArrayWriter result = new CharArrayWriter(len); + for (int i=0; i<len; i++) { + if (((i+2) < len) + && (text.charAt(i) == ']') + && (text.charAt(i+1) == ']') + && (text.charAt(i+2) == '>')) { + // match found + result.write(']'); + result.write(']'); + result.write('&'); + result.write('g'); + result.write('t'); + result.write(';'); + i += 2; + } else { + result.write(text.charAt(i)); + } + } + return result.toString(); + } + + /* + * Appends the attributes of the given Node to the XML view. + */ + private void printAttributes(Node n, boolean addDefaultNS) { + + /* + * Append "xmlns" attributes that represent tag libraries + */ + Attributes attrs = n.getTaglibAttributes(); + int len = (attrs == null) ? 0 : attrs.getLength(); + for (int i=0; i<len; i++) { + String name = attrs.getQName(i); + String value = attrs.getValue(i); + buf.append(" ").append(name).append("=\"").append(value).append("\"\n"); + } + + /* + * Append "xmlns" attributes that do not represent tag libraries + */ + attrs = n.getNonTaglibXmlnsAttributes(); + len = (attrs == null) ? 0 : attrs.getLength(); + boolean defaultNSSeen = false; + for (int i=0; i<len; i++) { + String name = attrs.getQName(i); + String value = attrs.getValue(i); + buf.append(" ").append(name).append("=\"").append(value).append("\"\n"); + defaultNSSeen |= "xmlns".equals(name); + } + if (addDefaultNS && !defaultNSSeen) { + buf.append(" xmlns=\"\"\n"); + } + resetDefaultNS = false; + + /* + * Append all other attributes + */ + attrs = n.getAttributes(); + len = (attrs == null) ? 0 : attrs.getLength(); + for (int i=0; i<len; i++) { + String name = attrs.getQName(i); + String value = attrs.getValue(i); + buf.append(" ").append(name).append("=\""); + buf.append(JspUtil.getExprInXml(value)).append("\"\n"); + } + } + + /* + * Appends XML prolog with encoding declaration. + */ + private void appendXmlProlog() { + buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + } + } +} +
Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageInfo.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageInfo.java?rev=800614&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageInfo.java (added) +++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/compiler/PageInfo.java Mon Aug 3 23:16:50 2009 @@ -0,0 +1,629 @@ +/* + * 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.struts2.jasper.compiler; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +import org.apache.struts2.jasper.Constants; +import org.apache.struts2.jasper.JasperException; +import javax.servlet.jsp.tagext.TagLibraryInfo; + +/** + * A repository for various info about the translation unit under compilation. + * + * @author Kin-man Chung + */ + +class PageInfo { + + private Vector imports; + private Vector dependants; + + private BeanRepository beanRepository; + private HashMap taglibsMap; + private HashMap jspPrefixMapper; + private HashMap xmlPrefixMapper; + private HashMap nonCustomTagPrefixMap; + private String jspFile; + private String defaultLanguage = "java"; + private String language; + private String defaultExtends = Constants.JSP_SERVLET_BASE; + private String xtends; + private String contentType = null; + private String session; + private boolean isSession = true; + private String bufferValue; + private int buffer = 8*1024; // XXX confirm + private String autoFlush; + private boolean isAutoFlush = true; + private String isThreadSafeValue; + private boolean isThreadSafe = true; + private String isErrorPageValue; + private boolean isErrorPage = false; + private String errorPage = null; + private String info; + + private boolean scriptless = false; + private boolean scriptingInvalid = false; + private String isELIgnoredValue; + private boolean isELIgnored = false; + private String omitXmlDecl = null; + private String doctypeName = null; + private String doctypePublic = null; + private String doctypeSystem = null; + + private boolean isJspPrefixHijacked; + + // Set of all element and attribute prefixes used in this translation unit + private HashSet prefixes; + + private boolean hasJspRoot = false; + private Vector includePrelude; + private Vector includeCoda; + private Vector pluginDcls; // Id's for tagplugin declarations + + + PageInfo(BeanRepository beanRepository, String jspFile) { + + this.jspFile = jspFile; + this.beanRepository = beanRepository; + this.taglibsMap = new HashMap(); + this.jspPrefixMapper = new HashMap(); + this.xmlPrefixMapper = new HashMap(); + this.nonCustomTagPrefixMap = new HashMap(); + this.imports = new Vector(); + this.dependants = new Vector(); + this.includePrelude = new Vector(); + this.includeCoda = new Vector(); + this.pluginDcls = new Vector(); + this.prefixes = new HashSet(); + + // Enter standard imports + for(int i = 0; i < Constants.STANDARD_IMPORTS.length; i++) + imports.add(Constants.STANDARD_IMPORTS[i]); + } + + /** + * Check if the plugin ID has been previously declared. Make a not + * that this Id is now declared. + * @return true if Id has been declared. + */ + public boolean isPluginDeclared(String id) { + if (pluginDcls.contains(id)) + return true; + pluginDcls.add(id); + return false; + } + + public void addImports(List imports) { + this.imports.addAll(imports); + } + + public void addImport(String imp) { + this.imports.add(imp); + } + + public List getImports() { + return imports; + } + + public String getJspFile() { + return jspFile; + } + + public void addDependant(String d) { + if (!dependants.contains(d) && !jspFile.equals(d)) + dependants.add(d); + } + + public List getDependants() { + return dependants; + } + + public BeanRepository getBeanRepository() { + return beanRepository; + } + + public void setScriptless(boolean s) { + scriptless = s; + } + + public boolean isScriptless() { + return scriptless; + } + + public void setScriptingInvalid(boolean s) { + scriptingInvalid = s; + } + + public boolean isScriptingInvalid() { + return scriptingInvalid; + } + + public List getIncludePrelude() { + return includePrelude; + } + + public void setIncludePrelude(Vector prelude) { + includePrelude = prelude; + } + + public List getIncludeCoda() { + return includeCoda; + } + + public void setIncludeCoda(Vector coda) { + includeCoda = coda; + } + + public void setHasJspRoot(boolean s) { + hasJspRoot = s; + } + + public boolean hasJspRoot() { + return hasJspRoot; + } + + public String getOmitXmlDecl() { + return omitXmlDecl; + } + + public void setOmitXmlDecl(String omit) { + omitXmlDecl = omit; + } + + public String getDoctypeName() { + return doctypeName; + } + + public void setDoctypeName(String doctypeName) { + this.doctypeName = doctypeName; + } + + public String getDoctypeSystem() { + return doctypeSystem; + } + + public void setDoctypeSystem(String doctypeSystem) { + this.doctypeSystem = doctypeSystem; + } + + public String getDoctypePublic() { + return doctypePublic; + } + + public void setDoctypePublic(String doctypePublic) { + this.doctypePublic = doctypePublic; + } + + /* Tag library and XML namespace management methods */ + + public void setIsJspPrefixHijacked(boolean isHijacked) { + isJspPrefixHijacked = isHijacked; + } + + public boolean isJspPrefixHijacked() { + return isJspPrefixHijacked; + } + + /* + * Adds the given prefix to the set of prefixes of this translation unit. + * + * @param prefix The prefix to add + */ + public void addPrefix(String prefix) { + prefixes.add(prefix); + } + + /* + * Checks to see if this translation unit contains the given prefix. + * + * @param prefix The prefix to check + * + * @return true if this translation unit contains the given prefix, false + * otherwise + */ + public boolean containsPrefix(String prefix) { + return prefixes.contains(prefix); + } + + /* + * Maps the given URI to the given tag library. + * + * @param uri The URI to map + * @param info The tag library to be associated with the given URI + */ + public void addTaglib(String uri, TagLibraryInfo info) { + taglibsMap.put(uri, info); + } + + /* + * Gets the tag library corresponding to the given URI. + * + * @return Tag library corresponding to the given URI + */ + public TagLibraryInfo getTaglib(String uri) { + return (TagLibraryInfo) taglibsMap.get(uri); + } + + /* + * Gets the collection of tag libraries that are associated with a URI + * + * @return Collection of tag libraries that are associated with a URI + */ + public Collection getTaglibs() { + return taglibsMap.values(); + } + + /* + * Checks to see if the given URI is mapped to a tag library. + * + * @param uri The URI to map + * + * @return true if the given URI is mapped to a tag library, false + * otherwise + */ + public boolean hasTaglib(String uri) { + return taglibsMap.containsKey(uri); + } + + /* + * Maps the given prefix to the given URI. + * + * @param prefix The prefix to map + * @param uri The URI to be associated with the given prefix + */ + public void addPrefixMapping(String prefix, String uri) { + jspPrefixMapper.put(prefix, uri); + } + + /* + * Pushes the given URI onto the stack of URIs to which the given prefix + * is mapped. + * + * @param prefix The prefix whose stack of URIs is to be pushed + * @param uri The URI to be pushed onto the stack + */ + public void pushPrefixMapping(String prefix, String uri) { + LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix); + if (stack == null) { + stack = new LinkedList(); + xmlPrefixMapper.put(prefix, stack); + } + stack.addFirst(uri); + } + + /* + * Removes the URI at the top of the stack of URIs to which the given + * prefix is mapped. + * + * @param prefix The prefix whose stack of URIs is to be popped + */ + public void popPrefixMapping(String prefix) { + LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix); + if (stack == null || stack.size() == 0) { + // XXX throw new Exception("XXX"); + } + stack.removeFirst(); + } + + /* + * Returns the URI to which the given prefix maps. + * + * @param prefix The prefix whose URI is sought + * + * @return The URI to which the given prefix maps + */ + public String getURI(String prefix) { + + String uri = null; + + LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix); + if (stack == null || stack.size() == 0) { + uri = (String) jspPrefixMapper.get(prefix); + } else { + uri = (String) stack.getFirst(); + } + + return uri; + } + + + /* Page/Tag directive attributes */ + + /* + * language + */ + public void setLanguage(String value, Node n, ErrorDispatcher err, + boolean pagedir) + throws JasperException { + + if (!"java".equalsIgnoreCase(value)) { + if (pagedir) + err.jspError(n, "jsp.error.page.language.nonjava"); + else + err.jspError(n, "jsp.error.tag.language.nonjava"); + } + + language = value; + } + + public String getLanguage(boolean useDefault) { + return (language == null && useDefault ? defaultLanguage : language); + } + + public String getLanguage() { + return getLanguage(true); + } + + + /* + * extends + */ + public void setExtends(String value, Node.PageDirective n) { + + xtends = value; + + /* + * If page superclass is top level class (i.e. not in a package) + * explicitly import it. If this is not done, the compiler will assume + * the extended class is in the same pkg as the generated servlet. + */ + if (value.indexOf('.') < 0) + n.addImport(value); + } + + /** + * Gets the value of the 'extends' page directive attribute. + * + * @param useDefault TRUE if the default + * (org.apache.jasper.runtime.HttpJspBase) should be returned if this + * attribute has not been set, FALSE otherwise + * + * @return The value of the 'extends' page directive attribute, or the + * default (org.apache.jasper.runtime.HttpJspBase) if this attribute has + * not been set and useDefault is TRUE + */ + public String getExtends(boolean useDefault) { + return (xtends == null && useDefault ? defaultExtends : xtends); + } + + /** + * Gets the value of the 'extends' page directive attribute. + * + * @return The value of the 'extends' page directive attribute, or the + * default (org.apache.jasper.runtime.HttpJspBase) if this attribute has + * not been set + */ + public String getExtends() { + return getExtends(true); + } + + + /* + * contentType + */ + public void setContentType(String value) { + contentType = value; + } + + public String getContentType() { + return contentType; + } + + + /* + * buffer + */ + public void setBufferValue(String value, Node n, ErrorDispatcher err) + throws JasperException { + + if ("none".equalsIgnoreCase(value)) + buffer = 0; + else { + if (value == null || !value.endsWith("kb")) + err.jspError(n, "jsp.error.page.invalid.buffer"); + try { + Integer k = new Integer(value.substring(0, value.length()-2)); + buffer = k.intValue() * 1024; + } catch (NumberFormatException e) { + err.jspError(n, "jsp.error.page.invalid.buffer"); + } + } + + bufferValue = value; + } + + public String getBufferValue() { + return bufferValue; + } + + public int getBuffer() { + return buffer; + } + + + /* + * session + */ + public void setSession(String value, Node n, ErrorDispatcher err) + throws JasperException { + + if ("true".equalsIgnoreCase(value)) + isSession = true; + else if ("false".equalsIgnoreCase(value)) + isSession = false; + else + err.jspError(n, "jsp.error.page.invalid.session"); + + session = value; + } + + public String getSession() { + return session; + } + + public boolean isSession() { + return isSession; + } + + + /* + * autoFlush + */ + public void setAutoFlush(String value, Node n, ErrorDispatcher err) + throws JasperException { + + if ("true".equalsIgnoreCase(value)) + isAutoFlush = true; + else if ("false".equalsIgnoreCase(value)) + isAutoFlush = false; + else + err.jspError(n, "jsp.error.autoFlush.invalid"); + + autoFlush = value; + } + + public String getAutoFlush() { + return autoFlush; + } + + public boolean isAutoFlush() { + return isAutoFlush; + } + + + /* + * isThreadSafe + */ + public void setIsThreadSafe(String value, Node n, ErrorDispatcher err) + throws JasperException { + + if ("true".equalsIgnoreCase(value)) + isThreadSafe = true; + else if ("false".equalsIgnoreCase(value)) + isThreadSafe = false; + else + err.jspError(n, "jsp.error.page.invalid.isthreadsafe"); + + isThreadSafeValue = value; + } + + public String getIsThreadSafe() { + return isThreadSafeValue; + } + + public boolean isThreadSafe() { + return isThreadSafe; + } + + + /* + * info + */ + public void setInfo(String value) { + info = value; + } + + public String getInfo() { + return info; + } + + + /* + * errorPage + */ + public void setErrorPage(String value) { + errorPage = value; + } + + public String getErrorPage() { + return errorPage; + } + + + /* + * isErrorPage + */ + public void setIsErrorPage(String value, Node n, ErrorDispatcher err) + throws JasperException { + + if ("true".equalsIgnoreCase(value)) + isErrorPage = true; + else if ("false".equalsIgnoreCase(value)) + isErrorPage = false; + else + err.jspError(n, "jsp.error.page.invalid.iserrorpage"); + + isErrorPageValue = value; + } + + public String getIsErrorPage() { + return isErrorPageValue; + } + + public boolean isErrorPage() { + return isErrorPage; + } + + + /* + * isELIgnored + */ + public void setIsELIgnored(String value, Node n, ErrorDispatcher err, + boolean pagedir) + throws JasperException { + + if ("true".equalsIgnoreCase(value)) + isELIgnored = true; + else if ("false".equalsIgnoreCase(value)) + isELIgnored = false; + else { + if (pagedir) + err.jspError(n, "jsp.error.page.invalid.iselignored"); + else + err.jspError(n, "jsp.error.tag.invalid.iselignored"); + } + + isELIgnoredValue = value; + } + + public void setELIgnored(boolean s) { + isELIgnored = s; + } + + public String getIsELIgnored() { + return isELIgnoredValue; + } + + public boolean isELIgnored() { + return isELIgnored; + } + + public void putNonCustomTagPrefix(String prefix, Mark where) { + nonCustomTagPrefixMap.put(prefix, where); + } + + public Mark getNonCustomTagPrefix(String prefix) { + return (Mark) nonCustomTagPrefixMap.get(prefix); + } +}