001 // Copyright 2007 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014 package org.apache.tapestry.enhance;
015
016 import java.util.HashSet;
017 import java.util.Set;
018
019 import javassist.CannotCompileException;
020 import javassist.ClassPath;
021 import javassist.ClassPool;
022 import javassist.CtClass;
023 import javassist.LoaderClassPath;
024
025 /**
026 * Used to ensure that {@link javassist.ClassPool#appendClassPath(javassist.ClassPath)} is invoked
027 * with a synchronized lock. Additionally, wraps around a shared
028 * {@link org.apache.hivemind.service.impl.ClassFactoryClassLoader}.
029 *
030 * @author Howard Lewis Ship
031 */
032 public class HiveMindClassPool extends ClassPool
033 {
034 private ClassFactoryClassLoader _loader = new ClassFactoryClassLoader();
035
036 /**
037 * Used to identify which class loaders have already been integrated into the pool.
038 */
039 private Set _loaders = new HashSet();
040
041 public HiveMindClassPool()
042 {
043 super(null);
044
045 appendClassLoader(Thread.currentThread().getContextClassLoader());
046 }
047
048 /**
049 * Convienience method for adding to the ClassPath for a particular class loader.
050 */
051 public synchronized void appendClassLoader(ClassLoader loader)
052 {
053 if (loader == null || loader == _loader || _loaders.contains(loader))
054 return;
055
056 _loader.addDelegateLoader(loader);
057
058 ClassPath path = new LoaderClassPath(loader);
059
060 appendClassPath(path);
061
062 _loaders.add(loader);
063 }
064
065 /**
066 * Invoked to convert an fabricated class into a real class. The new classes' class loader will
067 * be the delegating ClassFactoryClassLoader, which has visibility to all class loaders for all
068 * modules.
069 *
070 * @since 1.1
071 */
072 public Class toClass(CtClass ctClass) throws CannotCompileException
073 {
074 return toClass(ctClass, false);
075 }
076
077 public Class toClass(CtClass ctClass, boolean detach) throws CannotCompileException
078 {
079 Class clazz = ctClass.toClass(_loader, getClass().getProtectionDomain());
080
081 if (detach)
082 ctClass.detach();
083
084 return clazz;
085 }
086
087 public Set getLoaders()
088 {
089 return _loaders;
090 }
091 }