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: package org.apache.cocoon.servlet;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.net.URL;
022: import java.net.URLClassLoader;
023: import java.net.URLStreamHandlerFactory;
024:
025: /**
026: * The <code>ParanoidClassLoader</code> reverses the search order for classes.
027: * It checks this classloader before it checks its parent.
028: *
029: * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch </a>
030: * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez </a>
031: * @version CVS $Id: ParanoidClassLoader.java 30932 2004-07-29 17:35:38Z
032: * vgritsenko $
033: */
034:
035: public class ParanoidClassLoader extends URLClassLoader {
036:
037: /**
038: * Default constructor has no parents or initial <code>URL</code>s.
039: */
040: public ParanoidClassLoader() {
041: this (null, null, null);
042: }
043:
044: /**
045: * Alternate constructor to define a parent.
046: */
047: public ParanoidClassLoader(final ClassLoader parent) {
048: this (new URL[0], parent, null);
049: }
050:
051: /**
052: * Alternate constructor to define initial <code>URL</code>s.
053: */
054: public ParanoidClassLoader(final URL[] urls) {
055: this (urls, null, null);
056: }
057:
058: /**
059: * Alternate constructor to define a parent and initial <code>URL</code>
060: * s.
061: */
062: public ParanoidClassLoader(final URL[] urls,
063: final ClassLoader parent) {
064: this (urls, parent, null);
065: }
066:
067: /**
068: * Alternate constructor to define a parent, initial <code>URL</code>s,
069: * and a default <code>URLStreamHandlerFactory</code>.
070: */
071: public ParanoidClassLoader(final URL[] urls,
072: final ClassLoader parent,
073: final URLStreamHandlerFactory factory) {
074: super (urls, parent, factory);
075: }
076:
077: /**
078: * Extends <code>URLClassLoader</code>'s initialization methods so we
079: * return a <code>ParanoidClassLoad</code> instead.
080: */
081: public static final URLClassLoader newInstance(final URL[] urls) {
082: return new ParanoidClassLoader(urls);
083: }
084:
085: /**
086: * Extends <code>URLClassLoader</code>'s initialization methods so we
087: * return a <code>ParanoidClassLoad</code> instead.
088: */
089: public static final URLClassLoader newInstance(final URL[] urls,
090: final ClassLoader parent) {
091: return new ParanoidClassLoader(urls, parent);
092: }
093:
094: /**
095: * Loads the class from this <code>ClassLoader</class>. If the
096: * class does not exist in this one, we check the parent. Please
097: * note that this is the exact opposite of the
098: * <code>ClassLoader</code> spec. We use it to work around
099: * inconsistent class loaders from third party vendors.
100: *
101: * @param name the name of the class
102: * @param resolve if <code>true</code> then resolve the class
103: * @return the resulting <code>Class</code> object
104: * @exception ClassNotFoundException if the class could not be found
105: */
106: public final Class loadClass(String name, boolean resolve)
107: throws ClassNotFoundException {
108: // First check if it's already loaded
109: Class clazz = findLoadedClass(name);
110:
111: if (clazz == null) {
112:
113: try {
114: clazz = findClass(name);
115: //System.err.println("Paranoid load : " + name);
116: } catch (ClassNotFoundException cnfe) {
117: ClassLoader parent = getParent();
118: if (parent != null) {
119: // Ask to parent ClassLoader (can also throw a CNFE).
120: clazz = parent.loadClass(name);
121: } else {
122: // Propagate exception
123: throw cnfe;
124: }
125: }
126: }
127:
128: if (resolve) {
129: resolveClass(clazz);
130: }
131:
132: return clazz;
133: }
134:
135: /**
136: * Gets a resource from this <code>ClassLoader</class>. If the
137: * resource does not exist in this one, we check the parent.
138: * Please note that this is the exact opposite of the
139: * <code>ClassLoader</code> spec. We use it to work around
140: * inconsistent class loaders from third party vendors.
141: *
142: * @param name of resource
143: */
144: public final URL getResource(final String name) {
145:
146: URL resource = findResource(name);
147: ClassLoader parent = this .getParent();
148: if (resource == null && parent != null) {
149: resource = parent.getResource(name);
150: }
151:
152: return resource;
153: }
154:
155: /**
156: * Adds a new directory of class files.
157: *
158: * @param file
159: * for jar or directory
160: * @throws IOException
161: */
162: public final void addDirectory(File file) throws IOException {
163: this .addURL(file.getCanonicalFile().toURL());
164: }
165:
166: /**
167: * Adds a new URL
168: */
169:
170: public void addURL(URL url) {
171: super.addURL(url);
172: }
173: }
|