/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.context.support.internal.classloader;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.WeakHashMap;
import org.springframework.aop.framework.ProxyFactory;
/**
* Default implementation for {@link InternalAopClassLoaderFactory}. Uses an internal {@link WeakHashMap} to cache aop
* class loaders to prevent duplicated copies.
*
* @author Costin Leau
*/
class CachingAopClassLoaderFactory implements InternalAopClassLoaderFactory {
private static final String CGLIB_CLASS = "net.sf.cglib.proxy.Enhancer";
/** CGLIB class (if it's present) */
private final Class<?> cglibClass;
/** class loader -> aop class loader cache */
private final Map<ClassLoader, WeakReference<ChainedClassLoader>> cache =
new WeakHashMap<ClassLoader, WeakReference<ChainedClassLoader>>();
CachingAopClassLoaderFactory() {
// load CGLIB through Spring-AOP
ClassLoader springAopClassLoader = ProxyFactory.class.getClassLoader();
Class<?> clazz = null;
try {
clazz = springAopClassLoader.loadClass(CGLIB_CLASS);
} catch (ClassNotFoundException cnfe) {
// assume cglib is not present
}
cglibClass = clazz;
}
public ChainedClassLoader createClassLoader(final ClassLoader classLoader) {
// search key (should be fast as the default classloader (BundleDelegatingClassLoader) has identity
// equality/hashcode)
synchronized (cache) {
ChainedClassLoader aopClassLoader = null;
WeakReference<ChainedClassLoader> loaderReference = cache.get(classLoader);
if (loaderReference != null) {
aopClassLoader = loaderReference.get();
}
// no associated class loader found, create one and put it in the cache
if (aopClassLoader == null) {
if (System.getSecurityManager() != null) {
aopClassLoader = AccessController.doPrivileged(new PrivilegedAction<ChainedClassLoader>() {
public ChainedClassLoader run() {
return doCreateClassLoader(classLoader);
}
});
} else {
aopClassLoader = doCreateClassLoader(classLoader);
}
// save the class loader as a weak reference (since it refers to the given class loader)
cache.put(classLoader, new WeakReference<ChainedClassLoader>(aopClassLoader));
}
return aopClassLoader;
}
}
private ChainedClassLoader doCreateClassLoader(ClassLoader classLoader) {
// use the given class loader, spring-aop, cglib (if available) and then spring-dm core class loader (for its
// infrastructure interfaces)
if (cglibClass != null) {
return new ChainedClassLoader(new ClassLoader[] { classLoader, ProxyFactory.class.getClassLoader(),
cglibClass.getClassLoader(), CachingAopClassLoaderFactory.class.getClassLoader() });
} else {
return new ChainedClassLoader(new ClassLoader[] { classLoader, ProxyFactory.class.getClassLoader(),
CachingAopClassLoaderFactory.class.getClassLoader() });
}
}
}