1/* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16package javassist.scopedpool; 17 18import java.util.ArrayList; 19import java.util.Collections; 20import java.util.Iterator; 21import java.util.Map; 22import java.util.WeakHashMap; 23 24import javassist.ClassPool; 25import javassist.LoaderClassPath; 26 27/** 28 * An implementation of <code>ScopedClassPoolRepository</code>. 29 * It is an singleton. 30 * 31 * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> 32 * @version $Revision: 1.4 $ 33 */ 34public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository { 35 /** The instance */ 36 private static final ScopedClassPoolRepositoryImpl instance = new ScopedClassPoolRepositoryImpl(); 37 38 /** Whether to prune */ 39 private boolean prune = true; 40 41 /** Whether to prune when added to the classpool's cache */ 42 boolean pruneWhenCached; 43 44 /** The registered classloaders */ 45 protected Map registeredCLs = Collections 46 .synchronizedMap(new WeakHashMap()); 47 48 /** The default class pool */ 49 protected ClassPool classpool; 50 51 /** The factory for creating class pools */ 52 protected ScopedClassPoolFactory factory = new ScopedClassPoolFactoryImpl(); 53 54 /** 55 * Get the instance. 56 * 57 * @return the instance. 58 */ 59 public static ScopedClassPoolRepository getInstance() { 60 return instance; 61 } 62 63 /** 64 * Singleton. 65 */ 66 private ScopedClassPoolRepositoryImpl() { 67 classpool = ClassPool.getDefault(); 68 // FIXME This doesn't look correct 69 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 70 classpool.insertClassPath(new LoaderClassPath(cl)); 71 } 72 73 /** 74 * Returns the value of the prune attribute. 75 * 76 * @return the prune. 77 */ 78 public boolean isPrune() { 79 return prune; 80 } 81 82 /** 83 * Set the prune attribute. 84 * 85 * @param prune a new value. 86 */ 87 public void setPrune(boolean prune) { 88 this.prune = prune; 89 } 90 91 /** 92 * Create a scoped classpool. 93 * 94 * @param cl the classloader. 95 * @param src the original classpool. 96 * @return the classpool 97 */ 98 public ScopedClassPool createScopedClassPool(ClassLoader cl, ClassPool src) { 99 return factory.create(cl, src, this); 100 } 101 102 public ClassPool findClassPool(ClassLoader cl) { 103 if (cl == null) 104 return registerClassLoader(ClassLoader.getSystemClassLoader()); 105 106 return registerClassLoader(cl); 107 } 108 109 /** 110 * Register a classloader. 111 * 112 * @param ucl the classloader. 113 * @return the classpool 114 */ 115 public ClassPool registerClassLoader(ClassLoader ucl) { 116 synchronized (registeredCLs) { 117 // FIXME: Probably want to take this method out later 118 // so that AOP framework can be independent of JMX 119 // This is in here so that we can remove a UCL from the ClassPool as 120 // a 121 // ClassPool.classpath 122 if (registeredCLs.containsKey(ucl)) { 123 return (ClassPool)registeredCLs.get(ucl); 124 } 125 ScopedClassPool pool = createScopedClassPool(ucl, classpool); 126 registeredCLs.put(ucl, pool); 127 return pool; 128 } 129 } 130 131 /** 132 * Get the registered classloaders. 133 */ 134 public Map getRegisteredCLs() { 135 clearUnregisteredClassLoaders(); 136 return registeredCLs; 137 } 138 139 /** 140 * This method will check to see if a register classloader has been 141 * undeployed (as in JBoss) 142 */ 143 public void clearUnregisteredClassLoaders() { 144 ArrayList toUnregister = null; 145 synchronized (registeredCLs) { 146 Iterator it = registeredCLs.values().iterator(); 147 while (it.hasNext()) { 148 ScopedClassPool pool = (ScopedClassPool)it.next(); 149 if (pool.isUnloadedClassLoader()) { 150 it.remove(); 151 ClassLoader cl = pool.getClassLoader(); 152 if (cl != null) { 153 if (toUnregister == null) { 154 toUnregister = new ArrayList(); 155 } 156 toUnregister.add(cl); 157 } 158 } 159 } 160 if (toUnregister != null) { 161 for (int i = 0; i < toUnregister.size(); i++) { 162 unregisterClassLoader((ClassLoader)toUnregister.get(i)); 163 } 164 } 165 } 166 } 167 168 public void unregisterClassLoader(ClassLoader cl) { 169 synchronized (registeredCLs) { 170 ScopedClassPool pool = (ScopedClassPool)registeredCLs.remove(cl); 171 if (pool != null) 172 pool.close(); 173 } 174 } 175 176 public void insertDelegate(ScopedClassPoolRepository delegate) { 177 // Noop - this is the end 178 } 179 180 public void setClassPoolFactory(ScopedClassPoolFactory factory) { 181 this.factory = factory; 182 } 183 184 public ScopedClassPoolFactory getClassPoolFactory() { 185 return factory; 186 } 187} 188