001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.startup;
018:
019: import java.io.File;
020: import java.net.URL;
021: import java.util.ArrayList;
022:
023: import org.apache.catalina.loader.StandardClassLoader;
024: import org.apache.tomcat.util.compat.JdkCompat;
025:
026: /**
027: * <p>Utility class for building class loaders for Catalina. The factory
028: * method requires the following parameters in order to build a new class
029: * loader (with suitable defaults in all cases):</p>
030: * <ul>
031: * <li>A set of directories containing unpacked classes (and resources)
032: * that should be included in the class loader's
033: * repositories.</li>
034: * <li>A set of directories containing classes and resources in JAR files.
035: * Each readable JAR file discovered in these directories will be
036: * added to the class loader's repositories.</li>
037: * <li><code>ClassLoader</code> instance that should become the parent of
038: * the new class loader.</li>
039: * </ul>
040: *
041: * @author Craig R. McClanahan
042: * @version $Revision: 1.6.2.1 $ $Date: 2004/08/24 17:53:52 $
043: */
044:
045: public final class ClassLoaderFactory {
046:
047: // ------------------------------------------------------- Static Variables
048:
049: /**
050: * Debugging detail level for processing the startup.
051: */
052: private static int debug = 0;
053:
054: /**
055: * JDK compatibility support
056: */
057: private static final JdkCompat jdkCompat = JdkCompat.getJdkCompat();
058:
059: // ------------------------------------------------------ Static Properties
060:
061: /**
062: * Return the debugging detail level.
063: */
064: public static int getDebug() {
065:
066: return (debug);
067:
068: }
069:
070: /**
071: * Set the debugging detail level.
072: *
073: * @param newDebug The new debugging detail level
074: */
075: public static void setDebug(int newDebug) {
076:
077: debug = newDebug;
078:
079: }
080:
081: // --------------------------------------------------------- Public Methods
082:
083: /**
084: * Create and return a new class loader, based on the configuration
085: * defaults and the specified directory paths:
086: *
087: * @param unpacked Array of pathnames to unpacked directories that should
088: * be added to the repositories of the class loader, or <code>null</code>
089: * for no unpacked directories to be considered
090: * @param packed Array of pathnames to directories containing JAR files
091: * that should be added to the repositories of the class loader,
092: * or <code>null</code> for no 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[], ClassLoader parent) throws Exception {
100: return createClassLoader(unpacked, packed, null, parent);
101: }
102:
103: /**
104: * Create and return a new class loader, based on the configuration
105: * defaults and the specified directory paths:
106: *
107: * @param unpacked Array of pathnames to unpacked directories that should
108: * be added to the repositories of the class loader, or <code>null</code>
109: * for no unpacked directories to be considered
110: * @param packed Array of pathnames to directories containing JAR files
111: * that should be added to the repositories of the class loader,
112: * or <code>null</code> for no directories of JAR files to be considered
113: * @param urls Array of URLs to remote repositories, designing either JAR
114: * resources or uncompressed directories that should be added to
115: * the repositories of the class loader, or <code>null</code> for no
116: * directories of JAR files to be considered
117: * @param parent Parent class loader for the new class loader, or
118: * <code>null</code> for the system class loader.
119: *
120: * @exception Exception if an error occurs constructing the class loader
121: */
122: public static ClassLoader createClassLoader(File unpacked[],
123: File packed[], URL urls[], ClassLoader parent)
124: throws Exception {
125:
126: if (debug >= 1)
127: log("Creating new class loader");
128:
129: // Construct the "class path" for this class loader
130: ArrayList list = new ArrayList();
131:
132: // Add unpacked directories
133: if (unpacked != null) {
134: for (int i = 0; i < unpacked.length; i++) {
135: File file = unpacked[i];
136: if (!file.exists() || !file.canRead())
137: continue;
138: if (debug >= 1)
139: log(" Including directory or JAR "
140: + file.getAbsolutePath());
141: URL url = new URL("file", null, file.getCanonicalPath()
142: + File.separator);
143: list.add(url.toString());
144: }
145: }
146:
147: // Add packed directory JAR files
148: if (packed != null) {
149: for (int i = 0; i < packed.length; i++) {
150: File directory = packed[i];
151: if (!directory.isDirectory() || !directory.exists()
152: || !directory.canRead())
153: continue;
154: String filenames[] = directory.list();
155: for (int j = 0; j < filenames.length; j++) {
156: String filename = filenames[j].toLowerCase();
157: if (!filename.endsWith(".jar"))
158: continue;
159: File file = new File(directory, filenames[j]);
160: if (debug >= 1)
161: log(" Including jar file "
162: + file.getAbsolutePath());
163: URL url = new URL("file", null, file
164: .getCanonicalPath());
165:
166: if (ClassLoaderFactory.jdkCompat.isJava15()) {
167: if (url.toString().endsWith("xml-apis.jar")
168: || url.toString().endsWith(
169: "xercesImpl.jar")) {
170: // Do not load xml-apis.jar & xercesImpl.jar
171: // if JDK 5.0 is used
172: } else {
173: list.add(url.toString());
174: }
175: } else {
176: list.add(url.toString());
177: }
178: }
179: }
180: }
181:
182: // Add URLs
183: if (urls != null) {
184: for (int i = 0; i < urls.length; i++) {
185: list.add(urls[i].toString());
186: }
187: }
188:
189: // Construct the class loader itself
190: String array[] = (String[]) list
191: .toArray(new String[list.size()]);
192: StandardClassLoader classLoader = null;
193: if (parent == null)
194: classLoader = new StandardClassLoader(array);
195: else
196: classLoader = new StandardClassLoader(array, parent);
197: classLoader.setDelegate(true);
198: return (classLoader);
199:
200: }
201:
202: // -------------------------------------------------------- Private Methods
203:
204: /**
205: * Log a message for this class.
206: *
207: * @param message Message to be logged
208: */
209: private static void log(String message) {
210:
211: System.out.print("ClassLoaderFactory: ");
212: System.out.println(message);
213:
214: }
215:
216: /**
217: * Log a message and exception for this class.
218: *
219: * @param message Message to be logged
220: * @param exception Exception to be logged
221: */
222: private static void log(String message, Throwable exception) {
223:
224: log(message);
225: exception.printStackTrace(System.out);
226:
227: }
228:
229: }
|