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]>

Reply via email to