1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.compiler;
19
20 import org.apache.struts2.jasper.JasperException;
21 import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
22 import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
23 import org.apache.struts2.jasper.xmlparser.ParserUtils;
24 import org.apache.struts2.jasper.xmlparser.TreeNode;
25
26 import javax.servlet.ServletContext;
27 import java.io.InputStream;
28 import java.util.HashMap;
29 import java.util.Iterator;
30
31 /***
32 * Manages tag plugin optimizations.
33 *
34 * @author Kin-man Chung
35 */
36
37 public class TagPluginManager {
38
39 private static final String TAG_PLUGINS_XML = "/WEB-INF/tagPlugins.xml";
40 private static final String TAG_PLUGINS_ROOT_ELEM = "tag-plugins";
41
42 private boolean initialized = false;
43 private HashMap tagPlugins = null;
44 private ServletContext ctxt;
45 private PageInfo pageInfo;
46
47 public TagPluginManager(ServletContext ctxt) {
48 this.ctxt = ctxt;
49 }
50
51 public void apply(Node.Nodes page, ErrorDispatcher err, PageInfo pageInfo)
52 throws JasperException {
53
54 init(err);
55 if (tagPlugins == null || tagPlugins.size() == 0) {
56 return;
57 }
58
59 this.pageInfo = pageInfo;
60
61 page.visit(new Node.Visitor() {
62 public void visit(Node.CustomTag n)
63 throws JasperException {
64 invokePlugin(n);
65 visitBody(n);
66 }
67 });
68
69 }
70
71 private void init(ErrorDispatcher err) throws JasperException {
72 if (initialized)
73 return;
74
75 InputStream is = ctxt.getResourceAsStream(TAG_PLUGINS_XML);
76 if (is == null)
77 return;
78
79 TreeNode root = (new ParserUtils()).parseXMLDocument(TAG_PLUGINS_XML,
80 is);
81 if (root == null) {
82 return;
83 }
84
85 if (!TAG_PLUGINS_ROOT_ELEM.equals(root.getName())) {
86 err.jspError("jsp.error.plugin.wrongRootElement", TAG_PLUGINS_XML,
87 TAG_PLUGINS_ROOT_ELEM);
88 }
89
90 tagPlugins = new HashMap();
91 Iterator pluginList = root.findChildren("tag-plugin");
92 while (pluginList.hasNext()) {
93 TreeNode pluginNode = (TreeNode) pluginList.next();
94 TreeNode tagClassNode = pluginNode.findChild("tag-class");
95 if (tagClassNode == null) {
96
97 return;
98 }
99 String tagClass = tagClassNode.getBody().trim();
100 TreeNode pluginClassNode = pluginNode.findChild("plugin-class");
101 if (pluginClassNode == null) {
102
103 return;
104 }
105
106 String pluginClassStr = pluginClassNode.getBody();
107 TagPlugin tagPlugin = null;
108 try {
109 Class pluginClass = Class.forName(pluginClassStr);
110 tagPlugin = (TagPlugin) pluginClass.newInstance();
111 } catch (Exception e) {
112 throw new JasperException(e);
113 }
114 if (tagPlugin == null) {
115 return;
116 }
117 tagPlugins.put(tagClass, tagPlugin);
118 }
119 initialized = true;
120 }
121
122 /***
123 * Invoke tag plugin for the given custom tag, if a plugin exists for
124 * the custom tag's tag handler.
125 * <p/>
126 * The given custom tag node will be manipulated by the plugin.
127 */
128 private void invokePlugin(Node.CustomTag n) {
129 TagPlugin tagPlugin = (TagPlugin)
130 tagPlugins.get(n.getTagHandlerClass().getName());
131 if (tagPlugin == null) {
132 return;
133 }
134
135 TagPluginContext tagPluginContext = new TagPluginContextImpl(n, pageInfo);
136 n.setTagPluginContext(tagPluginContext);
137 tagPlugin.doTag(tagPluginContext);
138 }
139
140 static class TagPluginContextImpl implements TagPluginContext {
141 private Node.CustomTag node;
142 private Node.Nodes curNodes;
143 private PageInfo pageInfo;
144 private HashMap pluginAttributes;
145
146 TagPluginContextImpl(Node.CustomTag n, PageInfo pageInfo) {
147 this.node = n;
148 this.pageInfo = pageInfo;
149 curNodes = new Node.Nodes();
150 n.setAtETag(curNodes);
151 curNodes = new Node.Nodes();
152 n.setAtSTag(curNodes);
153 n.setUseTagPlugin(true);
154 pluginAttributes = new HashMap();
155 }
156
157 public TagPluginContext getParentContext() {
158 Node parent = node.getParent();
159 if (!(parent instanceof Node.CustomTag)) {
160 return null;
161 }
162 return ((Node.CustomTag) parent).getTagPluginContext();
163 }
164
165 public void setPluginAttribute(String key, Object value) {
166 pluginAttributes.put(key, value);
167 }
168
169 public Object getPluginAttribute(String key) {
170 return pluginAttributes.get(key);
171 }
172
173 public boolean isScriptless() {
174 return node.getChildInfo().isScriptless();
175 }
176
177 public boolean isConstantAttribute(String attribute) {
178 Node.JspAttribute attr = getNodeAttribute(attribute);
179 if (attr == null)
180 return false;
181 return attr.isLiteral();
182 }
183
184 public String getConstantAttribute(String attribute) {
185 Node.JspAttribute attr = getNodeAttribute(attribute);
186 if (attr == null)
187 return null;
188 return attr.getValue();
189 }
190
191 public boolean isAttributeSpecified(String attribute) {
192 return getNodeAttribute(attribute) != null;
193 }
194
195 public String getTemporaryVariableName() {
196 return JspUtil.nextTemporaryVariableName();
197 }
198
199 public void generateImport(String imp) {
200 pageInfo.addImport(imp);
201 }
202
203 public void generateDeclaration(String id, String text) {
204 if (pageInfo.isPluginDeclared(id)) {
205 return;
206 }
207 curNodes.add(new Node.Declaration(text, node.getStart(), null));
208 }
209
210 public void generateJavaSource(String sourceCode) {
211 curNodes.add(new Node.Scriptlet(sourceCode, node.getStart(),
212 null));
213 }
214
215 public void generateAttribute(String attributeName) {
216 curNodes.add(new Node.AttributeGenerator(node.getStart(),
217 attributeName,
218 node));
219 }
220
221 public void dontUseTagPlugin() {
222 node.setUseTagPlugin(false);
223 }
224
225 public void generateBody() {
226
227
228
229 curNodes = node.getAtETag();
230 }
231
232 private Node.JspAttribute getNodeAttribute(String attribute) {
233 Node.JspAttribute[] attrs = node.getJspAttributes();
234 for (int i = 0; attrs != null && i < attrs.length; i++) {
235 if (attrs[i].getName().equals(attribute)) {
236 return attrs[i];
237 }
238 }
239 return null;
240 }
241 }
242 }