View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.struts2.jasper.compiler;
19  
20  import org.apache.struts2.jasper.JasperException;
21  
22  import javax.servlet.jsp.tagext.TagVariableInfo;
23  import javax.servlet.jsp.tagext.VariableInfo;
24  import java.util.Hashtable;
25  import java.util.Vector;
26  
27  /***
28   * Class responsible for determining the scripting variables that every
29   * custom action needs to declare.
30   *
31   * @author Jan Luehe
32   */
33  class ScriptingVariabler {
34  
35      private static final Integer MAX_SCOPE = new Integer(Integer.MAX_VALUE);
36  
37      /*
38       * Assigns an identifier (of type integer) to every custom tag, in order
39       * to help identify, for every custom tag, the scripting variables that it
40       * needs to declare.
41       */
42      static class CustomTagCounter extends Node.Visitor {
43  
44          private int count;
45          private Node.CustomTag parent;
46  
47          public void visit(Node.CustomTag n) throws JasperException {
48              n.setCustomTagParent(parent);
49              Node.CustomTag tmpParent = parent;
50              parent = n;
51              visitBody(n);
52              parent = tmpParent;
53              n.setNumCount(new Integer(count++));
54          }
55      }
56  
57      /*
58       * For every custom tag, determines the scripting variables it needs to
59       * declare. 
60       */
61      static class ScriptingVariableVisitor extends Node.Visitor {
62  
63          private ErrorDispatcher err;
64          private Hashtable scriptVars;
65  
66          public ScriptingVariableVisitor(ErrorDispatcher err) {
67              this.err = err;
68              scriptVars = new Hashtable();
69          }
70  
71          public void visit(Node.CustomTag n) throws JasperException {
72              setScriptingVars(n, VariableInfo.AT_BEGIN);
73              setScriptingVars(n, VariableInfo.NESTED);
74              visitBody(n);
75              setScriptingVars(n, VariableInfo.AT_END);
76          }
77  
78          private void setScriptingVars(Node.CustomTag n, int scope)
79                  throws JasperException {
80  
81              TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
82              VariableInfo[] varInfos = n.getVariableInfos();
83              if (tagVarInfos.length == 0 && varInfos.length == 0) {
84                  return;
85              }
86  
87              Vector vec = new Vector();
88  
89              Integer ownRange = null;
90              if (scope == VariableInfo.AT_BEGIN
91                      || scope == VariableInfo.AT_END) {
92                  Node.CustomTag parent = n.getCustomTagParent();
93                  if (parent == null)
94                      ownRange = MAX_SCOPE;
95                  else
96                      ownRange = parent.getNumCount();
97              } else {
98                  // NESTED
99                  ownRange = n.getNumCount();
100             }
101 
102             if (varInfos.length > 0) {
103                 for (int i = 0; i < varInfos.length; i++) {
104                     if (varInfos[i].getScope() != scope
105                             || !varInfos[i].getDeclare()) {
106                         continue;
107                     }
108                     String varName = varInfos[i].getVarName();
109 
110                     Integer currentRange = (Integer) scriptVars.get(varName);
111                     if (currentRange == null
112                             || ownRange.compareTo(currentRange) > 0) {
113                         scriptVars.put(varName, ownRange);
114                         vec.add(varInfos[i]);
115                     }
116                 }
117             } else {
118                 for (int i = 0; i < tagVarInfos.length; i++) {
119                     if (tagVarInfos[i].getScope() != scope
120                             || !tagVarInfos[i].getDeclare()) {
121                         continue;
122                     }
123                     String varName = tagVarInfos[i].getNameGiven();
124                     if (varName == null) {
125                         varName = n.getTagData().getAttributeString(
126                                 tagVarInfos[i].getNameFromAttribute());
127                         if (varName == null) {
128                             err.jspError(n, "jsp.error.scripting.variable.missing_name",
129                                     tagVarInfos[i].getNameFromAttribute());
130                         }
131                     }
132 
133                     Integer currentRange = (Integer) scriptVars.get(varName);
134                     if (currentRange == null
135                             || ownRange.compareTo(currentRange) > 0) {
136                         scriptVars.put(varName, ownRange);
137                         vec.add(tagVarInfos[i]);
138                     }
139                 }
140             }
141 
142             n.setScriptingVars(vec, scope);
143         }
144     }
145 
146     public static void set(Node.Nodes page, ErrorDispatcher err)
147             throws JasperException {
148         page.visit(new CustomTagCounter());
149         page.visit(new ScriptingVariableVisitor(err));
150     }
151 }