View Javadoc

1   /*
2    * Copyright 2006-2008 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.osgi.context.internal.classloader;
18  
19  import java.lang.ref.WeakReference;
20  import java.util.Map;
21  import java.util.WeakHashMap;
22  
23  import org.springframework.aop.framework.ProxyFactory;
24  
25  /**
26   * Default implementation for {@link InternalAopClassLoaderFactory}. Uses an
27   * internal {@link WeakHashMap} to cache aop class loaders to prevent duplicated
28   * copies.
29   * 
30   * @author Costin Leau
31   */
32  class CachingAopClassLoaderFactory implements InternalAopClassLoaderFactory {
33  
34  	private static final String CGLIB_CLASS = "net.sf.cglib.proxy.Enhancer";
35  	/** CGLIB class (if it's present) */
36  	private final Class cglibClass;
37  
38  	/** class loader -> aop class loader cache */
39  	private final Map cache = new WeakHashMap();
40  
41  
42  	CachingAopClassLoaderFactory() {
43  		// load CGLIB through Spring-AOP
44  		ClassLoader springAopClassLoader = ProxyFactory.class.getClassLoader();
45  		Class clazz = null;
46  		try {
47  			clazz = springAopClassLoader.loadClass(CGLIB_CLASS);
48  		}
49  		catch (ClassNotFoundException cnfe) {
50  			// assume cglib is not present
51  		}
52  		cglibClass = clazz;
53  	}
54  
55  	public ClassLoader createClassLoader(ClassLoader classLoader) {
56  		// search key (should be fast as the default classloader (BundleDelegatingClassLoader) has identity equality/hashcode)
57  		synchronized (cache) {
58  			ClassLoader aopClassLoader = null;
59  			WeakReference loaderReference = (WeakReference) cache.get(classLoader);
60  
61  			if (loaderReference != null) {
62  				aopClassLoader = (ClassLoader) loaderReference.get();
63  			}
64  
65  			// no associated class loader found, create one and put it in the cache
66  			if (aopClassLoader == null) {
67  				// use the given class loader, spring-aop, cglib (if available) and then spring-dm core class loader (for its infrastructure interfaces)
68  				if (cglibClass != null) {
69  					aopClassLoader = new ChainedClassLoader(new ClassLoader[] { classLoader,
70  						ProxyFactory.class.getClassLoader(), cglibClass.getClassLoader(),
71  						CachingAopClassLoaderFactory.class.getClassLoader() });
72  				}
73  				else {
74  					aopClassLoader = new ChainedClassLoader(new ClassLoader[] { classLoader,
75  						ProxyFactory.class.getClassLoader(), CachingAopClassLoaderFactory.class.getClassLoader() });
76  				}
77  
78  				// save the class loader as a weak reference (since it refers to the given class loader)
79  				cache.put(classLoader, new WeakReference(aopClassLoader));
80  			}
81  			return aopClassLoader;
82  		}
83  	}
84  }