001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.loading;
023:
024: import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
025: import org.jboss.logging.Logger;
026: import org.jboss.mx.server.ServerConstants;
027: import org.jboss.util.loading.Translator;
028:
029: import javax.management.loading.ClassLoaderRepository;
030: import java.net.URL;
031: import java.util.HashMap;
032: import java.util.List;
033: import java.util.Vector;
034:
035: /**
036: * Abstract base class of all loader repository implementations
037: *
038: * @see org.jboss.mx.loading.BasicLoaderRepository
039: *
040: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
041: * @version $Revision: 57200 $
042: */
043: public abstract class LoaderRepository implements ServerConstants,
044: ClassLoaderRepository {
045:
046: // Attributes ----------------------------------------------------
047: protected static Vector loaders = new Vector();
048: protected static LoaderRepository instance = null;
049: protected Translator translator = null;
050:
051: /** The loaded classes cache, HashMap<String, Class>.
052: * Access synchronized via this.classes monitor.
053: */
054: private ConcurrentReaderHashMap classes = new ConcurrentReaderHashMap();
055:
056: /**
057: * Native signature to class map
058: */
059: private static HashMap nativeClassBySignature;
060:
061: // Static --------------------------------------------------------
062: private static final Logger log = Logger
063: .getLogger(LoaderRepository.class);
064:
065: /**
066: * Construct the native class map
067: */
068: static {
069: nativeClassBySignature = new HashMap();
070: nativeClassBySignature.put("boolean", boolean.class);
071: nativeClassBySignature.put("byte", byte.class);
072: nativeClassBySignature.put("char", char.class);
073: nativeClassBySignature.put("double", double.class);
074: nativeClassBySignature.put("float", float.class);
075: nativeClassBySignature.put("int", int.class);
076: nativeClassBySignature.put("long", long.class);
077: nativeClassBySignature.put("short", short.class);
078: nativeClassBySignature.put("void", void.class);
079:
080: nativeClassBySignature.put("boolean[]", boolean[].class);
081: nativeClassBySignature.put("byte[]", byte[].class);
082: nativeClassBySignature.put("char[]", char[].class);
083: nativeClassBySignature.put("double[]", double[].class);
084: nativeClassBySignature.put("float[]", float[].class);
085: nativeClassBySignature.put("int[]", int[].class);
086: nativeClassBySignature.put("long[]", long[].class);
087: nativeClassBySignature.put("short[]", short[].class);
088: }
089:
090: // Public --------------------------------------------------------
091: public Vector getLoaders() {
092: return loaders;
093: }
094:
095: public URL[] getURLs() {
096: return null;
097: }
098:
099: public Class getCachedClass(String classname) {
100: return (Class) classes.get(classname);
101: }
102:
103: public Translator getTranslator() {
104: return translator;
105: }
106:
107: public void setTranslator(Translator t) {
108: translator = t;
109: }
110:
111: /**
112: * Compare two loader repository, by default we do no special ordering
113: *
114: * @param lr the loader repository
115: * @return -1, 0, 1 depending upon the order
116: */
117: public int compare(LoaderRepository lr) {
118: if (lr == this )
119: return 0;
120: else
121: return -lr.reverseCompare(this );
122: }
123:
124: // BEGIN ClassLoaderRepository **************************************************************************************
125:
126: /**
127: * Loads a class from the repository. This method attempts to load the class
128: * using all the classloader registered to the repository.
129: *
130: * @param className the class to load
131: * @return the found class
132: * @exception ClassNotFoundException when there is no such class
133: */
134: public abstract Class loadClass(String className)
135: throws ClassNotFoundException;
136:
137: /**
138: * Loads a class from the repository, excluding the given
139: * classloader.
140: *
141: * @param loader the classloader to exclude
142: * @param className the class to load
143: * @return the found class
144: * @exception ClassNotFoundException when there is no such class
145: */
146: public abstract Class loadClassWithout(ClassLoader loader,
147: String className) throws ClassNotFoundException;
148:
149: /**
150: * Loads a class from the repository, using the classloaders that were
151: * registered before the given classloader.
152: *
153: * @param stop consult all the classloaders registered before this one
154: * in an attempt to load a class
155: * @param className name of the class to load
156: *
157: * @return loaded class instance
158: *
159: * @throws ClassNotFoundException if none of the consulted classloaders were
160: * able to load the requested class
161: */
162: public abstract Class loadClassBefore(ClassLoader stop,
163: String className) throws ClassNotFoundException;
164:
165: // END ClassLoaderRepository ****************************************************************************************
166:
167: /** Create RepositoryClassLoader and optionally add it to the repository
168: * @param url the URL to use for class loading
169: * @param addToRepository a flag indicating if the CL should be added to
170: * the repository
171: * @return the UCL instance
172: * @throws Exception
173: */
174: public abstract RepositoryClassLoader newClassLoader(final URL url,
175: boolean addToRepository) throws Exception;
176:
177: /** Create RepositoryClassLoader and optionally add it to the repository
178: * @param url the URL to use for class loading
179: * @param origURL an orignal URL to use as the URL for the CL CodeSource.
180: * This is useful when the url is a local copy that is difficult to use for
181: * security policy writing.
182: * @param addToRepository a flag indicating if the CL should be added to
183: * the repository
184: * @return the CL instance
185: * @throws Exception
186: */
187: public abstract RepositoryClassLoader newClassLoader(final URL url,
188: final URL origURL, boolean addToRepository)
189: throws Exception;
190:
191: /** Load the given class from the repository
192: * @param name
193: * @param resolve
194: * @param cl
195: * @return
196: * @throws ClassNotFoundException
197: */
198: public abstract Class loadClass(String name, boolean resolve,
199: ClassLoader cl) throws ClassNotFoundException;
200:
201: /** Find a resource URL for the given name
202: *
203: * @param name the resource name
204: * @param cl the requesting class loader
205: * @return The resource URL if found, null otherwise
206: */
207: public abstract URL getResource(String name, ClassLoader cl);
208:
209: /** Find all resource URLs for the given name. Since this typically
210: * entails an exhuastive search of the repository it can be a relatively
211: * slow operation.
212: *
213: * @param name the resource name
214: * @param cl the requesting class loader
215: * @param urls a list into which the located resource URLs will be placed
216: */
217: public abstract void getResources(String name, ClassLoader cl,
218: List urls);
219:
220: /** Add a class loader to the repository
221: */
222: public abstract void addClassLoader(ClassLoader cl);
223:
224: /** Update the set of URLs known to be associated with a previously added
225: * class loader.
226: *
227: * @param cl
228: * @param url
229: */
230: public abstract boolean addClassLoaderURL(ClassLoader cl, URL url);
231:
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: // Check for native classes
243: return (Class) nativeClassBySignature.get(className);
244: }
245:
246: /**
247: * Allow subclasses to override the ordering
248: *
249: * @param lr the loader repository
250: * @return -1, 0, 1 depending upon the order
251: */
252: protected int reverseCompare(LoaderRepository lr) {
253: return 0;
254: }
255:
256: /**
257: * Add a class to the the cache
258: */
259: void cacheLoadedClass(String name, Class cls, ClassLoader cl) {
260: synchronized (classes) {
261: // Update the global cache
262: classes.put(name, cls);
263: if (log.isTraceEnabled()) {
264: log.trace("cacheLoadedClass, classname: " + name
265: + ", class: " + cls + ", cl: " + cl);
266: }
267:
268: /**
269: * TODO: Adding this implementation is a hack for jmx 1.2 checkin.
270: * Had to add this because need getCachedClass() to work.
271: * However, this method does not add loaded classes to collection
272: * to be unloaded when called to remove classloader.
273: * Hopefully this will be a short term workaround.
274: * Contact telrod@e2technologies.net if you have questions. -TME
275: */
276: }
277: }
278:
279: void clear() {
280: classes.clear();
281: }
282: }
|