    001    // Copyright 2006, 2007, 2008 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
    015    package org.apache.tapestry5.ioc.internal.services;
    016
    017    import javassist.CtClass;
    018    import javassist.NotFoundException;
    019    import org.apache.tapestry5.ioc.services.ClassFabUtils;
    020
    021    import java.security.ProtectionDomain;
    022
    023    /**
    024     * Wrapper around Javassist's {@link javassist.ClassPool} that manages the creation of new instances of {@link
    025     * javassist.CtClass} and converts finished CtClass's into instantiable Classes.
    026     */
    027    public class CtClassSourceImpl implements CtClassSource
    028    {
    029        private static final String WRITE_DIR = System.getProperty("javassist-write-dir");
    030
    031        private final ClassFactoryClassPool pool;
    032
    033        private final ClassLoader loader;
    034
    035        private final ProtectionDomain domain = getClass().getProtectionDomain();
    036
    037        private int createdClassCount = 0;
    038
    039        /**
    040         * Returns the number of classes (and interfaces) created by this source.
    041         */
    042        public synchronized int getCreatedClassCount()
    043        {
    044            return createdClassCount;
    045        }
    046
    047        public CtClassSourceImpl(ClassFactoryClassPool pool, ClassLoader loader)
    048        {
    049            this.pool = pool;
    050            this.loader = loader;
    051        }
    052
    053        public synchronized CtClass toCtClass(Class searchClass)
    054        {
    055            ClassLoader loader = searchClass.getClassLoader();
    056
    057            // Add the class loader for the searchClass to the class pool and
    058            // delegating class loader if needed.
    059
    060            pool.addClassLoaderIfNeeded(loader);
    061
    062            String name = ClassFabUtils.toJavaClassName(searchClass);
    063
    064            return toCtClass(name);
    065        }
    066
    067        public CtClass toCtClass(String name)
    068        {
    069            try
    070            {
    071                return pool.get(name);
    072            }
    073            catch (NotFoundException ex)
    074            {
    075                throw new RuntimeException(ServiceMessages.unableToLookupClass(name, ex), ex);
    076            }
    077        }
    078
    079        public CtClass newClass(String name, Class superClass)
    080        {
    081            CtClass ctSuperClass = toCtClass(superClass);
    082
    083            return pool.makeClass(name, ctSuperClass);
    084        }
    085
    086
    087        public Class createClass(CtClass ctClass)
    088        {
    089            if (WRITE_DIR != null) writeClass(ctClass);
    090
    091            try
    092            {
    093                Class result = pool.toClass(ctClass, loader, domain);
    094
    095                synchronized (this)
    096                {
    097                    createdClassCount++;
    098                }
    099
    100                return result;
    101            }
    102            catch (Throwable ex)
    103            {
    104                throw new RuntimeException(ServiceMessages.unableToWriteClass(ctClass, ex), ex);
    105            }
    106        }
    107
    108        private void writeClass(CtClass ctClass)
    109        {
    110            try
    111            {
    112                ctClass.debugWriteFile(WRITE_DIR);
    113            }
    114            catch (Exception ex)
    115            {
    116                ex.printStackTrace(System.err);
    117            }
    118        }
    119    }