KickJava   Java API By Example, From Geeks To Geeks.

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


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

16 package org.jboss.web.tomcat.tc6.jasper;
17
18 import java.util.Set JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.jar.JarEntry JavaDoc;
23 import java.util.jar.JarInputStream JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.net.URLConnection JavaDoc;
30 import java.net.MalformedURLException JavaDoc;
31 import javax.servlet.ServletContext JavaDoc;
32 import java.util.Map JavaDoc; // SYNC
33

34 import org.apache.jasper.compiler.TldLocationsCache;
35 import org.apache.jasper.compiler.Localizer;
36 import org.apache.jasper.JasperException;
37 import org.apache.jasper.Constants;
38 import org.apache.jasper.xmlparser.TreeNode;
39 import org.apache.jasper.xmlparser.ParserUtils;
40 import org.jboss.logging.Logger;
41
42 /**
43  * A prototype TagLibCache that allows one to obtain shared tlds from the
44  * jbossweb sar conf/tlds directory.
45  * @author Scott.Stark@jboss.org
46  * @version $Revision: 45726 $
47  */

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

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

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

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

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

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

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