Hi Costin, > More info: > > The page is: > > <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> > > <logic:iterate id="id1" name="name1" property="prop1"> > <logic:iterate id="id2" name="name2" property="prop2"> > Foo > </logic:iterate> > </logic:iterate> > > I get: > > a$jsp.java:75:25:75:25: Error: No entity named "id2" was found in this > environment. > > And the generated code is: > ..... > /* ---- logic:iterate ---- */ > java.lang.Object _jspx_id2_1; > _jspx_id2_1 = id2; > org.apache.struts.taglib.logic.IterateTag > _jspx_th_logic_iterate_1 = (org.apache.struts.taglib.logic.IterateTag) > _jspx_tagPool_logic_iterate_property_name_id.get(org.apache.struts.taglib.logic. > IterateTag.class); > > .... > > No 'id2' is ever declared.
I was unable to reproduce the problem where a scripting variable is being declared multiple times. That used to be a bug with Jasper, which we fixed in Jasper2. However, I was able to reproduce the above problem with nested <logic:iterate> tags where 'id2' is never declared. The nested <logic:iterate> did not declare any of its NESTED scripting variables, since it assumed that those had already been declared by the encapsulating <logic:iterate>. This approach did not take into account the case where a tag's TEI determines the name of a scripting variable from the tag's "id" attribute. Attached is a patch that fixes the problem. Kin-Man has volunteered to apply it. I still don't seem to have commit privileges for tomcat. Let me know if you still run into any problems. Thanks, Jan
Executing ssh-askpass to query the password... Warning: Remote host denied X11 forwarding, perhaps xauth program could not be run on the server side. ? build ? build.properties cvs server: Diffing . cvs server: Diffing doc cvs server: Diffing src cvs server: Diffing src/bin cvs server: Diffing src/share cvs server: Diffing src/share/org cvs server: Diffing src/share/org/apache cvs server: Diffing src/share/org/apache/jasper cvs server: Diffing src/share/org/apache/jasper/compiler Index: src/share/org/apache/jasper/compiler/Generator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v retrieving revision 1.30 diff -u -r1.30 Generator.java --- src/share/org/apache/jasper/compiler/Generator.java 13 Jun 2002 22:56:11 -0000 1.30 +++ src/share/org/apache/jasper/compiler/Generator.java 21 Jun 2002 00:20:17 -0000 @@ -1467,14 +1467,21 @@ /* * Declares any NESTED scripting variables of the given custom tag, * if the given custom tag is not nested inside itself (i.e, has a - * nesting level of zero). In addition, a NESTED scripting variable is - * declared only if it has not already been declared in the same scope - * in the generated code, that is, if this custom tag's parent is + * nesting level of zero). If the custom tag does have a custom nesting + * level greater than 0, this method declares a scripting variable + * derived from the tag's "id" attribute (if present), only if its + * scope is NESTED and it does not match the "id" attribute of any of + * the enclosing tags of the same (custom) type. + * + * Additionally, a NESTED scripting variable is declared only if it + * has not already been declared in the same Java + * scope of the generated code, that is, if this custom tag's parent is * different from the parent of the custom tag that may already have * declared this variable. */ private void declareNestedScriptingVariables(Node.CustomTag n) { - if (n.getCustomNestingLevel() > 0) { + + if (n.getCustomNestingLevel() > 0 && !n.hasUnnestedIdAttribute()) { return; } @@ -1485,17 +1492,42 @@ } if (varInfos != null) { - for (int i=0; i<varInfos.length; i++) { - if ((varInfos[i].getScope() == VariableInfo.NESTED) - && varInfos[i].getDeclare()) { - String name = varInfos[i].getVarName(); - Node parent = (Node) nestedVars.get(name); - if ((parent == null) || (parent != n.getParent())) { - out.printin(varInfos[i].getClassName()); - out.print(" "); - out.print(name); - out.println(";"); - nestedVars.put(name, n.getParent()); + if (n.getCustomNestingLevel() == 0) { + // Declare *any* scripting variables with NESTED scope + for (int i=0; i<varInfos.length; i++) { + if ((varInfos[i].getScope() == VariableInfo.NESTED) + && varInfos[i].getDeclare()) { + String name = varInfos[i].getVarName(); + Node parent = (Node) nestedVars.get(name); + if (parent == null || parent != n.getParent()) { + out.printin(varInfos[i].getClassName()); + out.print(" "); + out.print(name); + out.println(";"); + nestedVars.put(name, n.getParent()); + } + } + } + } else { + /* + * Declare only scripting variable (with NESTED scope) + * derived from unnested "id" attribute + */ + String idAttr = n.getAttributeValue("id"); + for (int i=0; i<varInfos.length; i++) { + if ((varInfos[i].getScope() == VariableInfo.NESTED) + && varInfos[i].getDeclare()) { + String name = varInfos[i].getVarName(); + Node parent = (Node) nestedVars.get(name); + if ((parent == null || parent != n.getParent()) + && idAttr.equals(name)) { + out.printin(varInfos[i].getClassName()); + out.print(" "); + out.print(name); + out.println(" = null;"); + nestedVars.put(name, n.getParent()); + break; + } } } } @@ -1518,14 +1550,16 @@ } } } - } + } } /* - * For every scripting variable exposed by this custom tag, declares - * a variable where the current value of the scripting variable may - * be saved, so it can later be restored in this custom tag's end - * element. + * This method is called as part of the custom tag's start element. + * + * If the given custom tag has a custom nesting level greater than 0, + * declare temporary variables where the current values of the tag's + * scripting variables may be saved, so these values may be restored + * in the tag's end element. */ private void declareTemporaryScriptingVariables(Node.CustomTag n) { if (n.getCustomNestingLevel() == 0) { @@ -1573,12 +1607,13 @@ } /* - * For each scripting variable of a custom tag with a nesting level - * greater than 0, save its value to a temporary variable so that the - * scripting variable can be synchronized inside the nested custom tag - * without affecting the value it had at the start element of the - * custom tag, which will be restored when the end element of the - * custom tag is reached. + * This method is called as part of the custom tag's start element. + * + * If the given custom tag has a custom nesting level greater than 0, + * save the values of all its scripting variables to temporary + * variables, so the scripting variables may be synchronized + * without affecting the values they had at the tag's start element. + * Those values will be restored when the tag's end element is reached. */ private void saveScriptingVariables(Node.CustomTag n) { if (n.getCustomNestingLevel() == 0) { @@ -1619,9 +1654,11 @@ } /* - * For each scripting variable of a custom tag with a nesting level - * greater than 0, restore its original value that was saved in the - * start element of the custom tag. + * This method is called as part of the custom tag's end element. + * + * If the given custom tag has a custom nesting level greater than 0, + * restore its scripting variables to their original values that were + * saved in the tag's start element. */ private void restoreScriptingVariables(Node.CustomTag n) { if (n.getCustomNestingLevel() == 0) { Index: src/share/org/apache/jasper/compiler/Node.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Node.java,v retrieving revision 1.14 diff -u -r1.14 Node.java --- src/share/org/apache/jasper/compiler/Node.java 13 Jun 2002 22:56:11 -0000 1.14 +++ src/share/org/apache/jasper/compiler/Node.java 21 Jun 2002 00:20:18 -0000 @@ -673,7 +673,8 @@ private String tagHandlerPoolName; private TagInfo tagInfo; private VariableInfo[] varInfos; - private int nestingLevel; + private int customNestingLevel; + private boolean hasUnnestedIdAttribute; public CustomTag(Attributes attrs, Mark start, String name, String prefix, String shortName, @@ -683,7 +684,8 @@ this.prefix = prefix; this.shortName = shortName; this.tagInfo = tagInfo; - this.nestingLevel = computeCustomNestingLevel(); + this.customNestingLevel = computeCustomNestingLevel(); + this.hasUnnestedIdAttribute = determineHasUnnestedIdAttribute(); } public void accept(Visitor v) throws JasperException { @@ -789,15 +791,25 @@ } /* - * Gets this custom tag's nesting level. + * Returns true if this custom tag has an "id" attribute that does + * not match the "id" attribute of any of its enclosing parent tags of + * the same custom tag type, and false otherwise. + */ + public boolean hasUnnestedIdAttribute() { + return hasUnnestedIdAttribute; + } + + /* + * Gets this custom tag's custom nesting level, which is given as + * the number of times this custom tag is nested inside itself. */ public int getCustomNestingLevel() { - return nestingLevel; + return customNestingLevel; } /* - * Computes this custom tag's nesting level, which corresponds to the - * number of times this custom tag is nested inside itself. + * Computes this custom tag's custom nesting level, which corresponds + * to the number of times this custom tag is nested inside itself. * * Example: * @@ -829,6 +841,38 @@ p = p.parent; } return n; + } + + /* + * Checks to see if this custom tag has an "id" attribute that does + * not match the "id" attribute of any of its enclosing parent tags of + * the same custom tag type. + */ + private boolean determineHasUnnestedIdAttribute() { + boolean unnested = false; + + String id = getAttributeValue("id"); + if (id != null) { + if (customNestingLevel == 0) { + // tag not nested inside itself + unnested = true; + } else { + Node p = parent; + while (p != null) { + if ((p instanceof Node.CustomTag) + && name.equals(((Node.CustomTag) p).name) + && id.equals(p.getAttributeValue("id"))) { + break; + } + p = p.parent; + } + if (p == null) { + unnested = true; + } + } + } + + return unnested; } } cvs server: Diffing src/share/org/apache/jasper/core cvs server: Diffing src/share/org/apache/jasper/logging cvs server: Diffing src/share/org/apache/jasper/resources cvs server: Diffing src/share/org/apache/jasper/runtime cvs server: Diffing src/share/org/apache/jasper/servlet cvs server: Diffing src/share/org/apache/jasper/util cvs server: Diffing src/share/org/apache/jasper/xmlparser
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>