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 }