001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)DelegatingClassLoader.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.framework;
030:
031: import java.util.ArrayList;
032: import java.util.Iterator;
033: import java.util.logging.Logger;
034:
035: /**
036: * Implementation of a Component's delegating classloader.
037: * There is one instance of this classloader per component.
038: * This classloader walks through a chain of shared classloaders
039: * to try and load a class. It returns as soon as the first classloader
040: * in the chain is able to find the correct classloader.
041: *
042: * @author Sun Microsystems, Inc.
043: */
044: public final class DelegatingClassLoader extends
045: java.security.SecureClassLoader {
046: /**
047: * Reference to list of classloaders for this component's Shared
048: * Libraries.
049: */
050: private ArrayList mSharedClassLoaders;
051:
052: /**
053: * StringTranslator used to translate messages.
054: */
055: private StringTranslator mTranslator;
056:
057: /**
058: * handle to parent class loader
059: */
060: private ClassLoader mParentLoader;
061:
062: /**
063: * handle to system logger
064: */
065: private Logger mLogger;
066:
067: /**
068: * Constructor.
069: * @param parent the parent classloader to this DelegatingClassloader
070: */
071: public DelegatingClassLoader(ClassLoader parent) {
072: super (parent);
073:
074: ClassLoader systemCL = getSystemClassLoader();
075: mParentLoader = (parent != null) ? parent : systemCL;
076: mSharedClassLoaders = new ArrayList();
077:
078: // get logger , string translator from the env
079: EnvironmentContext eCtx = EnvironmentContext.getInstance();
080: mTranslator = (StringTranslator) eCtx
081: .getStringTranslatorFor(this );
082: //mLogger = (Logger)eCtx.getLogger();
083: //mLogger = Logger.getLogger(this.getClass().getPackage().getName());
084: }
085:
086: /**
087: * Adds a Shared Library classloader to this instance of the DCL.
088: * @param sharedLoader The instance of shared classloader to add.
089: * @throws IllegalArgumentException If the shared classloader passed in
090: * is null.
091: */
092: public void addSharedClassLoader(ClassLoader sharedLoader)
093: throws IllegalArgumentException {
094: if (null == sharedLoader) {
095: throw new IllegalArgumentException(mTranslator.getString(
096: LocalStringKeys.NULL_ARGUMENT, "sharedLoader"));
097: }
098: mSharedClassLoaders.add(sharedLoader);
099: }
100:
101: /**
102: * Overloaded loadClass method that works similarly to the
103: * <code>loadClass(String, boolean)</code> method with <code>
104: * false</code> asthe second argument.
105: *
106: * @param name The name of class to load.
107: * @return The loaded class.
108: * @throws ClassNotFoundException If the class cannot be loaded by this
109: * classloader.
110: */
111: public Class loadClass(String name) throws ClassNotFoundException {
112: return loadClass(name, false);
113: }
114:
115: /**
116: * Overloaded loadClass method .
117: * The purpose of overloading loadClass() here is
118: * not to implement the Shared Class "selfFirst" logic as it may seem.
119: * That happens inside the Shared Classloaders themselves when invoked
120: * inside findClass() of this class .
121: * The purpose of this method is to prevent shared classes such as XML
122: * libraries that may be found in the Appserver class path from being
123: * inadvertently loaded ahead of time by the DelegatingClassLoader rather
124: * than the class loaders for the Shared Libraries that contain the XML
125: * library . This can happen because findClass() inside
126: * DelegatingClassLoader is called after its parent (app server) class
127: * loader has been consulted . DelegatingClassLoader is not a real class
128: * loader - just a proxy for the shared class loaders and this method
129: * ensures that the behaviour is as such . By finally delegating to the
130: * parent app server class loader , this method ensures that class
131: * loading failures do not occur for components that do not have
132: * shared libraries and hence shared class loaders.
133: *
134: * @see java.lang.ClassLoader#loadClass(String, boolean)
135: * @see java.lang.ClassLoader#findClass(String)
136: *
137: *
138: * The sequence of looking for a class is as follows -
139: * <ul>
140: * <li>call findLoadedClass(String) to check if the class has
141: * already been loaded.
142: * <li>call findClass() to try loading the class locally, if it
143: * succeeds , hand back the class
144: * <li> finally hand control to parent and let the normal delegation
145: * class loading continue.
146: * <li> if class was not found in above sequence, throw a
147: * ClassNotFoundException
148: * <li> resolveClass is called at each stage before returning the
149: * loaded class
150: * </ul>
151: *
152: * @param name The name of class to load.
153: * @param resolve whether or not to resolve the class definition
154: * @return The loaded class.
155: * @throws ClassNotFoundException If the class cannot be loaded by this
156: * classloader.
157: */
158:
159: protected Class loadClass(String name, boolean resolve)
160: throws ClassNotFoundException {
161: Class class2Load = null;
162:
163: //mLogger.finest("Delegating ClassLoader - loadClass: " + name);
164:
165: // 1. call findLoadedClass, return if found
166: //
167: class2Load = findLoadedClass(name);
168:
169: if (class2Load != null) {
170: if (resolve) {
171: resolveClass(class2Load);
172: }
173:
174: //mLogger.finest("Class " + name + " will be loaded from cache");
175:
176: return class2Load;
177: }
178:
179: // loading it locally first
180: // this means "search the shared classloaders first
181: try {
182: class2Load = findClass(name);
183: if (class2Load != null) {
184: if (resolve) {
185: resolveClass(class2Load);
186: }
187:
188: //mLogger.finest("Class " + name + " will be loaded using " +
189: // this.toString()));
190: return class2Load;
191: }
192: } catch (ClassNotFoundException cnfe) {
193: ; // ignore
194: }
195:
196: // send it to the parent classloader
197: //
198: try {
199: class2Load = mParentLoader.loadClass(name);
200: if (resolve) {
201: resolveClass(class2Load);
202: }
203: //mLogger.finest("Class " + name + " will be loaded using " +
204: // mParentLoader.toString()));
205: return class2Load;
206: } catch (ClassNotFoundException cnfe) {
207: ; // ignore
208: }
209:
210: // all efforts are in vain - class was not found
211: throw new ClassNotFoundException(name);
212: }
213:
214: /**
215: * Overloaded findClass method to walk through the shared classloader chain.
216: * @param name The name of class to load.
217: * @return The loaded class.
218: * @throws ClassNotFoundException If the class cannot be loaded by this
219: * classloader.
220: */
221: public Class findClass(String name) throws ClassNotFoundException {
222: boolean found = false;
223: Class sharedClass = null;
224:
225: for (Iterator cItr = mSharedClassLoaders.iterator(); cItr
226: .hasNext();) {
227: try {
228: ClassLoader nextSharedCL = (ClassLoader) cItr.next();
229: sharedClass = nextSharedCL.loadClass(name);
230:
231: // if we reach here, we've loaded the class
232: // and can stop looking further.
233: found = true;
234: break;
235: } catch (ClassNotFoundException cnfe) {
236: continue;
237: }
238: }
239:
240: // if we reach here with found=false that means
241: // that the requested class was not in the shared classpath
242: if (!found) {
243: throw new ClassNotFoundException(name);
244: }
245:
246: return sharedClass;
247: }
248: }
|