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;
23 import java.net.URL;
24 import java.util.ArrayList;
25
26 import org.apache.catalina.loader.StandardClassLoader;
27 import org.apache.juli.logging.Log;
28 import org.apache.juli.logging.LogFactory;
29
30
31 /**
32 * <p>Utility class for building class loaders for Catalina. The factory
33 * method requires the following parameters in order to build a new class
34 * loader (with suitable defaults in all cases):</p>
35 * <ul>
36 * <li>A set of directories containing unpacked classes (and resources)
37 * that should be included in the class loader's
38 * repositories.</li>
39 * <li>A set of directories containing classes and resources in JAR files.
40 * Each readable JAR file discovered in these directories will be
41 * added to the class loader's repositories.</li>
42 * <li><code>ClassLoader</code> instance that should become the parent of
43 * the new class loader.</li>
44 * </ul>
45 *
46 * @author Craig R. McClanahan
47 * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
48 */
49
50 public final class ClassLoaderFactory {
51
52
53 private static Log log = LogFactory.getLog(ClassLoaderFactory.class);
54
55 protected static final Integer IS_DIR = new Integer(0);
56 protected static final Integer IS_JAR = new Integer(1);
57 protected static final Integer IS_GLOB = new Integer(2);
58 protected static final Integer IS_URL = new Integer(3);
59
60 // --------------------------------------------------------- Public Methods
61
62
63 /**
64 * Create and return a new class loader, based on the configuration
65 * defaults and the specified directory paths:
66 *
67 * @param unpacked Array of pathnames to unpacked directories that should
68 * be added to the repositories of the class loader, or <code>null</code>
69 * for no unpacked directories to be considered
70 * @param packed Array of pathnames to directories containing JAR files
71 * that should be added to the repositories of the class loader,
72 * or <code>null</code> for no directories of JAR files to be considered
73 * @param parent Parent class loader for the new class loader, or
74 * <code>null</code> for the system class loader.
75 *
76 * @exception Exception if an error occurs constructing the class loader
77 */
78 public static ClassLoader createClassLoader(File unpacked[],
79 File packed[],
80 ClassLoader parent)
81 throws Exception {
82 return createClassLoader(unpacked, packed, null, parent);
83 }
84
85
86 /**
87 * Create and return a new class loader, based on the configuration
88 * defaults and the specified directory paths:
89 *
90 * @param unpacked Array of pathnames to unpacked directories that should
91 * be added to the repositories of the class loader, or <code>null</code>
92 * for no unpacked directories to be considered
93 * @param packed Array of pathnames to directories containing JAR files
94 * that should be added to the repositories of the class loader,
95 * or <code>null</code> for no directories of JAR files to be considered
96 * @param urls Array of URLs to remote repositories, designing either JAR
97 * resources or uncompressed directories that should be added to
98 * the repositories of the class loader, or <code>null</code> for no
99 * directories of JAR files to be considered
100 * @param parent Parent class loader for the new class loader, or
101 * <code>null</code> for the system class loader.
102 *
103 * @exception Exception if an error occurs constructing the class loader
104 */
105 public static ClassLoader createClassLoader(File unpacked[],
106 File packed[],
107 URL urls[],
108 ClassLoader parent)
109 throws Exception {
110
111 if (log.isDebugEnabled())
112 log.debug("Creating new class loader");
113
114 // Construct the "class path" for this class loader
115 ArrayList list = new ArrayList();
116
117 // Add unpacked directories
118 if (unpacked != null) {
119 for (int i = 0; i < unpacked.length; i++) {
120 File file = unpacked[i];
121 if (!file.exists() || !file.canRead())
122 continue;
123 file = new File(file.getCanonicalPath() + File.separator);
124 URL url = file.toURL();
125 if (log.isDebugEnabled())
126 log.debug(" Including directory " + url);
127 list.add(url);
128 }
129 }
130
131 // Add packed directory JAR files
132 if (packed != null) {
133 for (int i = 0; i < packed.length; i++) {
134 File directory = packed[i];
135 if (!directory.isDirectory() || !directory.exists() ||
136 !directory.canRead())
137 continue;
138 String filenames[] = directory.list();
139 for (int j = 0; j < filenames.length; j++) {
140 String filename = filenames[j].toLowerCase();
141 if (!filename.endsWith(".jar"))
142 continue;
143 File file = new File(directory, filenames[j]);
144 if (log.isDebugEnabled())
145 log.debug(" Including jar file " + file.getAbsolutePath());
146 URL url = file.toURL();
147 list.add(url);
148 }
149 }
150 }
151
152 // Construct the class loader itself
153 URL[] array = (URL[]) list.toArray(new URL[list.size()]);
154 StandardClassLoader classLoader = null;
155 if (parent == null)
156 classLoader = new StandardClassLoader(array);
157 else
158 classLoader = new StandardClassLoader(array, parent);
159 return (classLoader);
160
161 }
162
163
164 /**
165 * Create and return a new class loader, based on the configuration
166 * defaults and the specified directory paths:
167 *
168 * @param locations Array of strings containing class directories, jar files,
169 * jar directories or URLS that should be added to the repositories of
170 * the class loader. The type is given by the member of param types.
171 * @param types Array of types for the members of param locations.
172 * Possible values are IS_DIR (class directory), IS_JAR (single jar file),
173 * IS_GLOB (directory of jar files) and IS_URL (URL).
174 * @param parent Parent class loader for the new class loader, or
175 * <code>null</code> for the system class loader.
176 *
177 * @exception Exception if an error occurs constructing the class loader
178 */
179 public static ClassLoader createClassLoader(String locations[],
180 Integer types[],
181 ClassLoader parent)
182 throws Exception {
183
184 if (log.isDebugEnabled())
185 log.debug("Creating new class loader");
186
187 // Construct the "class path" for this class loader
188 ArrayList list = new ArrayList();
189
190 if (locations != null && types != null && locations.length == types.length) {
191 for (int i = 0; i < locations.length; i++) {
192 String location = locations[i];
193 if ( types[i] == IS_URL ) {
194 URL url = new URL(location);
195 if (log.isDebugEnabled())
196 log.debug(" Including URL " + url);
197 list.add(url);
198 } else if ( types[i] == IS_DIR ) {
199 File directory = new File(location);
200 directory = new File(directory.getCanonicalPath());
201 if (!directory.exists() || !directory.isDirectory() ||
202 !directory.canRead())
203 continue;
204 URL url = directory.toURL();
205 if (log.isDebugEnabled())
206 log.debug(" Including directory " + url);
207 list.add(url);
208 } else if ( types[i] == IS_JAR ) {
209 File file=new File(location);
210 file = new File(file.getCanonicalPath());
211 if (!file.exists() || !file.canRead())
212 continue;
213 URL url = file.toURL();
214 if (log.isDebugEnabled())
215 log.debug(" Including jar file " + url);
216 list.add(url);
217 } else if ( types[i] == IS_GLOB ) {
218 File directory=new File(location);
219 if (!directory.exists() || !directory.isDirectory() ||
220 !directory.canRead())
221 continue;
222 if (log.isDebugEnabled())
223 log.debug(" Including directory glob "
224 + directory.getAbsolutePath());
225 String filenames[] = directory.list();
226 for (int j = 0; j < filenames.length; j++) {
227 String filename = filenames[j].toLowerCase();
228 if (!filename.endsWith(".jar"))
229 continue;
230 File file = new File(directory, filenames[j]);
231 file = new File(file.getCanonicalPath());
232 if (!file.exists() || !file.canRead())
233 continue;
234 if (log.isDebugEnabled())
235 log.debug(" Including glob jar file "
236 + file.getAbsolutePath());
237 URL url = file.toURL();
238 list.add(url);
239 }
240 }
241 }
242 }
243
244 // Construct the class loader itself
245 URL[] array = (URL[]) list.toArray(new URL[list.size()]);
246 if (log.isDebugEnabled())
247 for (int i = 0; i < array.length; i++) {
248 log.debug(" location " + i + " is " + array[i]);
249 }
250 StandardClassLoader classLoader = null;
251 if (parent == null)
252 classLoader = new StandardClassLoader(array);
253 else
254 classLoader = new StandardClassLoader(array, parent);
255 return (classLoader);
256
257 }
258
259
260 }