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