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 }