KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > startup > TldConfig


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

17
18
19 package org.apache.catalina.startup;
20
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.ObjectInputStream JavaDoc;
28 import java.io.ObjectOutputStream JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.net.URLClassLoader JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Enumeration JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38 import java.util.StringTokenizer JavaDoc;
39 import java.util.jar.JarEntry JavaDoc;
40 import java.util.jar.JarFile JavaDoc;
41
42 import javax.naming.NameClassPair JavaDoc;
43 import javax.naming.NamingEnumeration JavaDoc;
44 import javax.naming.NamingException JavaDoc;
45 import javax.naming.directory.DirContext JavaDoc;
46 import javax.servlet.ServletException JavaDoc;
47
48 import org.apache.catalina.Context;
49 import org.apache.catalina.Globals;
50 import org.apache.catalina.core.StandardContext;
51 import org.apache.catalina.util.StringManager;
52 import org.apache.tomcat.util.digester.Digester;
53 import org.xml.sax.InputSource JavaDoc;
54
55 /**
56  * Startup event listener for a <b>Context</b> that configures the properties
57  * of that Context, and the associated defined servlets.
58  *
59  * @author Craig R. McClanahan
60  * @author Jean-Francois Arcand
61  * @author Costin Manolache
62  */

63 public final class TldConfig {
64
65     // Names of JARs that are known not to contain any TLDs
66
private static HashSet JavaDoc noTldJars;
67
68     private static org.apache.commons.logging.Log log=
69         org.apache.commons.logging.LogFactory.getLog( TldConfig.class );
70
71     private static final String JavaDoc FILE_URL_PREFIX = "file:";
72     private static final int FILE_URL_PREFIX_LEN = FILE_URL_PREFIX.length();
73
74
75     /*
76      * Initializes the set of JARs that are known not to contain any TLDs
77      */

78     static {
79         noTldJars = new HashSet JavaDoc();
80         noTldJars.add("catalina.jar");
81         noTldJars.add("catalina-ant.jar");
82         noTldJars.add("catalina-cluster.jar");
83         noTldJars.add("catalina-optional.jar");
84         noTldJars.add("commons-el.jar");
85         noTldJars.add("commons-logging-api.jar");
86         noTldJars.add("commons-modeler.jar");
87         noTldJars.add("jasper-compiler.jar");
88         noTldJars.add("jasper-compiler-jdt.jar");
89         noTldJars.add("jasper-runtime.jar");
90         noTldJars.add("jsp-api.jar");
91         noTldJars.add("naming-resources.jar");
92         noTldJars.add("naming-factory.jar");
93         noTldJars.add("naming-factory-dbcp.jar");
94         noTldJars.add("servlet-api.jar");
95         noTldJars.add("servlets-cgi.jar");
96         noTldJars.add("servlets-default.jar");
97         noTldJars.add("servlets-invoker.jar");
98         noTldJars.add("servlets-ssi.jar");
99         noTldJars.add("servlets-webdav.jar");
100         noTldJars.add("tomcat-ajp.jar");
101         noTldJars.add("tomcat-coyote.jar");
102         noTldJars.add("tomcat-http.jar");
103         noTldJars.add("tomcat-util.jar");
104         // i18n JARs
105
noTldJars.add("catalina-i18n-en.jar");
106         noTldJars.add("catalina-i18n-es.jar");
107         noTldJars.add("catalina-i18n-fr.jar");
108         noTldJars.add("catalina-i18n-ja.jar");
109         // Misc JARs not included with Tomcat
110
noTldJars.add("ant.jar");
111         noTldJars.add("commons-dbcp.jar");
112         noTldJars.add("commons-beanutils.jar");
113         noTldJars.add("commons-fileupload-1.0.jar");
114         noTldJars.add("commons-pool.jar");
115         noTldJars.add("commons-digester.jar");
116         noTldJars.add("commons-logging.jar");
117         noTldJars.add("commons-collections.jar");
118         noTldJars.add("jmx.jar");
119         noTldJars.add("jmx-tools.jar");
120         noTldJars.add("xercesImpl.jar");
121         noTldJars.add("xmlParserAPIs.jar");
122         noTldJars.add("xml-apis.jar");
123         // JARs from J2SE runtime
124
noTldJars.add("sunjce_provider.jar");
125         noTldJars.add("ldapsec.jar");
126         noTldJars.add("localedata.jar");
127         noTldJars.add("dnsns.jar");
128     }
129
130
131     // ----------------------------------------------------- Instance Variables
132

133     /**
134      * The Context we are associated with.
135      */

136     private Context JavaDoc context = null;
137
138
139     /**
140      * The string resources for this package.
141      */

142     private static final StringManager sm =
143         StringManager.getManager(Constants.Package);
144
145     /**
146      * The <code>Digester</code> we will use to process tag library
147      * descriptor files.
148      */

149     private static Digester tldDigester = null;
150
151
152     /**
153      * Attribute value used to turn on/off TLD validation
154      */

155      private static boolean tldValidation = false;
156
157
158     /**
159      * Attribute value used to turn on/off TLD namespace awarenes.
160      */

161     private static boolean tldNamespaceAware = false;
162
163     private boolean rescan=true;
164
165     private ArrayList JavaDoc listeners=new ArrayList JavaDoc();
166
167     // --------------------------------------------------------- Public Methods
168

169     /**
170      * Sets the list of JARs that are known not to contain any TLDs.
171      *
172      * @param jarNames List of comma-separated names of JAR files that are
173      * known not to contain any TLDs
174      */

175     public static void setNoTldJars(String JavaDoc jarNames) {
176         if (jarNames != null) {
177             noTldJars.clear();
178             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(jarNames, ",");
179             while (tokenizer.hasMoreElements()) {
180                 noTldJars.add(tokenizer.nextToken());
181             }
182         }
183     }
184
185     /**
186      * Set the validation feature of the XML parser used when
187      * parsing xml instances.
188      * @param tldValidation true to enable xml instance validation
189      */

190     public void setTldValidation(boolean tldValidation){
191         TldConfig.tldValidation = tldValidation;
192     }
193
194     /**
195      * Get the server.xml <host> attribute's xmlValidation.
196      * @return true if validation is enabled.
197      *
198      */

199     public boolean getTldValidation(){
200         return tldValidation;
201     }
202
203     /**
204      * Get the server.xml <host> attribute's xmlNamespaceAware.
205      * @return true if namespace awarenes is enabled.
206      *
207      */

208     public boolean getTldNamespaceAware(){
209         return tldNamespaceAware;
210     }
211
212
213     /**
214      * Set the namespace aware feature of the XML parser used when
215      * parsing xml instances.
216      * @param tldNamespaceAware true to enable namespace awareness
217      */

218     public void setTldNamespaceAware(boolean tldNamespaceAware){
219         TldConfig.tldNamespaceAware = tldNamespaceAware;
220     }
221
222
223     public boolean isRescan() {
224         return rescan;
225     }
226
227     public void setRescan(boolean rescan) {
228         this.rescan = rescan;
229     }
230
231     public Context JavaDoc getContext() {
232         return context;
233     }
234
235     public void setContext(Context JavaDoc context) {
236         this.context = context;
237     }
238
239     public void addApplicationListener( String JavaDoc s ) {
240         //if(log.isDebugEnabled())
241
log.debug( "Add tld listener " + s);
242         listeners.add(s);
243     }
244
245     public String JavaDoc[] getTldListeners() {
246         String JavaDoc result[]=new String JavaDoc[listeners.size()];
247         listeners.toArray(result);
248         return result;
249     }
250
251
252     /**
253      * Scan for and configure all tag library descriptors found in this
254      * web application.
255      *
256      * @exception Exception if a fatal input/output or parsing error occurs
257      */

258     public void execute() throws Exception JavaDoc {
259         long t1=System.currentTimeMillis();
260
261         File JavaDoc tldCache=null;
262
263         if (context instanceof StandardContext) {
264             File JavaDoc workDir= (File JavaDoc)
265                 ((StandardContext)context).getServletContext().getAttribute(Globals.WORK_DIR_ATTR);
266             tldCache=new File JavaDoc( workDir, "tldCache.ser");
267         }
268
269         // Option to not rescan
270
if( ! rescan ) {
271             // find the cache
272
if( tldCache!= null && tldCache.exists()) {
273                 // just read it...
274
processCache(tldCache);
275                 return;
276             }
277         }
278
279         /*
280          * Acquire the list of TLD resource paths, possibly embedded in JAR
281          * files, to be processed
282          */

283         Set JavaDoc resourcePaths = tldScanResourcePaths();
284         Map JavaDoc jarPaths = getJarPaths();
285
286         // Check to see if we can use cached listeners
287
if (tldCache != null && tldCache.exists()) {
288             long lastModified = getLastModified(resourcePaths, jarPaths);
289             if (lastModified < tldCache.lastModified()) {
290                 processCache(tldCache);
291                 return;
292             }
293         }
294
295         // Scan each accumulated resource path for TLDs to be processed
296
Iterator JavaDoc paths = resourcePaths.iterator();
297         while (paths.hasNext()) {
298             String JavaDoc path = (String JavaDoc) paths.next();
299             if (path.endsWith(".jar")) {
300                 tldScanJar(path);
301             } else {
302                 tldScanTld(path);
303             }
304         }
305         if (jarPaths != null) {
306             paths = jarPaths.values().iterator();
307             while (paths.hasNext()) {
308                 tldScanJar((File JavaDoc) paths.next());
309             }
310         }
311
312         String JavaDoc list[] = getTldListeners();
313
314         if( tldCache!= null ) {
315             log.debug( "Saving tld cache: " + tldCache + " " + list.length);
316             try {
317                 FileOutputStream JavaDoc out=new FileOutputStream JavaDoc(tldCache);
318                 ObjectOutputStream JavaDoc oos=new ObjectOutputStream JavaDoc( out );
319                 oos.writeObject( list );
320                 oos.close();
321             } catch( IOException JavaDoc ex ) {
322                 ex.printStackTrace();
323             }
324         }
325
326         if( log.isDebugEnabled() )
327             log.debug( "Adding tld listeners:" + list.length);
328         for( int i=0; list!=null && i<list.length; i++ ) {
329             context.addApplicationListener(list[i]);
330         }
331
332         long t2=System.currentTimeMillis();
333         if( context instanceof StandardContext ) {
334             ((StandardContext)context).setTldScanTime(t2-t1);
335         }
336
337     }
338
339     // -------------------------------------------------------- Private Methods
340

341     /*
342      * Returns the last modification date of the given sets of resources.
343      *
344      * @param resourcePaths
345      * @param jarPaths
346      *
347      * @return Last modification date
348      */

349     private long getLastModified(Set JavaDoc resourcePaths, Map JavaDoc jarPaths)
350             throws Exception JavaDoc {
351
352         long lastModified = 0;
353
354         Iterator JavaDoc paths = resourcePaths.iterator();
355         while (paths.hasNext()) {
356             String JavaDoc path = (String JavaDoc) paths.next();
357             URL JavaDoc url = context.getServletContext().getResource(path);
358             if (url == null) {
359                 log.debug( "Null url "+ path );
360                 break;
361             }
362             long lastM = url.openConnection().getLastModified();
363             if (lastM > lastModified) lastModified = lastM;
364             if (log.isDebugEnabled()) {
365                 log.debug( "Last modified " + path + " " + lastM);
366             }
367         }
368
369         if (jarPaths != null) {
370             paths = jarPaths.values().iterator();
371             while (paths.hasNext()) {
372                 File JavaDoc jarFile = (File JavaDoc) paths.next();
373                 long lastM = jarFile.lastModified();
374                 if (lastM > lastModified) lastModified = lastM;
375                 if (log.isDebugEnabled()) {
376                     log.debug("Last modified " + jarFile.getAbsolutePath()
377                               + " " + lastM);
378                 }
379             }
380         }
381
382         return lastModified;
383     }
384
385     private void processCache(File JavaDoc tldCache ) throws IOException JavaDoc {
386         // read the cache and return;
387
try {
388             FileInputStream JavaDoc in=new FileInputStream JavaDoc(tldCache);
389             ObjectInputStream JavaDoc ois=new ObjectInputStream JavaDoc( in );
390             String JavaDoc list[]=(String JavaDoc [])ois.readObject();
391             if( log.isDebugEnabled() )
392                 log.debug("Reusing tldCache " + tldCache + " " + list.length);
393             for( int i=0; list!=null && i<list.length; i++ ) {
394                 context.addApplicationListener(list[i]);
395             }
396             ois.close();
397         } catch( ClassNotFoundException JavaDoc ex ) {
398             ex.printStackTrace();
399         }
400     }
401
402     /**
403      * Create (if necessary) and return a Digester configured to process a tag
404      * library descriptor, looking for additional listener classes to be
405      * registered.
406      */

407     private static Digester createTldDigester() {
408
409         return DigesterFactory.newDigester(tldValidation,
410                                            tldNamespaceAware,
411                                            new TldRuleSet());
412
413     }
414
415
416     /**
417      * Scan the JAR file at the specified resource path for TLDs in the
418      * <code>META-INF</code> subdirectory, and scan each TLD for application
419      * event listeners that need to be registered.
420      *
421      * @param resourcePath Resource path of the JAR file to scan
422      *
423      * @exception Exception if an exception occurs while scanning this JAR
424      */

425     private void tldScanJar(String JavaDoc resourcePath) throws Exception JavaDoc {
426
427         if (log.isDebugEnabled()) {
428             log.debug(" Scanning JAR at resource path '" + resourcePath + "'");
429         }
430
431         URL JavaDoc url = context.getServletContext().getResource(resourcePath);
432         if (url == null) {
433             throw new IllegalArgumentException JavaDoc
434                                 (sm.getString("contextConfig.tldResourcePath",
435                                               resourcePath));
436         }
437
438         File JavaDoc file = new File JavaDoc(url.getFile());
439         file = file.getCanonicalFile();
440         tldScanJar(file);
441
442     }
443
444     /**
445      * Scans all TLD entries in the given JAR for application listeners.
446      *
447      * @param file JAR file whose TLD entries are scanned for application
448      * listeners
449      */

450     private void tldScanJar(File JavaDoc file) throws Exception JavaDoc {
451
452         JarFile JavaDoc jarFile = null;
453         String JavaDoc name = null;
454
455         String JavaDoc jarPath = file.getAbsolutePath();
456
457         try {
458             jarFile = new JarFile JavaDoc(file);
459             Enumeration JavaDoc entries = jarFile.entries();
460             while (entries.hasMoreElements()) {
461                 JarEntry JavaDoc entry = (JarEntry JavaDoc) entries.nextElement();
462                 name = entry.getName();
463                 if (!name.startsWith("META-INF/")) {
464                     continue;
465                 }
466                 if (!name.endsWith(".tld")) {
467                     continue;
468                 }
469                 if (log.isTraceEnabled()) {
470                     log.trace(" Processing TLD at '" + name + "'");
471                 }
472                 try {
473                     tldScanStream(new InputSource JavaDoc(jarFile.getInputStream(entry)));
474                 } catch (Exception JavaDoc e) {
475                     log.error(sm.getString("contextConfig.tldEntryException",
476                                            name, jarPath, context.getPath()),
477                               e);
478                 }
479             }
480         } catch (Exception JavaDoc e) {
481             log.error(sm.getString("contextConfig.tldJarException",
482                                    jarPath, context.getPath()),
483                       e);
484         } finally {
485             if (jarFile != null) {
486                 try {
487                     jarFile.close();
488                 } catch (Throwable JavaDoc t) {
489                     // Ignore
490
}
491             }
492         }
493     }
494
495     /**
496      * Scan the TLD contents in the specified input stream, and register
497      * any application event listeners found there. <b>NOTE</b> - It is
498      * the responsibility of the caller to close the InputStream after this
499      * method returns.
500      *
501      * @param resourceStream InputStream containing a tag library descriptor
502      *
503      * @exception Exception if an exception occurs while scanning this TLD
504      */

505     private void tldScanStream(InputSource JavaDoc resourceStream)
506         throws Exception JavaDoc {
507
508         if (tldDigester == null){
509             tldDigester = createTldDigester();
510         }
511         
512         synchronized (tldDigester) {
513             try {
514                 tldDigester.push(this);
515                 tldDigester.parse(resourceStream);
516             } finally {
517                 tldDigester.reset();
518             }
519         }
520
521     }
522
523     /**
524      * Scan the TLD contents at the specified resource path, and register
525      * any application event listeners found there.
526      *
527      * @param resourcePath Resource path being scanned
528      *
529      * @exception Exception if an exception occurs while scanning this TLD
530      */

531     private void tldScanTld(String JavaDoc resourcePath) throws Exception JavaDoc {
532
533         if (log.isDebugEnabled()) {
534             log.debug(" Scanning TLD at resource path '" + resourcePath + "'");
535         }
536
537         InputSource JavaDoc inputSource = null;
538         try {
539             InputStream JavaDoc stream =
540                 context.getServletContext().getResourceAsStream(resourcePath);
541             if (stream == null) {
542                 throw new IllegalArgumentException JavaDoc
543                 (sm.getString("contextConfig.tldResourcePath",
544                         resourcePath));
545             }
546             inputSource = new InputSource JavaDoc(stream);
547             if (inputSource == null) {
548                 throw new IllegalArgumentException JavaDoc
549                     (sm.getString("contextConfig.tldResourcePath",
550                                   resourcePath));
551             }
552             tldScanStream(inputSource);
553         } catch (Exception JavaDoc e) {
554              throw new ServletException JavaDoc
555                  (sm.getString("contextConfig.tldFileException", resourcePath,
556                                context.getPath()),
557                   e);
558         }
559
560     }
561
562     /**
563      * Accumulate and return a Set of resource paths to be analyzed for
564      * tag library descriptors. Each element of the returned set will be
565      * the context-relative path to either a tag library descriptor file,
566      * or to a JAR file that may contain tag library descriptors in its
567      * <code>META-INF</code> subdirectory.
568      *
569      * @exception IOException if an input/output error occurs while
570      * accumulating the list of resource paths
571      */

572     private Set JavaDoc tldScanResourcePaths() throws IOException JavaDoc {
573         if (log.isDebugEnabled()) {
574             log.debug(" Accumulating TLD resource paths");
575         }
576         Set JavaDoc resourcePaths = new HashSet JavaDoc();
577
578         // Accumulate resource paths explicitly listed in the web application
579
// deployment descriptor
580
if (log.isTraceEnabled()) {
581             log.trace(" Scanning <taglib> elements in web.xml");
582         }
583         String JavaDoc taglibs[] = context.findTaglibs();
584         for (int i = 0; i < taglibs.length; i++) {
585             String JavaDoc resourcePath = context.findTaglib(taglibs[i]);
586             // FIXME - Servlet 2.4 DTD implies that the location MUST be
587
// a context-relative path starting with '/'?
588
if (!resourcePath.startsWith("/")) {
589                 resourcePath = "/WEB-INF/" + resourcePath;
590             }
591             if (log.isTraceEnabled()) {
592                 log.trace(" Adding path '" + resourcePath +
593                     "' for URI '" + taglibs[i] + "'");
594             }
595             resourcePaths.add(resourcePath);
596         }
597
598         DirContext JavaDoc resources = context.getResources();
599         if (resources != null) {
600             tldScanResourcePathsWebInf(resources, "/WEB-INF", resourcePaths);
601         }
602
603         // Return the completed set
604
return (resourcePaths);
605
606     }
607
608     /*
609      * Scans the web application's subdirectory identified by rootPath,
610      * along with its subdirectories, for TLDs.
611      *
612      * Initially, rootPath equals /WEB-INF. The /WEB-INF/classes and
613      * /WEB-INF/lib subdirectories are excluded from the search, as per the
614      * JSP 2.0 spec.
615      *
616      * @param resources The web application's resources
617      * @param rootPath The path whose subdirectories are to be searched for
618      * TLDs
619      * @param tldPaths The set of TLD resource paths to add to
620      */

621     private void tldScanResourcePathsWebInf(DirContext JavaDoc resources,
622                                             String JavaDoc rootPath,
623                                             Set JavaDoc tldPaths)
624             throws IOException JavaDoc {
625
626         if (log.isTraceEnabled()) {
627             log.trace(" Scanning TLDs in " + rootPath + " subdirectory");
628         }
629
630         try {
631             NamingEnumeration JavaDoc items = resources.list(rootPath);
632             while (items.hasMoreElements()) {
633                 NameClassPair JavaDoc item = (NameClassPair JavaDoc) items.nextElement();
634                 String JavaDoc resourcePath = rootPath + "/" + item.getName();
635                 if (!resourcePath.endsWith(".tld")
636                         && (resourcePath.startsWith("/WEB-INF/classes")
637                             || resourcePath.startsWith("/WEB-INF/lib"))) {
638                     continue;
639                 }
640                 if (resourcePath.endsWith(".tld")) {
641                     if (log.isTraceEnabled()) {
642                         log.trace(" Adding path '" + resourcePath + "'");
643                     }
644                     tldPaths.add(resourcePath);
645                 } else {
646                     tldScanResourcePathsWebInf(resources, resourcePath,
647                                                tldPaths);
648                 }
649             }
650         } catch (NamingException JavaDoc e) {
651             ; // Silent catch: it's valid that no /WEB-INF directory exists
652
}
653     }
654
655     /**
656      * Returns a map of the paths to all JAR files that are accessible to the
657      * webapp and will be scanned for TLDs.
658      *
659      * The map always includes all the JARs under WEB-INF/lib, as well as
660      * shared JARs in the classloader delegation chain of the webapp's
661      * classloader.
662      *
663      * The latter constitutes a Tomcat-specific extension to the TLD search
664      * order defined in the JSP spec. It allows tag libraries packaged as JAR
665      * files to be shared by web applications by simply dropping them in a
666      * location that all web applications have access to (e.g.,
667      * <CATALINA_HOME>/common/lib).
668      *
669      * The set of shared JARs to be scanned for TLDs is narrowed down by
670      * the <tt>noTldJars</tt> class variable, which contains the names of JARs
671      * that are known not to contain any TLDs.
672      *
673      * @return Map of JAR file paths
674      */

675     private Map JavaDoc getJarPaths() {
676
677         HashMap JavaDoc jarPathMap = null;
678
679         ClassLoader JavaDoc webappLoader = Thread.currentThread().getContextClassLoader();
680         ClassLoader JavaDoc loader = webappLoader;
681         while (loader != null) {
682             if (loader instanceof URLClassLoader JavaDoc) {
683                 URL JavaDoc[] urls = ((URLClassLoader JavaDoc) loader).getURLs();
684                 for (int i=0; i<urls.length; i++) {
685                     // Expect file URLs
686
// This is definitely not as clean as using JAR URLs either
687
// over file or the custom jndi handler, but a lot less
688
// buggy overall
689
File JavaDoc file = new File JavaDoc(urls[i].getFile());
690                     try {
691                         file = file.getCanonicalFile();
692                     } catch (IOException JavaDoc e) {
693                         // Ignore
694
}
695                     if (!file.exists()) {
696                         continue;
697                     }
698                     String JavaDoc path = file.getAbsolutePath();
699                     if (!path.endsWith(".jar")) {
700                         continue;
701                     }
702                     /*
703                      * Scan all JARs from WEB-INF/lib, plus any shared JARs
704                      * that are not known not to contain any TLDs
705                      */

706                     if (loader == webappLoader
707                             || noTldJars == null
708                             || !noTldJars.contains(file.getName())) {
709                         if (jarPathMap == null) {
710                             jarPathMap = new HashMap JavaDoc();
711                             jarPathMap.put(path, file);
712                         } else if (!jarPathMap.containsKey(path)) {
713                             jarPathMap.put(path, file);
714                         }
715                     }
716                 }
717             }
718             loader = loader.getParent();
719         }
720
721         return jarPathMap;
722     }
723 }
724
Popular Tags