diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/FieldWriter.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/FieldWriter.java index 880b39c87f..a5f252011b 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/FieldWriter.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/FieldWriter.java @@ -50,7 +50,7 @@ public class FieldWriter { private static void addPrivateTransient(CtClass target, CtClass type, String name) { addWithModifiers( target, type, name, Modifier.PRIVATE | Modifier.TRANSIENT, Transient.class ); - log.debugf( "Wrote field into [%s]: @Transient private transient %s %s() %s;%n", target.getName(), type.getName(), name ); + log.debugf( "Wrote field into [%s]: @Transient private transient %s %s;%n", target.getName(), type.getName(), name ); } private static void addWithModifiers(CtClass target, CtClass type, String name, int modifiers, Class ... annotations ) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java index d46e7cf8d0..15892bf438 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java @@ -16,7 +16,7 @@ import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; -import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer; +import org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl; /** * @author Steve Ebersole @@ -110,6 +110,6 @@ public class PersistenceUnitInfoDescriptor implements PersistenceUnitDescriptor @Override public void pushClassTransformer(Collection entityClassNames) { - persistenceUnitInfo.addTransformer( new InterceptFieldClassFileTransformer( entityClassNames ) ); + persistenceUnitInfo.addTransformer( new EnhancingClassTransformerImpl( entityClassNames ) ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancementContextImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancementContextImpl.java new file mode 100644 index 0000000000..c47045f581 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancementContextImpl.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpa.internal.enhance; + +import java.util.Collection; + +import javassist.CtClass; + +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +/** + * @author Steve Ebersole + */ +public class EnhancementContextImpl extends DefaultEnhancementContext { + private final Collection classNames; + private final ClassLoader classLoader; + + public EnhancementContextImpl(Collection classNames, ClassLoader classLoader) { + this.classNames = classNames; + this.classLoader = classLoader; + } + + @Override + public ClassLoader getLoadingClassLoader() { + return classLoader; + } + + @Override + public boolean isEntityClass(CtClass classDescriptor) { + return classNames.contains( classDescriptor.getName() ) + && super.isEntityClass( classDescriptor ); + } + + @Override + public boolean isCompositeClass(CtClass classDescriptor) { + return classNames.contains( classDescriptor.getName() ) + && super.isCompositeClass( classDescriptor ); + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancingClassTransformerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancingClassTransformerImpl.java new file mode 100644 index 0000000000..fe44aed7a3 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/enhance/EnhancingClassTransformerImpl.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpa.internal.enhance; + +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Collection; +import javax.persistence.spi.ClassTransformer; + +import org.hibernate.bytecode.enhance.spi.Enhancer; + +/** + * @author Steve Ebersole + */ +public class EnhancingClassTransformerImpl implements ClassTransformer { + private final Collection classNames; + + private Enhancer enhancer; + + public EnhancingClassTransformerImpl(Collection incomingClassNames) { + this.classNames = new ArrayList( incomingClassNames.size() ); + this.classNames.addAll( incomingClassNames ); + } + + @Override + public byte[] transform( + ClassLoader loader, + String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) throws IllegalClassFormatException { + if ( enhancer == null ) { + enhancer = new Enhancer( new EnhancementContextImpl( classNames, loader ) ); + } + + try { + return enhancer.enhance( className, classfileBuffer ); + } + catch (final Exception e) { + throw new IllegalClassFormatException( "Error performing enhancement" ) { + @Override + public synchronized Throwable getCause() { + return e; + } + }; + } + } + +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InstrumentedClassLoader.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InstrumentedClassLoader.java index 2deb279e14..046e3dbfe0 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InstrumentedClassLoader.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InstrumentedClassLoader.java @@ -13,7 +13,7 @@ import java.io.InputStream; import java.lang.instrument.IllegalClassFormatException; import java.util.List; -import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer; +import org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl; /** * @author Emmanuel Bernard @@ -79,7 +79,7 @@ public class InstrumentedClassLoader extends ClassLoader { catch (IOException e) { throw new ClassNotFoundException( name + " not found", e ); } - InterceptFieldClassFileTransformer t = new InterceptFieldClassFileTransformer( entities ); + EnhancingClassTransformerImpl t = new EnhancingClassTransformerImpl( entities ); byte[] transformed = new byte[0]; try { transformed = t.transform( diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InterceptFieldClassFileTransformerTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InterceptFieldClassFileTransformerTest.java index 46d803573b..569557410e 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InterceptFieldClassFileTransformerTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InterceptFieldClassFileTransformerTest.java @@ -20,11 +20,19 @@ import javassist.CtMethod; import javassist.bytecode.AttributeInfo; import javassist.bytecode.StackMapTable; +import org.hibernate.engine.spi.Managed; +import org.hibernate.engine.spi.ManagedComposite; +import org.hibernate.engine.spi.ManagedEntity; + import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.ExtraAssertions; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * @author Emmanuel Bernard * @author Hardy Ferentschik @@ -52,21 +60,25 @@ public class InterceptFieldClassFileTransformerTest { @Test public void testEnhancement() throws Exception { // sanity check that the class is unmodified and does not contain getFieldHandler() - try { - Simple.class.getDeclaredMethod( "getFieldHandler" ); - Assert.fail(); - } catch ( NoSuchMethodException nsme ) { - // success - } - + assertFalse( implementsManaged( Simple.class ) ); + Class clazz = loader.loadClass( entities.get( 0 ) ); - - // javassist is our default byte code enhancer. Enhancing will eg add the method getFieldHandler() - // see org.hibernate.bytecode.internal.javassist.FieldTransformer - Method method = clazz.getDeclaredMethod( "getFieldHandler" ); - Assert.assertNotNull( method ); + + // enhancement would have added the ManagedEntity interface... + assertTrue( implementsManaged( clazz ) ); } - + + private boolean implementsManaged(Class clazz) { + for ( Class intf : clazz.getInterfaces() ) { + if ( Managed.class.getName().equals( intf.getName() ) + || ManagedEntity.class.getName().equals( intf.getName() ) + || ManagedComposite.class.getName().equals( intf.getName() ) ) { + return true; + } + } + return false; + } + /** * Tests that methods that were enhanced by javassist have * StackMapTables for java verification. Without these, diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/Simple.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/Simple.java index be132be8e5..3e8f63a27f 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/Simple.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/Simple.java @@ -10,6 +10,8 @@ package org.hibernate.jpa.test.instrument; import java.util.Collection; +import javax.persistence.Entity; + import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer; @@ -19,6 +21,7 @@ import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer; * @author Emmanuel Bernard * @author Dustin Schultz */ +@Entity public class Simple { private String name;