01: /*
02: * Copyright (C) 2004, 2005 Joe Walnes.
03: * Copyright (C) 2006, 2007 XStream Committers.
04: * All rights reserved.
05: *
06: * The software in this package is published under the terms of the BSD
07: * style license a copy of which has been included with this distribution in
08: * the LICENSE.txt file.
09: *
10: * Created on 16. November 2004 by Joe Walnes
11: */
12: package com.thoughtworks.xstream.core.util;
13:
14: import java.util.ArrayList;
15: import java.util.Collections;
16: import java.util.Iterator;
17: import java.util.List;
18:
19: /**
20: * ClassLoader that is composed of other classloaders. Each loader will be used to try to load the particular class, until
21: * one of them succeeds. <b>Note:</b> The loaders will always be called in the REVERSE order they were added in.
22: *
23: * <p>The Composite class loader also has registered the classloader that loaded xstream.jar
24: * and (if available) the thread's context classloader.</p>
25: *
26: * <h1>Example</h1>
27: * <pre><code>CompositeClassLoader loader = new CompositeClassLoader();
28: * loader.add(MyClass.class.getClassLoader());
29: * loader.add(new AnotherClassLoader());
30: *
31: * loader.loadClass("com.blah.ChickenPlucker");
32: * </code></pre>
33: *
34: * <p>The above code will attempt to load a class from the following classloaders (in order):</p>
35: *
36: * <ul>
37: * <li>AnotherClassLoader (and all its parents)</li>
38: * <li>The classloader for MyClas (and all its parents)</li>
39: * <li>The thread's context classloader (and all its parents)</li>
40: * <li>The classloader for XStream (and all its parents)</li>
41: * </ul>
42: *
43: * @author Joe Walnes
44: * @since 1.0.3
45: */
46: public class CompositeClassLoader extends ClassLoader {
47:
48: private final List classLoaders = Collections
49: .synchronizedList(new ArrayList());
50:
51: public CompositeClassLoader() {
52: add(Object.class.getClassLoader()); // bootstrap loader.
53: add(getClass().getClassLoader()); // whichever classloader loaded this jar.
54: }
55:
56: /**
57: * Add a loader to the n
58: * @param classLoader
59: */
60: public void add(ClassLoader classLoader) {
61: if (classLoader != null) {
62: classLoaders.add(0, classLoader);
63: }
64: }
65:
66: public Class loadClass(String name) throws ClassNotFoundException {
67: for (Iterator iterator = classLoaders.iterator(); iterator
68: .hasNext();) {
69: ClassLoader classLoader = (ClassLoader) iterator.next();
70: try {
71: return classLoader.loadClass(name);
72: } catch (ClassNotFoundException notFound) {
73: // ok.. try another one
74: }
75: }
76: // One last try - the context class loader associated with the current thread. Often used in j2ee servers.
77: // Note: The contextClassLoader cannot be added to the classLoaders list up front as the thread that constructs
78: // XStream is potentially different to thread that uses it.
79: ClassLoader contextClassLoader = Thread.currentThread()
80: .getContextClassLoader();
81: if (contextClassLoader != null) {
82: return contextClassLoader.loadClass(name);
83: } else {
84: throw new ClassNotFoundException(name);
85: }
86: }
87:
88: }
|