Author: remy.maucherat(a)jboss.com
Date: 2010-03-25 13:19:10 -0400 (Thu, 25 Mar 2010)
New Revision: 1421
Modified:
trunk/java/org/apache/jasper/compiler/Compiler.java
trunk/java/org/apache/jasper/compiler/ELParser.java
trunk/java/org/apache/jasper/compiler/JspConfig.java
trunk/java/org/apache/jasper/compiler/JspDocumentParser.java
trunk/java/org/apache/jasper/compiler/Parser.java
trunk/java/org/apache/jasper/compiler/Validator.java
trunk/java/org/apache/jasper/resources/LocalStrings.properties
trunk/webapps/docs/changelog.xml
Log:
- Port Jasper fixes.
- Make ELParser aware of the deferred flag.
- JSP doc parser regression fix.
Modified: trunk/java/org/apache/jasper/compiler/Compiler.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Compiler.java 2010-03-25 17:17:13 UTC (rev
1420)
+++ trunk/java/org/apache/jasper/compiler/Compiler.java 2010-03-25 17:19:10 UTC (rev
1421)
@@ -149,6 +149,21 @@
pageInfo.setErrorOnUndeclaredNamespace(JspUtil.booleanValue(jspProperty
.isErrorOnUndeclaredNamespace()));
}
+ if (ctxt.isTagFile()) {
+ try {
+ double libraryVersion = Double.parseDouble(ctxt.getTagInfo()
+ .getTagLibrary().getRequiredVersion());
+ if (libraryVersion < 2.0) {
+ pageInfo.setIsELIgnored("true", null, errDispatcher,
true);
+ }
+ if (libraryVersion < 2.1) {
+ pageInfo.setDeferredSyntaxAllowedAsLiteral("true", null,
+ errDispatcher, true);
+ }
+ } catch (NumberFormatException ex) {
+ errDispatcher.jspError(ex);
+ }
+ }
ctxt.checkOutputDir();
String javaFileName = ctxt.getServletJavaFileName();
Modified: trunk/java/org/apache/jasper/compiler/ELParser.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/ELParser.java 2010-03-25 17:17:13 UTC (rev
1420)
+++ trunk/java/org/apache/jasper/compiler/ELParser.java 2010-03-25 17:19:10 UTC (rev
1421)
@@ -45,13 +45,16 @@
private boolean escapeBS; // is '\' an escape char in text outside EL?
+ private final boolean isDeferredSyntaxAllowedAsLiteral;
+
private static final String reservedWords[] = { "and", "div",
"empty",
"eq", "false", "ge", "gt",
"instanceof", "le", "lt", "mod", "ne",
"not", "null", "or", "true" };
- public ELParser(String expression) {
+ public ELParser(String expression, boolean isDeferredSyntaxAllowedAsLiteral) {
index = 0;
this.expression = expression;
+ this.isDeferredSyntaxAllowedAsLiteral = isDeferredSyntaxAllowedAsLiteral;
expr = new ELNode.Nodes();
}
@@ -61,10 +64,13 @@
* @param expression
* The input expression string of the form Char* ('${' Char*
* '}')* Char*
+ * @param isDeferredSyntaxAllowedAsLiteral
+ * Are deferred expressions treated as literals?
* @return Parsed EL expression in ELNode.Nodes
*/
- public static ELNode.Nodes parse(String expression) {
- ELParser parser = new ELParser(expression);
+ public static ELNode.Nodes parse(String expression,
+ boolean isDeferredSyntaxAllowedAsLiteral) {
+ ELParser parser = new ELParser(expression, isDeferredSyntaxAllowedAsLiteral);
while (parser.hasNextChar()) {
String text = parser.skipUntilEL();
if (text.length() > 0) {
@@ -187,11 +193,11 @@
buf.append('\\');
if (!escapeBS)
prev = '\\';
- } else if (ch == '$' || ch == '#') {
+ } else if (ch == '$' || (!isDeferredSyntaxAllowedAsLiteral
&& ch == '#')) {
buf.append(ch);
}
// else error!
- } else if (prev == '$' || prev == '#') {
+ } else if (prev == '$' || (!isDeferredSyntaxAllowedAsLiteral
&& prev == '#')) {
if (ch == '{') {
this.type = prev;
prev = 0;
@@ -200,7 +206,8 @@
buf.append(prev);
prev = 0;
}
- if (ch == '\\' || ch == '$' || ch == '#') {
+ if (ch == '\\' || ch == '$'
+ || (!isDeferredSyntaxAllowedAsLiteral && ch == '#')) {
prev = ch;
} else {
buf.append(ch);
Modified: trunk/java/org/apache/jasper/compiler/JspConfig.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/JspConfig.java 2010-03-25 17:17:13 UTC (rev
1420)
+++ trunk/java/org/apache/jasper/compiler/JspConfig.java 2010-03-25 17:19:10 UTC (rev
1421)
@@ -106,7 +106,11 @@
}
if (version < 2.4) {
defaultIsELIgnored = "true";
+ defaultDeferedSyntaxAllowedAsLiteral = "true";
}
+ if (version < 2.5) {
+ defaultDeferedSyntaxAllowedAsLiteral = "true";
+ }
jspProperties = new ArrayList<JspPropertyGroup>();
Iterator<String> urlPatternIterator =
jspPropertyGroups.keySet().iterator();
Modified: trunk/java/org/apache/jasper/compiler/JspDocumentParser.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/JspDocumentParser.java 2010-03-25 17:17:13 UTC
(rev 1420)
+++ trunk/java/org/apache/jasper/compiler/JspDocumentParser.java 2010-03-25 17:19:10 UTC
(rev 1421)
@@ -110,8 +110,6 @@
// Flag set to delay incrmenting tagDependentNesting until jsp:body
// is first encountered
private boolean tagDependentPending = false;
- // Tag being parsed that should have an empty body
- private Node tagEmptyBody = null;
/*
* Constructor
@@ -271,8 +269,6 @@
AttributesImpl nonTaglibAttrs = null;
AttributesImpl nonTaglibXmlnsAttrs = null;
- checkEmptyBody();
-
processChars();
checkPrefixes(uri, qName, attrs);
@@ -433,10 +429,9 @@
if (scriptlessBodyNode == null
&&
bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)) {
scriptlessBodyNode = node;
- } else if (TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType))
{
+ }
+ else if (TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType))
{
tagDependentPending = true;
- } else if (TagInfo.BODY_CONTENT_EMPTY.equals(bodyType)) {
- tagEmptyBody = node;
}
}
}
@@ -460,9 +455,7 @@
*
* @throws SAXException
*/
- public void characters(char[] buf, int offset, int len)
- throws SAXException {
- checkEmptyBody();
+ public void characters(char[] buf, int offset, int len) {
if (charBuffer == null) {
charBuffer = new StringBuilder();
}
@@ -620,10 +613,6 @@
public void endElement(String uri, String localName, String qName)
throws SAXException {
- if (tagEmptyBody != null) {
- tagEmptyBody = null;
- }
-
processChars();
if (directivesOnly &&
@@ -675,6 +664,23 @@
scriptlessBodyNode = null;
}
+ if (current instanceof Node.CustomTag) {
+ String bodyType = getBodyType((Node.CustomTag) current);
+ if (TagInfo.BODY_CONTENT_EMPTY.equalsIgnoreCase(bodyType)) {
+ // Children - if any - must be JSP attributes
+ Node.Nodes children = current.getBody();
+ if (children != null && children.size() > 0) {
+ for (int i = 0; i < children.size(); i++) {
+ Node child = children.getNode(i);
+ if (!(child instanceof Node.NamedAttribute)) {
+ throw new SAXParseException(Localizer.getMessage(
+ "jasper.error.emptybodycontent.nonempty",
+ current.qName), locator);
+ }
+ }
+ }
+ }
+ }
if (current.getParent() != null) {
current = current.getParent();
}
@@ -713,7 +719,6 @@
*/
public void startCDATA() throws SAXException {
- checkEmptyBody();
processChars(); // Flush char buffer and remove white spaces
startMark = new Mark(ctxt, path, locator.getLineNumber(),
locator.getColumnNumber());
@@ -1400,14 +1405,6 @@
return "";
}
- private void checkEmptyBody() throws SAXException {
- if (tagEmptyBody != null) {
- throw new SAXParseException(Localizer.getMessage(
- "jasper.error.emptybodycontent.nonempty",
- tagEmptyBody.qName), locator);
- }
- }
-
/*
* Gets SAXParser.
*
Modified: trunk/java/org/apache/jasper/compiler/Parser.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Parser.java 2010-03-25 17:17:13 UTC (rev 1420)
+++ trunk/java/org/apache/jasper/compiler/Parser.java 2010-03-25 17:19:10 UTC (rev 1421)
@@ -1455,9 +1455,11 @@
err.jspError(reader.mark(), "jsp.error.no.scriptlets");
} else if (reader.matches("<jsp:text")) {
parseXMLTemplateText(parent);
- } else if (reader.matches("${")) {
+ } else if (!pageInfo.isELIgnored() && reader.matches("${")) {
parseELExpression(parent, '$');
- } else if (reader.matches("#{")) {
+ } else if (!pageInfo.isELIgnored()
+ && !pageInfo.isDeferredSyntaxAllowedAsLiteral()
+ && reader.matches("#{")) {
parseELExpression(parent, '#');
} else if (reader.matches("<jsp:")) {
parseStandardAction(parent);
@@ -1506,10 +1508,12 @@
} else if (reader.matches("<jsp:text")) {
err.jspError(reader.mark(), "jsp.error.not.in.template",
"<jsp:text");
- } else if (reader.matches("${")) {
+ } else if (!pageInfo.isELIgnored() && reader.matches("${")) {
err.jspError(reader.mark(), "jsp.error.not.in.template",
"Expression language");
- } else if (reader.matches("#{")) {
+ } else if (!pageInfo.isELIgnored()
+ && !pageInfo.isDeferredSyntaxAllowedAsLiteral()
+ && reader.matches("#{")) {
err.jspError(reader.mark(), "jsp.error.not.in.template",
"Expression language");
} else if (reader.matches("<jsp:")) {
Modified: trunk/java/org/apache/jasper/compiler/Validator.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Validator.java 2010-03-25 17:17:13 UTC (rev
1420)
+++ trunk/java/org/apache/jasper/compiler/Validator.java 2010-03-25 17:19:10 UTC (rev
1421)
@@ -415,8 +415,6 @@
private ErrorDispatcher err;
- private TagInfo tagInfo;
-
private ClassLoader loader;
private final StringBuilder buf = new StringBuilder(32);
@@ -504,7 +502,6 @@
ValidateVisitor(Compiler compiler) {
this.pageInfo = compiler.getPageInfo();
this.err = compiler.getErrorDispatcher();
- this.tagInfo = compiler.getCompilationContext().getTagInfo();
this.loader = compiler.getCompilationContext().getClassLoader();
}
@@ -717,10 +714,7 @@
// JSP.2.2 - '#{' not allowed in template text
if (n.getType() == '#') {
- if (!pageInfo.isDeferredSyntaxAllowedAsLiteral()
- && (tagInfo == null
- || ((tagInfo != null) &&
!(tagInfo.getTagLibrary().getRequiredVersion().equals("2.0")
- ||
tagInfo.getTagLibrary().getRequiredVersion().equals("1.2"))))) {
+ if (!pageInfo.isDeferredSyntaxAllowedAsLiteral()) {
err.jspError(n, "jsp.error.el.template.deferred");
} else {
return;
@@ -731,7 +725,8 @@
StringBuilder expr = this.getBuffer();
expr.append(n.getType()).append('{').append(n.getText())
.append('}');
- ELNode.Nodes el = ELParser.parse(expr.toString());
+ ELNode.Nodes el = ELParser.parse(expr.toString(), pageInfo
+ .isDeferredSyntaxAllowedAsLiteral());
// validate/prepare expression
prepareExpression(el, n, expr.toString());
@@ -1062,10 +1057,6 @@
TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
Attributes attrs = n.getAttributes();
- boolean checkDeferred = !pageInfo.isDeferredSyntaxAllowedAsLiteral()
- &&
!(tagInfo.getTagLibrary().getRequiredVersion().equals("2.0")
- ||
tagInfo.getTagLibrary().getRequiredVersion().equals("1.2"));
-
for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
boolean found = false;
@@ -1073,30 +1064,39 @@
|| (!n.getRoot().isXmlSyntax() &&
attrs.getValue(i).startsWith("<%=")));
boolean elExpression = false;
boolean deferred = false;
- boolean deferredValueIsLiteral = false;
+ double libraryVersion = Double.parseDouble(
+ tagInfo.getTagLibrary().getRequiredVersion());
+ boolean deferredSyntaxAllowedAsLiteral =
+ pageInfo.isDeferredSyntaxAllowedAsLiteral() ||
+ libraryVersion < 2.1;
ELNode.Nodes el = null;
- if (!runtimeExpression) {
- el = ELParser.parse(attrs.getValue(i));
+ if (!runtimeExpression && !pageInfo.isELIgnored()) {
+ el = ELParser.parse(attrs.getValue(i),
+ deferredSyntaxAllowedAsLiteral);
Iterator<ELNode> nodes = el.iterator();
while (nodes.hasNext()) {
ELNode node = nodes.next();
if (node instanceof ELNode.Root) {
if (((ELNode.Root) node).getType() == '$') {
+ if (elExpression && deferred) {
+ err.jspError(n,
+
"jsp.error.attribute.deferredmix");
+ }
elExpression = true;
- } else if (checkDeferred && ((ELNode.Root)
node).getType() == '#') {
+ } else if (((ELNode.Root) node).getType() == '#') {
+ if (elExpression && !deferred) {
+ err.jspError(n,
+
"jsp.error.attribute.deferredmix");
+ }
elExpression = true;
deferred = true;
- if (pageInfo.isELIgnored()) {
- deferredValueIsLiteral = true;
- }
}
}
}
}
- boolean expression = runtimeExpression
- || (elExpression && (!pageInfo.isELIgnored() ||
(!"true".equalsIgnoreCase(pageInfo.getIsELIgnored()) && checkDeferred
&& deferred)));
+ boolean expression = runtimeExpression || elExpression;
for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++)
{
if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
@@ -1104,23 +1104,20 @@
|| attrs.getURI(i).length() == 0 || attrs
.getURI(i).equals(n.getURI()))) {
- if (tldAttrs[j].canBeRequestTime()
- || tldAttrs[j].isDeferredMethod() ||
tldAttrs[j].isDeferredValue()) { // JSP 2.1
+ TagAttributeInfo tldAttr = tldAttrs[j];
+ if (tldAttr.canBeRequestTime()
+ || tldAttr.isDeferredMethod() ||
tldAttr.isDeferredValue()) { // JSP 2.1
if (!expression) {
- if (deferredValueIsLiteral &&
!pageInfo.isDeferredSyntaxAllowedAsLiteral()) {
- err.jspError(n,
"jsp.error.attribute.custom.non_rt_with_expr",
- tldAttrs[j].getName());
- }
-
String expectedType = null;
- if (tldAttrs[j].isDeferredMethod()) {
+ if (tldAttr.isDeferredMethod()) {
// The String litteral must be castable to what is
declared as type
// for the attribute
- String m = tldAttrs[j].getMethodSignature();
+ String m = tldAttr.getMethodSignature();
if (m != null) {
- int rti = m.trim().indexOf(' ');
+ m = m.trim();
+ int rti = m.indexOf(' ');
if (rti > 0) {
expectedType = m.substring(0, rti).trim();
}
@@ -1134,12 +1131,12 @@
// of void - JSP.2.3.4
err.jspError(n,
"jsp.error.literal_with_void",
- tldAttrs[j].getName());
+ tldAttr.getName());
}
- if (tldAttrs[j].isDeferredValue()) {
+ if (tldAttr.isDeferredValue()) {
// The String litteral must be castable to what is
declared as type
// for the attribute
- expectedType = tldAttrs[j].getExpectedTypeName();
+ expectedType = tldAttr.getExpectedTypeName();
}
if (expectedType != null) {
Class expectedClass = String.class;
@@ -1148,7 +1145,7 @@
} catch (ClassNotFoundException e) {
err.jspError
(n,
"jsp.error.unknown_attribute_type",
- tldAttrs[j].getName(), expectedType);
+ tldAttr.getName(), expectedType);
}
// Check casting
try {
@@ -1156,25 +1153,25 @@
} catch (Exception e) {
err.jspError
(n, "jsp.error.coerce_to_type",
- tldAttrs[j].getName(), expectedType,
attrs.getValue(i));
+ tldAttr.getName(), expectedType,
attrs.getValue(i));
}
}
- jspAttrs[i] = new Node.JspAttribute(tldAttrs[j],
+ jspAttrs[i] = new Node.JspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i), attrs
.getLocalName(i),
attrs.getValue(i), false, null, false);
} else {
- if (deferred && !tldAttrs[j].isDeferredMethod()
&& !tldAttrs[j].isDeferredValue()) {
+ if (deferred && !tldAttr.isDeferredMethod()
&& !tldAttr.isDeferredValue()) {
// No deferred expressions allowed for this
attribute
err.jspError(n,
"jsp.error.attribute.custom.non_rt_with_expr",
- tldAttrs[j].getName());
+ tldAttr.getName());
}
- if (!deferred && !tldAttrs[j].canBeRequestTime())
{
+ if (!deferred && !tldAttr.canBeRequestTime()) {
// Only deferred expressions are allowed for this
attribute
err.jspError(n,
"jsp.error.attribute.custom.non_rt_with_expr",
- tldAttrs[j].getName());
+ tldAttr.getName());
}
Class expectedType = String.class;
@@ -1189,7 +1186,7 @@
if (elExpression) {
// El expression
validateFunctions(el, n);
- jspAttrs[i] = new Node.JspAttribute(tldAttrs[j],
+ jspAttrs[i] = new Node.JspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i),
attrs.getLocalName(i),
attrs.getValue(i), false, el, false);
@@ -1204,7 +1201,7 @@
}
} else {
// Runtime expression
- jspAttrs[i] = getJspAttribute(tldAttrs[j],
+ jspAttrs[i] = getJspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i),
attrs.getLocalName(i), attrs
.getValue(i), expectedType, n,
@@ -1222,9 +1219,9 @@
// Make sure its value does not contain any.
if (expression) {
err.jspError(n,
"jsp.error.attribute.custom.non_rt_with_expr",
- tldAttrs[j].getName());
+ tldAttr.getName());
}
- jspAttrs[i] = new Node.JspAttribute(tldAttrs[j],
+ jspAttrs[i] = new Node.JspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i), attrs
.getLocalName(i),
attrs.getValue(i), false, null, false);
@@ -1345,6 +1342,9 @@
result = new Node.JspAttribute(tai, qName, uri, localName,
value.substring(3, value.length() - 2), true, null,
dynamic);
+ } else if (pageInfo.isELIgnored()) {
+ result = new Node.JspAttribute(tai, qName, uri, localName,
+ value, false, null, dynamic);
} else {
// The attribute can contain expressions but is not a
// scriptlet expression; thus, we want to run it through
@@ -1352,22 +1352,10 @@
// validate expression syntax if string contains
// expression(s)
- ELNode.Nodes el = ELParser.parse(value);
-
- boolean deferred = false;
- Iterator<ELNode> nodes = el.iterator();
- while (nodes.hasNext()) {
- ELNode node = nodes.next();
- if (node instanceof ELNode.Root) {
- if (((ELNode.Root) node).getType() == '#') {
- deferred = true;
- }
- }
- }
+ ELNode.Nodes el = ELParser.parse(value, pageInfo
+ .isDeferredSyntaxAllowedAsLiteral());
- if (el.containsEL() && !pageInfo.isELIgnored()
- && ((!pageInfo.isDeferredSyntaxAllowedAsLiteral()
&& deferred)
- || !deferred)) {
+ if (el.containsEL()) {
validateFunctions(el, n);
@@ -1426,7 +1414,8 @@
boolean elExpression = false;
if (!runtimeExpression && !pageInfo.isELIgnored()) {
- Iterator<ELNode> nodes = ELParser.parse(value).iterator();
+ Iterator<ELNode> nodes = ELParser.parse(value,
+ pageInfo.isDeferredSyntaxAllowedAsLiteral()).iterator();
while (nodes.hasNext()) {
ELNode node = nodes.next();
if (node instanceof ELNode.Root) {
Modified: trunk/java/org/apache/jasper/resources/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/jasper/resources/LocalStrings.properties 2010-03-25 17:17:13 UTC
(rev 1420)
+++ trunk/java/org/apache/jasper/resources/LocalStrings.properties 2010-03-25 17:19:10 UTC
(rev 1421)
@@ -355,6 +355,7 @@
jsp.error.prolog_config_encoding_mismatch=Page-encoding specified in XML prolog ({0}) is
different from that specified in jsp-property-group ({1})
jsp.error.attribute.custom.non_rt_with_expr=According to TLD or attribute directive in
tag file, attribute {0} does not accept any expressions
jsp.error.attribute.standard.non_rt_with_expr=The {0} attribute of the {1} standard
action does not accept any expressions
+jsp.error.attribute.deferredmix=Cannot use both ${} and #{} EL expressions in the same
attribute value
jsp.error.scripting.variable.missing_name=Unable to determine scripting variable name
from attribute {0}
jasper.error.emptybodycontent.nonempty=According to TLD, tag {0} must be empty, but is
not
jsp.error.tagfile.nameNotUnique=The value of {0} and the value of {1} in line {2} are the
same.
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2010-03-25 17:17:13 UTC (rev 1420)
+++ trunk/webapps/docs/changelog.xml 2010-03-25 17:19:10 UTC (rev 1421)
@@ -23,6 +23,9 @@
</subsection>
<subsection name="Coyote">
<changelog>
+ <fix>
+ Add back SSL renegotiation as an option. (mturk)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
@@ -30,6 +33,13 @@
<fix>
<bug>48616</bug>: Additional variable declaration fixes. (kkolinko)
</fix>
+ <fix>
+ <bug>48827</bug>: Parser regression. (markt)
+ </fix>
+ <fix>
+ <bug>48668</bug>: Honor isELIgnored and isDeferredSyntaxAllowed in
the Parser.
+ ELParser is now aware of the isDeferredAsLiteral option. (kkolinko)
+ </fix>
</changelog>
</subsection>
</section>