001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.compiler;
019:
020: import java.util.*;
021: import java.io.*;
022: import javax.servlet.ServletContext;
023:
024: import org.apache.jasper.JasperException;
025: import org.apache.jasper.xmlparser.ParserUtils;
026: import org.apache.jasper.xmlparser.TreeNode;
027: import org.apache.jasper.compiler.tagplugin.TagPlugin;
028: import org.apache.jasper.compiler.tagplugin.TagPluginContext;
029:
030: /**
031: * Manages tag plugin optimizations.
032: * @author Kin-man Chung
033: */
034:
035: public class TagPluginManager {
036:
037: private static final String TAG_PLUGINS_XML = "/WEB-INF/tagPlugins.xml";
038: private static final String TAG_PLUGINS_ROOT_ELEM = "tag-plugins";
039:
040: private boolean initialized = false;
041: private HashMap tagPlugins = null;
042: private ServletContext ctxt;
043: private PageInfo pageInfo;
044:
045: public TagPluginManager(ServletContext ctxt) {
046: this .ctxt = ctxt;
047: }
048:
049: public void apply(Node.Nodes page, ErrorDispatcher err,
050: PageInfo pageInfo) throws JasperException {
051:
052: init(err);
053: if (tagPlugins == null || tagPlugins.size() == 0) {
054: return;
055: }
056:
057: this .pageInfo = pageInfo;
058:
059: page.visit(new Node.Visitor() {
060: public void visit(Node.CustomTag n) throws JasperException {
061: invokePlugin(n);
062: visitBody(n);
063: }
064: });
065:
066: }
067:
068: private void init(ErrorDispatcher err) throws JasperException {
069: if (initialized)
070: return;
071:
072: InputStream is = ctxt.getResourceAsStream(TAG_PLUGINS_XML);
073: if (is == null)
074: return;
075:
076: TreeNode root = (new ParserUtils()).parseXMLDocument(
077: TAG_PLUGINS_XML, is);
078: if (root == null) {
079: return;
080: }
081:
082: if (!TAG_PLUGINS_ROOT_ELEM.equals(root.getName())) {
083: err.jspError("jsp.error.plugin.wrongRootElement",
084: TAG_PLUGINS_XML, TAG_PLUGINS_ROOT_ELEM);
085: }
086:
087: tagPlugins = new HashMap();
088: Iterator pluginList = root.findChildren("tag-plugin");
089: while (pluginList.hasNext()) {
090: TreeNode pluginNode = (TreeNode) pluginList.next();
091: TreeNode tagClassNode = pluginNode.findChild("tag-class");
092: if (tagClassNode == null) {
093: // Error
094: return;
095: }
096: String tagClass = tagClassNode.getBody().trim();
097: TreeNode pluginClassNode = pluginNode
098: .findChild("plugin-class");
099: if (pluginClassNode == null) {
100: // Error
101: return;
102: }
103:
104: String pluginClassStr = pluginClassNode.getBody();
105: TagPlugin tagPlugin = null;
106: try {
107: Class pluginClass = Class.forName(pluginClassStr);
108: tagPlugin = (TagPlugin) pluginClass.newInstance();
109: } catch (Exception e) {
110: throw new JasperException(e);
111: }
112: if (tagPlugin == null) {
113: return;
114: }
115: tagPlugins.put(tagClass, tagPlugin);
116: }
117: initialized = true;
118: }
119:
120: /**
121: * Invoke tag plugin for the given custom tag, if a plugin exists for
122: * the custom tag's tag handler.
123: *
124: * The given custom tag node will be manipulated by the plugin.
125: */
126: private void invokePlugin(Node.CustomTag n) {
127: TagPlugin tagPlugin = (TagPlugin) tagPlugins.get(n
128: .getTagHandlerClass().getName());
129: if (tagPlugin == null) {
130: return;
131: }
132:
133: TagPluginContext tagPluginContext = new TagPluginContextImpl(n,
134: pageInfo);
135: n.setTagPluginContext(tagPluginContext);
136: tagPlugin.doTag(tagPluginContext);
137: }
138:
139: static class TagPluginContextImpl implements TagPluginContext {
140: private Node.CustomTag node;
141: private Node.Nodes curNodes;
142: private PageInfo pageInfo;
143: private HashMap pluginAttributes;
144:
145: TagPluginContextImpl(Node.CustomTag n, PageInfo pageInfo) {
146: this .node = n;
147: this .pageInfo = pageInfo;
148: curNodes = new Node.Nodes();
149: n.setAtETag(curNodes);
150: curNodes = new Node.Nodes();
151: n.setAtSTag(curNodes);
152: n.setUseTagPlugin(true);
153: pluginAttributes = new HashMap();
154: }
155:
156: public TagPluginContext getParentContext() {
157: Node parent = node.getParent();
158: if (!(parent instanceof Node.CustomTag)) {
159: return null;
160: }
161: return ((Node.CustomTag) parent).getTagPluginContext();
162: }
163:
164: public void setPluginAttribute(String key, Object value) {
165: pluginAttributes.put(key, value);
166: }
167:
168: public Object getPluginAttribute(String key) {
169: return pluginAttributes.get(key);
170: }
171:
172: public boolean isScriptless() {
173: return node.getChildInfo().isScriptless();
174: }
175:
176: public boolean isConstantAttribute(String attribute) {
177: Node.JspAttribute attr = getNodeAttribute(attribute);
178: if (attr == null)
179: return false;
180: return attr.isLiteral();
181: }
182:
183: public String getConstantAttribute(String attribute) {
184: Node.JspAttribute attr = getNodeAttribute(attribute);
185: if (attr == null)
186: return null;
187: return attr.getValue();
188: }
189:
190: public boolean isAttributeSpecified(String attribute) {
191: return getNodeAttribute(attribute) != null;
192: }
193:
194: public String getTemporaryVariableName() {
195: return JspUtil.nextTemporaryVariableName();
196: }
197:
198: public void generateImport(String imp) {
199: pageInfo.addImport(imp);
200: }
201:
202: public void generateDeclaration(String id, String text) {
203: if (pageInfo.isPluginDeclared(id)) {
204: return;
205: }
206: curNodes.add(new Node.Declaration(text, node.getStart(),
207: null));
208: }
209:
210: public void generateJavaSource(String sourceCode) {
211: curNodes.add(new Node.Scriptlet(sourceCode,
212: node.getStart(), null));
213: }
214:
215: public void generateAttribute(String attributeName) {
216: curNodes.add(new Node.AttributeGenerator(node.getStart(),
217: attributeName, node));
218: }
219:
220: public void dontUseTagPlugin() {
221: node.setUseTagPlugin(false);
222: }
223:
224: public void generateBody() {
225: // Since we'll generate the body anyway, this is really a nop,
226: // except for the fact that it lets us put the Java sources the
227: // plugins produce in the correct order (w.r.t the body).
228: curNodes = node.getAtETag();
229: }
230:
231: private Node.JspAttribute getNodeAttribute(String attribute) {
232: Node.JspAttribute[] attrs = node.getJspAttributes();
233: for (int i = 0; attrs != null && i < attrs.length; i++) {
234: if (attrs[i].getName().equals(attribute)) {
235: return attrs[i];
236: }
237: }
238: return null;
239: }
240: }
241: }
|