HHH-9822 - Switch runtime JPA Class transformation to use new bytecode Enhancer
This commit is contained in:
parent
99c643febc
commit
ae070f32c9
|
@ -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 ) {
|
||||
|
|
|
@ -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<String> entityClassNames) {
|
||||
persistenceUnitInfo.addTransformer( new InterceptFieldClassFileTransformer( entityClassNames ) );
|
||||
persistenceUnitInfo.addTransformer( new EnhancingClassTransformerImpl( entityClassNames ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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<String> classNames;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public EnhancementContextImpl(Collection<String> 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 );
|
||||
}
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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<String> classNames;
|
||||
|
||||
private Enhancer enhancer;
|
||||
|
||||
public EnhancingClassTransformerImpl(Collection<String> incomingClassNames) {
|
||||
this.classNames = new ArrayList<String>( 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue