Skip to content

Commit ae070f3

Browse files
committed
HHH-9822 - Switch runtime JPA Class transformation to use new bytecode Enhancer
1 parent 99c643f commit ae070f3

File tree

7 files changed

+130
-18
lines changed

7 files changed

+130
-18
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/FieldWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static void addFieldWithGetterAndSetter(CtClass target, CtClass type, Str
5050

5151
private static void addPrivateTransient(CtClass target, CtClass type, String name) {
5252
addWithModifiers( target, type, name, Modifier.PRIVATE | Modifier.TRANSIENT, Transient.class );
53-
log.debugf( "Wrote field into [%s]: @Transient private transient %s %s() %s;%n", target.getName(), type.getName(), name );
53+
log.debugf( "Wrote field into [%s]: @Transient private transient %s %s;%n", target.getName(), type.getName(), name );
5454
}
5555

5656
private static void addWithModifiers(CtClass target, CtClass type, String name, int modifiers, Class<?> ... annotations ) {

hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import javax.persistence.spi.PersistenceUnitTransactionType;
1717

1818
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
19-
import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer;
19+
import org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl;
2020

2121
/**
2222
* @author Steve Ebersole
@@ -110,6 +110,6 @@ public List<URL> getJarFileUrls() {
110110

111111
@Override
112112
public void pushClassTransformer(Collection<String> entityClassNames) {
113-
persistenceUnitInfo.addTransformer( new InterceptFieldClassFileTransformer( entityClassNames ) );
113+
persistenceUnitInfo.addTransformer( new EnhancingClassTransformerImpl( entityClassNames ) );
114114
}
115115
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.jpa.internal.enhance;
8+
9+
import java.util.Collection;
10+
11+
import javassist.CtClass;
12+
13+
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
14+
15+
/**
16+
* @author Steve Ebersole
17+
*/
18+
public class EnhancementContextImpl extends DefaultEnhancementContext {
19+
private final Collection<String> classNames;
20+
private final ClassLoader classLoader;
21+
22+
public EnhancementContextImpl(Collection<String> classNames, ClassLoader classLoader) {
23+
this.classNames = classNames;
24+
this.classLoader = classLoader;
25+
}
26+
27+
@Override
28+
public ClassLoader getLoadingClassLoader() {
29+
return classLoader;
30+
}
31+
32+
@Override
33+
public boolean isEntityClass(CtClass classDescriptor) {
34+
return classNames.contains( classDescriptor.getName() )
35+
&& super.isEntityClass( classDescriptor );
36+
}
37+
38+
@Override
39+
public boolean isCompositeClass(CtClass classDescriptor) {
40+
return classNames.contains( classDescriptor.getName() )
41+
&& super.isCompositeClass( classDescriptor );
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.jpa.internal.enhance;
8+
9+
import java.lang.instrument.IllegalClassFormatException;
10+
import java.security.ProtectionDomain;
11+
import java.util.ArrayList;
12+
import java.util.Collection;
13+
import javax.persistence.spi.ClassTransformer;
14+
15+
import org.hibernate.bytecode.enhance.spi.Enhancer;
16+
17+
/**
18+
* @author Steve Ebersole
19+
*/
20+
public class EnhancingClassTransformerImpl implements ClassTransformer {
21+
private final Collection<String> classNames;
22+
23+
private Enhancer enhancer;
24+
25+
public EnhancingClassTransformerImpl(Collection<String> incomingClassNames) {
26+
this.classNames = new ArrayList<String>( incomingClassNames.size() );
27+
this.classNames.addAll( incomingClassNames );
28+
}
29+
30+
@Override
31+
public byte[] transform(
32+
ClassLoader loader,
33+
String className,
34+
Class<?> classBeingRedefined,
35+
ProtectionDomain protectionDomain,
36+
byte[] classfileBuffer) throws IllegalClassFormatException {
37+
if ( enhancer == null ) {
38+
enhancer = new Enhancer( new EnhancementContextImpl( classNames, loader ) );
39+
}
40+
41+
try {
42+
return enhancer.enhance( className, classfileBuffer );
43+
}
44+
catch (final Exception e) {
45+
throw new IllegalClassFormatException( "Error performing enhancement" ) {
46+
@Override
47+
public synchronized Throwable getCause() {
48+
return e;
49+
}
50+
};
51+
}
52+
}
53+
54+
}

hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InstrumentedClassLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.lang.instrument.IllegalClassFormatException;
1414
import java.util.List;
1515

16-
import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer;
16+
import org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl;
1717

1818
/**
1919
* @author Emmanuel Bernard
@@ -79,7 +79,7 @@ public byte[] loadClassBytes(String name) throws ClassNotFoundException {
7979
catch (IOException e) {
8080
throw new ClassNotFoundException( name + " not found", e );
8181
}
82-
InterceptFieldClassFileTransformer t = new InterceptFieldClassFileTransformer( entities );
82+
EnhancingClassTransformerImpl t = new EnhancingClassTransformerImpl( entities );
8383
byte[] transformed = new byte[0];
8484
try {
8585
transformed = t.transform(

hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/InterceptFieldClassFileTransformerTest.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,19 @@
2020
import javassist.bytecode.AttributeInfo;
2121
import javassist.bytecode.StackMapTable;
2222

23+
import org.hibernate.engine.spi.Managed;
24+
import org.hibernate.engine.spi.ManagedComposite;
25+
import org.hibernate.engine.spi.ManagedEntity;
26+
2327
import org.hibernate.testing.TestForIssue;
28+
import org.hibernate.testing.junit4.ExtraAssertions;
2429
import org.junit.Assert;
2530
import org.junit.Before;
2631
import org.junit.Test;
2732

33+
import static org.junit.Assert.assertFalse;
34+
import static org.junit.Assert.assertTrue;
35+
2836
/**
2937
* @author Emmanuel Bernard
3038
* @author Hardy Ferentschik
@@ -52,21 +60,25 @@ public void setup() {
5260
@Test
5361
public void testEnhancement() throws Exception {
5462
// sanity check that the class is unmodified and does not contain getFieldHandler()
55-
try {
56-
Simple.class.getDeclaredMethod( "getFieldHandler" );
57-
Assert.fail();
58-
} catch ( NoSuchMethodException nsme ) {
59-
// success
60-
}
61-
63+
assertFalse( implementsManaged( Simple.class ) );
64+
6265
Class clazz = loader.loadClass( entities.get( 0 ) );
63-
64-
// javassist is our default byte code enhancer. Enhancing will eg add the method getFieldHandler()
65-
// see org.hibernate.bytecode.internal.javassist.FieldTransformer
66-
Method method = clazz.getDeclaredMethod( "getFieldHandler" );
67-
Assert.assertNotNull( method );
66+
67+
// enhancement would have added the ManagedEntity interface...
68+
assertTrue( implementsManaged( clazz ) );
6869
}
69-
70+
71+
private boolean implementsManaged(Class clazz) {
72+
for ( Class intf : clazz.getInterfaces() ) {
73+
if ( Managed.class.getName().equals( intf.getName() )
74+
|| ManagedEntity.class.getName().equals( intf.getName() )
75+
|| ManagedComposite.class.getName().equals( intf.getName() ) ) {
76+
return true;
77+
}
78+
}
79+
return false;
80+
}
81+
7082
/**
7183
* Tests that methods that were enhanced by javassist have
7284
* StackMapTables for java verification. Without these,

hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/instrument/Simple.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import java.util.Collection;
1212

13+
import javax.persistence.Entity;
14+
1315
import org.hibernate.jpa.internal.instrument.InterceptFieldClassFileTransformer;
1416

1517

@@ -19,6 +21,7 @@
1921
* @author Emmanuel Bernard
2022
* @author Dustin Schultz
2123
*/
24+
@Entity
2225
public class Simple {
2326
private String name;
2427

0 commit comments

Comments
 (0)