001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 2006 JBoss Inc. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.scopedpool;
017:
018: import java.util.ArrayList;
019: import java.util.Collections;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.WeakHashMap;
023:
024: import javassist.ClassPool;
025: import javassist.LoaderClassPath;
026:
027: /**
028: * An implementation of <code>ScopedClassPoolRepository</code>.
029: * It is an singleton.
030: *
031: * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
032: * @version $Revision: 1.3 $
033: */
034: public class ScopedClassPoolRepositoryImpl implements
035: ScopedClassPoolRepository {
036: /** The instance */
037: private static final ScopedClassPoolRepositoryImpl instance = new ScopedClassPoolRepositoryImpl();
038:
039: /** Whether to prune */
040: private boolean prune = true;
041:
042: /** Whether to prune when added to the classpool's cache */
043: boolean pruneWhenCached;
044:
045: /** The registered classloaders */
046: protected Map registeredCLs = Collections
047: .synchronizedMap(new WeakHashMap());
048:
049: /** The default class pool */
050: protected ClassPool classpool;
051:
052: /** The factory for creating class pools */
053: protected ScopedClassPoolFactory factory = new ScopedClassPoolFactoryImpl();
054:
055: /**
056: * Get the instance.
057: *
058: * @return the instance.
059: */
060: public static ScopedClassPoolRepository getInstance() {
061: return instance;
062: }
063:
064: /**
065: * Singleton.
066: */
067: private ScopedClassPoolRepositoryImpl() {
068: classpool = ClassPool.getDefault();
069: // FIXME This doesn't look correct
070: ClassLoader cl = Thread.currentThread().getContextClassLoader();
071: classpool.insertClassPath(new LoaderClassPath(cl));
072: }
073:
074: /**
075: * Returns the value of the prune attribute.
076: *
077: * @return the prune.
078: */
079: public boolean isPrune() {
080: return prune;
081: }
082:
083: /**
084: * Set the prune attribute.
085: *
086: * @param prune a new value.
087: */
088: public void setPrune(boolean prune) {
089: this .prune = prune;
090: }
091:
092: /**
093: * Create a scoped classpool.
094: *
095: * @param cl the classloader.
096: * @param src the original classpool.
097: * @return the classpool
098: */
099: public ScopedClassPool createScopedClassPool(ClassLoader cl,
100: ClassPool src) {
101: return factory.create(cl, src, this );
102: }
103:
104: public ClassPool findClassPool(ClassLoader cl) {
105: if (cl == null)
106: return registerClassLoader(ClassLoader
107: .getSystemClassLoader());
108:
109: return registerClassLoader(cl);
110: }
111:
112: /**
113: * Register a classloader.
114: *
115: * @param ucl the classloader.
116: * @return the classpool
117: */
118: public ClassPool registerClassLoader(ClassLoader ucl) {
119: synchronized (registeredCLs) {
120: // FIXME: Probably want to take this method out later
121: // so that AOP framework can be independent of JMX
122: // This is in here so that we can remove a UCL from the ClassPool as
123: // a
124: // ClassPool.classpath
125: if (registeredCLs.containsKey(ucl)) {
126: return (ClassPool) registeredCLs.get(ucl);
127: }
128: ScopedClassPool pool = createScopedClassPool(ucl, classpool);
129: registeredCLs.put(ucl, pool);
130: return pool;
131: }
132: }
133:
134: /**
135: * Get the registered classloaders.
136: */
137: public Map getRegisteredCLs() {
138: clearUnregisteredClassLoaders();
139: return registeredCLs;
140: }
141:
142: /**
143: * This method will check to see if a register classloader has been
144: * undeployed (as in JBoss)
145: */
146: public void clearUnregisteredClassLoaders() {
147: ArrayList toUnregister = null;
148: synchronized (registeredCLs) {
149: Iterator it = registeredCLs.values().iterator();
150: while (it.hasNext()) {
151: ScopedClassPool pool = (ScopedClassPool) it.next();
152: if (pool.isUnloadedClassLoader()) {
153: it.remove();
154: ClassLoader cl = pool.getClassLoader();
155: if (cl != null) {
156: if (toUnregister == null) {
157: toUnregister = new ArrayList();
158: }
159: toUnregister.add(cl);
160: }
161: }
162: }
163: if (toUnregister != null) {
164: for (int i = 0; i < toUnregister.size(); i++) {
165: unregisterClassLoader((ClassLoader) toUnregister
166: .get(i));
167: }
168: }
169: }
170: }
171:
172: public void unregisterClassLoader(ClassLoader cl) {
173: synchronized (registeredCLs) {
174: ScopedClassPool pool = (ScopedClassPool) registeredCLs
175: .remove(cl);
176: if (pool != null)
177: pool.close();
178: }
179: }
180:
181: public void insertDelegate(ScopedClassPoolRepository delegate) {
182: // Noop - this is the end
183: }
184:
185: public void setClassPoolFactory(ScopedClassPoolFactory factory) {
186: this .factory = factory;
187: }
188:
189: public ScopedClassPoolFactory getClassPoolFactory() {
190: return factory;
191: }
192: }
|