Author: epbernard
Date: 2006-05-04 18:36:54 -0400 (Thu, 04 May 2006)
New Revision: 9883
Added:
trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java
trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java
trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java
trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java
trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java
trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
Modified:
trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java
trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java
trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java
trunk/Hibernate3/test/org/hibernate/test/AllTests.java
trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
Log:
HHH-1719 add a bytecode entry for class transformation, also provide a ClassTransformer friendly ClassLoader (in the test suite), also add a JavassistInstrumentationTest
Added: trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,60 @@
+//$Id: $
+package org.hibernate.bytecode;
+
+import java.security.ProtectionDomain;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public abstract class AbstractClassTransformerImpl implements ClassTransformer {
+
+ final private Set<String> entities;
+ final private String[] packages;
+
+
+ public AbstractClassTransformerImpl(String[] packages, String[] classes) {
+ this.packages = packages;
+ if (classes == null) {
+ this.entities = null;
+ }
+ else {
+ this.entities = new HashSet<String>();
+ for ( String clazz : classes ) {
+ entities.add( clazz );
+ }
+ }
+ }
+
+ public byte[]
+ transform(
+ ClassLoader loader, String className, Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer
+ ) {
+ boolean enhance = false;
+ String safeClassName = className.replace( "/", "." );
+ if ( entities == null && packages == null ) {
+ enhance = true;
+ }
+ if ( ! enhance && entities != null && entities.contains( safeClassName ) ) {
+ enhance = true;
+ }
+ if ( ! enhance && packages != null ) {
+ for ( String packageName : packages ) {
+ if ( safeClassName.startsWith( packageName ) ) {
+ enhance = true;
+ break;
+ }
+ }
+ }
+ if ( ! enhance ) return classfileBuffer;
+
+ return doTransform( loader, className, classBeingRedefined, protectionDomain, classfileBuffer );
+ }
+
+ protected abstract byte[] doTransform(
+ ClassLoader loader, String className, Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer
+ );
+}
Modified: trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -47,11 +47,30 @@
*
* @param parent The parent classloader
* @param classpath The classpath to be searched
- * @param packages can be null; use to limnit the packages to be loaded
+ * @param packages can be null; use to limit the packages to be loaded
* via this classloader (and transformed).
* @return The appropriate ClassLoader.
*/
public ClassLoader generateDynamicFieldInterceptionClassLoader(ClassLoader parent, String[] classpath, String[] packages);
+ /**
+ * Generate a ClassTransformer capable of performing dynamic bytecode manipulation
+ * on classes as they are loaded for the purpose of field-level interception.
+ * The returned ClassTransformer can be combined to an appropriate ClassLoader
+ * is used for run-time bytecode manipulation as
+ * opposed to the more common build-time manipulation, since here we get
+ * into SecurityManager issues and such.
+ * <p/>
+ *
+ * @param packages can be null; use to limit the packages to be transformed
+ * via this classtransformer.
+ * @param classes can be null; use to limit the classes to be transformed
+ * via this class transformer.
+ * @return The appropriate ClassTransformer.
+ */
+ public ClassTransformer getEntityClassTransformer(
+ String[] packages, String[] classes
+ );
+
public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader);
}
Added: trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,34 @@
+//$Id: $
+package org.hibernate.bytecode;
+
+import java.security.ProtectionDomain;
+
+/**
+ * A persistence provider provides an instance of this interface
+ * to the PersistenceUnitInfo.addTransformer method.
+ * The supplied transformer instance will get called to transform
+ * entity class files when they are loaded and redefined. The transformation
+ * occurs before the class is defined by the JVM
+ *
+ *
+ * @author <a href="mailto:bi...@jb...">Bill Burke</a>
+ * @author Emmanuel Bernard
+ */
+public interface ClassTransformer
+{
+ /**
+ * Invoked when a class is being loaded or redefined to add hooks for persistence bytecode manipulation
+ *
+ * @param loader the defining class loaderof the class being transformed. It may be null if using bootstrap loader
+ * @param classname The name of the class being transformed
+ * @param classBeingRedefined If an already loaded class is being redefined, then pass this as a parameter
+ * @param protectionDomain ProtectionDomain of the class being (re)-defined
+ * @param classfileBuffer The input byte buffer in class file format
+ * @return A well-formed class file that can be loaded
+ */
+ byte[] transform(ClassLoader loader,
+ String classname,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer);
+}
Modified: trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -1,24 +1,24 @@
package org.hibernate.bytecode.cglib;
+import java.lang.reflect.Modifier;
+
+import net.sf.cglib.beans.BulkBean;
+import net.sf.cglib.beans.BulkBeanException;
+import net.sf.cglib.reflect.FastClass;
+import net.sf.cglib.transform.ClassFilter;
+import net.sf.cglib.transform.ClassTransformer;
+import net.sf.cglib.transform.ClassTransformerFactory;
+import net.sf.cglib.transform.TransformingClassLoader;
+import net.sf.cglib.transform.impl.InterceptFieldFilter;
+import net.sf.cglib.transform.impl.InterceptFieldTransformer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.hibernate.bytecode.BytecodeProvider;
import org.hibernate.bytecode.ProxyFactoryFactory;
import org.hibernate.bytecode.ReflectionOptimizer;
import org.hibernate.util.StringHelper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.objectweb.asm.Type;
-import net.sf.cglib.reflect.FastClass;
-import net.sf.cglib.beans.BulkBean;
-import net.sf.cglib.beans.BulkBeanException;
-import net.sf.cglib.transform.TransformingClassLoader;
-import net.sf.cglib.transform.ClassFilter;
-import net.sf.cglib.transform.ClassTransformerFactory;
-import net.sf.cglib.transform.ClassTransformer;
-import net.sf.cglib.transform.impl.InterceptFieldTransformer;
-import net.sf.cglib.transform.impl.InterceptFieldFilter;
-import java.lang.reflect.Modifier;
-
/**
* Bytecode provider implementation for CGLIB.
*
@@ -108,6 +108,12 @@
);
}
+ public org.hibernate.bytecode.ClassTransformer getEntityClassTransformer(
+ String[] packages, String[] classes
+ ) {
+ return new CglibClassTransformer( packages, classes );
+ }
+
public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader) {
}
Added: trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,115 @@
+//$Id: $
+package org.hibernate.bytecode.cglib;
+
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+
+import net.sf.cglib.transform.ClassTransformer;
+import net.sf.cglib.transform.TransformingClassGenerator;
+import net.sf.cglib.transform.ClassReaderGenerator;
+import net.sf.cglib.transform.impl.InterceptFieldEnabled;
+import net.sf.cglib.transform.impl.InterceptFieldFilter;
+import net.sf.cglib.transform.impl.InterceptFieldTransformer;
+import net.sf.cglib.core.ClassNameReader;
+import net.sf.cglib.core.DebuggingClassWriter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.bytecode.AbstractClassTransformerImpl;
+import org.hibernate.HibernateException;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.attrs.Attributes;
+
+/**
+ * Enhance the classes allowing them to implements InterceptFieldEnabled
+ * This interface is then used by Hibernate for some optimizations.
+ *
+ * @author Emmanuel Bernard
+ */
+public class CglibClassTransformer extends AbstractClassTransformerImpl {
+
+ private static Log log = LogFactory.getLog( CglibClassTransformer.class.getName() );
+
+ public CglibClassTransformer(String[] packages, String[] classes) {
+ super(packages, classes);
+ }
+
+ protected byte[] doTransform(
+ ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) {
+ ClassReader reader;
+ try {
+ reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) );
+ }
+ catch (IOException e) {
+ log.error( "Unable to read class", e );
+ throw new HibernateException( "Unable to read class: " + e.getMessage() );
+ }
+
+ String name[] = ClassNameReader.getClassInfo( reader );
+ ClassWriter w = new DebuggingClassWriter( true );
+ ClassTransformer t = getClassTransformer( name );
+ if ( t != null ) {
+ if ( log.isDebugEnabled() ) {
+ log.debug( "Enhancing " + className );
+ }
+ ByteArrayOutputStream out;
+ byte[] result;
+ try {
+ reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) );
+ new TransformingClassGenerator(
+ new ClassReaderGenerator(
+ reader,
+ attributes(), skipDebug()
+ ), t
+ ).generateClass( w );
+ out = new ByteArrayOutputStream();
+ out.write( w.toByteArray() );
+ result = out.toByteArray();
+ out.close();
+ }
+ catch (Exception e) {
+ log.error( "Unable to transform class", e );
+ throw new HibernateException( "Unable to transform class: " + e.getMessage() );
+ }
+ return result;
+ }
+ return classfileBuffer;
+ }
+
+
+ private Attribute[] attributes() {
+ return Attributes.getDefaultAttributes();
+ }
+
+ private boolean skipDebug() {
+ return false;
+ }
+
+ private ClassTransformer getClassTransformer(String[] classInfo) {
+
+ if ( Arrays.asList( classInfo ).contains( InterceptFieldEnabled.class.getName() ) ) {
+ return null;
+ }
+ else {
+ return new InterceptFieldTransformer(
+ new InterceptFieldFilter() {
+ public boolean acceptRead(Type owner, String name) {
+ return true;
+ }
+
+ public boolean acceptWrite(Type owner, String name) {
+ return true;
+ }
+ }
+ );
+ }
+
+ }
+}
Modified: trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -1,14 +1,15 @@
package org.hibernate.bytecode.javassist;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.hibernate.bytecode.BytecodeProvider;
+import org.hibernate.bytecode.ClassTransformer;
import org.hibernate.bytecode.ProxyFactoryFactory;
import org.hibernate.bytecode.ReflectionOptimizer;
import org.hibernate.util.StringHelper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import java.lang.reflect.Modifier;
-
/**
* Bytecode provider implementation for Javassist.
*
@@ -78,6 +79,12 @@
return new TransformingClassLoader( parent, classpath );
}
+ public ClassTransformer getEntityClassTransformer(
+ String[] packages, String[] classes
+ ) {
+ return new JavassistClassTransformer( packages, classes );
+ }
+
public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader) {
if ( ! TransformingClassLoader.class.isAssignableFrom( classLoader.getClass() ) ) {
return;
Added: trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,104 @@
+//$Id: $
+package org.hibernate.bytecode.javassist;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.ProtectionDomain;
+
+import javassist.bytecode.ClassFile;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.bytecode.AbstractClassTransformerImpl;
+import org.hibernate.tool.instrument.javassist.FieldFilter;
+import org.hibernate.tool.instrument.javassist.FieldHandled;
+import org.hibernate.tool.instrument.javassist.FieldTransformer;
+
+/**
+ * Enhance the classes allowing them to implements InterceptFieldEnabled
+ * This interface is then used by Hibernate for some optimizations.
+ *
+ * @author Emmanuel Bernard
+ */
+public class JavassistClassTransformer extends AbstractClassTransformerImpl {
+
+ private static Log log = LogFactory.getLog( JavassistClassTransformer.class.getName() );
+
+ public JavassistClassTransformer(String[] packages, String[] classes) {
+ super(packages, classes);
+ }
+
+ protected byte[] doTransform(
+ ClassLoader loader, String className, Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer
+ ) {
+ ClassFile classfile = null;
+ try {
+ // WARNING: classfile only
+ classfile = new ClassFile( new DataInputStream( new ByteArrayInputStream( classfileBuffer ) ) );
+ }
+ catch (IOException e) {
+ log.error( "Unable to build enhancement metamodel for " + className );
+ return classfileBuffer;
+ }
+ FieldTransformer transformer = getFieldTransformer( classfile );
+ if ( transformer != null ) {
+ if ( log.isDebugEnabled() ) {
+ log.debug( "Enhancing " + className );
+ }
+ DataOutputStream out = null;
+ try {
+ transformer.transform( classfile );
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ out = new DataOutputStream( byteStream );
+ classfile.write( out );
+ return byteStream.toByteArray();
+ }
+ catch (Exception e) {
+ log.error( "Unable to transform class", e );
+ throw new HibernateException( "Unable to transform class: " + e.getMessage() );
+ }
+ finally {
+ try {
+ if ( out != null ) out.close();
+ }
+ catch (IOException e) {
+ //swallow
+ }
+ }
+ }
+ return classfileBuffer;
+ }
+
+ protected FieldTransformer getFieldTransformer(ClassFile classfile) {
+ if ( alreadyInstrumented( classfile ) ) {
+ return null;
+ }
+ else {
+ return new FieldTransformer(
+ new FieldFilter() {
+ public boolean handleRead(String desc, String name) {
+ return true;
+ }
+
+ public boolean handleWrite(String desc, String name) {
+ return true;
+ }
+ }
+ );
+ }
+ }
+
+ private boolean alreadyInstrumented(ClassFile classfile) {
+ String[] intfs = classfile.getInterfaces();
+ for ( int i = 0; i < intfs.length; i++ ) {
+ if ( FieldHandled.class.getName().equals( intfs[i] ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Modified: trunk/Hibernate3/test/org/hibernate/test/AllTests.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/AllTests.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/test/org/hibernate/test/AllTests.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -47,6 +47,7 @@
import org.hibernate.test.immutable.ImmutableTest;
import org.hibernate.test.instrument.buildtime.InstrumentTest;
import org.hibernate.test.instrument.runtime.CGLIBInstrumentationTest;
+import org.hibernate.test.instrument.runtime.JavassistInstrumentationTest;
import org.hibernate.test.interceptor.InterceptorTest;
import org.hibernate.test.interfaceproxy.InterfaceProxyTest;
import org.hibernate.test.iterate.IterateTest;
@@ -282,6 +283,7 @@
suite.addTest( InstrumentCacheTest2.suite() );
}
suite.addTest( CGLIBInstrumentationTest.suite() );
+ suite.addTest( JavassistInstrumentationTest.suite() );
suite.addTest( SybaseTimestampVersioningTest.suite() );
suite.addTest( DbVersionTest.suite() );
suite.addTest( TimestampGeneratedValuesWithCachingTest.suite() );
Modified: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -1,7 +1,6 @@
package org.hibernate.test.instrument.runtime;
import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.BytecodeProvider;
@@ -15,16 +14,17 @@
private BytecodeProvider provider;
protected ClassLoader buildIsolatedClassLoader(ClassLoader parent) {
- String myFileName = AbstractTransformingClassLoaderInstrumentTestCase.class.getName().replace( '.', '/' ) + ".class";
- URL fileURL = this.getClass().getClassLoader().getResource( myFileName );
- String filePath = fileURL.getPath();
- String classPath = filePath.substring( 0, filePath.length() - myFileName.length() );
+// String myFileName = AbstractTransformingClassLoaderInstrumentTestCase.class.getName().replace( '.', '/' ) + ".class";
+// URL fileURL = this.getClass().getClassLoader().getResource( myFileName );
+// String filePath = fileURL.getPath();
+// String classPath = filePath.substring( 0, filePath.length() - myFileName.length() );
provider = buildBytecodeProvider();
- return provider.generateDynamicFieldInterceptionClassLoader(
+ return new InstrumentedClassLoader(
parent,
- new String[] { classPath },
- new String[] { "org.hibernate.test.instrument" }
- );
+ provider.getEntityClassTransformer(
+ new String[] { "org.hibernate.test.instrument" },
+ null) );
+
}
protected void releaseIsolatedClassLoader(ClassLoader isolatedLoader) {
Added: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,81 @@
+//$Id: $
+package org.hibernate.test.instrument.runtime;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.hibernate.HibernateException;
+import org.hibernate.bytecode.ClassTransformer;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class InstrumentedClassLoader extends ClassLoader {
+
+ private ClassTransformer classTransformer;
+
+ public InstrumentedClassLoader(ClassLoader parent, ClassTransformer classTransformer) {
+ super( parent );
+ this.classTransformer = classTransformer;
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ if ( name.startsWith( "java" ) ) return getParent().loadClass( name );
+ Class c = findLoadedClass( name );
+ if ( c != null ) return c;
+ InputStream is = this.getResourceAsStream( name.replace( ".", "/" ) + ".class" );
+ if ( is == null ) throw new ClassNotFoundException( name );
+ byte[] buffer = new byte[409600];
+ byte[] originalClass = new byte[0];
+ int r = 0;
+ try {
+ r = is.read( buffer );
+ }
+ catch (IOException e) {
+ throw new ClassNotFoundException( name + " not found", e );
+ }
+ while ( r >= buffer.length ) {
+ byte[] temp = new byte[ originalClass.length + buffer.length ];
+ System.arraycopy( originalClass, 0, temp, 0, originalClass.length );
+ System.arraycopy( buffer, 0, temp, originalClass.length, buffer.length );
+ originalClass = temp;
+ }
+ if ( r != -1 ) {
+ byte[] temp = new byte[ originalClass.length + r ];
+ System.arraycopy( originalClass, 0, temp, 0, originalClass.length );
+ System.arraycopy( buffer, 0, temp, originalClass.length, r );
+ originalClass = temp;
+ }
+ try {
+ is.close();
+ }
+ catch (IOException e) {
+ throw new ClassNotFoundException( name + " not found", e );
+ }
+ if (classTransformer != null) {
+ byte[] transformed = new byte[0];
+ try {
+ transformed = classTransformer.transform(
+ getParent(),
+ name,
+ null,
+ null,
+ originalClass
+ );
+ if ( originalClass == transformed) {
+ return getParent().loadClass(name);
+ }
+ else {
+ return defineClass( name, transformed, 0, transformed.length );
+ }
+ }
+ catch (HibernateException e) {
+ throw new ClassNotFoundException( name + " not found", e );
+ }
+ }
+ else {
+ return getParent().loadClass(name);
+ }
+ }
+}
Added: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2006-05-04 20:46:47 UTC (rev 9882)
+++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2006-05-04 22:36:54 UTC (rev 9883)
@@ -0,0 +1,20 @@
+//$Id: $
+package org.hibernate.test.instrument.runtime;
+
+import org.hibernate.bytecode.BytecodeProvider;
+import org.hibernate.bytecode.javassist.BytecodeProviderImpl;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JavassistInstrumentationTest extends AbstractTransformingClassLoaderInstrumentTestCase {
+ protected BytecodeProvider buildBytecodeProvider() {
+ return new BytecodeProviderImpl();
+ }
+
+ public static Test suite() {
+ return new TestSuite( JavassistInstrumentationTest.class );
+ }
+}
|