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.catalina.startup;
019:
020: import java.io.File;
021: import java.net.URL;
022: import java.util.ArrayList;
023:
024: import org.apache.catalina.loader.StandardClassLoader;
025: import org.apache.juli.logging.Log;
026: import org.apache.juli.logging.LogFactory;
027:
028: /**
029: * <p>Utility class for building class loaders for Catalina. The factory
030: * method requires the following parameters in order to build a new class
031: * loader (with suitable defaults in all cases):</p>
032: * <ul>
033: * <li>A set of directories containing unpacked classes (and resources)
034: * that should be included in the class loader's
035: * repositories.</li>
036: * <li>A set of directories containing classes and resources in JAR files.
037: * Each readable JAR file discovered in these directories will be
038: * added to the class loader's repositories.</li>
039: * <li><code>ClassLoader</code> instance that should become the parent of
040: * the new class loader.</li>
041: * </ul>
042: *
043: * @author Craig R. McClanahan
044: * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
045: */
046:
047: public final class ClassLoaderFactory {
048:
049: private static Log log = LogFactory
050: .getLog(ClassLoaderFactory.class);
051:
052: protected static final Integer IS_DIR = new Integer(0);
053: protected static final Integer IS_JAR = new Integer(1);
054: protected static final Integer IS_GLOB = new Integer(2);
055: protected static final Integer IS_URL = new Integer(3);
056:
057: // --------------------------------------------------------- Public Methods
058:
059: /**
060: * Create and return a new class loader, based on the configuration
061: * defaults and the specified directory paths:
062: *
063: * @param unpacked Array of pathnames to unpacked directories that should
064: * be added to the repositories of the class loader, or <code>null</code>
065: * for no unpacked directories to be considered
066: * @param packed Array of pathnames to directories containing JAR files
067: * that should be added to the repositories of the class loader,
068: * or <code>null</code> for no directories of JAR files to be considered
069: * @param parent Parent class loader for the new class loader, or
070: * <code>null</code> for the system class loader.
071: *
072: * @exception Exception if an error occurs constructing the class loader
073: */
074: public static ClassLoader createClassLoader(File unpacked[],
075: File packed[], ClassLoader parent) throws Exception {
076: return createClassLoader(unpacked, packed, null, parent);
077: }
078:
079: /**
080: * Create and return a new class loader, based on the configuration
081: * defaults and the specified directory paths:
082: *
083: * @param unpacked Array of pathnames to unpacked directories that should
084: * be added to the repositories of the class loader, or <code>null</code>
085: * for no unpacked directories to be considered
086: * @param packed Array of pathnames to directories containing JAR files
087: * that should be added to the repositories of the class loader,
088: * or <code>null</code> for no directories of JAR files to be considered
089: * @param urls Array of URLs to remote repositories, designing either JAR
090: * resources or uncompressed directories that should be added to
091: * the repositories of the class loader, or <code>null</code> for no
092: * directories of JAR files to be considered
093: * @param parent Parent class loader for the new class loader, or
094: * <code>null</code> for the system class loader.
095: *
096: * @exception Exception if an error occurs constructing the class loader
097: */
098: public static ClassLoader createClassLoader(File unpacked[],
099: File packed[], URL urls[], ClassLoader parent)
100: throws Exception {
101:
102: if (log.isDebugEnabled())
103: log.debug("Creating new class loader");
104:
105: // Construct the "class path" for this class loader
106: ArrayList list = new ArrayList();
107:
108: // Add unpacked directories
109: if (unpacked != null) {
110: for (int i = 0; i < unpacked.length; i++) {
111: File file = unpacked[i];
112: if (!file.exists() || !file.canRead())
113: continue;
114: file = new File(file.getCanonicalPath()
115: + File.separator);
116: URL url = file.toURL();
117: if (log.isDebugEnabled())
118: log.debug(" Including directory " + url);
119: list.add(url);
120: }
121: }
122:
123: // Add packed directory JAR files
124: if (packed != null) {
125: for (int i = 0; i < packed.length; i++) {
126: File directory = packed[i];
127: if (!directory.isDirectory() || !directory.exists()
128: || !directory.canRead())
129: continue;
130: String filenames[] = directory.list();
131: for (int j = 0; j < filenames.length; j++) {
132: String filename = filenames[j].toLowerCase();
133: if (!filename.endsWith(".jar"))
134: continue;
135: File file = new File(directory, filenames[j]);
136: if (log.isDebugEnabled())
137: log.debug(" Including jar file "
138: + file.getAbsolutePath());
139: URL url = file.toURL();
140: list.add(url);
141: }
142: }
143: }
144:
145: // Construct the class loader itself
146: URL[] array = (URL[]) list.toArray(new URL[list.size()]);
147: StandardClassLoader classLoader = null;
148: if (parent == null)
149: classLoader = new StandardClassLoader(array);
150: else
151: classLoader = new StandardClassLoader(array, parent);
152: return (classLoader);
153:
154: }
155:
156: /**
157: * Create and return a new class loader, based on the configuration
158: * defaults and the specified directory paths:
159: *
160: * @param locations Array of strings containing class directories, jar files,
161: * jar directories or URLS that should be added to the repositories of
162: * the class loader. The type is given by the member of param types.
163: * @param types Array of types for the members of param locations.
164: * Possible values are IS_DIR (class directory), IS_JAR (single jar file),
165: * IS_GLOB (directory of jar files) and IS_URL (URL).
166: * @param parent Parent class loader for the new class loader, or
167: * <code>null</code> for the system class loader.
168: *
169: * @exception Exception if an error occurs constructing the class loader
170: */
171: public static ClassLoader createClassLoader(String locations[],
172: Integer types[], ClassLoader parent) throws Exception {
173:
174: if (log.isDebugEnabled())
175: log.debug("Creating new class loader");
176:
177: // Construct the "class path" for this class loader
178: ArrayList list = new ArrayList();
179:
180: if (locations != null && types != null
181: && locations.length == types.length) {
182: for (int i = 0; i < locations.length; i++) {
183: String location = locations[i];
184: if (types[i] == IS_URL) {
185: URL url = new URL(location);
186: if (log.isDebugEnabled())
187: log.debug(" Including URL " + url);
188: list.add(url);
189: } else if (types[i] == IS_DIR) {
190: File directory = new File(location);
191: directory = new File(directory.getCanonicalPath());
192: if (!directory.exists() || !directory.isDirectory()
193: || !directory.canRead())
194: continue;
195: URL url = directory.toURL();
196: if (log.isDebugEnabled())
197: log.debug(" Including directory " + url);
198: list.add(url);
199: } else if (types[i] == IS_JAR) {
200: File file = new File(location);
201: file = new File(file.getCanonicalPath());
202: if (!file.exists() || !file.canRead())
203: continue;
204: URL url = file.toURL();
205: if (log.isDebugEnabled())
206: log.debug(" Including jar file " + url);
207: list.add(url);
208: } else if (types[i] == IS_GLOB) {
209: File directory = new File(location);
210: if (!directory.exists() || !directory.isDirectory()
211: || !directory.canRead())
212: continue;
213: if (log.isDebugEnabled())
214: log.debug(" Including directory glob "
215: + directory.getAbsolutePath());
216: String filenames[] = directory.list();
217: for (int j = 0; j < filenames.length; j++) {
218: String filename = filenames[j].toLowerCase();
219: if (!filename.endsWith(".jar"))
220: continue;
221: File file = new File(directory, filenames[j]);
222: file = new File(file.getCanonicalPath());
223: if (!file.exists() || !file.canRead())
224: continue;
225: if (log.isDebugEnabled())
226: log.debug(" Including glob jar file "
227: + file.getAbsolutePath());
228: URL url = file.toURL();
229: list.add(url);
230: }
231: }
232: }
233: }
234:
235: // Construct the class loader itself
236: URL[] array = (URL[]) list.toArray(new URL[list.size()]);
237: if (log.isDebugEnabled())
238: for (int i = 0; i < array.length; i++) {
239: log.debug(" location " + i + " is " + array[i]);
240: }
241: StandardClassLoader classLoader = null;
242: if (parent == null)
243: classLoader = new StandardClassLoader(array);
244: else
245: classLoader = new StandardClassLoader(array, parent);
246: return (classLoader);
247:
248: }
249:
250: }
|