001: //========================================================================
002: //$Id: TagLibConfiguration.java,v 1.4 2005/08/13 00:01:27 gregwilkins Exp $
003: //Copyright 2004 Mort Bay Consulting Pty. Ltd.
004: //------------------------------------------------------------------------
005: //Licensed under the Apache License, Version 2.0 (the "License");
006: //you may not use this file except in compliance with the License.
007: //You may obtain a copy of the License at
008: //http://www.apache.org/licenses/LICENSE-2.0
009: //Unless required by applicable law or agreed to in writing, software
010: //distributed under the License is distributed on an "AS IS" BASIS,
011: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: //See the License for the specific language governing permissions and
013: //limitations under the License.
014: //========================================================================
015:
016: package org.mortbay.jetty.webapp;
017:
018: import java.io.IOException;
019: import java.net.MalformedURLException;
020: import java.net.URL;
021: import java.util.ArrayList;
022: import java.util.EventListener;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Set;
027:
028: import org.mortbay.log.Log;
029: import org.mortbay.resource.Resource;
030: import org.mortbay.util.Loader;
031: import org.mortbay.util.TypeUtil;
032: import org.mortbay.xml.XmlParser;
033:
034: /* ------------------------------------------------------------ */
035: /** TagLibConfiguration.
036: *
037: * The class searches for TLD descriptors found in web.xml, in WEB-INF/*.tld files of the web app
038: * or *.tld files withing jars found in WEB-INF/lib of the webapp. Any listeners defined in these
039: * tld's are added to the context.
040: *
041: * <bile>This is total rubbish special case for JSPs! If there was a general use-case for web app
042: * frameworks to register listeners directly, then a generic mechanism could have been added to the servlet
043: * spec. Instead some special purpose JSP support is required that breaks all sorts of encapsualtion rules as
044: * the servlet container must go searching for and then parsing the descriptors for one particular framework.
045: * It only appears to be used by JSF, which is being developed by the same developer who implemented this
046: * feature in the first place!
047: * </bile>
048: *
049: * @author gregw
050: *
051: */
052: public class TagLibConfiguration implements Configuration {
053: WebAppContext _context;
054: String[] _serverTagLibClasses = {
055: "org.apache.jasper.servlet.JspServlet", //find tlds bundled with jasper (jstl)
056: "com.sun.faces.config.ConfigureListener", //find tlds from sun's jsf impl
057: "org.apache.myfaces.webapp.MyFacesServlet" //find tlds from myfaces impl
058: };
059:
060: public void setWebAppContext(WebAppContext context) {
061: _context = context;
062: }
063:
064: public WebAppContext getWebAppContext() {
065: return _context;
066: }
067:
068: public void configureClassLoader() throws Exception {
069: }
070:
071: /* ------------------------------------------------------------ */
072: /*
073: * @see org.mortbay.jetty.servlet.WebAppContext.Configuration#configureDefaults()
074: */
075: public void configureDefaults() throws Exception {
076: }
077:
078: /* ------------------------------------------------------------ */
079: /**
080: * @return List of {@link Resource}s for jar files in which to search for TLDs
081: * @throws IOException
082: * @throws MalformedURLException
083: */
084: protected List getJarResourceList() throws MalformedURLException,
085: IOException {
086: List list = new ArrayList();
087:
088: Resource web_inf = _context.getWebInf();
089: if (web_inf != null && web_inf.exists()) {
090: Resource lib = web_inf.addPath("lib/");
091: if (lib.exists() && lib.isDirectory()) {
092: String[] contents = lib.list();
093: for (int i = 0; i < contents.length; i++) {
094: if (contents[i] != null
095: && contents[i].toLowerCase().endsWith(
096: ".jar"))
097: list.add(lib.addPath(contents[i]));
098: }
099: }
100: }
101:
102: list.addAll(getServerJarResourceList());
103:
104: Log.debug("TLD search {}", list);
105: return list;
106:
107: }
108:
109: protected List getServerJarResourceList()
110: throws MalformedURLException, IOException {
111: List list = new ArrayList();
112:
113: for (int i = 0; _serverTagLibClasses != null
114: && i < _serverTagLibClasses.length; i++) {
115: URL jar = TypeUtil.jarFor(_serverTagLibClasses[i]);
116: if (jar != null)
117: list.add(Resource.newResource(jar));
118: }
119: return list;
120: }
121:
122: /* ------------------------------------------------------------ */
123: private void findTLDs(Set tlds, Resource dir)
124: throws MalformedURLException, IOException {
125: String[] meta_contents = dir.list();
126: for (int j = 0; j < meta_contents.length; j++) {
127: Resource r = dir.addPath(meta_contents[j]);
128: if (r.isDirectory())
129: findTLDs(tlds, r);
130: else if (meta_contents[j].toLowerCase().endsWith(".tld"))
131: tlds.add(r);
132: }
133: }
134:
135: /* ------------------------------------------------------------ */
136: /*
137: * @see org.mortbay.jetty.servlet.WebAppContext.Configuration#configureWebApp()
138: */
139: public void configureWebApp() throws Exception {
140: Set tlds = new HashSet();
141:
142: // Find tld's from web.xml
143: // When the XMLConfigurator (or other configurator) parsed the web.xml,
144: // It should have created aliases for all TLDs. So search resources aliases
145: // for aliases ending in tld
146: if (_context.getResourceAliases() != null
147: && _context.getBaseResource() != null
148: && _context.getBaseResource().exists()) {
149: Iterator iter = _context.getResourceAliases().values()
150: .iterator();
151: while (iter.hasNext()) {
152: String location = (String) iter.next();
153: if (location != null
154: && location.toLowerCase().endsWith(".tld")) {
155: if (!location.startsWith("/"))
156: location = "/WEB-INF/" + location;
157: Resource l = _context.getBaseResource().addPath(
158: location);
159: tlds.add(l);
160: }
161: }
162: }
163:
164: // Look for any tlds in WEB-INF directly.
165: Resource web_inf = _context.getWebInf();
166: if (web_inf != null) {
167: String[] contents = web_inf.list();
168: for (int i = 0; i < contents.length; i++) {
169: if (contents[i] != null
170: && contents[i].toLowerCase().endsWith(".tld")) {
171: Resource l = _context.getWebInf().addPath(
172: contents[i]);
173: tlds.add(l);
174: }
175:
176: }
177: }
178:
179: // Look for tlds in any jars
180: List jars = getJarResourceList();
181: for (int i = 0; i < jars.size(); i++) {
182: Resource jar = (Resource) jars.get(i);
183: Resource meta = Resource.newResource("jar:" + jar.getURL()
184: + "!/META-INF/", false);
185: if (meta.exists())
186: findTLDs(tlds, meta);
187: }
188:
189: // Create a TLD parser
190: XmlParser parser = new XmlParser(false);
191: parser
192: .redirectEntity(
193: "web-jsptaglib_1_1.dtd",
194: Loader
195: .getResource(
196: TagLibConfiguration.class,
197: "javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd",
198: false));
199: parser
200: .redirectEntity(
201: "web-jsptaglib_1_2.dtd",
202: Loader
203: .getResource(
204: TagLibConfiguration.class,
205: "javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd",
206: false));
207: parser
208: .redirectEntity(
209: "web-jsptaglib_2_0.xsd",
210: Loader
211: .getResource(
212: TagLibConfiguration.class,
213: "javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd",
214: false));
215: parser
216: .redirectEntity(
217: "web-jsptaglibrary_1_1.dtd",
218: Loader
219: .getResource(
220: TagLibConfiguration.class,
221: "javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd",
222: false));
223: parser
224: .redirectEntity(
225: "web-jsptaglibrary_1_2.dtd",
226: Loader
227: .getResource(
228: TagLibConfiguration.class,
229: "javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd",
230: false));
231: parser
232: .redirectEntity(
233: "web-jsptaglibrary_2_0.xsd",
234: Loader
235: .getResource(
236: TagLibConfiguration.class,
237: "javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd",
238: false));
239: parser.setXpath("/taglib/listener/listener-class");
240: // Parse all the discovered TLDs
241: Iterator iter = tlds.iterator();
242: while (iter.hasNext()) {
243: try {
244: Resource tld = (Resource) iter.next();
245: if (Log.isDebugEnabled())
246: Log.debug("TLD=" + tld);
247:
248: XmlParser.Node root = parser.parse(tld.getURL()
249: .toString());
250:
251: if (root == null) {
252: Log.warn("No TLD root in {}", tld);
253: continue;
254: }
255:
256: for (int i = 0; i < root.size(); i++) {
257: Object o = root.get(i);
258: if (o instanceof XmlParser.Node) {
259: XmlParser.Node node = (XmlParser.Node) o;
260: if ("listener".equals(node.getTag())) {
261: String className = node.getString(
262: "listener-class", false, true);
263: if (Log.isDebugEnabled())
264: Log.debug("listener=" + className);
265:
266: try {
267: Class listenerClass = getWebAppContext()
268: .loadClass(className);
269: EventListener l = (EventListener) listenerClass
270: .newInstance();
271: _context.addEventListener(l);
272: } catch (Exception e) {
273: Log.warn(
274: "Could not instantiate listener "
275: + className, e);
276: }
277: }
278: }
279: }
280: } catch (Exception e) {
281: Log.warn(e);
282: }
283: }
284: }
285:
286: public void deconfigureWebApp() throws Exception {
287: }
288:
289: /* ------------------------------------------------------------ */
290: /**
291: * @return
292: */
293: public String[] getServerTagLibClasses() {
294: return _serverTagLibClasses;
295: }
296:
297: /* ------------------------------------------------------------ */
298: /**
299: * @param serverTagLibClasses An array of class names. The jars that these
300: * classes are loaded from will be examined for TLD files (even if these jars
301: * are on the server or system classpath).
302: */
303: public void setServerTagLibClasses(String[] serverTagLibClasses) {
304: _serverTagLibClasses = serverTagLibClasses;
305: }
306: }
|