KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc5 > jasper > TagLibCache


1 /*
2 * JBoss, the OpenSource J2EE webOS
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */

7 /*
8  * Copyright 1999,2004 The Apache Software Foundation.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */

22 package org.jboss.web.tomcat.tc5.jasper;
23
24 import java.util.Set JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.jar.JarEntry JavaDoc;
29 import java.util.jar.JarInputStream JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.FileInputStream JavaDoc;
32 import java.io.FileNotFoundException JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.net.URL JavaDoc;
35 import java.net.URLConnection JavaDoc;
36 import java.net.MalformedURLException JavaDoc;
37 import javax.servlet.ServletContext JavaDoc;
38
39 import org.apache.jasper.compiler.TldLocationsCache;
40 import org.apache.jasper.compiler.Localizer;
41 import org.apache.jasper.JasperException;
42 import org.apache.jasper.Constants;
43 import org.apache.jasper.xmlparser.TreeNode;
44 import org.apache.jasper.xmlparser.ParserUtils;
45 import org.jboss.logging.Logger;
46
47 /**
48  * A prototype TagLibCache that allows one to obtain shared tlds from the
49  * jbossweb sar conf/tlds directory.
50  * @author Scott.Stark@jboss.org
51  * @version $Revision: 1.1.2.3 $
52  */

53 public class TagLibCache extends TldLocationsCache
54 {
55    private static final String JavaDoc WEB_XML = "/WEB-INF/web.xml";
56    private static final String JavaDoc JAR_FILE_SUFFIX = ".jar";
57
58    private static Logger log = Logger.getLogger(TagLibCache.class);
59
60    private ServletContext JavaDoc ctx;
61    private HashMap JavaDoc mappings;
62    private ArrayList JavaDoc tagLibJars;
63
64    public TagLibCache(ServletContext JavaDoc ctx, ArrayList JavaDoc tagLibJars)
65    {
66       super(ctx, true);
67       this.ctx = ctx;
68       this.tagLibJars = tagLibJars;
69    }
70
71    /**
72     * Gets the 'location' of the TLD associated with the given taglib 'uri'.
73     *
74     * Returns null if the uri is not associated with any tag library 'exposed'
75     * in the web application. A tag library is 'exposed' either explicitly in
76     * web.xml or implicitly via the uri tag in the TLD of a taglib deployed in a
77     * jar file (WEB-INF/lib).
78     * @param uri The taglib uri
79     * @return An array of two Strings: The first element denotes the real path
80     * to the TLD. If the path to the TLD points to a jar file, then the
81     * second element denotes the name of the TLD entry in the jar file.
82     * Returns null if the uri is not associated with any tag library
83     * 'exposed' in the web application.
84     */

85    public String JavaDoc[] getLocation(String JavaDoc uri) throws JasperException
86    {
87       if (mappings == null)
88          init();
89       String JavaDoc[] locations = (String JavaDoc[]) mappings.get(uri);
90       return locations;
91    }
92
93    private void init() throws JasperException
94    {
95       try
96       {
97          mappings = new HashMap JavaDoc();
98          processWebDotXml();
99          loadStandardTlds();
100          processTldsInFileSystem("/WEB-INF/");
101       }
102       catch (Exception JavaDoc ex)
103       {
104          String JavaDoc msg = Localizer.getMessage("jsp.error.internal.tldinit", ex.getMessage());
105          throw new JasperException(msg, ex);
106       }
107    }
108
109    /*
110     * Populates taglib map described in web.xml.
111     */

112    protected void processWebDotXml() throws Exception JavaDoc
113    {
114
115       InputStream JavaDoc is = null;
116
117       try
118       {
119          // Acquire input stream to web application deployment descriptor
120
String JavaDoc altDDName = (String JavaDoc) ctx.getAttribute(Constants.ALT_DD_ATTR);
121          if (altDDName != null)
122          {
123             try
124             {
125                is = new FileInputStream JavaDoc(altDDName);
126             }
127             catch (FileNotFoundException JavaDoc e)
128             {
129                log.warn(Localizer.getMessage("jsp.error.internal.filenotfound",
130                   altDDName));
131             }
132          }
133          else
134          {
135             is = ctx.getResourceAsStream(WEB_XML);
136             if (is == null)
137             {
138                log.warn(Localizer.getMessage("jsp.error.internal.filenotfound",
139                   WEB_XML));
140             }
141          }
142
143          if (is == null)
144          {
145             return;
146          }
147
148          // Parse the web application deployment descriptor
149
TreeNode webtld = null;
150          // altDDName is the absolute path of the DD
151
if (altDDName != null)
152          {
153             webtld = new ParserUtils().parseXMLDocument(altDDName, is);
154          }
155          else
156          {
157             webtld = new ParserUtils().parseXMLDocument(WEB_XML, is);
158          }
159
160          // Allow taglib to be an element of the root or jsp-config (JSP2.0)
161
TreeNode jspConfig = webtld.findChild("jsp-config");
162          if (jspConfig != null)
163          {
164             webtld = jspConfig;
165          }
166          Iterator JavaDoc taglibs = webtld.findChildren("taglib");
167          while (taglibs.hasNext())
168          {
169
170             // Parse the next <taglib> element
171
TreeNode taglib = (TreeNode) taglibs.next();
172             String JavaDoc tagUri = null;
173             String JavaDoc tagLoc = null;
174             TreeNode child = taglib.findChild("taglib-uri");
175             if (child != null)
176                tagUri = child.getBody();
177             child = taglib.findChild("taglib-location");
178             if (child != null)
179                tagLoc = child.getBody();
180
181             // Save this location if appropriate
182
if (tagLoc == null)
183                continue;
184             if (uriType(tagLoc) == NOROOT_REL_URI)
185                tagLoc = "/WEB-INF/" + tagLoc;
186             String JavaDoc tagLoc2 = null;
187             if (tagLoc.endsWith(JAR_FILE_SUFFIX))
188             {
189                tagLoc = ctx.getResource(tagLoc).toString();
190                tagLoc2 = "META-INF/taglib.tld";
191             }
192             mappings.put(tagUri, new String JavaDoc[]{tagLoc, tagLoc2});
193          }
194       }
195       finally
196       {
197          if (is != null)
198          {
199             try
200             {
201                is.close();
202             }
203             catch (Throwable JavaDoc t)
204             {
205             }
206          }
207       }
208    }
209
210    protected void loadStandardTlds() throws MalformedURLException JavaDoc
211    {
212       if( tagLibJars.size() == 0 )
213          return;
214
215       // Locate the conf/web.xml
216
ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
217       URL JavaDoc web = loader.getResource("conf/web.xml");
218       URL JavaDoc sarURL = new URL JavaDoc(web, "..");
219       for(int n = 0; n < tagLibJars.size(); n ++)
220       {
221          String JavaDoc jarPath = (String JavaDoc) tagLibJars.get(n);
222          try
223          {
224             URL JavaDoc url = new URL JavaDoc(sarURL, jarPath);
225             String JavaDoc resourcePath = url.toString();
226             log.debug("Scanning for tlds in: "+resourcePath);
227             URLConnection JavaDoc conn = url.openConnection();
228             conn.setUseCaches(false);
229             scanJar(conn, resourcePath, true);
230          }
231          catch (Exception JavaDoc e)
232          {
233             log.debug("Failed to scan: "+jarPath, e);
234          }
235       }
236    }
237
238    /*
239     * Searches the filesystem under /WEB-INF for any TLD files, and adds
240     * an implicit map entry to the taglib map for any TLD that has a <uri>
241     * element.
242     */

243    protected void processTldsInFileSystem(String JavaDoc startPath)
244       throws Exception JavaDoc
245    {
246
247       Set JavaDoc dirList = ctx.getResourcePaths(startPath);
248       if (dirList != null)
249       {
250          Iterator JavaDoc it = dirList.iterator();
251          while (it.hasNext())
252          {
253             String JavaDoc path = (String JavaDoc) it.next();
254             if (path.endsWith("/"))
255             {
256                processTldsInFileSystem(path);
257             }
258             if( path.endsWith(".jar") )
259             {
260                URL JavaDoc resURL = ctx.getResource(path);
261                URLConnection JavaDoc conn = resURL.openConnection();
262                conn.setUseCaches(false);
263                this.scanJar(conn, resURL.toString(), false);
264             }
265             else if ( path.endsWith(".tld") == true )
266             {
267                InputStream JavaDoc stream = ctx.getResourceAsStream(path);
268                String JavaDoc uri = null;
269                try
270                {
271                   uri = getUriFromTld(path, stream);
272                }
273                finally
274                {
275                   if (stream != null)
276                   {
277                      try
278                      {
279                         stream.close();
280                      }
281                      catch (Throwable JavaDoc t)
282                      {
283                         // do nothing
284
}
285                   }
286                }
287                // Add implicit map entry only if its uri is not already
288
// present in the map
289
if (uri != null && mappings.get(uri) == null)
290                {
291                   mappings.put(uri, new String JavaDoc[]{path, null});
292                }
293             }
294          }
295       }
296    }
297
298    /**
299     * Scans the given JarInputStream for TLD files located in META-INF (or a
300     * subdirectory of it), adding an implicit map entry to the taglib map for
301     * any TLD that has a <uri> element.
302     * @param conn - the
303     * @param ignore true if any exceptions raised when processing the given JAR
304     * should be ignored, false otherwise
305     */

306    private void scanJar(URLConnection JavaDoc conn, String JavaDoc resourcePath, boolean ignore)
307       throws JasperException, IOException JavaDoc
308    {
309       InputStream JavaDoc connIS = conn.getInputStream();
310       JarInputStream JavaDoc jis = new JarInputStream JavaDoc(connIS);
311       try
312       {
313          JarEntry JavaDoc entry = jis.getNextJarEntry();
314          while( entry != null )
315          {
316             String JavaDoc name = entry.getName();
317             if( name.endsWith(".tld") == false )
318             {
319                entry = jis.getNextJarEntry();
320                continue;
321             }
322
323             EntryInputStream eis = new EntryInputStream(jis);
324             String JavaDoc uri = getUriFromTld(resourcePath, eis);
325             // Add implicit map entry only if its uri is not already
326
// present in the map
327
if (uri != null && mappings.get(uri) == null)
328             {
329                mappings.put(uri, new String JavaDoc[]{resourcePath, name});
330             }
331             entry = jis.getNextJarEntry();
332          }
333       }
334       catch (Exception JavaDoc ex)
335       {
336          if (!ignore)
337          {
338             throw new JasperException(ex);
339          }
340       }
341       finally
342       {
343          if( jis != null )
344          {
345             try
346             {
347                jis.close();
348             }
349             catch (Throwable JavaDoc t)
350             {
351                // ignore
352
}
353          }
354
355          if (connIS != null)
356          {
357             try
358             {
359                connIS.close();
360             }
361             catch (Throwable JavaDoc t)
362             {
363                // ignore
364
}
365          }
366       }
367    }
368
369    /*
370     * Returns the value of the uri element of the given TLD, or null if the
371     * given TLD does not contain any such element.
372     */

373    private String JavaDoc getUriFromTld(String JavaDoc resourcePath, InputStream JavaDoc in)
374       throws JasperException
375    {
376       // Parse the tag library descriptor at the specified resource path
377
TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath, in);
378       TreeNode uri = tld.findChild("uri");
379       if (uri != null)
380       {
381          String JavaDoc body = uri.getBody();
382          if (body != null)
383             return body;
384       }
385
386       return null;
387    }
388
389    /**
390     * Used to ignore the close on the jar entry input stream since this
391     * closes the jar stream, not just the entry.
392     */

393    static class EntryInputStream extends InputStream JavaDoc
394    {
395       private JarInputStream JavaDoc jis;
396       EntryInputStream(JarInputStream JavaDoc jis)
397       {
398          this.jis = jis;
399       }
400
401       public int read() throws IOException JavaDoc
402       {
403          return jis.read();
404       }
405
406       public int available() throws IOException JavaDoc
407       {
408          return jis.available();
409       }
410
411       public void close() throws IOException JavaDoc
412       {
413          
414       }
415
416       public void reset() throws IOException JavaDoc
417       {
418          jis.reset();
419       }
420
421       public boolean markSupported()
422       {
423          return jis.markSupported();
424       }
425
426       public synchronized void mark(int readlimit)
427       {
428          jis.mark(readlimit);
429       }
430
431       public long skip(long n) throws IOException JavaDoc
432       {
433          return jis.skip(n);
434       }
435
436       public int read(byte b[], int off, int len) throws IOException JavaDoc
437       {
438          return jis.read(b, off, len);
439       }
440    }
441 }
442
Popular Tags