diff --git a/pom.xml b/pom.xml index b4a8655..e472b6f 100644 --- a/pom.xml +++ b/pom.xml @@ -154,7 +154,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 11 11 @@ -178,7 +178,7 @@ org.apache.felix maven-bundle-plugin - 5.1.2 + 5.1.4 org.glassfish.wasp @@ -213,7 +213,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.2.2 diff --git a/src/main/java/org/glassfish/wasp/Constants.java b/src/main/java/org/glassfish/wasp/Constants.java index 5b78158..97b15c8 100644 --- a/src/main/java/org/glassfish/wasp/Constants.java +++ b/src/main/java/org/glassfish/wasp/Constants.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -109,16 +110,16 @@ public class Constants { */ public static final String TAGLIB_DTD_PUBLIC_ID_11 = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"; public static final String TAGLIB_DTD_RESOURCE_PATH_11 = "/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd"; - + public static final String TAGLIB_DTD_PUBLIC_ID_12 = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"; public static final String TAGLIB_DTD_RESOURCE_PATH_12 = "/javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd"; - + public static final String TAGLIB_SCHEMA_PUBLIC_ID_20 = "web-jsptaglibrary_2_0.xsd"; public static final String TAGLIB_SCHEMA_RESOURCE_PATH_20 = "/javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd"; - + public static final String TAGLIB_SCHEMA_PUBLIC_ID_21 = "web-jsptaglibrary_2_1.xsd"; public static final String TAGLIB_SCHEMA_RESOURCE_PATH_21 = "/javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd"; - + public static final String SCHEMA_LOCATION_JSP_20 = "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"; public static final String SCHEMA_LOCATION_JSP_21 = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"; @@ -128,27 +129,19 @@ public class Constants { */ public static final String WEBAPP_DTD_PUBLIC_ID_22 = "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"; public static final String WEBAPP_DTD_RESOURCE_PATH_22 = "/javax/servlet/resources/web-app_2_2.dtd"; - + public static final String WEBAPP_DTD_PUBLIC_ID_23 = "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"; public static final String WEBAPP_DTD_RESOURCE_PATH_23 = "/javax/servlet/resources/web-app_2_3.dtd"; - + public static final String WEBAPP_SCHEMA_PUBLIC_ID_24 = "web-app_2_4.xsd"; public static final String WEBAPP_SCHEMA_RESOURCE_PATH_24 = "/javax/servlet/resources/web-app_2_4.xsd"; - + public static final String WEBAPP_SCHEMA_PUBLIC_ID_25 = "web-app_2_5.xsd"; public static final String WEBAPP_SCHEMA_RESOURCE_PATH_25 = "/javax/servlet/resources/web-app_2_5.xsd"; - + public static final String SCHEMA_LOCATION_WEBAPP_24 = "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"; public static final String SCHEMA_LOCATION_WEBAPP_25 = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"; - - /** - * Default URLs to download the pluging for Netscape and IE. - */ - public static final String NS_PLUGIN_URL = "http://java.sun.com/products/plugin/"; - - public static final String IE_PLUGIN_URL = "http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0"; - /** * Prefix to use for generated temporary variable names */ diff --git a/src/main/java/org/glassfish/wasp/EmbeddedServletOptions.java b/src/main/java/org/glassfish/wasp/EmbeddedServletOptions.java index 3b92745..83e1e24 100644 --- a/src/main/java/org/glassfish/wasp/EmbeddedServletOptions.java +++ b/src/main/java/org/glassfish/wasp/EmbeddedServletOptions.java @@ -1,7 +1,7 @@ /* + * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation - * Copyright (c) 2021 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -125,12 +125,6 @@ public final class EmbeddedServletOptions implements Options { */ private File scratchDir; - /** - * Need to have this as is for versions 4 and 5 of IE. Can be set from the initParams so if it changes in the future all - * that is needed is to have a jsp initParam of type ieClassId="" - */ - private String ieClassId = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"; - /** * What classpath should I use while compiling generated servlets? */ @@ -315,14 +309,6 @@ public boolean isDefaultBufferNone() { return defaultBufferNone; } - /** - * Class ID for use in the plugin tag when the browser is IE. - */ - @Override - public String getIeClassId() { - return ieClassId; - } - /** * What is my scratch dir? */ @@ -339,7 +325,6 @@ public String getClassPath() { return classpath; } - // START PWC 1.2 6311155 /** * Gets the system class path. * @@ -349,7 +334,6 @@ public String getClassPath() { public String getSystemClassPath() { return sysClassPath; } - // END PWC 1.2 6311155 /** * Is generation of X-Powered-By response header enabled/disabled? @@ -500,21 +484,14 @@ public EmbeddedServletOptions(ServletConfig config, ServletContext context) { parseModificationTestInterval(modificationTestIntervalStr); } - String ieClassId = config.getInitParameter("ieClassId"); - if (ieClassId != null) { - this.ieClassId = ieClassId; - } - String classpath = config.getInitParameter("classpath"); if (classpath != null) { this.classpath = classpath; } - // START PWC 1.2 6311155 String sysClassPath = config.getInitParameter("com.sun.appserv.jsp.classpath"); if (sysClassPath != null) { this.sysClassPath = sysClassPath; - // END PWC 1.2 6311155 } /* diff --git a/src/main/java/org/glassfish/wasp/JspC.java b/src/main/java/org/glassfish/wasp/JspC.java index c174a8e..47f086f 100644 --- a/src/main/java/org/glassfish/wasp/JspC.java +++ b/src/main/java/org/glassfish/wasp/JspC.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * Copyright (c) 2021 Contributors to the Eclipse Foundation @@ -97,8 +98,6 @@ */ public class JspC implements Options { - public static final String DEFAULT_IE_CLASS_ID = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"; - // Logger private static Logger log = Logger.getLogger(JspC.class.getName()); @@ -156,7 +155,6 @@ public class JspC implements Options { private boolean mappedFile; private boolean poolingEnabled = true; private File scratchDir; - private String ieClassId = DEFAULT_IE_CLASS_ID; private String targetPackage; private String targetClassName; private String uriBase; @@ -547,25 +545,6 @@ public void setDefaultBufferNone(boolean defaultBufferNone) { this.defaultBufferNone = defaultBufferNone; } - /** - * Sets the class-id value to be sent to Internet Explorer when using <jsp:plugin> tags. - * - * @param ieClassId Class-id value - */ - public void setIeClassId(String ieClassId) { - this.ieClassId = ieClassId; - } - - /** - * Gets the class-id value that is sent to Internet Explorer when using <jsp:plugin> tags. - * - * @return Class-id value - */ - @Override - public String getIeClassId() { - return ieClassId; - } - @Override public File getScratchDir() { return scratchDir; diff --git a/src/main/java/org/glassfish/wasp/Options.java b/src/main/java/org/glassfish/wasp/Options.java index e7daf00..0751b0c 100644 --- a/src/main/java/org/glassfish/wasp/Options.java +++ b/src/main/java/org/glassfish/wasp/Options.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -88,11 +89,6 @@ public interface Options { */ boolean getTrimSpaces(); - /** - * Class ID for use in the plugin tag when the browser is IE. - */ - String getIeClassId(); - /** * What is my scratch dir? */ diff --git a/src/main/java/org/glassfish/wasp/compiler/Compiler.java b/src/main/java/org/glassfish/wasp/compiler/Compiler.java index 2f9fff7..4aa5651 100644 --- a/src/main/java/org/glassfish/wasp/compiler/Compiler.java +++ b/src/main/java/org/glassfish/wasp/compiler/Compiler.java @@ -1,6 +1,8 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,9 +33,9 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.glassfish.wasp.WaspException; import org.glassfish.wasp.JspCompilationContext; import org.glassfish.wasp.Options; +import org.glassfish.wasp.WaspException; import org.glassfish.wasp.servlet.JspServletWrapper; /** @@ -126,6 +128,11 @@ private void generateJava() throws Exception { pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty.isELIgnored())); pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty.isScriptingInvalid())); pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty.getTrimSpaces())); + + if (jspProperty.getErrorOnELNotFound() != null) { + pageInfo.setErrorOnELNotFound(JspUtil.booleanValue(jspProperty.getErrorOnELNotFound())); + } + pageInfo.setDeferredSyntaxAllowedAsLiteral(JspUtil.booleanValue(jspProperty.getPoundAllowed())); pageInfo.setErrorOnUndeclaredNamespace(JspUtil.booleanValue(jspProperty.errorOnUndeclaredNamespace())); @@ -551,6 +558,7 @@ public boolean isOutDated(boolean checkClass) { URLConnection includeUconn = includeUrl.openConnection(); long includeLastModified = 0; if (includeUconn instanceof JarURLConnection) { + includeUconn.setUseCaches(false); includeLastModified = ((JarURLConnection) includeUconn).getJarEntry().getTime(); } else { includeLastModified = includeUconn.getLastModified(); diff --git a/src/main/java/org/glassfish/wasp/compiler/Generator.java b/src/main/java/org/glassfish/wasp/compiler/Generator.java index adecae4..f5c6363 100644 --- a/src/main/java/org/glassfish/wasp/compiler/Generator.java +++ b/src/main/java/org/glassfish/wasp/compiler/Generator.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -33,8 +34,8 @@ import java.util.Set; import org.glassfish.wasp.Constants; -import org.glassfish.wasp.WaspException; import org.glassfish.wasp.JspCompilationContext; +import org.glassfish.wasp.WaspException; import org.glassfish.wasp.runtime.JspRuntimeLibrary; import org.xml.sax.Attributes; @@ -431,6 +432,17 @@ private void genPreambleMethods() throws WaspException { out.printil("}"); out.println(); + out.printil("public boolean getErrorOnELNotFound() {"); + out.pushIndent(); + if (pageInfo.isErrorOnELNotFound()) { + out.printil("return true;"); + } else { + out.printil("return false;"); + } + out.popIndent(); + out.printil("}"); + out.println(); + // Method to get bytes from String if (genBytes) { out.printil("private static byte[] _jspx_getBytes(String s) {"); @@ -490,10 +502,6 @@ private void generatePreamble(Node.Nodes page) throws WaspException { out.print(" extends "); out.println(pageInfo.getExtends()); out.printin(" implements org.glassfish.wasp.runtime.JspSourceDependent"); - if (!pageInfo.isThreadSafe()) { - out.println(","); - out.printin(" SingleThreadModel"); - } out.println(" {"); out.pushIndent(); @@ -1177,207 +1185,7 @@ private String makeAttr(String attr, String value) { @Override public void visit(Node.PlugIn n) throws WaspException { - - /** - * A visitor to handle in a plugin - */ - class ParamVisitor extends Node.Visitor { - - private boolean ie; - - ParamVisitor(boolean ie) { - this.ie = ie; - } - - @Override - public void visit(Node.ParamAction n) throws WaspException { - - String name = n.getTextAttribute("name"); - if (name.equalsIgnoreCase("object")) { - name = "java_object"; - } else if (name.equalsIgnoreCase("type")) { - name = "java_type"; - } - - n.setBeginJavaLine(out.getJavaLine()); - // XXX - Fixed a bug here - value used to be output - // inline, which is only okay if value is not an EL - // expression. Also, key/value pairs for the - // embed tag were not being generated correctly. - // Double check that this is now the correct behavior. - if (ie) { - // We want something of the form - // out.println( "" ); - out.printil("out.write( \"\" );"); - out.printil("out.write(\"\\n\");"); - } else { - // We want something of the form - // out.print( " blah=\"" + ... + "\"" ); - out.printil("out.write( \" " + escape(name) + "=\\\"\" + " + attributeValue(n.getValue(), false, String.class) + " + \"\\\"\" );"); - } - - n.setEndJavaLine(out.getJavaLine()); - } - } - - String type = n.getTextAttribute("type"); - String code = n.getTextAttribute("code"); - String name = n.getTextAttribute("name"); - Node.JspAttribute height = n.getHeight(); - Node.JspAttribute width = n.getWidth(); - String hspace = n.getTextAttribute("hspace"); - String vspace = n.getTextAttribute("vspace"); - String align = n.getTextAttribute("align"); - String iepluginurl = n.getTextAttribute("iepluginurl"); - String nspluginurl = n.getTextAttribute("nspluginurl"); - String codebase = n.getTextAttribute("codebase"); - String archive = n.getTextAttribute("archive"); - String jreversion = n.getTextAttribute("jreversion"); - - String widthStr = null; - if (width != null) { - if (width.isNamedAttribute()) { - widthStr = generateNamedAttributeValue(width.getNamedAttributeNode()); - } else { - widthStr = attributeValue(width, false, String.class); - } - } - - String heightStr = null; - if (height != null) { - if (height.isNamedAttribute()) { - heightStr = generateNamedAttributeValue(height.getNamedAttributeNode()); - } else { - heightStr = attributeValue(height, false, String.class); - } - } - - if (iepluginurl == null) { - iepluginurl = Constants.IE_PLUGIN_URL; - } - if (nspluginurl == null) { - nspluginurl = Constants.NS_PLUGIN_URL; - } - n.setBeginJavaLine(out.getJavaLine()); - - // If any of the params have their values specified by - // jsp:attribute, prepare those values first. - // Look for a params node and prepare its param subelements: - Node.JspBody jspBody = findJspBody(n); - if (jspBody != null) { - Node.Nodes subelements = jspBody.getBody(); - if (subelements != null) { - for (int i = 0; i < subelements.size(); i++) { - Node m = subelements.getNode(i); - if (m instanceof Node.ParamsAction) { - prepareParams(m); - break; - } - } - } - } - - // XXX - Fixed a bug here - width and height can be set - // dynamically. Double-check if this generation is correct. - - // IE style plugin - // - // First compose the runtime output string - String s0 = "'; - - // Then print the output string to the java file - out.printil("out.write(" + quote(s0) + s1 + s2 + " + " + quote(s3) + ");"); - out.printil("out.write(\"\\n\");"); - - // for java_code - s0 = "'; - out.printil("out.write(" + quote(s0) + ");"); - out.printil("out.write(\"\\n\");"); - - // for java_codebase - if (codebase != null) { - s0 = "'; - out.printil("out.write(" + quote(s0) + ");"); - out.printil("out.write(\"\\n\");"); - } - - // for java_archive - if (archive != null) { - s0 = "'; - out.printil("out.write(" + quote(s0) + ");"); - out.printil("out.write(\"\\n\");"); - } - - // for type - s0 = " for each in the plugin body - */ - if (n.getBody() != null) { - n.getBody().visit(new ParamVisitor(true)); - } - - /* - * Netscape style plugin part - */ - out.printil("out.write(" + quote("") + ");"); - out.printil("out.write(\"\\n\");"); - s0 = " in plugin body - */ - if (n.getBody() != null) { - n.getBody().visit(new ParamVisitor(false)); - } - - out.printil("out.write(" + quote("/>") + ");"); - out.printil("out.write(\"\\n\");"); - - out.printil("out.write(" + quote("") + ");"); - out.printil("out.write(\"\\n\");"); - - /* - * Fallback - */ - if (n.getBody() != null) { - visitBody(n); - out.printil("out.write(\"\\n\");"); - } - - out.printil("out.write(" + quote("") + ");"); - out.printil("out.write(\"\\n\");"); - - out.printil("out.write(" + quote("") + ");"); - out.printil("out.write(\"\\n\");"); - - out.printil("out.write(" + quote("") + ");"); - out.printil("out.write(\"\\n\");"); - n.setEndJavaLine(out.getJavaLine()); } @@ -3326,9 +3134,9 @@ private void generateSetJspContext(TagInfo tagInfo) { out.println(");"); } if (aliasSeen) { - out.printil("this.jspContext = new org.glassfish.wasp.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, aliasMap);"); + out.printil("this.jspContext = new org.glassfish.wasp.runtime.JspContextWrapper(this, ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, aliasMap);"); } else { - out.printil("this.jspContext = new org.glassfish.wasp.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, null);"); + out.printil("this.jspContext = new org.glassfish.wasp.runtime.JspContextWrapper(this, ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, null);"); } out.popIndent(); out.printil("}"); diff --git a/src/main/java/org/glassfish/wasp/compiler/JspConfig.java b/src/main/java/org/glassfish/wasp/compiler/JspConfig.java index 08523fc..6f20b86 100644 --- a/src/main/java/org/glassfish/wasp/compiler/JspConfig.java +++ b/src/main/java/org/glassfish/wasp/compiler/JspConfig.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -44,10 +45,11 @@ public class JspConfig { private ServletContext ctxt; private boolean initialized = false; - private String defaultIsXml = null; // unspecified - private String defaultIsELIgnored = null; // unspecified + private String defaultIsXml; // unspecified + private String defaultIsELIgnored; // unspecified private String defaultIsScriptingInvalid = "false"; private String defaultTrimSpaces = "false"; + private String defaultErrorOnELNotFound = "false"; private String defaultPoundAllowed = "false"; private String defaultErrorOnUndeclaredNamespace = "false"; private JspProperty defaultJspProperty; @@ -72,6 +74,7 @@ private void processWebDotXml(ServletContext ctxt) throws WaspException { String elIgnored = jpg.getElIgnored(); String isXml = jpg.getIsXml(); String trimSpaces = jpg.getTrimDirectiveWhitespaces(); + String errorOnELNotFound = jpg.getErrorOnELNotFound(); String poundAllowed = jpg.getDeferredSyntaxAllowedAsLiteral(); String buffer = jpg.getBuffer(); String defaultContentType = jpg.getDefaultContentType(); @@ -121,8 +124,20 @@ private void processWebDotXml(ServletContext ctxt) throws WaspException { } } - JspProperty property = new JspProperty(isXml, elIgnored, scriptingInvalid, trimSpaces, poundAllowed, pageEncoding, includePrelude, includeCoda, - defaultContentType, buffer, errorOnUndeclaredNamespace); + JspProperty property = new JspProperty( + isXml, + elIgnored, + scriptingInvalid, + trimSpaces, + errorOnELNotFound, + poundAllowed, + pageEncoding, + includePrelude, + includeCoda, + defaultContentType, + buffer, + errorOnUndeclaredNamespace); + JspPropertyGroup propertyGroup = new JspPropertyGroup(path, extension, property); jspProperties.add(propertyGroup); @@ -131,7 +146,6 @@ private void processWebDotXml(ServletContext ctxt) throws WaspException { } private synchronized void init() throws WaspException { - if (!initialized) { processWebDotXml(ctxt); @@ -140,8 +154,17 @@ private synchronized void init() throws WaspException { defaultIsELIgnored = "true"; } - defaultJspProperty = new JspProperty(defaultIsXml, defaultIsELIgnored, defaultIsScriptingInvalid, defaultTrimSpaces, defaultPoundAllowed, null, - null, null, null, null, defaultErrorOnUndeclaredNamespace); + defaultJspProperty = + new JspProperty( + defaultIsXml, + defaultIsELIgnored, + defaultIsScriptingInvalid, + defaultTrimSpaces, + defaultErrorOnELNotFound, + defaultPoundAllowed, + null, null, null, null, null, + defaultErrorOnUndeclaredNamespace); + initialized = true; } } @@ -212,6 +235,7 @@ public JspProperty findJspProperty(String uri) throws WaspException { JspPropertyGroup elIgnoredMatch = null; JspPropertyGroup scriptingInvalidMatch = null; JspPropertyGroup trimSpacesMatch = null; + JspPropertyGroup errorOnELNotFoundMatch = null; JspPropertyGroup poundAllowedMatch = null; JspPropertyGroup pageEncodingMatch = null; JspPropertyGroup defaultContentTypeMatch = null; @@ -269,6 +293,9 @@ public JspProperty findJspProperty(String uri) throws WaspException { if (jp.getTrimSpaces() != null) { trimSpacesMatch = selectProperty(trimSpacesMatch, jpg); } + if (jp.getErrorOnELNotFound() != null) { + errorOnELNotFoundMatch = selectProperty(errorOnELNotFoundMatch, jpg); + } if (jp.getPoundAllowed() != null) { poundAllowedMatch = selectProperty(poundAllowedMatch, jpg); } @@ -287,6 +314,7 @@ public JspProperty findJspProperty(String uri) throws WaspException { String isELIgnored = defaultIsELIgnored; String isScriptingInvalid = defaultIsScriptingInvalid; String trimSpaces = defaultTrimSpaces; + String errorOnELNotFound = defaultErrorOnELNotFound; String poundAllowed = defaultPoundAllowed; String pageEncoding = null; String defaultContentType = null; @@ -305,6 +333,9 @@ public JspProperty findJspProperty(String uri) throws WaspException { if (trimSpacesMatch != null) { trimSpaces = trimSpacesMatch.getJspProperty().getTrimSpaces(); } + if (errorOnELNotFoundMatch != null) { + errorOnELNotFound = errorOnELNotFoundMatch.getJspProperty().getErrorOnELNotFound(); + } if (poundAllowedMatch != null) { poundAllowed = poundAllowedMatch.getJspProperty().getPoundAllowed(); } @@ -321,8 +352,19 @@ public JspProperty findJspProperty(String uri) throws WaspException { errorOnUndeclaredNamespace = errorOnUndeclaredNamespaceMatch.getJspProperty().errorOnUndeclaredNamespace(); } - return new JspProperty(isXml, isELIgnored, isScriptingInvalid, trimSpaces, poundAllowed, pageEncoding, includePreludes, includeCodas, - defaultContentType, buffer, errorOnUndeclaredNamespace); + return new JspProperty( + isXml, + isELIgnored, + isScriptingInvalid, + trimSpaces, + errorOnELNotFound, + poundAllowed, + pageEncoding, + includePreludes, + includeCodas, + defaultContentType, + buffer, + errorOnUndeclaredNamespace); } /** diff --git a/src/main/java/org/glassfish/wasp/compiler/JspProperty.java b/src/main/java/org/glassfish/wasp/compiler/JspProperty.java index 29ae107..67eafbd 100644 --- a/src/main/java/org/glassfish/wasp/compiler/JspProperty.java +++ b/src/main/java/org/glassfish/wasp/compiler/JspProperty.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -26,6 +27,7 @@ public class JspProperty { private String scriptingInvalid; private String pageEncoding; private String trimSpaces; + private String errorOnELNotFound; private String poundAllowed; private List includePrelude; private List includeCoda; @@ -33,13 +35,14 @@ public class JspProperty { private String defaultContentType; private String errorOnUndeclaredNamespace; - public JspProperty(String isXml, String elIgnored, String scriptingInvalid, String trimSpaces, String poundAllowed, String pageEncoding, + public JspProperty(String isXml, String elIgnored, String scriptingInvalid, String trimSpaces, String errorOnELNotFound, String poundAllowed, String pageEncoding, List includePrelude, List includeCoda, String defaultContentType, String buffer, String errorOnUndeclaredNamespace) { this.isXml = isXml; this.elIgnored = elIgnored; this.scriptingInvalid = scriptingInvalid; this.trimSpaces = trimSpaces; + this.errorOnELNotFound = errorOnELNotFound; this.poundAllowed = poundAllowed; this.pageEncoding = pageEncoding; this.includePrelude = includePrelude; @@ -69,6 +72,10 @@ public String getTrimSpaces() { return trimSpaces; } + public String getErrorOnELNotFound() { + return errorOnELNotFound; + } + public String getPoundAllowed() { return poundAllowed; } diff --git a/src/main/java/org/glassfish/wasp/compiler/JspPropertyGroup.java b/src/main/java/org/glassfish/wasp/compiler/JspPropertyGroup.java index d33822f..ba2cc46 100644 --- a/src/main/java/org/glassfish/wasp/compiler/JspPropertyGroup.java +++ b/src/main/java/org/glassfish/wasp/compiler/JspPropertyGroup.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -40,4 +41,5 @@ public String getExtension() { public JspProperty getJspProperty() { return jspProperty; } + } diff --git a/src/main/java/org/glassfish/wasp/compiler/Jsr199JavaCompiler.java b/src/main/java/org/glassfish/wasp/compiler/Jsr199JavaCompiler.java index 098e941..0593e0e 100644 --- a/src/main/java/org/glassfish/wasp/compiler/Jsr199JavaCompiler.java +++ b/src/main/java/org/glassfish/wasp/compiler/Jsr199JavaCompiler.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -34,10 +35,10 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; @@ -273,7 +274,7 @@ protected JavaFileObject getOutputFile(final String className, final URI uri) { Map> packageMap = rtctxt.getPackageMap(); Map packageFiles = packageMap.get(packageName); if (packageFiles == null) { - packageFiles = new HashMap<>(); + packageFiles = new ConcurrentHashMap<>(); packageMap.put(packageName, packageFiles); } packageFiles.put(className, classFile); diff --git a/src/main/java/org/glassfish/wasp/compiler/PageInfo.java b/src/main/java/org/glassfish/wasp/compiler/PageInfo.java index dfc3054..1beae99 100644 --- a/src/main/java/org/glassfish/wasp/compiler/PageInfo.java +++ b/src/main/java/org/glassfish/wasp/compiler/PageInfo.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -55,7 +56,7 @@ public class PageInfo { private String language; private String defaultExtends = Constants.JSP_SERVLET_BASE; private String xtends; - private String contentType = null; + private String contentType; private String session; private boolean isSession = true; private String bufferValue; @@ -65,31 +66,34 @@ public class PageInfo { private String isThreadSafeValue; private boolean isThreadSafe = true; private String isErrorPageValue; - private boolean isErrorPage = false; - private String errorPage = null; + private boolean isErrorPage; + private String errorPage; private String info; private int maxTagNesting = 0; - private boolean scriptless = false; - private boolean scriptingInvalid = false; + private boolean scriptless; + private boolean scriptingInvalid; 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 isELIgnored; + private String omitXmlDecl; + private String doctypeName; + private String doctypePublic; + private String doctypeSystem; private String deferredSyntaxAllowedAsLiteralValue; - private boolean deferredSyntaxAllowedAsLiteral = false; + private boolean deferredSyntaxAllowedAsLiteral; private String trimDirectiveWhitespacesValue; - private boolean trimDirectiveWhitespaces = false; - private boolean errorOnUndeclaredNamespace = false; + private boolean trimDirectiveWhitespaces; + private String errorOnELNotFoundValue; + private boolean errorOnELNotFound; + + private boolean errorOnUndeclaredNamespace; private boolean isJspPrefixHijacked; // Set of all element and attribute prefixes used in this translation unit private HashSet prefixes; - private boolean hasJspRoot = false; + private boolean hasJspRoot; private List includePrelude; private List includeCoda; private List pluginDcls; // Id's for tagplugin declarations @@ -98,7 +102,6 @@ public class PageInfo { private String rootPath; PageInfo(BeanRepository beanRepository, String jspFile) { - this.jspFile = jspFile; this.beanRepository = beanRepository; this.taglibsMap = new HashMap<>(); @@ -147,9 +150,9 @@ public String getJspFile() { return jspFile; } - public void addDependant(String d) { - if (!dependants.contains(d) && !jspFile.equals(d)) { - dependants.add(d); + public void addDependant(String dependant) { + if (!dependants.contains(dependant) && !jspFile.equals(dependant)) { + dependants.add(dependant); } } @@ -169,16 +172,16 @@ public void setMaxTagNesting(int maxTagNesting) { this.maxTagNesting = maxTagNesting; } - public void setScriptless(boolean s) { - scriptless = s; + public void setScriptless(boolean scriptless) { + this.scriptless = scriptless; } public boolean isScriptless() { return scriptless; } - public void setScriptingInvalid(boolean s) { - scriptingInvalid = s; + public void setScriptingInvalid(boolean scriptingInvalid) { + this.scriptingInvalid = scriptingInvalid; } public boolean isScriptingInvalid() { @@ -359,7 +362,6 @@ public void popPrefixMapping(String prefix) { * @return The URI to which the given prefix maps */ public String getURI(String prefix) { - String uri = null; LinkedList stack = xmlPrefixMapper.get(prefix); @@ -377,13 +379,12 @@ public String getURI(String prefix) { /* * language */ - public void setLanguage(String value, Node n, ErrorDispatcher err, boolean pagedir) throws WaspException { - + public void setLanguage(String value, Node node, ErrorDispatcher err, boolean pagedir) throws WaspException { if (!"java".equalsIgnoreCase(value)) { if (pagedir) { - err.jspError(n, "jsp.error.page.language.nonjava"); + err.jspError(node, "jsp.error.page.language.nonjava"); } else { - err.jspError(n, "jsp.error.tag.language.nonjava"); + err.jspError(node, "jsp.error.tag.language.nonjava"); } } @@ -401,8 +402,7 @@ public String getLanguage() { /* * extends */ - public void setExtends(String value, Node.PageDirective n) { - + public void setExtends(String value, Node.PageDirective pageDirective) { xtends = value; /* @@ -410,7 +410,7 @@ public void setExtends(String value, Node.PageDirective n) { * will assume the extended class is in the same pkg as the generated servlet. */ if (value.indexOf('.') < 0) { - n.addImport(value); + pageDirective.addImport(value); } } @@ -451,26 +451,24 @@ public String getContentType() { /* * buffer */ - public void setBufferValue(String value, Node n, ErrorDispatcher err) throws WaspException { - + public void setBufferValue(String value, Node node, ErrorDispatcher err) throws WaspException { if ("none".equalsIgnoreCase(value)) { buffer = 0; } else { if (value == null || !value.endsWith("kb")) { - if (n == null) { + if (node == null) { err.jspError("jsp.error.jspproperty.invalid.buffer"); } else { - err.jspError(n, "jsp.error.page.invalid.buffer"); + err.jspError(node, "jsp.error.page.invalid.buffer"); } } try { - Integer k = new Integer(value.substring(0, value.length() - 2)); - buffer = k.intValue() * 1024; + buffer = Integer.parseInt(value.substring(0, value.length() - 2)) * 1024; } catch (NumberFormatException e) { - if (n == null) { + if (node == null) { err.jspError("jsp.error.jspproperty.invalid.buffer"); } else { - err.jspError(n, "jsp.error.page.invalid.buffer"); + err.jspError(node, "jsp.error.page.invalid.buffer"); } } } @@ -493,14 +491,13 @@ public void setBuffer(int size) { /* * session */ - public void setSession(String value, Node n, ErrorDispatcher err) throws WaspException { - + public void setSession(String value, Node node, ErrorDispatcher err) throws WaspException { if ("true".equalsIgnoreCase(value)) { isSession = true; } else if ("false".equalsIgnoreCase(value)) { isSession = false; } else { - err.jspError(n, "jsp.error.page.invalid.session"); + err.jspError(node, "jsp.error.page.invalid.session"); } session = value; @@ -517,14 +514,13 @@ public boolean isSession() { /* * autoFlush */ - public void setAutoFlush(String value, Node n, ErrorDispatcher err) throws WaspException { - + public void setAutoFlush(String value, Node node, ErrorDispatcher err) throws WaspException { if ("true".equalsIgnoreCase(value)) { isAutoFlush = true; } else if ("false".equalsIgnoreCase(value)) { isAutoFlush = false; } else { - err.jspError(n, "jsp.error.autoFlush.invalid"); + err.jspError(node, "jsp.error.autoFlush.invalid"); } autoFlush = value; @@ -541,14 +537,13 @@ public boolean isAutoFlush() { /* * isThreadSafe */ - public void setIsThreadSafe(String value, Node n, ErrorDispatcher err) throws WaspException { - + public void setIsThreadSafe(String value, Node node, ErrorDispatcher err) throws WaspException { if ("true".equalsIgnoreCase(value)) { isThreadSafe = true; } else if ("false".equalsIgnoreCase(value)) { isThreadSafe = false; } else { - err.jspError(n, "jsp.error.page.invalid.isthreadsafe"); + err.jspError(node, "jsp.error.page.invalid.isthreadsafe"); } isThreadSafeValue = value; @@ -587,14 +582,13 @@ public String getErrorPage() { /* * isErrorPage */ - public void setIsErrorPage(String value, Node n, ErrorDispatcher err) throws WaspException { - + public void setIsErrorPage(String value, Node node, ErrorDispatcher err) throws WaspException { if ("true".equalsIgnoreCase(value)) { isErrorPage = true; } else if ("false".equalsIgnoreCase(value)) { isErrorPage = false; } else { - err.jspError(n, "jsp.error.page.invalid.iserrorpage"); + err.jspError(node, "jsp.error.page.invalid.iserrorpage"); } isErrorPageValue = value; @@ -611,25 +605,24 @@ public boolean isErrorPage() { /* * isELIgnored */ - public void setIsELIgnored(String value, Node n, ErrorDispatcher err, boolean pagedir) throws WaspException { - + public void setIsELIgnored(String value, Node node, ErrorDispatcher err, boolean pagedir) throws WaspException { if ("true".equalsIgnoreCase(value)) { isELIgnored = true; } else if ("false".equalsIgnoreCase(value)) { isELIgnored = false; } else { if (pagedir) { - err.jspError(n, "jsp.error.page.invalid.iselignored"); + err.jspError(node, "jsp.error.page.invalid.iselignored"); } else { - err.jspError(n, "jsp.error.tag.invalid.iselignored"); + err.jspError(node, "jsp.error.tag.invalid.iselignored"); } } isELIgnoredValue = value; } - public void setELIgnored(boolean s) { - isELIgnored = s; + public void setELIgnored(boolean isELIgnored) { + this.isELIgnored = isELIgnored; } public String getIsELIgnored() { @@ -643,25 +636,24 @@ public boolean isELIgnored() { /* * deferredSyntaxAllowedAsLiteral */ - public void setDeferredSyntaxAllowedAsLiteral(String value, Node n, ErrorDispatcher err, boolean pagedir) throws WaspException { - + public void setDeferredSyntaxAllowedAsLiteral(String value, Node node, ErrorDispatcher err, boolean pagedir) throws WaspException { if ("true".equalsIgnoreCase(value)) { deferredSyntaxAllowedAsLiteral = true; } else if ("false".equalsIgnoreCase(value)) { deferredSyntaxAllowedAsLiteral = false; } else { if (pagedir) { - err.jspError(n, "jsp.error.page.invalid.deferred"); + err.jspError(node, "jsp.error.page.invalid.deferred"); } else { - err.jspError(n, "jsp.error.tag.invalid.deferred"); + err.jspError(node, "jsp.error.tag.invalid.deferred"); } } deferredSyntaxAllowedAsLiteralValue = value; } - public void setDeferredSyntaxAllowedAsLiteral(boolean s) { - deferredSyntaxAllowedAsLiteral = s; + public void setDeferredSyntaxAllowedAsLiteral(boolean deferredSyntaxAllowedAsLiteral) { + this.deferredSyntaxAllowedAsLiteral = deferredSyntaxAllowedAsLiteral; } public String getDeferredSyntaxAllowedAsLiteral() { @@ -675,17 +667,16 @@ public boolean isDeferredSyntaxAllowedAsLiteral() { /* * trimDirectiveWhitespaces */ - public void setTrimDirectiveWhitespaces(String value, Node n, ErrorDispatcher err, boolean pagedir) throws WaspException { - + public void setTrimDirectiveWhitespaces(String value, Node node, ErrorDispatcher err, boolean pagedir) throws WaspException { if ("true".equalsIgnoreCase(value)) { trimDirectiveWhitespaces = true; } else if ("false".equalsIgnoreCase(value)) { trimDirectiveWhitespaces = false; } else { if (pagedir) { - err.jspError(n, "jsp.error.page.invalid.trim"); + err.jspError(node, "jsp.error.page.invalid.trim"); } else { - err.jspError(n, "jsp.error.tag.invalid.trim"); + err.jspError(node, "jsp.error.tag.invalid.trim"); } } @@ -704,6 +695,38 @@ public boolean isTrimDirectiveWhitespaces() { return trimDirectiveWhitespaces; } + + /* + * errorOnELNotFound + */ + public void setErrorOnELNotFound(String value, Node node, ErrorDispatcher err, boolean pagedir) throws WaspException { + if ("true".equalsIgnoreCase(value)) { + errorOnELNotFound = true; + } else if ("false".equalsIgnoreCase(value)) { + errorOnELNotFound = false; + } else { + if (pagedir) { + err.jspError(node, "jsp.error.page.invalid.errorOnELNotFound"); + } else { + err.jspError(node, "jsp.error.tag.invalid.errorOnELNotFound"); + } + } + + errorOnELNotFoundValue = value; + } + + public void setErrorOnELNotFound(boolean errorOnELNotFound) { + this.errorOnELNotFound = errorOnELNotFound; + } + + public String getErrorOnELNotFound() { + return errorOnELNotFoundValue; + } + + public boolean isErrorOnELNotFound() { + return errorOnELNotFound; + } + public void setErrorOnUndeclaredNamespace(boolean s) { errorOnUndeclaredNamespace = s; } diff --git a/src/main/java/org/glassfish/wasp/compiler/TagFileProcessor.java b/src/main/java/org/glassfish/wasp/compiler/TagFileProcessor.java index 83e498e..9f8a472 100644 --- a/src/main/java/org/glassfish/wasp/compiler/TagFileProcessor.java +++ b/src/main/java/org/glassfish/wasp/compiler/TagFileProcessor.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,14 @@ package org.glassfish.wasp.compiler; +import static jakarta.servlet.jsp.tagext.TagInfo.BODY_CONTENT_EMPTY; +import static jakarta.servlet.jsp.tagext.TagInfo.BODY_CONTENT_SCRIPTLESS; +import static jakarta.servlet.jsp.tagext.TagInfo.BODY_CONTENT_TAG_DEPENDENT; +import static org.glassfish.wasp.Constants.JSP_VERSION_2_1; +import static org.glassfish.wasp.compiler.JspUtil.booleanValue; +import static org.glassfish.wasp.compiler.JspUtil.checkAttributes; +import static org.glassfish.wasp.compiler.JspUtil.getTagHandlerClassName; + import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; @@ -25,8 +34,8 @@ import java.util.List; import org.glassfish.wasp.Constants; -import org.glassfish.wasp.WaspException; import org.glassfish.wasp.JspCompilationContext; +import org.glassfish.wasp.WaspException; import org.glassfish.wasp.runtime.JspSourceDependent; import org.glassfish.wasp.servlet.JspServletWrapper; @@ -46,56 +55,78 @@ class TagFileProcessor { - private ArrayList tempVector; + private ArrayList tempCompilers; /** * A visitor the tag file */ private static class TagFileDirectiveVisitor extends Node.Visitor { - private static final JspUtil.ValidAttribute[] tagDirectiveAttrs = { new JspUtil.ValidAttribute("display-name"), - new JspUtil.ValidAttribute("body-content"), new JspUtil.ValidAttribute("dynamic-attributes"), new JspUtil.ValidAttribute("small-icon"), - new JspUtil.ValidAttribute("large-icon"), new JspUtil.ValidAttribute("description"), new JspUtil.ValidAttribute("example"), - new JspUtil.ValidAttribute("pageEncoding"), new JspUtil.ValidAttribute("language"), new JspUtil.ValidAttribute("import"), - new JspUtil.ValidAttribute("isELIgnored"), new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), - new JspUtil.ValidAttribute("trimDirectiveWhitespaces") }; + private static final JspUtil.ValidAttribute[] tagDirectiveAttrs = { + new JspUtil.ValidAttribute("display-name"), + new JspUtil.ValidAttribute("body-content"), + new JspUtil.ValidAttribute("dynamic-attributes"), + new JspUtil.ValidAttribute("small-icon"), + new JspUtil.ValidAttribute("large-icon"), + new JspUtil.ValidAttribute("description"), + new JspUtil.ValidAttribute("example"), + new JspUtil.ValidAttribute("pageEncoding"), + new JspUtil.ValidAttribute("language"), + new JspUtil.ValidAttribute("import"), + new JspUtil.ValidAttribute("isELIgnored"), + new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), + new JspUtil.ValidAttribute("trimDirectiveWhitespaces"), + new JspUtil.ValidAttribute("errorOnELNotFound") }; private static final JspUtil.ValidAttribute[] attributeDirectiveAttrs = { new JspUtil.ValidAttribute("name", true), - new JspUtil.ValidAttribute("required"), new JspUtil.ValidAttribute("fragment"), new JspUtil.ValidAttribute("rtexprvalue"), - new JspUtil.ValidAttribute("type"), new JspUtil.ValidAttribute("description"), new JspUtil.ValidAttribute("deferredValue"), - new JspUtil.ValidAttribute("deferredValueType"), new JspUtil.ValidAttribute("deferredMethod"), + new JspUtil.ValidAttribute("required"), + new JspUtil.ValidAttribute("fragment"), + new JspUtil.ValidAttribute("rtexprvalue"), + new JspUtil.ValidAttribute("type"), + new JspUtil.ValidAttribute("description"), + new JspUtil.ValidAttribute("deferredValue"), + new JspUtil.ValidAttribute("deferredValueType"), + new JspUtil.ValidAttribute("deferredMethod"), new JspUtil.ValidAttribute("deferredMethodSignature") }; - private static final JspUtil.ValidAttribute[] variableDirectiveAttrs = { new JspUtil.ValidAttribute("name-given"), - new JspUtil.ValidAttribute("name-from-attribute"), new JspUtil.ValidAttribute("alias"), new JspUtil.ValidAttribute("variable-class"), - new JspUtil.ValidAttribute("scope"), new JspUtil.ValidAttribute("declare"), new JspUtil.ValidAttribute("description") }; + private static final JspUtil.ValidAttribute[] variableDirectiveAttrs = { + new JspUtil.ValidAttribute("name-given"), + new JspUtil.ValidAttribute("name-from-attribute"), + new JspUtil.ValidAttribute("alias"), + new JspUtil.ValidAttribute("variable-class"), + new JspUtil.ValidAttribute("scope"), + new JspUtil.ValidAttribute("declare"), + new JspUtil.ValidAttribute("description") }; private ErrorDispatcher err; private TagLibraryInfo tagLibInfo; - private String name = null; - private String path = null; - private TagExtraInfo tei = null; - private String bodycontent = null; - private String description = null; - private String displayName = null; - private String smallIcon = null; - private String largeIcon = null; + private String name; + private String path; + private TagExtraInfo tei; + private String bodycontent; + private String description; + private String displayName; + private String smallIcon; + private String largeIcon; private String dynamicAttrsMapName; - private String example = null; + private String example; - private List attributeVector; - private List variableVector; + private List tagAttributes; + private List tagVariables; private HashMap nameTable = new HashMap<>(); private HashMap nameFromTable = new HashMap<>(); - // The tag file's JSP version - private Double jspVersionDouble; + // The tag file's Jakarta Pages version + private Double jakartaPagesVersionDouble; private enum Name { - ATTR_NAME("name", "attribute"), VAR_NAME_GIVEN("name-given", "variable"), VAR_NAME_FROM("name-from-attribute", "variable"), - VAR_ALIAS("alias", "variable"), TAG_DYNAMIC("dynamic-attributes", "tag"); + ATTR_NAME("name", "attribute"), + VAR_NAME_GIVEN("name-given", "variable"), + VAR_NAME_FROM("name-from-attribute", "variable"), + VAR_ALIAS("alias", "variable"), + TAG_DYNAMIC("dynamic-attributes", "tag"); private String attribute; private String directive; @@ -119,88 +150,89 @@ public TagFileDirectiveVisitor(Compiler compiler, TagLibraryInfo tagLibInfo, Str this.tagLibInfo = tagLibInfo; this.name = name; this.path = path; - attributeVector = new ArrayList<>(); - variableVector = new ArrayList<>(); + tagAttributes = new ArrayList<>(); + tagVariables = new ArrayList<>(); - jspVersionDouble = Double.valueOf(tagLibInfo.getRequiredVersion()); + jakartaPagesVersionDouble = Double.valueOf(tagLibInfo.getRequiredVersion()); } @Override - public void visit(Node.JspRoot n) throws WaspException { + public void visit(Node.JspRoot root) throws WaspException { /* * If a tag file in XML syntax contains a jsp:root element, the value of its "version" attribute must match the tag - * file's JSP version. + * file's Jakarta Pages version. */ - String jspRootVersion = n.getTextAttribute("version"); + String jspRootVersion = root.getTextAttribute("version"); if (jspRootVersion == null) { - err.jspError(n, "jsp.error.mandatory.attribute", n.getQName(), "version"); + err.jspError(root, "jsp.error.mandatory.attribute", root.getQName(), "version"); } - if (!jspRootVersion.equals(jspVersionDouble.toString())) { - err.jspError(n, "jsp.error.tagfile.jspVersionMismatch", jspRootVersion, jspVersionDouble.toString()); + if (!jspRootVersion.equals(jakartaPagesVersionDouble.toString())) { + err.jspError(root, "jsp.error.tagfile.jspVersionMismatch", jspRootVersion, jakartaPagesVersionDouble.toString()); } - visitBody(n); + + visitBody(root); } @Override - public void visit(Node.TagDirective n) throws WaspException { + public void visit(Node.TagDirective tagDirective) throws WaspException { + checkAttributes("Tag directive", tagDirective, tagDirectiveAttrs, err); - JspUtil.checkAttributes("Tag directive", n, tagDirectiveAttrs, err); - - bodycontent = checkConflict(n, bodycontent, "body-content"); - if (bodycontent != null && !bodycontent.equals(TagInfo.BODY_CONTENT_EMPTY) && !bodycontent.equals(TagInfo.BODY_CONTENT_TAG_DEPENDENT) - && !bodycontent.equals(TagInfo.BODY_CONTENT_SCRIPTLESS)) { - err.jspError(n, "jsp.error.tagdirective.badbodycontent", bodycontent); + bodycontent = checkConflict(tagDirective, bodycontent, "body-content"); + if (bodycontent != null && !bodycontent.equals(BODY_CONTENT_EMPTY) && !bodycontent.equals(BODY_CONTENT_TAG_DEPENDENT) + && !bodycontent.equals(BODY_CONTENT_SCRIPTLESS)) { + err.jspError(tagDirective, "jsp.error.tagdirective.badbodycontent", bodycontent); } - dynamicAttrsMapName = checkConflict(n, dynamicAttrsMapName, "dynamic-attributes"); + + dynamicAttrsMapName = checkConflict(tagDirective, dynamicAttrsMapName, "dynamic-attributes"); if (dynamicAttrsMapName != null) { - checkUniqueName(dynamicAttrsMapName, Name.TAG_DYNAMIC, n); + checkUniqueName(dynamicAttrsMapName, Name.TAG_DYNAMIC, tagDirective); } - smallIcon = checkConflict(n, smallIcon, "small-icon"); - largeIcon = checkConflict(n, largeIcon, "large-icon"); - description = checkConflict(n, description, "description"); - displayName = checkConflict(n, displayName, "display-name"); - example = checkConflict(n, example, "example"); - if (n.getAttributeValue("deferredSyntaxAllowedAsLiteral") != null && Double.compare(jspVersionDouble, Constants.JSP_VERSION_2_1) < 0) { + smallIcon = checkConflict(tagDirective, smallIcon, "small-icon"); + largeIcon = checkConflict(tagDirective, largeIcon, "large-icon"); + description = checkConflict(tagDirective, description, "description"); + displayName = checkConflict(tagDirective, displayName, "display-name"); + example = checkConflict(tagDirective, example, "example"); + + if (tagDirective.getAttributeValue("deferredSyntaxAllowedAsLiteral") != null && Double.compare(jakartaPagesVersionDouble, JSP_VERSION_2_1) < 0) { err.jspError("jsp.error.invalidTagDirectiveAttrUnless21", "deferredSyntaxAllowedAsLiteral"); } // Additional tag directives are validated in Validator } - private String checkConflict(Node n, String oldAttrValue, String attr) throws WaspException { - + private String checkConflict(Node node, String oldAttrValue, String attr) throws WaspException { String result = oldAttrValue; - String attrValue = n.getAttributeValue(attr); + String attrValue = node.getAttributeValue(attr); if (attrValue != null) { if (oldAttrValue != null && !oldAttrValue.equals(attrValue)) { - err.jspError(n, "jsp.error.tag.conflict.attr", attr, oldAttrValue, attrValue); + err.jspError(node, "jsp.error.tag.conflict.attr", attr, oldAttrValue, attrValue); } result = attrValue; } + return result; } @Override - public void visit(Node.AttributeDirective n) throws WaspException { - - JspUtil.checkAttributes("Attribute directive", n, attributeDirectiveAttrs, err); + public void visit(Node.AttributeDirective attributeDirective) throws WaspException { + checkAttributes("Attribute directive", attributeDirective, attributeDirectiveAttrs, err); - String attrName = n.getAttributeValue("name"); - boolean required = JspUtil.booleanValue(n.getAttributeValue("required")); + String attrName = attributeDirective.getAttributeValue("name"); + boolean required = booleanValue(attributeDirective.getAttributeValue("required")); boolean rtexprvalue = true; - String rtexprvalueString = n.getAttributeValue("rtexprvalue"); + String rtexprvalueString = attributeDirective.getAttributeValue("rtexprvalue"); if (rtexprvalueString != null) { - rtexprvalue = JspUtil.booleanValue(rtexprvalueString); + rtexprvalue = booleanValue(rtexprvalueString); } - boolean fragment = JspUtil.booleanValue(n.getAttributeValue("fragment")); - String type = n.getAttributeValue("type"); + boolean fragment = booleanValue(attributeDirective.getAttributeValue("fragment")); + String type = attributeDirective.getAttributeValue("type"); - String deferredValue = n.getAttributeValue("deferredValue"); - String deferredMethod = n.getAttributeValue("deferredMethod"); - String expectedType = n.getAttributeValue("deferredValueType"); - String methodSignature = n.getAttributeValue("deferredMethodSignature"); - if (Double.compare(jspVersionDouble, Constants.JSP_VERSION_2_1) < 0) { + String deferredValue = attributeDirective.getAttributeValue("deferredValue"); + String deferredMethod = attributeDirective.getAttributeValue("deferredMethod"); + String expectedType = attributeDirective.getAttributeValue("deferredValueType"); + String methodSignature = attributeDirective.getAttributeValue("deferredMethodSignature"); + if (Double.compare(jakartaPagesVersionDouble, Constants.JSP_VERSION_2_1) < 0) { if (deferredValue != null) { err.jspError("jsp.error.invalidAttrDirectiveAttrUnless21", "deferredValue"); } @@ -215,8 +247,8 @@ public void visit(Node.AttributeDirective n) throws WaspException { } } - boolean isDeferredValue = JspUtil.booleanValue(deferredValue); - boolean isDeferredMethod = JspUtil.booleanValue(deferredMethod); + boolean isDeferredValue = booleanValue(deferredValue); + boolean isDeferredMethod = booleanValue(deferredMethod); if (expectedType == null) { if (isDeferredValue) { expectedType = "java.lang.Object"; @@ -243,13 +275,14 @@ public void visit(Node.AttributeDirective n) throws WaspException { // type is fixed to "JspFragment" and a translation error // must occur if specified. if (type != null) { - err.jspError(n, "jsp.error.fragmentwithtype"); + err.jspError(attributeDirective, "jsp.error.fragmentwithtype"); } + // rtexprvalue is fixed to "true" and a translation error // must occur if specified. rtexprvalue = true; if (rtexprvalueString != null) { - err.jspError(n, "jsp.error.frgmentwithrtexprvalue"); + err.jspError(attributeDirective, "jsp.error.frgmentwithrtexprvalue"); } } else if (type == null) { if (isDeferredValue) { @@ -266,19 +299,23 @@ public void visit(Node.AttributeDirective n) throws WaspException { if (isDeferredValue || isDeferredMethod) { rtexprvalue = false; } - TagAttributeInfo tagAttributeInfo = new TagAttributeInfo(attrName, required, type, rtexprvalue, fragment, description, isDeferredValue, - isDeferredMethod, expectedType, methodSignature); - attributeVector.add(tagAttributeInfo); - checkUniqueName(attrName, Name.ATTR_NAME, n, tagAttributeInfo); + + TagAttributeInfo tagAttributeInfo = + new TagAttributeInfo( + attrName, required, type, + rtexprvalue, fragment, description, isDeferredValue, + isDeferredMethod, expectedType, methodSignature); + tagAttributes.add(tagAttributeInfo); + + checkUniqueName(attrName, Name.ATTR_NAME, attributeDirective, tagAttributeInfo); } @Override - public void visit(Node.VariableDirective n) throws WaspException { + public void visit(Node.VariableDirective variableDirective) throws WaspException { + checkAttributes("Variable directive", variableDirective, variableDirectiveAttrs, err); - JspUtil.checkAttributes("Variable directive", n, variableDirectiveAttrs, err); - - String nameGiven = n.getAttributeValue("name-given"); - String nameFromAttribute = n.getAttributeValue("name-from-attribute"); + String nameGiven = variableDirective.getAttributeValue("name-given"); + String nameFromAttribute = variableDirective.getAttributeValue("name-from-attribute"); if (nameGiven == null && nameFromAttribute == null) { err.jspError("jsp.error.variable.either.name"); } @@ -287,24 +324,24 @@ public void visit(Node.VariableDirective n) throws WaspException { err.jspError("jsp.error.variable.both.name"); } - String alias = n.getAttributeValue("alias"); + String alias = variableDirective.getAttributeValue("alias"); if (nameFromAttribute != null && alias == null || nameFromAttribute == null && alias != null) { err.jspError("jsp.error.variable.alias"); } - String className = n.getAttributeValue("variable-class"); + String className = variableDirective.getAttributeValue("variable-class"); if (className == null) { className = "java.lang.String"; } - String declareStr = n.getAttributeValue("declare"); + String declareStr = variableDirective.getAttributeValue("declare"); boolean declare = true; if (declareStr != null) { - declare = JspUtil.booleanValue(declareStr); + declare = booleanValue(declareStr); } int scope = VariableInfo.NESTED; - String scopeStr = n.getAttributeValue("scope"); + String scopeStr = variableDirective.getAttributeValue("scope"); if (scopeStr != null) { if ("NESTED".equals(scopeStr)) { // Already the default @@ -321,33 +358,33 @@ public void visit(Node.VariableDirective n) throws WaspException { * name of the attribute whose value (at invocation-time) denotes the name of the variable that is being aliased */ nameGiven = alias; - checkUniqueName(nameFromAttribute, Name.VAR_NAME_FROM, n); - checkUniqueName(alias, Name.VAR_ALIAS, n); + checkUniqueName(nameFromAttribute, Name.VAR_NAME_FROM, variableDirective); + checkUniqueName(alias, Name.VAR_ALIAS, variableDirective); } else { // name-given specified - checkUniqueName(nameGiven, Name.VAR_NAME_GIVEN, n); + checkUniqueName(nameGiven, Name.VAR_NAME_GIVEN, variableDirective); } - variableVector.add(new TagVariableInfo(nameGiven, nameFromAttribute, className, declare, scope)); + tagVariables.add(new TagVariableInfo(nameGiven, nameFromAttribute, className, declare, scope)); } public TagInfo getTagInfo() throws WaspException { - if (name == null) { // XXX Get it from tag file name } if (bodycontent == null) { - bodycontent = TagInfo.BODY_CONTENT_SCRIPTLESS; + bodycontent = BODY_CONTENT_SCRIPTLESS; } - String tagClassName = JspUtil.getTagHandlerClassName(path, err); - - TagVariableInfo[] tagVariableInfos = variableVector.toArray(new TagVariableInfo[0]); + String tagClassName = getTagHandlerClassName(path, err); - TagAttributeInfo[] tagAttributeInfo = attributeVector.toArray(new TagAttributeInfo[0]); + TagVariableInfo[] tagVariableInfos = tagVariables.toArray(new TagVariableInfo[0]); + TagAttributeInfo[] tagAttributeInfo = tagAttributes.toArray(new TagAttributeInfo[0]); - return new WaspTagInfo(name, tagClassName, bodycontent, description, tagLibInfo, tei, tagAttributeInfo, displayName, smallIcon, largeIcon, + return new WaspTagInfo( + name, tagClassName, + bodycontent, description, tagLibInfo, tei, tagAttributeInfo, displayName, smallIcon, largeIcon, tagVariableInfos, dynamicAttrsMapName); } @@ -386,22 +423,21 @@ TagAttributeInfo getTagAttributeInfo() { * Also, 'name-from' attribute of a variable directive cannot have the same value as that from another variable * directive. */ - private void checkUniqueName(String name, Name type, Node n) throws WaspException { - checkUniqueName(name, type, n, null); + private void checkUniqueName(String name, Name type, Node node) throws WaspException { + checkUniqueName(name, type, node, null); } - private void checkUniqueName(String name, Name type, Node n, TagAttributeInfo attr) throws WaspException { - + private void checkUniqueName(String name, Name type, Node node, TagAttributeInfo attr) throws WaspException { HashMap table = type == Name.VAR_NAME_FROM ? nameFromTable : nameTable; NameEntry nameEntry = table.get(name); if (nameEntry != null) { if (type != Name.TAG_DYNAMIC || nameEntry.getType() != Name.TAG_DYNAMIC) { int line = nameEntry.getNode().getStart().getLineNumber(); - err.jspError(n, "jsp.error.tagfile.nameNotUnique", type.getAttribute(), type.getDirective(), nameEntry.getType().getAttribute(), + err.jspError(node, "jsp.error.tagfile.nameNotUnique", type.getAttribute(), type.getDirective(), nameEntry.getType().getAttribute(), nameEntry.getType().getDirective(), Integer.toString(line)); } } else { - table.put(name, new NameEntry(type, n, attr)); + table.put(name, new NameEntry(type, node, attr)); } } @@ -410,9 +446,9 @@ private void checkUniqueName(String name, Name type, Node n, TagAttributeInfo at */ void postCheck() throws WaspException { // Check that var.name-from-attributes has valid values. - Iterator iter = nameFromTable.keySet().iterator(); + Iterator iter = nameFromTable.keySet().iterator(); while (iter.hasNext()) { - String nameFrom = (String) iter.next(); + String nameFrom = iter.next(); NameEntry nameEntry = nameTable.get(nameFrom); NameEntry nameFromEntry = nameFromTable.get(nameFrom); Node nameFromNode = nameFromEntry.getNode(); @@ -433,26 +469,25 @@ void postCheck() throws WaspException { * Parses the tag file, and collects information on the directives included in it. The method is used to obtain the info * on the tag file, when the handler that it represents is referenced. The tag file is not compiled here. * - * @param pc the current ParserController used in this compilation + * @param parserController the current ParserController used in this compilation * @param name the tag name as specified in the TLD * @param tagfile the path for the tagfile * @param tagLibInfo the TagLibraryInfo object associated with this TagInfo * @return a TagInfo object assembled from the directives in the tag file. */ - public static TagInfo parseTagFileDirectives(ParserController pc, String name, String path, TagLibraryInfo tagLibInfo) throws WaspException { - - ErrorDispatcher err = pc.getCompiler().getErrorDispatcher(); + public static TagInfo parseTagFileDirectives(ParserController parserController, String name, String path, TagLibraryInfo tagLibInfo) throws WaspException { + ErrorDispatcher err = parserController.getCompiler().getErrorDispatcher(); Node.Nodes page = null; try { - page = pc.parseTagFileDirectives(path); + page = parserController.parseTagFileDirectives(path); } catch (FileNotFoundException e) { err.jspError("jsp.error.file.not.found", path); } catch (IOException e) { err.jspError("jsp.error.file.not.found", path); } - TagFileDirectiveVisitor tagFileVisitor = new TagFileDirectiveVisitor(pc.getCompiler(), tagLibInfo, name, path); + TagFileDirectiveVisitor tagFileVisitor = new TagFileDirectiveVisitor(parserController.getCompiler(), tagLibInfo, name, path); page.visit(tagFileVisitor); tagFileVisitor.postCheck(); @@ -462,21 +497,24 @@ public static TagInfo parseTagFileDirectives(ParserController pc, String name, S /** * Compiles and loads a tagfile. */ - private Class loadTagFile(Compiler compiler, String tagFilePath, TagInfo tagInfo, PageInfo parentPageInfo) throws WaspException { - - JspCompilationContext ctxt = compiler.getCompilationContext(); - JspRuntimeContext rctxt = ctxt.getRuntimeContext(); + private Class loadTagFile(Compiler compiler, String tagFilePath, TagInfo tagInfo, PageInfo parentPageInfo) throws WaspException { + JspCompilationContext compilationContext = compiler.getCompilationContext(); + JspRuntimeContext runtimeContext = compilationContext.getRuntimeContext(); - synchronized (rctxt) { - JspServletWrapper wrapper = rctxt.getWrapper(tagFilePath); + synchronized (runtimeContext) { + JspServletWrapper wrapper = runtimeContext.getWrapper(tagFilePath); if (wrapper == null) { - wrapper = new JspServletWrapper(ctxt.getServletContext(), ctxt.getOptions(), tagFilePath, tagInfo, ctxt.getRuntimeContext(), - ctxt.getTagFileJarUrls().get(tagFilePath)); - rctxt.addWrapper(tagFilePath, wrapper); + wrapper = new JspServletWrapper( + compilationContext.getServletContext(), + compilationContext.getOptions(), tagFilePath, tagInfo, + compilationContext.getRuntimeContext(), + compilationContext.getTagFileJarUrls().get(tagFilePath)); + + runtimeContext.addWrapper(tagFilePath, wrapper); // Use same classloader and classpath for compiling tag files - wrapper.getJspEngineContext().setClassLoader(ctxt.getClassLoader()); - wrapper.getJspEngineContext().setClassPath(ctxt.getClassPath()); + wrapper.getJspEngineContext().setClassLoader(compilationContext.getClassLoader()); + wrapper.getJspEngineContext().setClassPath(compilationContext.getClassPath()); } else { // Make sure that JspCompilationContext gets the latest TagInfo // for the tag file. TagInfo instance was created the last @@ -485,19 +523,23 @@ private Class loadTagFile(Compiler compiler, String tagFilePath, TagInfo tagInfo wrapper.getJspEngineContext().setTagInfo(tagInfo); } - Class tagClazz; + Class tagClazz; int tripCount = wrapper.incTripCount(); try { if (tripCount > 0) { + // When tripCount is greater than zero, a circular // dependency exists. The circularily dependant tag // file is compiled in prototype mode, to avoid infinite // recursion. - JspServletWrapper tempWrapper = new JspServletWrapper(ctxt.getServletContext(), ctxt.getOptions(), tagFilePath, tagInfo, - ctxt.getRuntimeContext(), ctxt.getTagFileJarUrls().get(tagFilePath)); + JspServletWrapper tempWrapper = new JspServletWrapper( + compilationContext.getServletContext(), + compilationContext.getOptions(), tagFilePath, tagInfo, + compilationContext.getRuntimeContext(), + compilationContext.getTagFileJarUrls().get(tagFilePath)); tagClazz = tempWrapper.loadTagFilePrototype(); - tempVector.add(tempWrapper.getJspEngineContext().getCompiler()); + tempCompilers.add(tempWrapper.getJspEngineContext().getCompiler()); } else { tagClazz = wrapper.loadTagFile(); } @@ -509,7 +551,7 @@ private Class loadTagFile(Compiler compiler, String tagFilePath, TagInfo tagInfo // dependant list. The only reliable dependency information // can only be obtained from the tag instance. try { - Object tagIns = tagClazz.newInstance(); + Object tagIns = tagClazz.getDeclaredConstructor().newInstance(); if (tagIns instanceof JspSourceDependent) { for (String dependant : ((JspSourceDependent) tagIns).getDependants()) { parentPageInfo.addDependant(dependant); @@ -533,30 +575,30 @@ private class TagFileLoaderVisitor extends Node.Visitor { private PageInfo pageInfo; TagFileLoaderVisitor(Compiler compiler) { - this.compiler = compiler; this.pageInfo = compiler.getPageInfo(); } @Override - public void visit(Node.CustomTag n) throws WaspException { - TagFileInfo tagFileInfo = n.getTagFileInfo(); + public void visit(Node.CustomTag customTag) throws WaspException { + TagFileInfo tagFileInfo = customTag.getTagFileInfo(); if (tagFileInfo != null) { String tagFilePath = tagFileInfo.getPath(); if (tagFilePath.startsWith("/META-INF/")) { // For tags in JARs, add the TLD and the tag as a dependency String[] location = compiler.getCompilationContext().getTldLocation(tagFileInfo.getTagInfo().getTagLibrary().getURI()); + // Add TLD pageInfo.addDependant("jar:" + location[0] + "!/" + location[1]); + // Add Tag pageInfo.addDependant("jar:" + location[0] + "!" + tagFilePath); } else { pageInfo.addDependant(tagFilePath); } - Class c = loadTagFile(compiler, tagFilePath, n.getTagInfo(), pageInfo); - n.setTagHandlerClass(c); + customTag.setTagHandlerClass(loadTagFile(compiler, tagFilePath, customTag.getTagInfo(), pageInfo)); } - visitBody(n); + visitBody(customTag); } } @@ -565,8 +607,7 @@ public void visit(Node.CustomTag n) throws WaspException { * in the tag files are assumed to have been proccessed and encapsulated as TagFileInfo in the CustomTag nodes. */ public void loadTagFiles(Compiler compiler, Node.Nodes page) throws WaspException { - - tempVector = new ArrayList<>(); + tempCompilers = new ArrayList<>(); page.visit(new TagFileLoaderVisitor(compiler)); } @@ -576,14 +617,14 @@ public void loadTagFiles(Compiler compiler, Node.Nodes page) throws WaspExceptio * @param classFileName If non-null, remove only the class file with with this name. */ public void removeProtoTypeFiles(String classFileName) { - Iterator iter = tempVector.iterator(); + Iterator iter = tempCompilers.iterator(); while (iter.hasNext()) { - Compiler c = iter.next(); + Compiler compiler = iter.next(); if (classFileName == null) { - c.removeGeneratedClassFiles(); - } else if (classFileName.equals(c.getCompilationContext().getClassFileName())) { - c.removeGeneratedClassFiles(); - tempVector.remove(c); + compiler.removeGeneratedClassFiles(); + } else if (classFileName.equals(compiler.getCompilationContext().getClassFileName())) { + compiler.removeGeneratedClassFiles(); + tempCompilers.remove(compiler); return; } } diff --git a/src/main/java/org/glassfish/wasp/compiler/Validator.java b/src/main/java/org/glassfish/wasp/compiler/Validator.java index 5e7f302..470d96b 100644 --- a/src/main/java/org/glassfish/wasp/compiler/Validator.java +++ b/src/main/java/org/glassfish/wasp/compiler/Validator.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,9 @@ package org.glassfish.wasp.compiler; +import static org.glassfish.wasp.compiler.JspUtil.checkAttributes; +import static org.glassfish.wasp.compiler.JspUtil.checkScope; + import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -24,8 +28,8 @@ import java.util.Hashtable; import java.util.Iterator; -import org.glassfish.wasp.WaspException; import org.glassfish.wasp.JspCompilationContext; +import org.glassfish.wasp.WaspException; import org.glassfish.wasp.runtime.JspRuntimeLibrary; import org.xml.sax.Attributes; @@ -58,12 +62,23 @@ static class DirectiveVisitor extends Node.Visitor { private PageInfo pageInfo; private ErrorDispatcher err; - private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = { new JspUtil.ValidAttribute("language"), new JspUtil.ValidAttribute("extends"), - new JspUtil.ValidAttribute("import"), new JspUtil.ValidAttribute("session"), new JspUtil.ValidAttribute("buffer"), - new JspUtil.ValidAttribute("autoFlush"), new JspUtil.ValidAttribute("isThreadSafe"), new JspUtil.ValidAttribute("info"), - new JspUtil.ValidAttribute("errorPage"), new JspUtil.ValidAttribute("isErrorPage"), new JspUtil.ValidAttribute("contentType"), - new JspUtil.ValidAttribute("pageEncoding"), new JspUtil.ValidAttribute("isELIgnored"), - new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), new JspUtil.ValidAttribute("trimDirectiveWhitespaces") }; + private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = { + new JspUtil.ValidAttribute("language"), + new JspUtil.ValidAttribute("extends"), + new JspUtil.ValidAttribute("import"), + new JspUtil.ValidAttribute("session"), + new JspUtil.ValidAttribute("buffer"), + new JspUtil.ValidAttribute("autoFlush"), + new JspUtil.ValidAttribute("isThreadSafe"), + new JspUtil.ValidAttribute("info"), + new JspUtil.ValidAttribute("errorPage"), + new JspUtil.ValidAttribute("isErrorPage"), + new JspUtil.ValidAttribute("contentType"), + new JspUtil.ValidAttribute("pageEncoding"), + new JspUtil.ValidAttribute("isELIgnored"), + new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), + new JspUtil.ValidAttribute("trimDirectiveWhitespaces"), + new JspUtil.ValidAttribute("errorOnELNotFound") }; private boolean pageEncodingSeen = false; @@ -87,8 +102,7 @@ public void visit(Node.IncludeDirective n) throws WaspException { @Override public void visit(Node.PageDirective n) throws WaspException { - - JspUtil.checkAttributes("Page directive", n, pageDirectiveAttrs, err); + checkAttributes("Page directive", n, pageDirectiveAttrs, err); // JSP.2.10.1 Attributes attrs = n.getAttributes(); @@ -184,6 +198,13 @@ public void visit(Node.PageDirective n) throws WaspException { } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(value)) { err.jspError(n, "jsp.error.page.conflict.trim", pageInfo.getTrimDirectiveWhitespaces(), value); } + } else if ("errorOnELNotFound".equals(attr)) { + if (pageInfo.getErrorOnELNotFound() == null) { + pageInfo.setErrorOnELNotFound(value, n, err, true); + } else if (!pageInfo.getErrorOnELNotFound().equals(value)) { + err.jspError(n, "jsp.error.page.conflict.errorOnELNotFound", + pageInfo.getErrorOnELNotFound(), value); + } } } @@ -266,6 +287,12 @@ public void visit(Node.TagDirective n) throws WaspException { } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(value)) { err.jspError(n, "jsp.error.tag.conflict.trim", pageInfo.getTrimDirectiveWhitespaces(), value); } + } else if ("errorOnELNotFound".equals(attr)) { + if (pageInfo.getErrorOnELNotFound() == null) { + pageInfo.setErrorOnELNotFound(value, n, err, false); + } else if (!pageInfo.getErrorOnELNotFound().equals(value)) { + err.jspError(n, "jsp.error.tag.conflict.errorOnELNotFound", pageInfo.getErrorOnELNotFound(), value); + } } } @@ -347,47 +374,81 @@ static class ValidateVisitor extends Node.Visitor { private ClassLoader loader; private JspCompilationContext ctxt; - private static final JspUtil.ValidAttribute[] jspRootAttrs = { new JspUtil.ValidAttribute("xsi:schemaLocation"), + private static final JspUtil.ValidAttribute[] jspRootAttrs = { + new JspUtil.ValidAttribute("xsi:schemaLocation"), new JspUtil.ValidAttribute("version", true) }; - private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { new JspUtil.ValidAttribute("file", true) }; + private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { + new JspUtil.ValidAttribute("file", true) }; - private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = { new JspUtil.ValidAttribute("uri"), new JspUtil.ValidAttribute("tagdir"), + private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = { + new JspUtil.ValidAttribute("uri"), + new JspUtil.ValidAttribute("tagdir"), new JspUtil.ValidAttribute("prefix", true) }; - private static final JspUtil.ValidAttribute[] includeActionAttrs = { new JspUtil.ValidAttribute("page", true), new JspUtil.ValidAttribute("flush") }; + private static final JspUtil.ValidAttribute[] includeActionAttrs = { + new JspUtil.ValidAttribute("page", true), + new JspUtil.ValidAttribute("flush") }; - private static final JspUtil.ValidAttribute[] paramActionAttrs = { new JspUtil.ValidAttribute("name", true), + private static final JspUtil.ValidAttribute[] paramActionAttrs = { + new JspUtil.ValidAttribute("name", true), new JspUtil.ValidAttribute("value", true) }; - private static final JspUtil.ValidAttribute[] forwardActionAttrs = { new JspUtil.ValidAttribute("page", true) }; + private static final JspUtil.ValidAttribute[] forwardActionAttrs = { + new JspUtil.ValidAttribute("page", true) }; - private static final JspUtil.ValidAttribute[] getPropertyAttrs = { new JspUtil.ValidAttribute("name", true), + private static final JspUtil.ValidAttribute[] getPropertyAttrs = { + new JspUtil.ValidAttribute("name", true), new JspUtil.ValidAttribute("property", true) }; - private static final JspUtil.ValidAttribute[] setPropertyAttrs = { new JspUtil.ValidAttribute("name", true), - new JspUtil.ValidAttribute("property", true), new JspUtil.ValidAttribute("value", false), new JspUtil.ValidAttribute("param") }; - - private static final JspUtil.ValidAttribute[] useBeanAttrs = { new JspUtil.ValidAttribute("id", true), new JspUtil.ValidAttribute("scope"), - new JspUtil.ValidAttribute("class"), new JspUtil.ValidAttribute("type"), new JspUtil.ValidAttribute("beanName", false) }; - - private static final JspUtil.ValidAttribute[] plugInAttrs = { new JspUtil.ValidAttribute("type", true), new JspUtil.ValidAttribute("code", true), - new JspUtil.ValidAttribute("codebase"), new JspUtil.ValidAttribute("align"), new JspUtil.ValidAttribute("archive"), - new JspUtil.ValidAttribute("height", false), new JspUtil.ValidAttribute("hspace"), new JspUtil.ValidAttribute("jreversion"), - new JspUtil.ValidAttribute("name"), new JspUtil.ValidAttribute("vspace"), new JspUtil.ValidAttribute("width", false), - new JspUtil.ValidAttribute("nspluginurl"), new JspUtil.ValidAttribute("iepluginurl") }; - - private static final JspUtil.ValidAttribute[] attributeAttrs = { new JspUtil.ValidAttribute("name", true), new JspUtil.ValidAttribute("trim"), + private static final JspUtil.ValidAttribute[] setPropertyAttrs = { + new JspUtil.ValidAttribute("name", true), + new JspUtil.ValidAttribute("property", true), + new JspUtil.ValidAttribute("value", false), + new JspUtil.ValidAttribute("param") }; + + private static final JspUtil.ValidAttribute[] useBeanAttrs = { + new JspUtil.ValidAttribute("id", true), + new JspUtil.ValidAttribute("scope"), + new JspUtil.ValidAttribute("class"), + new JspUtil.ValidAttribute("type"), + new JspUtil.ValidAttribute("beanName", false) }; + + private static final JspUtil.ValidAttribute[] plugInAttrs = { + new JspUtil.ValidAttribute("type", true), + new JspUtil.ValidAttribute("code", true), + new JspUtil.ValidAttribute("codebase"), + new JspUtil.ValidAttribute("align"), + new JspUtil.ValidAttribute("archive"), + new JspUtil.ValidAttribute("height", false), + new JspUtil.ValidAttribute("hspace"), + new JspUtil.ValidAttribute("jreversion"), + new JspUtil.ValidAttribute("name"), + new JspUtil.ValidAttribute("vspace"), + new JspUtil.ValidAttribute("width", false), + new JspUtil.ValidAttribute("nspluginurl"), + new JspUtil.ValidAttribute("iepluginurl") }; + + private static final JspUtil.ValidAttribute[] attributeAttrs = { + new JspUtil.ValidAttribute("name", true), + new JspUtil.ValidAttribute("trim"), new JspUtil.ValidAttribute("omit") }; - private static final JspUtil.ValidAttribute[] invokeAttrs = { new JspUtil.ValidAttribute("fragment", true), new JspUtil.ValidAttribute("var"), - new JspUtil.ValidAttribute("varReader"), new JspUtil.ValidAttribute("scope") }; + private static final JspUtil.ValidAttribute[] invokeAttrs = { + new JspUtil.ValidAttribute("fragment", true), + new JspUtil.ValidAttribute("var"), + new JspUtil.ValidAttribute("varReader"), + new JspUtil.ValidAttribute("scope") }; - private static final JspUtil.ValidAttribute[] doBodyAttrs = { new JspUtil.ValidAttribute("var"), new JspUtil.ValidAttribute("varReader"), + private static final JspUtil.ValidAttribute[] doBodyAttrs = { + new JspUtil.ValidAttribute("var"), + new JspUtil.ValidAttribute("varReader"), new JspUtil.ValidAttribute("scope") }; - private static final JspUtil.ValidAttribute[] jspOutputAttrs = { new JspUtil.ValidAttribute("omit-xml-declaration"), - new JspUtil.ValidAttribute("doctype-root-element"), new JspUtil.ValidAttribute("doctype-public"), + private static final JspUtil.ValidAttribute[] jspOutputAttrs = { + new JspUtil.ValidAttribute("omit-xml-declaration"), + new JspUtil.ValidAttribute("doctype-root-element"), + new JspUtil.ValidAttribute("doctype-public"), new JspUtil.ValidAttribute("doctype-system") }; /* @@ -402,7 +463,7 @@ static class ValidateVisitor extends Node.Visitor { @Override public void visit(Node.JspRoot n) throws WaspException { - JspUtil.checkAttributes("Jsp:root", n, jspRootAttrs, err); + checkAttributes("Jsp:root", n, jspRootAttrs, err); String version = n.getTextAttribute("version"); if (!version.equals("1.2") && !version.equals("2.0") && !version.equals("2.1")) { err.jspError(n, "jsp.error.jsproot.version.invalid", version); @@ -412,13 +473,14 @@ public void visit(Node.JspRoot n) throws WaspException { @Override public void visit(Node.IncludeDirective n) throws WaspException { - JspUtil.checkAttributes("Include directive", n, includeDirectiveAttrs, err); + checkAttributes("Include directive", n, includeDirectiveAttrs, err); visitBody(n); } @Override public void visit(Node.TaglibDirective n) throws WaspException { - JspUtil.checkAttributes("Taglib directive", n, taglibDirectiveAttrs, err); + checkAttributes("Taglib directive", n, taglibDirectiveAttrs, err); + // Either 'uri' or 'tagdir' attribute must be specified String uri = n.getAttributeValue("uri"); String tagdir = n.getAttributeValue("tagdir"); @@ -432,7 +494,8 @@ public void visit(Node.TaglibDirective n) throws WaspException { @Override public void visit(Node.ParamAction n) throws WaspException { - JspUtil.checkAttributes("Param action", n, paramActionAttrs, err); + checkAttributes("Param action", n, paramActionAttrs, err); + // make sure the value of the 'name' attribute is not a // request-time expression throwErrorIfExpression(n, "name", "jsp:param"); @@ -452,26 +515,26 @@ public void visit(Node.ParamsAction n) throws WaspException { @Override public void visit(Node.IncludeAction n) throws WaspException { - JspUtil.checkAttributes("Include action", n, includeActionAttrs, err); + checkAttributes("Include action", n, includeActionAttrs, err); n.setPage(getJspAttribute("page", null, null, n.getAttributeValue("page"), n, false, null)); visitBody(n); } @Override public void visit(Node.ForwardAction n) throws WaspException { - JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err); + checkAttributes("Forward", n, forwardActionAttrs, err); n.setPage(getJspAttribute("page", null, null, n.getAttributeValue("page"), n, false, null)); visitBody(n); } @Override public void visit(Node.GetProperty n) throws WaspException { - JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs, err); + checkAttributes("GetProperty", n, getPropertyAttrs, err); } @Override public void visit(Node.SetProperty n) throws WaspException { - JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs, err); + checkAttributes("SetProperty", n, setPropertyAttrs, err); String property = n.getTextAttribute("property"); String param = n.getTextAttribute("param"); String value = n.getAttributeValue("value"); @@ -493,121 +556,122 @@ public void visit(Node.SetProperty n) throws WaspException { } @Override - public void visit(Node.UseBean n) throws WaspException { - JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err); - - String name = n.getTextAttribute("id"); - String scope = n.getTextAttribute("scope"); - JspUtil.checkScope(scope, n, err); - String className = n.getTextAttribute("class"); - String type = n.getTextAttribute("type"); + public void visit(Node.UseBean useBean) throws WaspException { + checkAttributes("UseBean", useBean, useBeanAttrs, err); + + String name = useBean.getTextAttribute("id"); + String scope = useBean.getTextAttribute("scope"); + checkScope(scope, useBean, err); + String className = useBean.getTextAttribute("class"); + String type = useBean.getTextAttribute("type"); BeanRepository beanInfo = pageInfo.getBeanRepository(); if (className == null && type == null) { - err.jspError(n, "jsp.error.usebean.missingType"); + err.jspError(useBean, "jsp.error.usebean.missingType"); } if (beanInfo.checkVariable(name)) { - err.jspError(n, "jsp.error.usebean.duplicate", name); + err.jspError(useBean, "jsp.error.usebean.duplicate", name); } if ("session".equals(scope) && !pageInfo.isSession()) { - err.jspError(n, "jsp.error.usebean.noSession"); + err.jspError(useBean, "jsp.error.usebean.noSession"); } - Node.JspAttribute jattr = getJspAttribute("beanName", null, null, n.getAttributeValue("beanName"), n, false, null); - n.setBeanName(jattr); + Node.JspAttribute jattr = getJspAttribute("beanName", null, null, useBean.getAttributeValue("beanName"), useBean, false, null); + useBean.setBeanName(jattr); if (className != null && jattr != null) { - err.jspError(n, "jsp.error.usebean.notBoth"); + err.jspError(useBean, "jsp.error.usebean.notBoth"); } if (className == null) { className = type; } - beanInfo.addBean(n, name, className, scope); + beanInfo.addBean(useBean, name, className, scope); - visitBody(n); + visitBody(useBean); } @Override - public void visit(Node.PlugIn n) throws WaspException { - JspUtil.checkAttributes("Plugin", n, plugInAttrs, err); - - throwErrorIfExpression(n, "type", "jsp:plugin"); - throwErrorIfExpression(n, "code", "jsp:plugin"); - throwErrorIfExpression(n, "codebase", "jsp:plugin"); - throwErrorIfExpression(n, "align", "jsp:plugin"); - throwErrorIfExpression(n, "archive", "jsp:plugin"); - throwErrorIfExpression(n, "hspace", "jsp:plugin"); - throwErrorIfExpression(n, "jreversion", "jsp:plugin"); - throwErrorIfExpression(n, "name", "jsp:plugin"); - throwErrorIfExpression(n, "vspace", "jsp:plugin"); - throwErrorIfExpression(n, "nspluginurl", "jsp:plugin"); - throwErrorIfExpression(n, "iepluginurl", "jsp:plugin"); - - String type = n.getTextAttribute("type"); + public void visit(Node.PlugIn plugIn) throws WaspException { + checkAttributes("Plugin", plugIn, plugInAttrs, err); + + throwErrorIfExpression(plugIn, "type", "jsp:plugin"); + throwErrorIfExpression(plugIn, "code", "jsp:plugin"); + throwErrorIfExpression(plugIn, "codebase", "jsp:plugin"); + throwErrorIfExpression(plugIn, "align", "jsp:plugin"); + throwErrorIfExpression(plugIn, "archive", "jsp:plugin"); + throwErrorIfExpression(plugIn, "hspace", "jsp:plugin"); + throwErrorIfExpression(plugIn, "jreversion", "jsp:plugin"); + throwErrorIfExpression(plugIn, "name", "jsp:plugin"); + throwErrorIfExpression(plugIn, "vspace", "jsp:plugin"); + throwErrorIfExpression(plugIn, "nspluginurl", "jsp:plugin"); + throwErrorIfExpression(plugIn, "iepluginurl", "jsp:plugin"); + + String type = plugIn.getTextAttribute("type"); if (type == null) { - err.jspError(n, "jsp.error.plugin.notype"); + err.jspError(plugIn, "jsp.error.plugin.notype"); } if (!type.equals("bean") && !type.equals("applet")) { - err.jspError(n, "jsp.error.plugin.badtype"); + err.jspError(plugIn, "jsp.error.plugin.badtype"); } - if (n.getTextAttribute("code") == null) { - err.jspError(n, "jsp.error.plugin.nocode"); + if (plugIn.getTextAttribute("code") == null) { + err.jspError(plugIn, "jsp.error.plugin.nocode"); } - Node.JspAttribute width = getJspAttribute("width", null, null, n.getAttributeValue("width"), n, false, null); - n.setWidth(width); + Node.JspAttribute width = getJspAttribute("width", null, null, plugIn.getAttributeValue("width"), plugIn, false, null); + plugIn.setWidth(width); - Node.JspAttribute height = getJspAttribute("height", null, null, n.getAttributeValue("height"), n, false, null); - n.setHeight(height); + Node.JspAttribute height = getJspAttribute("height", null, null, plugIn.getAttributeValue("height"), plugIn, false, null); + plugIn.setHeight(height); - visitBody(n); + visitBody(plugIn); } @Override - public void visit(Node.NamedAttribute n) throws WaspException { - JspUtil.checkAttributes("Attribute", n, attributeAttrs, err); - String omit = n.getAttributeValue("omit"); + public void visit(Node.NamedAttribute namedAttribute) throws WaspException { + checkAttributes("Attribute", namedAttribute, attributeAttrs, err); + String omit = namedAttribute.getAttributeValue("omit"); if (omit != null) { - n.setOmit(getJspAttribute("omit", null, null, omit, n, false, null)); + namedAttribute.setOmit(getJspAttribute("omit", null, null, omit, namedAttribute, false, null)); } - visitBody(n); + visitBody(namedAttribute); } @Override - public void visit(Node.JspBody n) throws WaspException { - visitBody(n); + public void visit(Node.JspBody pagesBody) throws WaspException { + visitBody(pagesBody); } @Override - public void visit(Node.Declaration n) throws WaspException { + public void visit(Node.Declaration declaration) throws WaspException { if (pageInfo.isScriptingInvalid()) { - err.jspError(n.getStart(), "jsp.error.no.scriptlets"); + err.jspError(declaration.getStart(), "jsp.error.no.scriptlets"); } } @Override - public void visit(Node.Expression n) throws WaspException { + public void visit(Node.Expression expression) throws WaspException { if (pageInfo.isScriptingInvalid()) { - err.jspError(n.getStart(), "jsp.error.no.scriptlets"); + err.jspError(expression.getStart(), "jsp.error.no.scriptlets"); } } @Override - public void visit(Node.Scriptlet n) throws WaspException { + public void visit(Node.Scriptlet scriptlet) throws WaspException { if (pageInfo.isScriptingInvalid()) { - err.jspError(n.getStart(), "jsp.error.no.scriptlets"); + err.jspError(scriptlet.getStart(), "jsp.error.no.scriptlets"); } } @Override - public void visit(Node.ELExpression n) throws WaspException { + public void visit(Node.ELExpression expression) throws WaspException { if (pageInfo.isELIgnored()) { return; } - String expressions = n.getText(); + + String expressions = expression.getText(); if (expressions.charAt(0) == '#') { if (pageInfo.isDeferredSyntaxAllowedAsLiteral()) { return; @@ -622,54 +686,58 @@ public void visit(Node.ELExpression n) throws WaspException { } } - err.jspError(n.getStart(), "jsp.error.not.in.template", "#{...}"); + err.jspError(expression.getStart(), "jsp.error.not.in.template", "#{...}"); } ELNode.Nodes el = ELParser.parse(expressions); - validateFunctions(el, n); - JspUtil.validateExpressions(n.getStart(), expressions, getFunctionMapper(el), err); - n.setEL(el); + validateFunctions(el, expression); + JspUtil.validateExpressions(expression.getStart(), expressions, getFunctionMapper(el), err); + expression.setEL(el); } @Override - public void visit(Node.UninterpretedTag n) throws WaspException { - if (n.getNamedAttributeNodes().size() != 0) { - err.jspError(n, "jsp.error.namedAttribute.invalidUse"); + public void visit(Node.UninterpretedTag uninterpretedTag) throws WaspException { + if (uninterpretedTag.getNamedAttributeNodes().size() != 0) { + err.jspError(uninterpretedTag, "jsp.error.namedAttribute.invalidUse"); } - Attributes attrs = n.getAttributes(); + Attributes attrs = uninterpretedTag.getAttributes(); if (attrs != null) { int attrSize = attrs.getLength(); Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize]; for (int i = 0; i < attrSize; i++) { - jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), n, false, null); + jspAttrs[i] = getJspAttribute( + attrs.getQName(i), + attrs.getURI(i), + attrs.getLocalName(i), + attrs.getValue(i), + uninterpretedTag, false, null); } - n.setJspAttributes(jspAttrs); + uninterpretedTag.setJspAttributes(jspAttrs); } - visitBody(n); + visitBody(uninterpretedTag); } @Override - public void visit(Node.CustomTag n) throws WaspException { - - TagInfo tagInfo = n.getTagInfo(); + public void visit(Node.CustomTag customTag) throws WaspException { + TagInfo tagInfo = customTag.getTagInfo(); if (tagInfo == null) { - err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); + err.jspError(customTag, "jsp.error.missing.tagInfo", customTag.getQName()); } /* * The bodycontent of a SimpleTag cannot be JSP. */ - if (n.implementsSimpleTag() && tagInfo.getBodyContent().equals(TagInfo.BODY_CONTENT_JSP)) { - err.jspError(n, "jsp.error.simpletag.badbodycontent", tagInfo.getTagClassName()); + if (customTag.implementsSimpleTag() && tagInfo.getBodyContent().equals(TagInfo.BODY_CONTENT_JSP)) { + err.jspError(customTag, "jsp.error.simpletag.badbodycontent", tagInfo.getTagClassName()); } /* * If the tag handler declares in the TLD that it supports dynamic attributes, it also must implement the * DynamicAttributes interface. */ - if (tagInfo.hasDynamicAttributes() && !n.implementsDynamicAttributes()) { - err.jspError(n, "jsp.error.dynamic.attributes.not.implemented", n.getQName()); + if (tagInfo.hasDynamicAttributes() && !customTag.implementsDynamicAttributes()) { + err.jspError(customTag, "jsp.error.dynamic.attributes.not.implemented", customTag.getQName()); } /* @@ -677,8 +745,8 @@ public void visit(Node.CustomTag n) throws WaspException { * sure that the same attribute is not specified in both attributes or named attributes. */ TagAttributeInfo[] tldAttrs = tagInfo.getAttributes(); - String customActionUri = n.getURI(); - Attributes attrs = n.getAttributes(); + String customActionUri = customTag.getURI(); + Attributes attrs = customTag.getAttributes(); int attrsSize = attrs == null ? 0 : attrs.getLength(); for (int i = 0; i < tldAttrs.length; i++) { String attr = null; @@ -688,17 +756,17 @@ public void visit(Node.CustomTag n) throws WaspException { attr = attrs.getValue(customActionUri, tldAttrs[i].getName()); } } - Node.NamedAttribute na = n.getNamedAttributeNode(tldAttrs[i].getName()); + Node.NamedAttribute na = customTag.getNamedAttributeNode(tldAttrs[i].getName()); if (tldAttrs[i].isRequired() && attr == null && na == null) { - err.jspError(n, "jsp.error.missing_attribute", tldAttrs[i].getName(), n.getLocalName()); + err.jspError(customTag, "jsp.error.missing_attribute", tldAttrs[i].getName(), customTag.getLocalName()); } if (attr != null && na != null) { - err.jspError(n, "jsp.error.duplicate.name.jspattribute", tldAttrs[i].getName()); + err.jspError(customTag, "jsp.error.duplicate.name.jspattribute", tldAttrs[i].getName()); } } - Node.Nodes naNodes = n.getNamedAttributeNodes(); + Node.Nodes naNodes = customTag.getNamedAttributeNodes(); int jspAttrsSize = naNodes.size() + attrsSize; Node.JspAttribute[] jspAttrs = null; if (jspAttrsSize > 0) { @@ -706,8 +774,8 @@ public void visit(Node.CustomTag n) throws WaspException { } Hashtable tagDataAttrs = new Hashtable<>(attrsSize); - checkXmlAttributes(n, jspAttrs, tagDataAttrs); - checkNamedAttributes(n, jspAttrs, attrsSize, tagDataAttrs); + checkXmlAttributes(customTag, jspAttrs, tagDataAttrs); + checkNamedAttributes(customTag, jspAttrs, attrsSize, tagDataAttrs); TagData tagData = new TagData(tagDataAttrs); @@ -716,25 +784,24 @@ public void visit(Node.CustomTag n) throws WaspException { // class that returns a non-null object. TagExtraInfo tei = tagInfo.getTagExtraInfo(); if (tei != null && tei.getVariableInfo(tagData) != null && tei.getVariableInfo(tagData).length > 0 && tagInfo.getTagVariableInfos().length > 0) { - err.jspError("jsp.error.non_null_tei_and_var_subelems", n.getQName()); + err.jspError("jsp.error.non_null_tei_and_var_subelems", customTag.getQName()); } - n.setTagData(tagData); - n.setJspAttributes(jspAttrs); + customTag.setTagData(tagData); + customTag.setJspAttributes(jspAttrs); - visitBody(n); + visitBody(customTag); } @Override - public void visit(Node.JspElement n) throws WaspException { - - Attributes attrs = n.getAttributes(); + public void visit(Node.JspElement pagesElement) throws WaspException { + Attributes attrs = pagesElement.getAttributes(); if (attrs == null) { - err.jspError(n, "jsp.error.jspelement.missing.name"); + err.jspError(pagesElement, "jsp.error.jspelement.missing.name"); } int xmlAttrLen = attrs.getLength(); - Node.Nodes namedAttrs = n.getNamedAttributeNodes(); + Node.Nodes namedAttrs = pagesElement.getNamedAttributeNodes(); // XML-style 'name' attribute, which is mandatory, must not be // included in JspAttribute array @@ -746,16 +813,16 @@ public void visit(Node.JspElement n) throws WaspException { // Process XML-style attributes for (int i = 0; i < xmlAttrLen; i++) { if ("name".equals(attrs.getLocalName(i))) { - n.setNameAttribute(getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), n, false, null)); + pagesElement.setNameAttribute(getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), pagesElement, false, null)); } else { if (jspAttrIndex < jspAttrSize) { - jspAttrs[jspAttrIndex++] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), n, false, + jspAttrs[jspAttrIndex++] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), pagesElement, false, null); } } } - if (n.getNameAttribute() == null) { - err.jspError(n, "jsp.error.jspelement.missing.name"); + if (pagesElement.getNameAttribute() == null) { + err.jspError(pagesElement, "jsp.error.jspelement.missing.name"); } // Process named attributes @@ -764,23 +831,23 @@ public void visit(Node.JspElement n) throws WaspException { jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na, false); } - n.setJspAttributes(jspAttrs); + pagesElement.setJspAttributes(jspAttrs); - visitBody(n); + visitBody(pagesElement); } @Override - public void visit(Node.JspOutput n) throws WaspException { - JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs, err); + public void visit(Node.JspOutput pagesOutput) throws WaspException { + checkAttributes("jsp:output", pagesOutput, jspOutputAttrs, err); - if (n.getBody() != null) { - err.jspError(n, "jsp.error.jspoutput.nonemptybody"); + if (pagesOutput.getBody() != null) { + err.jspError(pagesOutput, "jsp.error.jspoutput.nonemptybody"); } - String omitXmlDecl = n.getAttributeValue("omit-xml-declaration"); - String doctypeName = n.getAttributeValue("doctype-root-element"); - String doctypePublic = n.getAttributeValue("doctype-public"); - String doctypeSystem = n.getAttributeValue("doctype-system"); + String omitXmlDecl = pagesOutput.getAttributeValue("omit-xml-declaration"); + String doctypeName = pagesOutput.getAttributeValue("doctype-root-element"); + String doctypePublic = pagesOutput.getAttributeValue("doctype-public"); + String doctypeSystem = pagesOutput.getAttributeValue("doctype-system"); String omitXmlDeclOld = pageInfo.getOmitXmlDecl(); String doctypeNameOld = pageInfo.getDoctypeName(); @@ -788,27 +855,27 @@ public void visit(Node.JspOutput n) throws WaspException { String doctypeSystemOld = pageInfo.getDoctypeSystem(); if (omitXmlDecl != null && omitXmlDeclOld != null && !omitXmlDecl.equals(omitXmlDeclOld)) { - err.jspError(n, "jsp.error.jspoutput.conflict", "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl); + err.jspError(pagesOutput, "jsp.error.jspoutput.conflict", "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl); } if (doctypeName != null && doctypeNameOld != null && !doctypeName.equals(doctypeNameOld)) { - err.jspError(n, "jsp.error.jspoutput.conflict", "doctype-root-element", doctypeNameOld, doctypeName); + err.jspError(pagesOutput, "jsp.error.jspoutput.conflict", "doctype-root-element", doctypeNameOld, doctypeName); } if (doctypePublic != null && doctypePublicOld != null && !doctypePublic.equals(doctypePublicOld)) { - err.jspError(n, "jsp.error.jspoutput.conflict", "doctype-public", doctypePublicOld, doctypePublic); + err.jspError(pagesOutput, "jsp.error.jspoutput.conflict", "doctype-public", doctypePublicOld, doctypePublic); } if (doctypeSystem != null && doctypeSystemOld != null && !doctypeSystem.equals(doctypeSystemOld)) { - err.jspError(n, "jsp.error.jspoutput.conflict", "doctype-system", doctypeSystemOld, doctypeSystem); + err.jspError(pagesOutput, "jsp.error.jspoutput.conflict", "doctype-system", doctypeSystemOld, doctypeSystem); } if (doctypeName == null && doctypeSystem != null || doctypeName != null && doctypeSystem == null) { - err.jspError(n, "jsp.error.jspoutput.doctypenamesystem"); + err.jspError(pagesOutput, "jsp.error.jspoutput.doctypenamesystem"); } if (doctypePublic != null && doctypeSystem == null) { - err.jspError(n, "jsp.error.jspoutput.doctypepulicsystem"); + err.jspError(pagesOutput, "jsp.error.jspoutput.doctypepulicsystem"); } if (omitXmlDecl != null) { @@ -826,38 +893,36 @@ public void visit(Node.JspOutput n) throws WaspException { } @Override - public void visit(Node.InvokeAction n) throws WaspException { + public void visit(Node.InvokeAction invokeAction) throws WaspException { + checkAttributes("Invoke", invokeAction, invokeAttrs, err); - JspUtil.checkAttributes("Invoke", n, invokeAttrs, err); + String scope = invokeAction.getTextAttribute("scope"); + checkScope(scope, invokeAction, err); - String scope = n.getTextAttribute("scope"); - JspUtil.checkScope(scope, n, err); - - String var = n.getTextAttribute("var"); - String varReader = n.getTextAttribute("varReader"); + String var = invokeAction.getTextAttribute("var"); + String varReader = invokeAction.getTextAttribute("varReader"); if (scope != null && var == null && varReader == null) { - err.jspError(n, "jsp.error.missing_var_or_varReader"); + err.jspError(invokeAction, "jsp.error.missing_var_or_varReader"); } if (var != null && varReader != null) { - err.jspError(n, "jsp.error.var_and_varReader"); + err.jspError(invokeAction, "jsp.error.var_and_varReader"); } } @Override - public void visit(Node.DoBodyAction n) throws WaspException { - - JspUtil.checkAttributes("DoBody", n, doBodyAttrs, err); + public void visit(Node.DoBodyAction doBodyAction) throws WaspException { + checkAttributes("DoBody", doBodyAction, doBodyAttrs, err); - String scope = n.getTextAttribute("scope"); - JspUtil.checkScope(scope, n, err); + String scope = doBodyAction.getTextAttribute("scope"); + checkScope(scope, doBodyAction, err); - String var = n.getTextAttribute("var"); - String varReader = n.getTextAttribute("varReader"); + String var = doBodyAction.getTextAttribute("var"); + String varReader = doBodyAction.getTextAttribute("varReader"); if (scope != null && var == null && varReader == null) { - err.jspError(n, "jsp.error.missing_var_or_varReader"); + err.jspError(doBodyAction, "jsp.error.missing_var_or_varReader"); } if (var != null && varReader != null) { - err.jspError(n, "jsp.error.var_and_varReader"); + err.jspError(doBodyAction, "jsp.error.var_and_varReader"); } } @@ -867,9 +932,8 @@ public void visit(Node.DoBodyAction n) throws WaspException { * This can probably be done globally, when taglib directives are processed. We do it here so checking is done only for * the attributes are actually used. */ - private void checkSetter(Node.CustomTag n, TagAttributeInfo tldattr) throws WaspException { - - Class handler = n.getTagHandlerClass(); + private void checkSetter(Node.CustomTag customTag, TagAttributeInfo tldattr) throws WaspException { + Class handler = customTag.getTagHandlerClass(); if (handler == null) { // Handler unknown. Maybe tag file? return; @@ -884,25 +948,26 @@ private void checkSetter(Node.CustomTag n, TagAttributeInfo tldattr) throws Wasp } catch (Exception ex) { } if (setter == null) { - err.jspError(n, "jsp.error.setter.none", handlerName, property); + err.jspError(customTag, "jsp.error.setter.none", handlerName, property); } - Class setterType = setter.getParameterTypes()[0]; + + Class setterType = setter.getParameterTypes()[0]; String typeName = setterType.getName(); if (tldattr.isDeferredValue()) { if (tldattr.canBeRequestTime()) { if (!"java.lang.Object".equals(typeName)) { - err.jspError(n, "jsp.error.setter.notobject", handlerName, property); + err.jspError(customTag, "jsp.error.setter.notobject", handlerName, property); } return; } if (!"jakarta.el.ValueExpression".equals(typeName)) { - err.jspError(n, "jsp.error.setter.notvalueexpression", handlerName, property); + err.jspError(customTag, "jsp.error.setter.notvalueexpression", handlerName, property); } return; } if (tldattr.isDeferredMethod()) { if (!"jakarta.el.MethodExpression".equals(typeName)) { - err.jspError(n, "jsp.error.setter.notmethodexpression", handlerName, property); + err.jspError(customTag, "jsp.error.setter.notmethodexpression", handlerName, property); } } /* @@ -928,36 +993,36 @@ private void checkSetter(Node.CustomTag n, TagAttributeInfo tldattr) throws Wasp * An action attribute may have a prefix different from that of the action invocation only if the underlying tag handler * supports dynamic attributes, in which case the attribute with the different prefix is considered a dynamic attribute. */ - private void checkXmlAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs, Hashtable tagDataAttrs) throws WaspException { - - TagInfo tagInfo = n.getTagInfo(); + private void checkXmlAttributes(Node.CustomTag customTag, Node.JspAttribute[] jspAttrs, Hashtable tagDataAttrs) throws WaspException { + TagInfo tagInfo = customTag.getTagInfo(); if (tagInfo == null) { - err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); + err.jspError(customTag, "jsp.error.missing.tagInfo", customTag.getQName()); } + TagAttributeInfo[] tldAttrs = tagInfo.getAttributes(); - Attributes attrs = n.getAttributes(); + Attributes attrs = customTag.getAttributes(); for (int i = 0; attrs != null && i < attrs.getLength(); i++) { boolean found = false; for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) { if (attrs.getLocalName(i).equals(tldAttrs[j].getName()) - && (attrs.getURI(i) == null || attrs.getURI(i).length() == 0 || attrs.getURI(i).equals(n.getURI()))) { + && (attrs.getURI(i) == null || attrs.getURI(i).length() == 0 || attrs.getURI(i).equals(customTag.getURI()))) { - checkSetter(n, tldAttrs[j]); + checkSetter(customTag, tldAttrs[j]); if (tldAttrs[j].canBeRequestTime() || tldAttrs[j].isDeferredValue() || tldAttrs[j].isDeferredMethod()) { - jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), n, false, tldAttrs[j]); + jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), customTag, false, tldAttrs[j]); ELNode.Nodes el = jspAttrs[i].getEL(); if (el != null) { if (el.hasDollarExpression()) { if (!tldAttrs[j].canBeRequestTime()) { - err.jspError(n, "jsp.error.el.deferred.dollar", tldAttrs[j].getName()); + err.jspError(customTag, "jsp.error.el.deferred.dollar", tldAttrs[j].getName()); } } else if (el.hasPoundExpression()) { boolean isLiteral = pageInfo.isDeferredSyntaxAllowedAsLiteral(); if (!tldAttrs[j].isDeferredValue() && !tldAttrs[j].isDeferredMethod()) { - if (n.getJspVersion() >= 2.1 && !isLiteral) { - err.jspError(n, "jsp.error.el.nondeferred.pound", tldAttrs[j].getName()); + if (customTag.getJspVersion() >= 2.1 && !isLiteral) { + err.jspError(customTag, "jsp.error.el.nondeferred.pound", tldAttrs[j].getName()); } else { isLiteral = true; } @@ -975,9 +1040,9 @@ private void checkXmlAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs, } else { // Attribute does not accept any expressions. // Make sure its value does not contain any. - String litAttr = getLiteral(n, attrs.getValue(i)); + String litAttr = getLiteral(customTag, attrs.getValue(i)); if (litAttr == null) { - err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr", tldAttrs[j].getName()); + err.jspError(customTag, "jsp.error.attribute.custom.non_rt_with_expr", tldAttrs[j].getName()); } jspAttrs[i] = new Node.JspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), litAttr, false, null, false); } @@ -992,9 +1057,9 @@ private void checkXmlAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs, } if (!found) { if (tagInfo.hasDynamicAttributes()) { - jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), n, true, null); + jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs.getURI(i), attrs.getLocalName(i), attrs.getValue(i), customTag, true, null); } else { - err.jspError(n, "jsp.error.bad_attribute", attrs.getQName(i), n.getLocalName()); + err.jspError(customTag, "jsp.error.bad_attribute", attrs.getQName(i), customTag.getLocalName()); } } } @@ -1003,15 +1068,14 @@ private void checkXmlAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs, /* * Make sure the given custom action does not have any invalid named attributes */ - private void checkNamedAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs, int start, Hashtable tagDataAttrs) - throws WaspException { - - TagInfo tagInfo = n.getTagInfo(); + private void checkNamedAttributes(Node.CustomTag customTag, Node.JspAttribute[] jspAttrs, int start, Hashtable tagDataAttrs) throws WaspException { + TagInfo tagInfo = customTag.getTagInfo(); if (tagInfo == null) { - err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); + err.jspError(customTag, "jsp.error.missing.tagInfo", customTag.getQName()); } + TagAttributeInfo[] tldAttrs = tagInfo.getAttributes(); - Node.Nodes naNodes = n.getNamedAttributeNodes(); + Node.Nodes naNodes = customTag.getNamedAttributeNodes(); for (int i = 0; i < naNodes.size(); i++) { Node.NamedAttribute na = (Node.NamedAttribute) naNodes.getNode(i); @@ -1024,7 +1088,7 @@ private void checkNamedAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs */ String attrPrefix = na.getPrefix(); if (na.getLocalName().equals(tldAttrs[j].getName()) - && (attrPrefix == null || attrPrefix.length() == 0 || attrPrefix.equals(n.getPrefix()))) { + && (attrPrefix == null || attrPrefix.length() == 0 || attrPrefix.equals(customTag.getPrefix()))) { jspAttrs[start + i] = new Node.JspAttribute(na, false); NamedAttributeVisitor nav = null; if (na.getBody() != null) { @@ -1044,7 +1108,7 @@ private void checkNamedAttributes(Node.CustomTag n, Node.JspAttribute[] jspAttrs if (tagInfo.hasDynamicAttributes()) { jspAttrs[start + i] = new Node.JspAttribute(na, true); } else { - err.jspError(n, "jsp.error.bad_attribute", na.getName(), n.getLocalName()); + err.jspError(customTag, "jsp.error.bad_attribute", na.getName(), customTag.getLocalName()); } } } @@ -1142,18 +1206,18 @@ private Node.JspAttribute getJspAttribute(String qName, String uri, String local * * @return null, if the attribute is an expression otherwise, the literal string for the attribute */ - private String getLiteral(Node n, String value) { - if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) { + private String getLiteral(Node node, String value) { + if (node.getRoot().isXmlSyntax() && value.startsWith("%=")) { return null; } - if (!n.getRoot().isXmlSyntax() && value.startsWith("<%=")) { + if (!node.getRoot().isXmlSyntax() && value.startsWith("<%=")) { return null; } if (pageInfo.isELIgnored()) { return value; } - boolean poundExpressionIgnored = n instanceof Node.CustomTag - && (((Node.CustomTag) n).getJspVersion() < 2.1 || pageInfo.isDeferredSyntaxAllowedAsLiteral()); + boolean poundExpressionIgnored = node instanceof Node.CustomTag + && (((Node.CustomTag) node).getJspVersion() < 2.1 || pageInfo.isDeferredSyntaxAllowedAsLiteral()); int size = value.length(); StringBuilder buf = new StringBuilder(size); char p = ' '; @@ -1189,9 +1253,9 @@ private String getLiteral(Node n, String value) { * Throws exception if the value of the attribute with the given name in the given node is given as an RT or EL * expression, but the spec requires a static value. */ - private void throwErrorIfExpression(Node n, String attrName, String actionName) throws WaspException { - if (n.getAttributes() != null && n.getAttributes().getValue(attrName) != null && getLiteral(n, n.getAttributes().getValue(attrName)) == null) { - err.jspError(n, "jsp.error.attribute.standard.non_rt_with_expr", attrName, actionName); + private void throwErrorIfExpression(Node node, String attrName, String actionName) throws WaspException { + if (node.getAttributes() != null && node.getAttributes().getValue(attrName) != null && getLiteral(node, node.getAttributes().getValue(attrName)) == null) { + err.jspError(node, "jsp.error.attribute.standard.non_rt_with_expr", attrName, actionName); } } @@ -1232,10 +1296,10 @@ public boolean hasDynamicContent() { } } - private String findUri(String prefix, Node n) { + private String findUri(String prefix, Node node) { - for (Node p = n; p != null; p = p.getParent()) { - Attributes attrs = p.getTaglibAttributes(); + for (Node parentNode = node; parentNode != null; parentNode = parentNode.getParent()) { + Attributes attrs = parentNode.getTaglibAttributes(); if (attrs == null) { continue; } @@ -1308,22 +1372,22 @@ public void visit(ELNode.Function func) throws WaspException { el.visit(new FVVisitor(n)); } - private void processSignature(ELNode.Function func) throws WaspException { - FunctionInfo funcInfo = func.getFunctionInfo(); + private void processSignature(ELNode.Function function) throws WaspException { + FunctionInfo funcInfo = function.getFunctionInfo(); String signature = funcInfo.getFunctionSignature(); - func.setMethodName(getMethod(signature)); - func.setParameters(getParameters(signature)); + function.setMethodName(getMethod(signature)); + function.setParameters(getParameters(signature)); } /** * Get the return type from the signature. */ private String getReturnType(String signature) throws WaspException { - int start = signature.indexOf(' '); if (start < 0) { err.jspError("jsp.error.tld.invalid.signature", signature); } + return signature.substring(0, start); } @@ -1331,15 +1395,16 @@ private String getReturnType(String signature) throws WaspException { * Get the method name from the signature. */ private String getMethod(String signature) throws WaspException { - int start = signature.indexOf(' '); if (start < 0) { err.jspError("jsp.error.tld.invalid.signature", signature); } + int end = signature.indexOf('('); if (end < 0) { err.jspError("jsp.error.tld.invalid.signature", signature); } + return signature.substring(start + 1, end).trim(); } @@ -1349,8 +1414,8 @@ private String getMethod(String signature) throws WaspException { * @return An array of parameter class names */ private String[] getParameters(String signature) throws WaspException { - ArrayList params = new ArrayList<>(); + // Signature is of the form // S ( ',' )* )? ')' diff --git a/src/main/java/org/glassfish/wasp/resources/messages.properties b/src/main/java/org/glassfish/wasp/resources/messages.properties index 68786c7..2d10320 100644 --- a/src/main/java/org/glassfish/wasp/resources/messages.properties +++ b/src/main/java/org/glassfish/wasp/resources/messages.properties @@ -1,6 +1,7 @@ # # Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. # Copyright 2004 The Apache Software Foundation +# Copyright (c) 2021 Contributors to the Eclipse Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -238,7 +239,7 @@ where options include:\n\ \ -trimSpaces Trim spaces in template text between actions, directives\n\ \ -smap Generate SMAP info for JSR45 debugging\n\ \ -dumpsmap Dump SMAP info for JSR45 debugging into a file\n\ -\ -validate Validate .tld and web.xml files against their schemas and dtds\n\ +\ -validate Validate .tld files against their schemas and dtds\n\ \ -compilerSourceVM Provides source compatibility with specified JDK release\n\ \ \n\ \ -compilerTargetVM Generates class files for specified VM version\n\ diff --git a/src/main/java/org/glassfish/wasp/runtime/ELContextImpl.java b/src/main/java/org/glassfish/wasp/runtime/ELContextImpl.java index b58256d..ee3b903 100644 --- a/src/main/java/org/glassfish/wasp/runtime/ELContextImpl.java +++ b/src/main/java/org/glassfish/wasp/runtime/ELContextImpl.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -31,6 +32,11 @@ * @author Kin-man Chung */ public class ELContextImpl extends ELContext { + + private FunctionMapper functionMapper; + private VariableMapper variableMapper; + private ELResolver resolver; + /** * Constructs a new ELContext associated with the given ELResolver. */ @@ -60,8 +66,4 @@ public void setVariableMapper(VariableMapper varMapper) { public VariableMapper getVariableMapper() { return variableMapper; } - - private FunctionMapper functionMapper; - private VariableMapper variableMapper; - private ELResolver resolver; } diff --git a/src/main/java/org/glassfish/wasp/runtime/ELContextWrapper.java b/src/main/java/org/glassfish/wasp/runtime/ELContextWrapper.java new file mode 100644 index 0000000..db1dcc3 --- /dev/null +++ b/src/main/java/org/glassfish/wasp/runtime/ELContextWrapper.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glassfish.wasp.runtime; + +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import jakarta.el.ELContext; +import jakarta.el.ELResolver; +import jakarta.el.EvaluationListener; +import jakarta.el.FunctionMapper; +import jakarta.el.ImportHandler; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.el.NotFoundELResolver; + +public class ELContextWrapper extends ELContext { + + private final ELContext wrapped; + private final boolean errorOnELNotFound; + + public ELContextWrapper(ELContext wrapped, boolean errorOnELNotFound) { + this.wrapped = wrapped; + this.errorOnELNotFound = errorOnELNotFound; + } + + ELContext getWrappedELContext() { + return wrapped; + } + + @Override + public void setPropertyResolved(boolean resolved) { + wrapped.setPropertyResolved(resolved); + } + + @Override + public void setPropertyResolved(Object base, Object property) { + wrapped.setPropertyResolved(base, property); + } + + @Override + public boolean isPropertyResolved() { + return wrapped.isPropertyResolved(); + } + + @Override + public void putContext(Class key, Object contextObject) { + wrapped.putContext(key, contextObject); + } + + @Override + public Object getContext(Class key) { + if (key == NotFoundELResolver.class) { + return errorOnELNotFound; + } + + return wrapped.getContext(key); + } + + @Override + public ImportHandler getImportHandler() { + return wrapped.getImportHandler(); + } + + @Override + public Locale getLocale() { + return wrapped.getLocale(); + } + + @Override + public void setLocale(Locale locale) { + wrapped.setLocale(locale); + } + + @Override + public void addEvaluationListener(EvaluationListener listener) { + wrapped.addEvaluationListener(listener); + } + + @Override + public List getEvaluationListeners() { + return wrapped.getEvaluationListeners(); + } + + @Override + public void notifyBeforeEvaluation(String expression) { + wrapped.notifyBeforeEvaluation(expression); + } + + @Override + public void notifyAfterEvaluation(String expression) { + wrapped.notifyAfterEvaluation(expression); + } + + @Override + public void notifyPropertyResolved(Object base, Object property) { + wrapped.notifyPropertyResolved(base, property); + } + + @Override + public boolean isLambdaArgument(String name) { + return wrapped.isLambdaArgument(name); + } + + @Override + public Object getLambdaArgument(String name) { + return wrapped.getLambdaArgument(name); + } + + @Override + public void enterLambdaScope(Map arguments) { + wrapped.enterLambdaScope(arguments); + } + + @Override + public void exitLambdaScope() { + wrapped.exitLambdaScope(); + } + + @Override + public T convertToType(Object obj, Class type) { + return wrapped.convertToType(obj, type); + } + + @Override + public ELResolver getELResolver() { + return wrapped.getELResolver(); + } + + @Override + public FunctionMapper getFunctionMapper() { + return wrapped.getFunctionMapper(); + } + + @Override + public VariableMapper getVariableMapper() { + return wrapped.getVariableMapper(); + } +} \ No newline at end of file diff --git a/src/main/java/org/glassfish/wasp/runtime/JspContextWrapper.java b/src/main/java/org/glassfish/wasp/runtime/JspContextWrapper.java index d331f4d..f134be2 100644 --- a/src/main/java/org/glassfish/wasp/runtime/JspContextWrapper.java +++ b/src/main/java/org/glassfish/wasp/runtime/JspContextWrapper.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,10 @@ package org.glassfish.wasp.runtime; +import static jakarta.servlet.jsp.tagext.VariableInfo.AT_BEGIN; +import static jakarta.servlet.jsp.tagext.VariableInfo.AT_END; +import static jakarta.servlet.jsp.tagext.VariableInfo.NESTED; + import java.io.IOException; import java.io.Writer; import java.util.ArrayList; @@ -24,6 +29,7 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.glassfish.wasp.compiler.Localizer; @@ -42,7 +48,7 @@ import jakarta.servlet.jsp.el.ExpressionEvaluator; import jakarta.servlet.jsp.el.VariableResolver; import jakarta.servlet.jsp.tagext.BodyContent; -import jakarta.servlet.jsp.tagext.VariableInfo; +import jakarta.servlet.jsp.tagext.JspTag; /** * Implementation of a JSP Context Wrapper. @@ -55,26 +61,30 @@ */ public class JspContextWrapper extends PageContext { + // Tag for this wrapper is created + private JspTag jspTag; + // Invoking JSP context private PageContext invokingJspCtxt; private Hashtable pageAttributes; // ArrayList of NESTED scripting variables - private ArrayList nestedVars; + private List nestedVars; // ArrayList of AT_BEGIN scripting variables - private ArrayList atBeginVars; + private List atBeginVars; // ArrayList of AT_END scripting variables - private ArrayList atEndVars; + private List atEndVars; private Map aliases; - private HashMap originalNestedVars; + private Map originalNestedVars; private ELContext elContext; - public JspContextWrapper(JspContext jspContext, ArrayList nestedVars, ArrayList atBeginVars, ArrayList atEndVars, + public JspContextWrapper(JspTag jspTag, JspContext jspContext, ArrayList nestedVars, ArrayList atBeginVars, ArrayList atEndVars, Map aliases) { + this.jspTag = jspTag; this.invokingJspCtxt = (PageContext) jspContext; this.nestedVars = nestedVars; this.atBeginVars = atBeginVars; @@ -95,7 +105,6 @@ public void initialize(Servlet servlet, ServletRequest request, ServletResponse @Override public Object getAttribute(String name) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -105,7 +114,6 @@ public Object getAttribute(String name) { @Override public Object getAttribute(String name, int scope) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -119,7 +127,6 @@ public Object getAttribute(String name, int scope) { @Override public void setAttribute(String name, Object value) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -133,7 +140,6 @@ public void setAttribute(String name, Object value) { @Override public void setAttribute(String name, Object value, int scope) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -151,30 +157,28 @@ public void setAttribute(String name, Object value, int scope) { @Override public Object findAttribute(String name) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } - Object o = pageAttributes.get(name); - if (o == null) { - o = invokingJspCtxt.getAttribute(name, REQUEST_SCOPE); - if (o == null) { + Object attribute = pageAttributes.get(name); + if (attribute == null) { + attribute = invokingJspCtxt.getAttribute(name, REQUEST_SCOPE); + if (attribute == null) { if (getSession() != null) { - o = invokingJspCtxt.getAttribute(name, SESSION_SCOPE); + attribute = invokingJspCtxt.getAttribute(name, SESSION_SCOPE); } - if (o == null) { - o = invokingJspCtxt.getAttribute(name, APPLICATION_SCOPE); + if (attribute == null) { + attribute = invokingJspCtxt.getAttribute(name, APPLICATION_SCOPE); } } } - return o; + return attribute; } @Override public void removeAttribute(String name) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -189,7 +193,6 @@ public void removeAttribute(String name) { @Override public void removeAttribute(String name, int scope) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -203,7 +206,6 @@ public void removeAttribute(String name, int scope) { @Override public int getAttributesScope(String name) { - if (name == null) { throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name")); } @@ -269,28 +271,49 @@ public ServletContext getServletContext() { return invokingJspCtxt.getServletContext(); } - static public PageContext getRootPageContext(PageContext pc) { - while (pc instanceof JspContextWrapper) { - pc = ((JspContextWrapper) pc).invokingJspCtxt; + static public PageContext getRootPageContext(PageContext pageContect) { + while (pageContect instanceof JspContextWrapper) { + pageContect = ((JspContextWrapper) pageContect).invokingJspCtxt; } - return pc; + + return pageContect; } @Override public ELContext getELContext() { if (elContext == null) { - PageContext pc = invokingJspCtxt; - while (pc instanceof JspContextWrapper) { - pc = ((JspContextWrapper) pc).invokingJspCtxt; - } - PageContextImpl pci = (PageContextImpl) pc; - elContext = pci.getJspApplicationContext().createELContext(invokingJspCtxt.getELContext().getELResolver()); - elContext.putContext(jakarta.servlet.jsp.JspContext.class, this); - ((ELContextImpl) elContext).setVariableMapper(new VariableMapperImpl()); + ELContextImpl elContextImpl = (ELContextImpl) + getRootPageContextImpl().getJspApplicationContext() + .createELContext( + invokingJspCtxt.getELContext() + .getELResolver()); + + elContextImpl.putContext(JspContext.class, this); + elContextImpl.setVariableMapper(new VariableMapperImpl()); + + elContext = new ELContextWrapper(elContextImpl, isErrorOnELNotFound()); } + return elContext; } + public PageContextImpl getRootPageContextImpl() { + PageContext pageContext = invokingJspCtxt; + while (pageContext instanceof JspContextWrapper) { + pageContext = ((JspContextWrapper) pageContext).invokingJspCtxt; + } + + return (PageContextImpl) pageContext; + } + + public boolean isErrorOnELNotFound() { + if (jspTag instanceof JspSourceDependent) { + return ((JspSourceDependent) jspTag).getErrorOnELNotFound(); + } + + return false; + } + @Override public void forward(String relativeUrlPath) throws ServletException, IOException { invokingJspCtxt.forward(relativeUrlPath); @@ -354,16 +377,16 @@ public void syncBeginTagFile() { * Synchronize variables before fragment invokation */ public void syncBeforeInvoke() { - copyTagToPageScope(VariableInfo.NESTED); - copyTagToPageScope(VariableInfo.AT_BEGIN); + copyTagToPageScope(NESTED); + copyTagToPageScope(AT_BEGIN); } /** * Synchronize variables at end of tag file */ public void syncEndTagFile() { - copyTagToPageScope(VariableInfo.AT_BEGIN); - copyTagToPageScope(VariableInfo.AT_END); + copyTagToPageScope(AT_BEGIN); + copyTagToPageScope(AT_END); restoreNestedVariables(); } @@ -377,17 +400,17 @@ private void copyTagToPageScope(int scope) { Iterator iter = null; switch (scope) { - case VariableInfo.NESTED: + case NESTED: if (nestedVars != null) { iter = nestedVars.iterator(); } break; - case VariableInfo.AT_BEGIN: + case AT_BEGIN: if (atBeginVars != null) { iter = atBeginVars.iterator(); } break; - case VariableInfo.AT_END: + case AT_END: if (atEndVars != null) { iter = atEndVars.iterator(); } @@ -396,10 +419,10 @@ private void copyTagToPageScope(int scope) { while (iter != null && iter.hasNext()) { String varName = iter.next(); - Object obj = getAttribute(varName); + Object attribute = getAttribute(varName); varName = findAlias(varName); - if (obj != null) { - invokingJspCtxt.setAttribute(varName, obj); + if (attribute != null) { + invokingJspCtxt.setAttribute(varName, attribute); } else { invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE); } @@ -415,9 +438,9 @@ private void saveNestedVariables() { while (iter.hasNext()) { String varName = iter.next(); varName = findAlias(varName); - Object obj = invokingJspCtxt.getAttribute(varName); - if (obj != null) { - originalNestedVars.put(varName, obj); + Object attribute = invokingJspCtxt.getAttribute(varName); + if (attribute != null) { + originalNestedVars.put(varName, attribute); } } } @@ -432,9 +455,9 @@ private void restoreNestedVariables() { while (iter.hasNext()) { String varName = iter.next(); varName = findAlias(varName); - Object obj = originalNestedVars.get(varName); - if (obj != null) { - invokingJspCtxt.setAttribute(varName, obj); + Object nestedVar = originalNestedVars.get(varName); + if (nestedVar != null) { + invokingJspCtxt.setAttribute(varName, nestedVar); } else { invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE); } @@ -450,7 +473,6 @@ private void restoreNestedVariables() { * @return The variable name for which varName is used as an alias, or varName if it is not being used as an alias */ private String findAlias(String varName) { - if (aliases == null) { return varName; } @@ -459,6 +481,7 @@ private String findAlias(String varName) { if (alias == null) { return varName; } + return alias; } } diff --git a/src/main/java/org/glassfish/wasp/runtime/JspSourceDependent.java b/src/main/java/org/glassfish/wasp/runtime/JspSourceDependent.java index 4d30e38..8b24394 100644 --- a/src/main/java/org/glassfish/wasp/runtime/JspSourceDependent.java +++ b/src/main/java/org/glassfish/wasp/runtime/JspSourceDependent.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,8 @@ package org.glassfish.wasp.runtime; +import java.util.List; + /** * Interface for tracking the source files dependencies, for the purpose of compiling out of date pages. This is used * for 1) files that are included by page directives 2) files that are included by include-prelude and include-coda in @@ -28,5 +31,9 @@ public interface JspSourceDependent { /** * Returns a list of files names that the current page has a source dependency on. */ - java.util.List getDependants(); + List getDependants(); + + default boolean getErrorOnELNotFound() { + return false; + } } diff --git a/src/main/java/org/glassfish/wasp/runtime/PageContextImpl.java b/src/main/java/org/glassfish/wasp/runtime/PageContextImpl.java index 3a109b1..95d6d9d 100644 --- a/src/main/java/org/glassfish/wasp/runtime/PageContextImpl.java +++ b/src/main/java/org/glassfish/wasp/runtime/PageContextImpl.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,8 @@ package org.glassfish.wasp.runtime; +import static java.lang.Boolean.TRUE; + import java.io.IOException; import java.io.Writer; import java.security.AccessController; @@ -56,12 +59,15 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import jakarta.servlet.jsp.JspContext; import jakarta.servlet.jsp.JspException; import jakarta.servlet.jsp.JspFactory; import jakarta.servlet.jsp.JspWriter; import jakarta.servlet.jsp.PageContext; import jakarta.servlet.jsp.el.ExpressionEvaluator; import jakarta.servlet.jsp.el.ImplicitObjectELResolver; +import jakarta.servlet.jsp.el.ImportELResolver; +import jakarta.servlet.jsp.el.NotFoundELResolver; import jakarta.servlet.jsp.el.ScopedAttributeELResolver; import jakarta.servlet.jsp.el.VariableResolver; import jakarta.servlet.jsp.tagext.BodyContent; @@ -665,6 +671,8 @@ private ELResolver getELResolver() { celResolver.add(new ArrayELResolver()); celResolver.add(new BeanELResolver()); celResolver.add(new ScopedAttributeELResolver()); + celResolver.add(new ImportELResolver()); + celResolver.add(new NotFoundELResolver()); elResolver = celResolver; } return elResolver; @@ -674,9 +682,16 @@ private ELResolver getELResolver() { public ELContext getELContext() { if (elContext == null) { elContext = getJspApplicationContext().createELContext(getELResolver()); - elContext.putContext(jakarta.servlet.jsp.JspContext.class, this); + elContext.putContext(JspContext.class, this); ((ELContextImpl) elContext).setVariableMapper(new VariableMapperImpl()); + + if (servlet instanceof JspSourceDependent) { + if (((JspSourceDependent) servlet).getErrorOnELNotFound()) { + elContext.putContext(NotFoundELResolver.class, TRUE); + } + } } + return elContext; } @@ -816,7 +831,6 @@ public void handlePageException(final Throwable t) throws IOException, ServletEx } private void doHandlePageException(Throwable t) throws IOException, ServletException { - if (errorPageURL != null && !errorPageURL.equals("")) { /* @@ -869,9 +883,7 @@ private void doHandlePageException(Throwable t) throws IOException, ServletExcep } Throwable rootCause = null; - if (t instanceof JspException) { - rootCause = ((JspException) t).getRootCause(); - } else if (t instanceof ELException) { + if (t instanceof ELException || t instanceof JspException) { rootCause = t.getCause(); } @@ -884,7 +896,6 @@ private void doHandlePageException(Throwable t) throws IOException, ServletExcep } private static ExpressionFactory getExpressionFactory(PageContext pageContext) { - PageContextImpl pc = (PageContextImpl) JspContextWrapper.getRootPageContext(pageContext); return pc.getJspApplicationContext().getExpressionFactory(); } @@ -898,61 +909,69 @@ private static ExpressionFactory getExpressionFactory(PageContext pageContext) { * @param functionMap Maps prefix and name to Method * @return The result of the evaluation */ - public static Object evaluateExpression(final String expression, final Class expectedType, final PageContext pageContext, - final ProtectedFunctionMapper functionMap) throws ELException { + public static Object evaluateExpression(final String expression, final Class expectedType, final PageContext pageContext, final ProtectedFunctionMapper functionMap) throws ELException { Object retValue; if (SecurityUtil.isPackageProtectionEnabled()) { try { retValue = AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - ELContextImpl elContext = (ELContextImpl) pageContext.getELContext(); - elContext.setFunctionMapper(functionMap); - ExpressionFactory expFactory = getExpressionFactory(pageContext); - ValueExpression expr = expFactory.createValueExpression(elContext, expression, expectedType); - return expr.getValue(elContext); + ELContext elContext = pageContext.getELContext(); + toELContextImpl(elContext).setFunctionMapper(functionMap); + + return getExpressionFactory(pageContext) + .createValueExpression(elContext, expression, expectedType) + .getValue(elContext); }); } catch (PrivilegedActionException ex) { Exception realEx = ex.getException(); if (realEx instanceof ELException) { throw (ELException) realEx; - } else { - throw new ELException(realEx); } + + throw new ELException(realEx); } } else { - ELContextImpl elContext = (ELContextImpl) pageContext.getELContext(); - elContext.setFunctionMapper(functionMap); - ExpressionFactory expFactory = getExpressionFactory(pageContext); - ValueExpression expr = expFactory.createValueExpression(elContext, expression, expectedType); - retValue = expr.getValue(elContext); + ELContext elContext = pageContext.getELContext(); + toELContextImpl(elContext).setFunctionMapper(functionMap); + + retValue = getExpressionFactory(pageContext) + .createValueExpression(elContext, expression, expectedType) + .getValue(elContext); } + return retValue; } - public static ValueExpression getValueExpression(String expression, PageContext pageContext, Class expectedType, FunctionMapper functionMap) { + public static ValueExpression getValueExpression(String expression, PageContext pageContext, Class expectedType, FunctionMapper functionMap) { // ELResolvers are not used in createValueExpression - ELContextImpl elctxt = (ELContextImpl) pageContext.getELContext(); - elctxt.setFunctionMapper(functionMap); - ExpressionFactory expFactory = getExpressionFactory(pageContext); - return expFactory.createValueExpression(elctxt, expression, expectedType); + ELContext elctxt = pageContext.getELContext(); + toELContextImpl(elctxt).setFunctionMapper(functionMap); + return getExpressionFactory(pageContext).createValueExpression(elctxt, expression, expectedType); } - public static MethodExpression getMethodExpression(String expression, PageContext pageContext, FunctionMapper functionMap, Class expectedType, - Class[] paramTypes) { - - ELContextImpl elctxt = (ELContextImpl) pageContext.getELContext(); - elctxt.setFunctionMapper(functionMap); - ExpressionFactory expFactory = getExpressionFactory(pageContext); - return expFactory.createMethodExpression(elctxt, expression, expectedType, paramTypes); + public static MethodExpression getMethodExpression(String expression, PageContext pageContext, FunctionMapper functionMap, Class expectedType, Class[] paramTypes) { + ELContext elctxt = pageContext.getELContext(); + toELContextImpl(elctxt).setFunctionMapper(functionMap); + return getExpressionFactory(pageContext).createMethodExpression(elctxt, expression, expectedType, paramTypes); } public static void setValueVariable(PageContext pageContext, String variable, ValueExpression expression) { - ELContextImpl elctxt = (ELContextImpl) pageContext.getELContext(); - elctxt.getVariableMapper().setVariable(variable, expression); + toELContextImpl(pageContext.getELContext()) + .getVariableMapper() + .setVariable(variable, expression); } public static void setMethodVariable(PageContext pageContext, String variable, MethodExpression expression) { - ExpressionFactory expFactory = getExpressionFactory(pageContext); - ValueExpression exp = expFactory.createValueExpression(expression, Object.class); - setValueVariable(pageContext, variable, exp); + setValueVariable( + pageContext, + variable, + getExpressionFactory(pageContext).createValueExpression(expression, Object.class)); + } + + public static ELContextImpl toELContextImpl(ELContext elContext) { + if (elContext instanceof ELContextWrapper) { + return (ELContextImpl) ((ELContextWrapper) elContext).getWrappedELContext(); + } + + return (ELContextImpl) elContext; } }