1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.mx.loading;
23
24 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
25 import org.jboss.logging.Logger;
26 import org.jboss.mx.server.ServerConstants;
27 import org.jboss.util.loading.Translator;
28
29 import javax.management.loading.ClassLoaderRepository;
30 import java.net.URL;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Vector;
34
35 /**
36 * Abstract base class of all loader repository implementations
37 *
38 * @see org.jboss.mx.loading.BasicLoaderRepository
39 *
40 * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
41 * @version $Revision: 37459 $
42 */
43 public abstract class LoaderRepository
44 implements ServerConstants, ClassLoaderRepository
45 {
46
47 // Attributes ----------------------------------------------------
48 protected static Vector loaders = new Vector();
49 protected static LoaderRepository instance = null;
50 protected Translator translator = null;
51
52 /** The loaded classes cache, HashMap<String, Class>.
53 * Access synchronized via this.classes monitor.
54 */
55 private ConcurrentReaderHashMap classes = new ConcurrentReaderHashMap();
56
57
58 /**
59 * Native signature to class map
60 */
61 private static HashMap nativeClassBySignature;
62
63 // Static --------------------------------------------------------
64 private static final Logger log = Logger.getLogger(LoaderRepository.class);
65
66 /**
67 * Construct the native class map
68 */
69 static
70 {
71 nativeClassBySignature = new HashMap();
72 nativeClassBySignature.put("boolean", boolean.class);
73 nativeClassBySignature.put("byte", byte.class);
74 nativeClassBySignature.put("char", char.class);
75 nativeClassBySignature.put("double", double.class);
76 nativeClassBySignature.put("float", float.class);
77 nativeClassBySignature.put("int", int.class);
78 nativeClassBySignature.put("long", long.class);
79 nativeClassBySignature.put("short", short.class);
80 nativeClassBySignature.put("void", void.class);
81
82 nativeClassBySignature.put("boolean[]", boolean[].class);
83 nativeClassBySignature.put("byte[]", byte[].class);
84 nativeClassBySignature.put("char[]", char[].class);
85 nativeClassBySignature.put("double[]", double[].class);
86 nativeClassBySignature.put("float[]", float[].class);
87 nativeClassBySignature.put("int[]", int[].class);
88 nativeClassBySignature.put("long[]", long[].class);
89 nativeClassBySignature.put("short[]", short[].class);
90 }
91
92 // Public --------------------------------------------------------
93 public Vector getLoaders()
94 {
95 return loaders;
96 }
97
98 public URL[] getURLs()
99 {
100 return null;
101 }
102
103 public Class getCachedClass(String classname)
104 {
105 return (Class)classes.get(classname);
106 }
107
108 public Translator getTranslator()
109 {
110 return translator;
111 }
112
113 public void setTranslator(Translator t)
114 {
115 translator = t;
116 }
117
118 /**
119 * Compare two loader repository, by default we do no special ordering
120 *
121 * @param lr the loader repository
122 * @return -1, 0, 1 depending upon the order
123 */
124 public int compare(LoaderRepository lr)
125 {
126 if (lr == this)
127 return 0;
128 else
129 return -lr.reverseCompare(this);
130 }
131
132 // BEGIN ClassLoaderRepository **************************************************************************************
133
134 /**
135 * Loads a class from the repository. This method attempts to load the class
136 * using all the classloader registered to the repository.
137 *
138 * @param className the class to load
139 * @return the found class
140 * @exception ClassNotFoundException when there is no such class
141 */
142 public abstract Class loadClass(String className) throws ClassNotFoundException;
143
144 /**
145 * Loads a class from the repository, excluding the given
146 * classloader.
147 *
148 * @param loader the classloader to exclude
149 * @param className the class to load
150 * @return the found class
151 * @exception ClassNotFoundException when there is no such class
152 */
153 public abstract Class loadClassWithout(ClassLoader loader, String className) throws ClassNotFoundException;
154
155 /**
156 * Loads a class from the repository, using the classloaders that were
157 * registered before the given classloader.
158 *
159 * @param stop consult all the classloaders registered before this one
160 * in an attempt to load a class
161 * @param className name of the class to load
162 *
163 * @return loaded class instance
164 *
165 * @throws ClassNotFoundException if none of the consulted classloaders were
166 * able to load the requested class
167 */
168 public abstract Class loadClassBefore(ClassLoader stop, String className) throws ClassNotFoundException;
169
170 // END ClassLoaderRepository ****************************************************************************************
171
172 /** Create RepositoryClassLoader and optionally add it to the repository
173 * @param url the URL to use for class loading
174 * @param addToRepository a flag indicating if the CL should be added to
175 * the repository
176 * @return the UCL instance
177 * @throws Exception
178 */
179 public abstract RepositoryClassLoader newClassLoader(final URL url, boolean addToRepository)
180 throws Exception;
181 /** Create RepositoryClassLoader and optionally add it to the repository
182 * @param url the URL to use for class loading
183 * @param origURL an orignal URL to use as the URL for the CL CodeSource.
184 * This is useful when the url is a local copy that is difficult to use for
185 * security policy writing.
186 * @param addToRepository a flag indicating if the CL should be added to
187 * the repository
188 * @return the CL instance
189 * @throws Exception
190 */
191 public abstract RepositoryClassLoader newClassLoader(final URL url, final URL origURL,
192 boolean addToRepository)
193 throws Exception;
194
195 /** Load the given class from the repository
196 * @param name
197 * @param resolve
198 * @param cl
199 * @return
200 * @throws ClassNotFoundException
201 */
202 public abstract Class loadClass(String name, boolean resolve, ClassLoader cl)
203 throws ClassNotFoundException;
204
205 /** Find a resource URL for the given name
206 *
207 * @param name the resource name
208 * @param cl the requesting class loader
209 * @return The resource URL if found, null otherwise
210 */
211 public abstract URL getResource(String name, ClassLoader cl);
212 /** Find all resource URLs for the given name. Since this typically
213 * entails an exhuastive search of the repository it can be a relatively
214 * slow operation.
215 *
216 * @param name the resource name
217 * @param cl the requesting class loader
218 * @param urls a list into which the located resource URLs will be placed
219 */
220 public abstract void getResources(String name, ClassLoader cl, List urls);
221
222 /** Add a class loader to the repository
223 */
224 public abstract void addClassLoader(ClassLoader cl);
225 /** Update the set of URLs known to be associated with a previously added
226 * class loader.
227 *
228 * @param cl
229 * @param url
230 */
231 public abstract boolean addClassLoaderURL(ClassLoader cl, URL url);
232 /** Remove a cladd loader from the repository.
233 * @param cl
234 */
235 public abstract void removeClassLoader(ClassLoader cl);
236
237 /**
238 * Return the class of a java native type
239 * @return the class, or null if className is not a native class name
240 */
241 public static final Class getNativeClassForName(String className)
242 {
243 // Check for native classes
244 return (Class)nativeClassBySignature.get(className);
245 }
246
247 /**
248 * Allow subclasses to override the ordering
249 *
250 * @param lr the loader repository
251 * @return -1, 0, 1 depending upon the order
252 */
253 protected int reverseCompare(LoaderRepository lr)
254 {
255 return 0;
256 }
257
258 /**
259 * Add a class to the the cache
260 */
261 void cacheLoadedClass(String name, Class cls, ClassLoader cl)
262 {
263 synchronized( classes )
264 {
265 // Update the global cache
266 classes.put(name, cls);
267 if( log.isTraceEnabled() )
268 {
269 log.trace("cacheLoadedClass, classname: "+name+", class: "+cls
270 +", cl: "+cl);
271 }
272
273 /**
274 * TODO: Adding this implementation is a hack for jmx 1.2 checkin.
275 * Had to add this because need getCachedClass() to work.
276 * However, this method does not add loaded classes to collection
277 * to be unloaded when called to remove classloader.
278 * Hopefully this will be a short term workaround.
279 * Contact telrod@e2technologies.net if you have questions. -TME
280 */
281 }
282 }
283
284 void clear()
285 {
286 classes.clear();
287 }
288 }