View Javadoc

1   // ========================================================================
2   // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  
15  package org.eclipse.jetty.webapp;
16  
17  import java.io.InputStream;
18  import java.net.URI;
19  import java.net.URL;
20  import java.net.URLClassLoader;
21  import java.util.jar.JarEntry;
22  import java.util.jar.JarInputStream;
23  import java.util.regex.Pattern;
24  
25  import org.eclipse.jetty.util.log.Log;
26  import org.eclipse.jetty.util.resource.Resource;
27  
28  /**
29   * JarScannerConfiguration
30   *
31   * Abstract base class for configurations that want to scan jars in
32   * WEB-INF/lib and the classloader hierarchy.
33   * 
34   * Jar name matching based on regexp patterns is provided.
35   * 
36   * Subclasses should implement the processEntry(URL jarUrl, JarEntry entry)
37   * method to handle entries in jar files whose names match the supplied 
38   * pattern.
39   */
40  public abstract class JarScanner extends org.eclipse.jetty.util.PatternMatcher
41  {
42  
43      public abstract void processEntry (URI jarUri, JarEntry entry);
44      
45      /**
46       * Find jar names from the provided list matching a pattern.
47       * 
48       * If the pattern is null and isNullInclusive is true, then
49       * all jar names will match.
50       * 
51       * A pattern is a set of acceptable jar names. Each acceptable
52       * jar name is a regex. Each regex can be separated by either a
53       * "," or a "|". If you use a "|" this or's together the jar
54       * name patterns. This means that ordering of the matches is
55       * unimportant to you. If instead, you want to match particular
56       * jar names, and you want to match them in order, you should
57       * separate the regexs with "," instead. 
58       * 
59       * Eg "aaa-.*\\.jar|bbb-.*\\.jar"
60       * Will iterate over the jar names and match
61       * in any order.
62       * 
63       * Eg "aaa-*\\.jar,bbb-.*\\.jar"
64       * Will iterate over the jar names, matching
65       * all those starting with "aaa-" first, then "bbb-".
66       *
67       * @param pattern
68       * @param uris
69       * @param isNullInclusive if true, an empty pattern means all names match, if false, none match
70       * @throws Exception
71       */
72      public void scan (Pattern pattern, URI[] uris, boolean isNullInclusive)
73      throws Exception
74      {
75         super.match(pattern, uris, isNullInclusive);
76      }
77      
78      /**
79       * Find jar names from the classloader matching a pattern.
80       * 
81       * If the pattern is null and isNullInclusive is true, then
82       * all jar names in the classloader will match.
83       * 
84       * A pattern is a set of acceptable jar names. Each acceptable
85       * jar name is a regex. Each regex can be separated by either a
86       * "," or a "|". If you use a "|" this or's together the jar
87       * name patterns. This means that ordering of the matches is
88       * unimportant to you. If instead, you want to match particular
89       * jar names, and you want to match them in order, you should
90       * separate the regexs with "," instead. 
91       * 
92       * Eg "aaa-.*\\.jar|bbb-.*\\.jar"
93       * Will iterate over the jar names in the classloader and match
94       * in any order.
95       * 
96       * Eg "aaa-*\\.jar,bbb-.*\\.jar"
97       * Will iterate over the jar names in the classloader, matching
98       * all those starting with "aaa-" first, then "bbb-".
99       * 
100      * If visitParent is true, then the pattern is applied to the
101      * parent loader hierarchy. If false, it is only applied to the
102      * classloader passed in.
103      * 
104      * @param pattern
105      * @param loader
106      * @param isNullInclusive
107      * @param visitParent
108      * @throws Exception
109      */
110     public void scan (Pattern pattern, ClassLoader loader, boolean isNullInclusive, boolean visitParent)
111     throws Exception
112     {
113         while (loader!=null)
114         {
115             if (loader instanceof URLClassLoader)
116             {
117                 URL[] urls = ((URLClassLoader)loader).getURLs();
118                 if (urls != null)
119                 {
120                     URI[] uris = new URI[urls.length];
121                     int i=0;
122                     for (URL u : urls)
123                         uris[i++] = u.toURI();
124                     scan (pattern, uris, isNullInclusive);
125                 }
126             }     
127             if (visitParent)
128                 loader=loader.getParent();
129             else
130                 loader = null;
131         }  
132     }
133     
134     
135     public void matched (URI uri)
136     throws Exception
137     {
138         Log.debug("Search of {}",uri);
139         if (uri.toString().toLowerCase().endsWith(".jar"))
140         {
141          
142             InputStream in = Resource.newResource(uri).getInputStream();
143             if (in==null)
144                 return;
145 
146             JarInputStream jar_in = new JarInputStream(in);
147             try
148             { 
149                 JarEntry entry = jar_in.getNextJarEntry();
150                 while (entry!=null)
151                 {
152                     processEntry(uri, entry);
153                     entry = jar_in.getNextJarEntry();
154                 }
155             }
156             finally
157             {
158                 jar_in.close();
159             }   
160         }
161     }
162 }