/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package org.googlecode.perftrace.javassist.scopedpool;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import org.googlecode.perftrace.javassist.ClassPool;
import org.googlecode.perftrace.javassist.LoaderClassPath;
/**
* An implementation of <code>ScopedClassPoolRepository</code>.
* It is an singleton.
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @version $Revision: 1.4 $
*/
public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository {
/** The instance */
private static final ScopedClassPoolRepositoryImpl instance = new ScopedClassPoolRepositoryImpl();
/** Whether to prune */
private boolean prune = true;
/** Whether to prune when added to the classpool's cache */
boolean pruneWhenCached;
/** The registered classloaders */
protected Map registeredCLs = Collections
.synchronizedMap(new WeakHashMap());
/** The default class pool */
protected ClassPool classpool;
/** The factory for creating class pools */
protected ScopedClassPoolFactory factory = new ScopedClassPoolFactoryImpl();
/**
* Get the instance.
*
* @return the instance.
*/
public static ScopedClassPoolRepository getInstance() {
return instance;
}
/**
* Singleton.
*/
private ScopedClassPoolRepositoryImpl() {
classpool = ClassPool.getDefault();
// FIXME This doesn't look correct
ClassLoader cl = Thread.currentThread().getContextClassLoader();
classpool.insertClassPath(new LoaderClassPath(cl));
}
/**
* Returns the value of the prune attribute.
*
* @return the prune.
*/
public boolean isPrune() {
return prune;
}
/**
* Set the prune attribute.
*
* @param prune a new value.
*/
public void setPrune(boolean prune) {
this.prune = prune;
}
/**
* Create a scoped classpool.
*
* @param cl the classloader.
* @param src the original classpool.
* @return the classpool
*/
public ScopedClassPool createScopedClassPool(ClassLoader cl, ClassPool src) {
return factory.create(cl, src, this);
}
public ClassPool findClassPool(ClassLoader cl) {
if (cl == null)
return registerClassLoader(ClassLoader.getSystemClassLoader());
return registerClassLoader(cl);
}
/**
* Register a classloader.
*
* @param ucl the classloader.
* @return the classpool
*/
public ClassPool registerClassLoader(ClassLoader ucl) {
synchronized (registeredCLs) {
// FIXME: Probably want to take this method out later
// so that AOP framework can be independent of JMX
// This is in here so that we can remove a UCL from the ClassPool as
// a
// ClassPool.classpath
if (registeredCLs.containsKey(ucl)) {
return (ClassPool)registeredCLs.get(ucl);
}
ScopedClassPool pool = createScopedClassPool(ucl, classpool);
registeredCLs.put(ucl, pool);
return pool;
}
}
/**
* Get the registered classloaders.
*/
public Map getRegisteredCLs() {
clearUnregisteredClassLoaders();
return registeredCLs;
}
/**
* This method will check to see if a register classloader has been
* undeployed (as in JBoss)
*/
public void clearUnregisteredClassLoaders() {
ArrayList toUnregister = null;
synchronized (registeredCLs) {
Iterator it = registeredCLs.values().iterator();
while (it.hasNext()) {
ScopedClassPool pool = (ScopedClassPool)it.next();
if (pool.isUnloadedClassLoader()) {
it.remove();
ClassLoader cl = pool.getClassLoader();
if (cl != null) {
if (toUnregister == null) {
toUnregister = new ArrayList();
}
toUnregister.add(cl);
}
}
}
if (toUnregister != null) {
for (int i = 0; i < toUnregister.size(); i++) {
unregisterClassLoader((ClassLoader)toUnregister.get(i));
}
}
}
}
public void unregisterClassLoader(ClassLoader cl) {
synchronized (registeredCLs) {
ScopedClassPool pool = (ScopedClassPool)registeredCLs.remove(cl);
if (pool != null)
pool.close();
}
}
public void insertDelegate(ScopedClassPoolRepository delegate) {
// Noop - this is the end
}
public void setClassPoolFactory(ScopedClassPoolFactory factory) {
this.factory = factory;
}
public ScopedClassPoolFactory getClassPoolFactory() {
return factory;
}
}