1 /**
2  * The utillib library.
3  * More information is available at http://www.jinchess.com/.
4  * Copyright (C) 2003 Alexander Maryanovsky.
5  * All rights reserved.
6  *
7  * The utillib library is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * The utillib library is distributed in the hope that it will
13  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with utillib library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 package free.util;
23 
24 import java.util.Vector;
25 import java.util.Hashtable;
26 import java.util.Enumeration;
27 import java.io.InputStream;
28 import java.net.URL;
29 
30 
31 /**
32  * A class loader which delegates loading to other classloaders.
33  */
34 
35 public class DelegatingClassLoader extends ChildClassLoader{
36 
37 
38 
39   /**
40    * A list of <code>ChildClassLoaders</code> to which we delegate.
41    */
42 
43   private final Vector delegates = new Vector();
44 
45 
46 
47   /**
48    * The set of class/resource names we are currently in the process of loading.
49    * This is needed to avoid endless recursion in case of delegate
50    * ChildClassLoaders that have this classloader as their parent.
51    */
52 
53   private final Hashtable beingLoaded = new Hashtable();
54 
55 
56 
57   /**
58    * Creates a new <code>DelegatingClassLoader</code> with the specified parent
59    * class loader.
60    */
61 
DelegatingClassLoader(ChildClassLoader parent)62   public DelegatingClassLoader(ChildClassLoader parent){
63     super(parent);
64   }
65 
66 
67 
68   /**
69    * Creates a new <code>DelegatingClassLoader</code> with no parent.
70    */
71 
DelegatingClassLoader()72   public DelegatingClassLoader(){
73     super();
74   }
75 
76 
77 
78   /**
79    * Adds a delegate class loader.
80    */
81 
addDelegate(ChildClassLoader classLoader)82   public void addDelegate(ChildClassLoader classLoader){
83     delegates.addElement(classLoader);
84   }
85 
86 
87 
88   /**
89    * Removes the specified delegate class loader.
90    */
91 
removeDelegate(ChildClassLoader classLoader)92   public void removeDelegate(ChildClassLoader classLoader){
93     delegates.removeElement(classLoader);
94   }
95 
96 
97 
98   /**
99    * Loads and optionally resolves the specified class.
100    */
101 
loadClassImpl(String name, boolean resolve)102   protected Class loadClassImpl(String name, boolean resolve){
103     if (beingLoaded.containsKey(name)) // Avoid endless recursion
104       return null;
105 
106     beingLoaded.put(name, name);
107     Class c = null;
108     Enumeration loaders = delegates.elements();
109     while (loaders.hasMoreElements()){
110       ChildClassLoader loader = (ChildClassLoader)loaders.nextElement();
111       try{
112         c = loader.loadClass(name, resolve);
113         if (c != null)
114           break;
115       } catch (ClassNotFoundException e){}
116     }
117 
118     beingLoaded.remove(name);
119     return c;
120   }
121 
122 
123 
124   /**
125    * Returns an <code>InputStream</code> for reading the resource with the
126    * specified name.
127    */
128 
getResourceAsStreamImpl(String name)129   protected InputStream getResourceAsStreamImpl(String name){
130     if (beingLoaded.containsKey(name)) // Avoid endless recursion
131       return null;
132 
133     beingLoaded.put(name, name);
134     InputStream in = null;
135     Enumeration loaders = delegates.elements();
136     while (loaders.hasMoreElements()){
137       ChildClassLoader loader = (ChildClassLoader)loaders.nextElement();
138       in = loader.getResourceAsStream(name);
139       if (in != null)
140         break;
141     }
142 
143     beingLoaded.remove(name);
144     return in;
145   }
146 
147 
148 
149   /**
150    * Returns a <code>URL</code> pointing to the resource with the specified
151    * name.
152    */
153 
getResourceImpl(String name)154   protected URL getResourceImpl(String name){
155     if (beingLoaded.containsKey(name)) // Avoid endless recursion
156       return null;
157 
158     beingLoaded.put(name, name);
159     URL url = null;
160     Enumeration loaders = delegates.elements();
161     while (loaders.hasMoreElements()){
162       ChildClassLoader loader = (ChildClassLoader)loaders.nextElement();
163       url = loader.getResource(name);
164       if (url != null)
165         break;
166     }
167 
168     beingLoaded.remove(name);
169     return url;
170   }
171 
172 
173 
174 }