Source Code Cross Referenced for TldLocationsCache.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » jasper » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » apache tomcat 6.0.14 » org.apache.jasper.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.io.InputStream;
021:        import java.net.JarURLConnection;
022:        import java.net.MalformedURLException;
023:        import java.net.URL;
024:        import java.net.URLClassLoader;
025:        import java.net.URLConnection;
026:        import java.util.Enumeration;
027:        import java.util.Hashtable;
028:        import java.util.HashSet;
029:        import java.util.Iterator;
030:        import java.util.Set;
031:        import java.util.StringTokenizer;
032:        import java.util.jar.JarEntry;
033:        import java.util.jar.JarFile;
034:        import org.xml.sax.InputSource;
035:
036:        import javax.servlet.ServletContext;
037:
038:        import org.apache.jasper.Constants;
039:        import org.apache.jasper.JasperException;
040:        import org.apache.jasper.xmlparser.ParserUtils;
041:        import org.apache.jasper.xmlparser.TreeNode;
042:        import org.apache.juli.logging.Log;
043:        import org.apache.juli.logging.LogFactory;
044:
045:        /**
046:         * A container for all tag libraries that are defined "globally"
047:         * for the web application.
048:         * 
049:         * Tag Libraries can be defined globally in one of two ways:
050:         *   1. Via <taglib> elements in web.xml:
051:         *      the uri and location of the tag-library are specified in
052:         *      the <taglib> element.
053:         *   2. Via packaged jar files that contain .tld files
054:         *      within the META-INF directory, or some subdirectory
055:         *      of it. The taglib is 'global' if it has the <uri>
056:         *      element defined.
057:         *
058:         * A mapping between the taglib URI and its associated TaglibraryInfoImpl
059:         * is maintained in this container.
060:         * Actually, that's what we'd like to do. However, because of the
061:         * way the classes TagLibraryInfo and TagInfo have been defined,
062:         * it is not currently possible to share an instance of TagLibraryInfo
063:         * across page invocations. A bug has been submitted to the spec lead.
064:         * In the mean time, all we do is save the 'location' where the
065:         * TLD associated with a taglib URI can be found.
066:         *
067:         * When a JSP page has a taglib directive, the mappings in this container
068:         * are first searched (see method getLocation()).
069:         * If a mapping is found, then the location of the TLD is returned.
070:         * If no mapping is found, then the uri specified
071:         * in the taglib directive is to be interpreted as the location for
072:         * the TLD of this tag library.
073:         *
074:         * @author Pierre Delisle
075:         * @author Jan Luehe
076:         */
077:
078:        public class TldLocationsCache {
079:
080:            // Logger
081:            private Log log = LogFactory.getLog(TldLocationsCache.class);
082:
083:            /**
084:             * The types of URI one may specify for a tag library
085:             */
086:            public static final int ABS_URI = 0;
087:            public static final int ROOT_REL_URI = 1;
088:            public static final int NOROOT_REL_URI = 2;
089:
090:            private static final String WEB_XML = "/WEB-INF/web.xml";
091:            private static final String FILE_PROTOCOL = "file:";
092:            private static final String JAR_FILE_SUFFIX = ".jar";
093:
094:            // Names of JARs that are known not to contain any TLDs
095:            private static HashSet<String> noTldJars;
096:
097:            /**
098:             * The mapping of the 'global' tag library URI to the location (resource
099:             * path) of the TLD associated with that tag library. The location is
100:             * returned as a String array:
101:             *    [0] The location
102:             *    [1] If the location is a jar file, this is the location of the tld.
103:             */
104:            private Hashtable mappings;
105:
106:            private boolean initialized;
107:            private ServletContext ctxt;
108:            private boolean redeployMode;
109:
110:            //*********************************************************************
111:            // Constructor and Initilizations
112:
113:            /*
114:             * Initializes the set of JARs that are known not to contain any TLDs
115:             */
116:            static {
117:                noTldJars = new HashSet<String>();
118:                // Bootstrap JARs
119:                noTldJars.add("bootstrap.jar");
120:                noTldJars.add("commons-daemon.jar");
121:                noTldJars.add("tomcat-juli.jar");
122:                // Main JARs
123:                noTldJars.add("annotations-api.jar");
124:                noTldJars.add("catalina.jar");
125:                noTldJars.add("catalina-ant.jar");
126:                noTldJars.add("catalina-ha.jar");
127:                noTldJars.add("catalina-tribes.jar");
128:                noTldJars.add("el-api.jar");
129:                noTldJars.add("jasper.jar");
130:                noTldJars.add("jasper-el.jar");
131:                noTldJars.add("jasper-jdt.jar");
132:                noTldJars.add("jsp-api.jar");
133:                noTldJars.add("servlet-api.jar");
134:                noTldJars.add("tomcat-coyote.jar");
135:                noTldJars.add("tomcat-dbcp.jar");
136:                // i18n JARs
137:                noTldJars.add("tomcat-i18n-en.jar");
138:                noTldJars.add("tomcat-i18n-es.jar");
139:                noTldJars.add("tomcat-i18n-fr.jar");
140:                noTldJars.add("tomcat-i18n-ja.jar");
141:                // Misc JARs not included with Tomcat
142:                noTldJars.add("ant.jar");
143:                noTldJars.add("commons-dbcp.jar");
144:                noTldJars.add("commons-beanutils.jar");
145:                noTldJars.add("commons-fileupload-1.0.jar");
146:                noTldJars.add("commons-pool.jar");
147:                noTldJars.add("commons-digester.jar");
148:                noTldJars.add("commons-logging.jar");
149:                noTldJars.add("commons-collections.jar");
150:                noTldJars.add("jmx.jar");
151:                noTldJars.add("jmx-tools.jar");
152:                noTldJars.add("xercesImpl.jar");
153:                noTldJars.add("xmlParserAPIs.jar");
154:                noTldJars.add("xml-apis.jar");
155:                // JARs from J2SE runtime
156:                noTldJars.add("sunjce_provider.jar");
157:                noTldJars.add("ldapsec.jar");
158:                noTldJars.add("localedata.jar");
159:                noTldJars.add("dnsns.jar");
160:                noTldJars.add("tools.jar");
161:                noTldJars.add("sunpkcs11.jar");
162:            }
163:
164:            public TldLocationsCache(ServletContext ctxt) {
165:                this (ctxt, true);
166:            }
167:
168:            /** Constructor. 
169:             *
170:             * @param ctxt the servlet context of the web application in which Jasper 
171:             * is running
172:             * @param redeployMode if true, then the compiler will allow redeploying 
173:             * a tag library from the same jar, at the expense of slowing down the
174:             * server a bit. Note that this may only work on JDK 1.3.1_01a and later,
175:             * because of JDK bug 4211817 fixed in this release.
176:             * If redeployMode is false, a faster but less capable mode will be used.
177:             */
178:            public TldLocationsCache(ServletContext ctxt, boolean redeployMode) {
179:                this .ctxt = ctxt;
180:                this .redeployMode = redeployMode;
181:                mappings = new Hashtable();
182:                initialized = false;
183:            }
184:
185:            /**
186:             * Sets the list of JARs that are known not to contain any TLDs.
187:             *
188:             * @param jarNames List of comma-separated names of JAR files that are 
189:             * known not to contain any TLDs 
190:             */
191:            public static void setNoTldJars(String jarNames) {
192:                if (jarNames != null) {
193:                    noTldJars.clear();
194:                    StringTokenizer tokenizer = new StringTokenizer(jarNames,
195:                            ",");
196:                    while (tokenizer.hasMoreElements()) {
197:                        noTldJars.add(tokenizer.nextToken());
198:                    }
199:                }
200:            }
201:
202:            /**
203:             * Gets the 'location' of the TLD associated with the given taglib 'uri'.
204:             *
205:             * Returns null if the uri is not associated with any tag library 'exposed'
206:             * in the web application. A tag library is 'exposed' either explicitly in
207:             * web.xml or implicitly via the uri tag in the TLD of a taglib deployed
208:             * in a jar file (WEB-INF/lib).
209:             * 
210:             * @param uri The taglib uri
211:             *
212:             * @return An array of two Strings: The first element denotes the real
213:             * path to the TLD. If the path to the TLD points to a jar file, then the
214:             * second element denotes the name of the TLD entry in the jar file.
215:             * Returns null if the uri is not associated with any tag library 'exposed'
216:             * in the web application.
217:             */
218:            public String[] getLocation(String uri) throws JasperException {
219:                if (!initialized) {
220:                    init();
221:                }
222:                return (String[]) mappings.get(uri);
223:            }
224:
225:            /** 
226:             * Returns the type of a URI:
227:             *     ABS_URI
228:             *     ROOT_REL_URI
229:             *     NOROOT_REL_URI
230:             */
231:            public static int uriType(String uri) {
232:                if (uri.indexOf(':') != -1) {
233:                    return ABS_URI;
234:                } else if (uri.startsWith("/")) {
235:                    return ROOT_REL_URI;
236:                } else {
237:                    return NOROOT_REL_URI;
238:                }
239:            }
240:
241:            private void init() throws JasperException {
242:                if (initialized)
243:                    return;
244:                try {
245:                    processWebDotXml();
246:                    scanJars();
247:                    processTldsInFileSystem("/WEB-INF/");
248:                    initialized = true;
249:                } catch (Exception ex) {
250:                    throw new JasperException(Localizer.getMessage(
251:                            "jsp.error.internal.tldinit", ex.getMessage()));
252:                }
253:            }
254:
255:            /*
256:             * Populates taglib map described in web.xml.
257:             */
258:            private void processWebDotXml() throws Exception {
259:
260:                InputStream is = null;
261:
262:                try {
263:                    // Acquire input stream to web application deployment descriptor
264:                    String altDDName = (String) ctxt
265:                            .getAttribute(Constants.ALT_DD_ATTR);
266:                    URL uri = null;
267:                    if (altDDName != null) {
268:                        try {
269:                            uri = new URL(FILE_PROTOCOL
270:                                    + altDDName.replace('\\', '/'));
271:                        } catch (MalformedURLException e) {
272:                            if (log.isWarnEnabled()) {
273:                                log.warn(Localizer.getMessage(
274:                                        "jsp.error.internal.filenotfound",
275:                                        altDDName));
276:                            }
277:                        }
278:                    } else {
279:                        uri = ctxt.getResource(WEB_XML);
280:                        if (uri == null && log.isWarnEnabled()) {
281:                            log
282:                                    .warn(Localizer.getMessage(
283:                                            "jsp.error.internal.filenotfound",
284:                                            WEB_XML));
285:                        }
286:                    }
287:
288:                    if (uri == null) {
289:                        return;
290:                    }
291:                    is = uri.openStream();
292:                    InputSource ip = new InputSource(is);
293:                    ip.setSystemId(uri.toExternalForm());
294:
295:                    // Parse the web application deployment descriptor
296:                    TreeNode webtld = null;
297:                    // altDDName is the absolute path of the DD
298:                    if (altDDName != null) {
299:                        webtld = new ParserUtils().parseXMLDocument(altDDName,
300:                                ip);
301:                    } else {
302:                        webtld = new ParserUtils()
303:                                .parseXMLDocument(WEB_XML, ip);
304:                    }
305:
306:                    // Allow taglib to be an element of the root or jsp-config (JSP2.0)
307:                    TreeNode jspConfig = webtld.findChild("jsp-config");
308:                    if (jspConfig != null) {
309:                        webtld = jspConfig;
310:                    }
311:                    Iterator taglibs = webtld.findChildren("taglib");
312:                    while (taglibs.hasNext()) {
313:
314:                        // Parse the next <taglib> element
315:                        TreeNode taglib = (TreeNode) taglibs.next();
316:                        String tagUri = null;
317:                        String tagLoc = null;
318:                        TreeNode child = taglib.findChild("taglib-uri");
319:                        if (child != null)
320:                            tagUri = child.getBody();
321:                        child = taglib.findChild("taglib-location");
322:                        if (child != null)
323:                            tagLoc = child.getBody();
324:
325:                        // Save this location if appropriate
326:                        if (tagLoc == null)
327:                            continue;
328:                        if (uriType(tagLoc) == NOROOT_REL_URI)
329:                            tagLoc = "/WEB-INF/" + tagLoc;
330:                        String tagLoc2 = null;
331:                        if (tagLoc.endsWith(JAR_FILE_SUFFIX)) {
332:                            tagLoc = ctxt.getResource(tagLoc).toString();
333:                            tagLoc2 = "META-INF/taglib.tld";
334:                        }
335:                        mappings.put(tagUri, new String[] { tagLoc, tagLoc2 });
336:                    }
337:                } finally {
338:                    if (is != null) {
339:                        try {
340:                            is.close();
341:                        } catch (Throwable t) {
342:                        }
343:                    }
344:                }
345:            }
346:
347:            /**
348:             * Scans the given JarURLConnection for TLD files located in META-INF
349:             * (or a subdirectory of it), adding an implicit map entry to the taglib
350:             * map for any TLD that has a <uri> element.
351:             *
352:             * @param conn The JarURLConnection to the JAR file to scan
353:             * @param ignore true if any exceptions raised when processing the given
354:             * JAR should be ignored, false otherwise
355:             */
356:            private void scanJar(JarURLConnection conn, boolean ignore)
357:                    throws JasperException {
358:
359:                JarFile jarFile = null;
360:                String resourcePath = conn.getJarFileURL().toString();
361:                try {
362:                    if (redeployMode) {
363:                        conn.setUseCaches(false);
364:                    }
365:                    jarFile = conn.getJarFile();
366:                    Enumeration entries = jarFile.entries();
367:                    while (entries.hasMoreElements()) {
368:                        JarEntry entry = (JarEntry) entries.nextElement();
369:                        String name = entry.getName();
370:                        if (!name.startsWith("META-INF/"))
371:                            continue;
372:                        if (!name.endsWith(".tld"))
373:                            continue;
374:                        InputStream stream = jarFile.getInputStream(entry);
375:                        try {
376:                            String uri = getUriFromTld(resourcePath, stream);
377:                            // Add implicit map entry only if its uri is not already
378:                            // present in the map
379:                            if (uri != null && mappings.get(uri) == null) {
380:                                mappings.put(uri, new String[] { resourcePath,
381:                                        name });
382:                            }
383:                        } finally {
384:                            if (stream != null) {
385:                                try {
386:                                    stream.close();
387:                                } catch (Throwable t) {
388:                                    // do nothing
389:                                }
390:                            }
391:                        }
392:                    }
393:                } catch (Exception ex) {
394:                    if (!redeployMode) {
395:                        // if not in redeploy mode, close the jar in case of an error
396:                        if (jarFile != null) {
397:                            try {
398:                                jarFile.close();
399:                            } catch (Throwable t) {
400:                                // ignore
401:                            }
402:                        }
403:                    }
404:                    if (!ignore) {
405:                        throw new JasperException(ex);
406:                    }
407:                } finally {
408:                    if (redeployMode) {
409:                        // if in redeploy mode, always close the jar
410:                        if (jarFile != null) {
411:                            try {
412:                                jarFile.close();
413:                            } catch (Throwable t) {
414:                                // ignore
415:                            }
416:                        }
417:                    }
418:                }
419:            }
420:
421:            /*
422:             * Searches the filesystem under /WEB-INF for any TLD files, and adds
423:             * an implicit map entry to the taglib map for any TLD that has a <uri>
424:             * element.
425:             */
426:            private void processTldsInFileSystem(String startPath)
427:                    throws Exception {
428:
429:                Set dirList = ctxt.getResourcePaths(startPath);
430:                if (dirList != null) {
431:                    Iterator it = dirList.iterator();
432:                    while (it.hasNext()) {
433:                        String path = (String) it.next();
434:                        if (path.endsWith("/")) {
435:                            processTldsInFileSystem(path);
436:                        }
437:                        if (!path.endsWith(".tld")) {
438:                            continue;
439:                        }
440:                        InputStream stream = ctxt.getResourceAsStream(path);
441:                        String uri = null;
442:                        try {
443:                            uri = getUriFromTld(path, stream);
444:                        } finally {
445:                            if (stream != null) {
446:                                try {
447:                                    stream.close();
448:                                } catch (Throwable t) {
449:                                    // do nothing
450:                                }
451:                            }
452:                        }
453:                        // Add implicit map entry only if its uri is not already
454:                        // present in the map
455:                        if (uri != null && mappings.get(uri) == null) {
456:                            mappings.put(uri, new String[] { path, null });
457:                        }
458:                    }
459:                }
460:            }
461:
462:            /*
463:             * Returns the value of the uri element of the given TLD, or null if the
464:             * given TLD does not contain any such element.
465:             */
466:            private String getUriFromTld(String resourcePath, InputStream in)
467:                    throws JasperException {
468:                // Parse the tag library descriptor at the specified resource path
469:                TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath,
470:                        in);
471:                TreeNode uri = tld.findChild("uri");
472:                if (uri != null) {
473:                    String body = uri.getBody();
474:                    if (body != null)
475:                        return body;
476:                }
477:
478:                return null;
479:            }
480:
481:            /*
482:             * Scans all JARs accessible to the webapp's classloader and its
483:             * parent classloaders for TLDs.
484:             * 
485:             * The list of JARs always includes the JARs under WEB-INF/lib, as well as
486:             * all shared JARs in the classloader delegation chain of the webapp's
487:             * classloader.
488:             *
489:             * Considering JARs in the classloader delegation chain constitutes a
490:             * Tomcat-specific extension to the TLD search
491:             * order defined in the JSP spec. It allows tag libraries packaged as JAR
492:             * files to be shared by web applications by simply dropping them in a 
493:             * location that all web applications have access to (e.g.,
494:             * <CATALINA_HOME>/common/lib).
495:             *
496:             * The set of shared JARs to be scanned for TLDs is narrowed down by
497:             * the <tt>noTldJars</tt> class variable, which contains the names of JARs
498:             * that are known not to contain any TLDs.
499:             */
500:            private void scanJars() throws Exception {
501:
502:                ClassLoader webappLoader = Thread.currentThread()
503:                        .getContextClassLoader();
504:                ClassLoader loader = webappLoader;
505:
506:                while (loader != null) {
507:                    if (loader instanceof  URLClassLoader) {
508:                        URL[] urls = ((URLClassLoader) loader).getURLs();
509:                        for (int i = 0; i < urls.length; i++) {
510:                            URLConnection conn = urls[i].openConnection();
511:                            if (conn instanceof  JarURLConnection) {
512:                                if (needScanJar(loader, webappLoader,
513:                                        ((JarURLConnection) conn).getJarFile()
514:                                                .getName())) {
515:                                    scanJar((JarURLConnection) conn, true);
516:                                }
517:                            } else {
518:                                String urlStr = urls[i].toString();
519:                                if (urlStr.startsWith(FILE_PROTOCOL)
520:                                        && urlStr.endsWith(JAR_FILE_SUFFIX)
521:                                        && needScanJar(loader, webappLoader,
522:                                                urlStr)) {
523:                                    URL jarURL = new URL("jar:" + urlStr + "!/");
524:                                    scanJar((JarURLConnection) jarURL
525:                                            .openConnection(), true);
526:                                }
527:                            }
528:                        }
529:                    }
530:
531:                    loader = loader.getParent();
532:                }
533:            }
534:
535:            /*
536:             * Determines if the JAR file with the given <tt>jarPath</tt> needs to be
537:             * scanned for TLDs.
538:             *
539:             * @param loader The current classloader in the parent chain
540:             * @param webappLoader The webapp classloader
541:             * @param jarPath The JAR file path
542:             *
543:             * @return TRUE if the JAR file identified by <tt>jarPath</tt> needs to be
544:             * scanned for TLDs, FALSE otherwise
545:             */
546:            private boolean needScanJar(ClassLoader loader,
547:                    ClassLoader webappLoader, String jarPath) {
548:                if (loader == webappLoader) {
549:                    // JARs under WEB-INF/lib must be scanned unconditionally according
550:                    // to the spec.
551:                    return true;
552:                } else {
553:                    String jarName = jarPath;
554:                    int slash = jarPath.lastIndexOf('/');
555:                    if (slash >= 0) {
556:                        jarName = jarPath.substring(slash + 1);
557:                    }
558:                    return (!noTldJars.contains(jarName));
559:                }
560:            }
561:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.