1
17 package org.apache.jasper.compiler;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.security.AccessController;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.servlet.ServletContext;
27
28 import org.apache.jasper.Constants;
29 import org.apache.jasper.JasperException;
30 import org.apache.jasper.compiler.tagplugin.TagPlugin;
31 import org.apache.jasper.compiler.tagplugin.TagPluginContext;
32 import org.apache.tomcat.util.descriptor.tagplugin.TagPluginParser;
33 import org.apache.tomcat.util.security.PrivilegedGetTccl;
34 import org.apache.tomcat.util.security.PrivilegedSetTccl;
35 import org.xml.sax.SAXException;
36
37
42 public class TagPluginManager {
43
44 private static final String META_INF_JASPER_TAG_PLUGINS_XML =
45 "META-INF/org.apache.jasper/tagPlugins.xml";
46 private static final String TAG_PLUGINS_XML = "/WEB-INF/tagPlugins.xml";
47 private final ServletContext ctxt;
48 private HashMap<String, TagPlugin> tagPlugins;
49 private boolean initialized = false;
50
51 public TagPluginManager(ServletContext ctxt) {
52 this.ctxt = ctxt;
53 }
54
55 public void apply(Node.Nodes page, ErrorDispatcher err, PageInfo pageInfo)
56 throws JasperException {
57
58 init(err);
59 if (!tagPlugins.isEmpty()) {
60 page.visit(new NodeVisitor(this, pageInfo));
61 }
62 }
63
64 private void init(ErrorDispatcher err) throws JasperException {
65 if (initialized)
66 return;
67
68 String blockExternalString = ctxt.getInitParameter(
69 Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
70 boolean blockExternal;
71 if (blockExternalString == null) {
72 blockExternal = true;
73 } else {
74 blockExternal = Boolean.parseBoolean(blockExternalString);
75 }
76
77 TagPluginParser parser;
78 ClassLoader original;
79 if (Constants.IS_SECURITY_ENABLED) {
80 PrivilegedGetTccl pa = new PrivilegedGetTccl();
81 original = AccessController.doPrivileged(pa);
82 } else {
83 original = Thread.currentThread().getContextClassLoader();
84 }
85 try {
86 if (Constants.IS_SECURITY_ENABLED) {
87 PrivilegedSetTccl pa =
88 new PrivilegedSetTccl(TagPluginManager.class.getClassLoader());
89 AccessController.doPrivileged(pa);
90 } else {
91 Thread.currentThread().setContextClassLoader(
92 TagPluginManager.class.getClassLoader());
93 }
94
95 parser = new TagPluginParser(ctxt, blockExternal);
96
97 Enumeration<URL> urls =
98 ctxt.getClassLoader().getResources(META_INF_JASPER_TAG_PLUGINS_XML);
99 while (urls.hasMoreElements()) {
100 URL url = urls.nextElement();
101 parser.parse(url);
102 }
103
104 URL url = ctxt.getResource(TAG_PLUGINS_XML);
105 if (url != null) {
106 parser.parse(url);
107 }
108 } catch (IOException | SAXException e) {
109 throw new JasperException(e);
110 } finally {
111 if (Constants.IS_SECURITY_ENABLED) {
112 PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
113 AccessController.doPrivileged(pa);
114 } else {
115 Thread.currentThread().setContextClassLoader(original);
116 }
117 }
118
119 Map<String, String> plugins = parser.getPlugins();
120 tagPlugins = new HashMap<>(plugins.size());
121 for (Map.Entry<String, String> entry : plugins.entrySet()) {
122 try {
123 String tagClass = entry.getKey();
124 String pluginName = entry.getValue();
125 Class<?> pluginClass = ctxt.getClassLoader().loadClass(pluginName);
126 TagPlugin plugin = (TagPlugin) pluginClass.getConstructor().newInstance();
127 tagPlugins.put(tagClass, plugin);
128 } catch (Exception e) {
129 err.jspError(e);
130 }
131 }
132 initialized = true;
133 }
134
135
141 private void invokePlugin(Node.CustomTag n, PageInfo pageInfo) {
142 TagPlugin tagPlugin = tagPlugins.get(n.getTagHandlerClass().getName());
143 if (tagPlugin == null) {
144 return;
145 }
146
147 TagPluginContext tagPluginContext = new TagPluginContextImpl(n, pageInfo);
148 n.setTagPluginContext(tagPluginContext);
149 tagPlugin.doTag(tagPluginContext);
150 }
151
152 private static class NodeVisitor extends Node.Visitor {
153 private final TagPluginManager manager;
154 private final PageInfo pageInfo;
155
156 public NodeVisitor(TagPluginManager manager, PageInfo pageInfo) {
157 this.manager = manager;
158 this.pageInfo = pageInfo;
159 }
160
161 @Override
162 public void visit(Node.CustomTag n) throws JasperException {
163 manager.invokePlugin(n, pageInfo);
164 visitBody(n);
165 }
166 }
167
168 private static class TagPluginContextImpl implements TagPluginContext {
169 private final Node.CustomTag node;
170 private final PageInfo pageInfo;
171 private final HashMap<String, Object> pluginAttributes;
172 private Node.Nodes curNodes;
173
174 TagPluginContextImpl(Node.CustomTag n, PageInfo pageInfo) {
175 this.node = n;
176 this.pageInfo = pageInfo;
177 curNodes = new Node.Nodes();
178 n.setAtETag(curNodes);
179 curNodes = new Node.Nodes();
180 n.setAtSTag(curNodes);
181 n.setUseTagPlugin(true);
182 pluginAttributes = new HashMap<>();
183 }
184
185 @Override
186 public TagPluginContext getParentContext() {
187 Node parent = node.getParent();
188 if (!(parent instanceof Node.CustomTag)) {
189 return null;
190 }
191 return ((Node.CustomTag) parent).getTagPluginContext();
192 }
193
194 @Override
195 public void setPluginAttribute(String key, Object value) {
196 pluginAttributes.put(key, value);
197 }
198
199 @Override
200 public Object getPluginAttribute(String key) {
201 return pluginAttributes.get(key);
202 }
203
204 @Override
205 public boolean isScriptless() {
206 return node.getChildInfo().isScriptless();
207 }
208
209 @Override
210 public boolean isConstantAttribute(String attribute) {
211 Node.JspAttribute attr = getNodeAttribute(attribute);
212 if (attr == null)
213 return false;
214 return attr.isLiteral();
215 }
216
217 @Override
218 public String getConstantAttribute(String attribute) {
219 Node.JspAttribute attr = getNodeAttribute(attribute);
220 if (attr == null)
221 return null;
222 return attr.getValue();
223 }
224
225 @Override
226 public boolean isAttributeSpecified(String attribute) {
227 return getNodeAttribute(attribute) != null;
228 }
229
230 @Override
231 public String getTemporaryVariableName() {
232 return node.getRoot().nextTemporaryVariableName();
233 }
234
235 @Override
236 public void generateImport(String imp) {
237 pageInfo.addImport(imp);
238 }
239
240 @Override
241 public void generateDeclaration(String id, String text) {
242 if (pageInfo.isPluginDeclared(id)) {
243 return;
244 }
245 curNodes.add(new Node.Declaration(text, node.getStart(), null));
246 }
247
248 @Override
249 public void generateJavaSource(String sourceCode) {
250 curNodes.add(new Node.Scriptlet(sourceCode, node.getStart(),
251 null));
252 }
253
254 @Override
255 public void generateAttribute(String attributeName) {
256 curNodes.add(new Node.AttributeGenerator(node.getStart(),
257 attributeName,
258 node));
259 }
260
261 @Override
262 public void dontUseTagPlugin() {
263 node.setUseTagPlugin(false);
264 }
265
266 @Override
267 public void generateBody() {
268
269
270
271 curNodes = node.getAtETag();
272 }
273
274 @Override
275 public boolean isTagFile() {
276 return pageInfo.isTagFile();
277 }
278
279 private Node.JspAttribute getNodeAttribute(String attribute) {
280 Node.JspAttribute[] attrs = node.getJspAttributes();
281 for (int i = 0; attrs != null && i < attrs.length; i++) {
282 if (attrs[i].getName().equals(attribute)) {
283 return attrs[i];
284 }
285 }
286 return null;
287 }
288 }
289
290 }
291
292