HHH-11882 - Remove old bytecode enhancer testing infrastructure
This commit is contained in:
parent
d3ce7ded37
commit
a2803d7703
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.testing.bytecode.enhancement;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import javax.tools.JavaFileObject;
|
|
||||||
|
|
||||||
import org.hibernate.internal.CoreLogging;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
//
|
|
||||||
//import com.sun.tools.classfile.ConstantPoolException;
|
|
||||||
//import com.sun.tools.javap.JavapTask;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* utility class to use in bytecode enhancement tests
|
|
||||||
*
|
|
||||||
* @author Luis Barreiro
|
|
||||||
*/
|
|
||||||
public abstract class DecompileUtils {
|
|
||||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( DecompileUtils.class );
|
|
||||||
|
|
||||||
// Had to gut this because Java does not make JAVAP available via ToolProvider
|
|
||||||
// instead on has to rely on tools.jar classes directly :(
|
|
||||||
|
|
||||||
public static void decompileDumpedClass(String workingDir, String className) {
|
|
||||||
// try {
|
|
||||||
// JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
|
||||||
// StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
|
|
||||||
// fileManager.setLocation(
|
|
||||||
// StandardLocation.CLASS_OUTPUT,
|
|
||||||
// Collections.singletonList( new File( workingDir ) )
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// JavapTask javapTask = new JavapTask();
|
|
||||||
// String filename = workingDir + File.separator + getFilenameForClassName( className );
|
|
||||||
// for ( JavaFileObject jfo : fileManager.getJavaFileObjects( filename ) ) {
|
|
||||||
// try {
|
|
||||||
// Set<String> interfaceNames = new HashSet<String>();
|
|
||||||
// Set<String> fieldNames = new HashSet<String>();
|
|
||||||
// Set<String> methodNames = new HashSet<String>();
|
|
||||||
//
|
|
||||||
// JavapTask.ClassFileInfo info = javapTask.read( jfo );
|
|
||||||
//
|
|
||||||
// log.infof( "decompiled class [%s]", info.cf.getName() );
|
|
||||||
//
|
|
||||||
// for ( int i : info.cf.interfaces ) {
|
|
||||||
// interfaceNames.add( info.cf.constant_pool.getClassInfo( i ).getName() );
|
|
||||||
// log.debugf( "declared iFace = ", info.cf.constant_pool.getClassInfo( i ).getName() );
|
|
||||||
// }
|
|
||||||
// for ( com.sun.tools.classfile.Field f : info.cf.fields ) {
|
|
||||||
// fieldNames.add( f.getName( info.cf.constant_pool ) );
|
|
||||||
// log.debugf( "declared field = ", f.getName( info.cf.constant_pool ) );
|
|
||||||
// }
|
|
||||||
// for ( com.sun.tools.classfile.Method m : info.cf.methods ) {
|
|
||||||
// methodNames.add( m.getName( info.cf.constant_pool ) );
|
|
||||||
// log.debugf( "declared method = ", m.getName( info.cf.constant_pool ) );
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // checks signature against known interfaces
|
|
||||||
// if ( interfaceNames.contains( PersistentAttributeInterceptor.class.getName() ) ) {
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.INTERCEPTOR_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.INTERCEPTOR_GETTER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.INTERCEPTOR_SETTER_NAME ) );
|
|
||||||
// }
|
|
||||||
// if ( interfaceNames.contains( ManagedEntity.class.getName() ) ) {
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME ) );
|
|
||||||
//
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.ENTITY_ENTRY_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.ENTITY_ENTRY_GETTER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.ENTITY_ENTRY_SETTER_NAME ) );
|
|
||||||
//
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.PREVIOUS_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.PREVIOUS_GETTER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.PREVIOUS_SETTER_NAME ) );
|
|
||||||
//
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.NEXT_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.NEXT_GETTER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.NEXT_SETTER_NAME ) );
|
|
||||||
// }
|
|
||||||
// if ( interfaceNames.contains( SelfDirtinessTracker.class.getName() ) ) {
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_GET_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CLEAR_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_HAS_CHANGED_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_SUSPEND_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COLLECTION_GET_NAME ) );
|
|
||||||
// }
|
|
||||||
// if ( interfaceNames.contains( CompositeTracker.class.getName() ) ) {
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_COMPOSITE_FIELD_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER ) );
|
|
||||||
// }
|
|
||||||
// if ( interfaceNames.contains( CompositeOwner.class.getName() ) ) {
|
|
||||||
// assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
|
|
||||||
// assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (ConstantPoolException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (IOException ioe) {
|
|
||||||
// assertNull( "Failed to open class file", ioe );
|
|
||||||
// }
|
|
||||||
// catch (RuntimeException re) {
|
|
||||||
// log.warnf( re, "WARNING: UNABLE DECOMPILE DUE TO %s", re.getMessage() );
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getFilenameForClassName(String className) {
|
|
||||||
return className.replace( '.', File.separatorChar ) + JavaFileObject.Kind.CLASS.extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.testing.bytecode.enhancement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Luis Barreiro
|
|
||||||
*/
|
|
||||||
public interface EnhancerTestTask {
|
|
||||||
|
|
||||||
Class<?>[] getAnnotatedClasses();
|
|
||||||
|
|
||||||
void prepare();
|
|
||||||
|
|
||||||
void execute();
|
|
||||||
|
|
||||||
void complete();
|
|
||||||
|
|
||||||
}
|
|
|
@ -6,36 +6,17 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.bytecode.enhancement;
|
package org.hibernate.testing.bytecode.enhancement;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import javassist.ClassPool;
|
|
||||||
import javassist.CtClass;
|
|
||||||
import javassist.LoaderClassPath;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
|
|
||||||
import org.hibernate.bytecode.enhance.spi.Enhancer;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.engine.internal.MutableEntityEntryFactory;
|
import org.hibernate.engine.internal.MutableEntityEntryFactory;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.internal.CoreLogging;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@ -46,139 +27,6 @@ import static org.junit.Assert.fail;
|
||||||
* @author Luis Barreiro
|
* @author Luis Barreiro
|
||||||
*/
|
*/
|
||||||
public abstract class EnhancerTestUtils extends BaseUnitTestCase {
|
public abstract class EnhancerTestUtils extends BaseUnitTestCase {
|
||||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( EnhancerTestUtils.class );
|
|
||||||
|
|
||||||
private static String workingDir = System.getProperty( "java.io.tmpdir" );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* method that performs the enhancement of a class
|
|
||||||
* also checks the signature of enhanced entities methods using 'javap' decompiler
|
|
||||||
*/
|
|
||||||
public static Class<?> enhanceAndDecompile(Class<?> classToEnhance, ClassLoader cl) throws Exception {
|
|
||||||
CtClass entityCtClass = generateCtClassForAnEntity( classToEnhance );
|
|
||||||
|
|
||||||
byte[] original = entityCtClass.toBytecode();
|
|
||||||
byte[] enhanced = Environment.getBytecodeProvider().getEnhancer( new EnhancerTestContext() ).enhance( entityCtClass.getName(), original );
|
|
||||||
assertFalse( "entity was not enhanced", enhanced == null );
|
|
||||||
log.infof( "enhanced entity [%s]", entityCtClass.getName() );
|
|
||||||
|
|
||||||
ClassPool cp = new ClassPool( false );
|
|
||||||
cp.appendClassPath( new LoaderClassPath( cl ) );
|
|
||||||
CtClass enhancedCtClass = cp.makeClass( new ByteArrayInputStream( enhanced ) );
|
|
||||||
|
|
||||||
enhancedCtClass.debugWriteFile( workingDir );
|
|
||||||
DecompileUtils.decompileDumpedClass( workingDir, classToEnhance.getName() );
|
|
||||||
|
|
||||||
Class<?> enhancedClass = enhancedCtClass.toClass( cl, EnhancerTestUtils.class.getProtectionDomain() );
|
|
||||||
assertNotNull( enhancedClass );
|
|
||||||
return enhancedClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CtClass generateCtClassForAnEntity(Class<?> entityClassToEnhance) throws Exception {
|
|
||||||
ClassPool cp = new ClassPool( false );
|
|
||||||
ClassLoader cl = EnhancerTestUtils.class.getClassLoader();
|
|
||||||
return cp.makeClass( cl.getResourceAsStream( entityClassToEnhance.getName().replace( '.', '/' ) + ".class" ) );
|
|
||||||
}
|
|
||||||
/* --- */
|
|
||||||
|
|
||||||
public static <T extends EnhancerTestTask> void runEnhancerTestTask(Class<T> task) {
|
|
||||||
runEnhancerTestTask( task, new EnhancerTestContext() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends EnhancerTestTask> void runEnhancerTestTask(Class<T> task, EnhancementContext context) {
|
|
||||||
EnhancerTestTask taskObject = null;
|
|
||||||
ClassLoader defaultCL = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
ClassLoader cl = EnhancerTestUtils.getEnhancerClassLoader( context, task.getPackage().getName() );
|
|
||||||
EnhancerTestUtils.setupClassLoader( cl, task );
|
|
||||||
EnhancerTestUtils.setupClassLoader( cl, task.newInstance().getAnnotatedClasses() );
|
|
||||||
|
|
||||||
Thread.currentThread().setContextClassLoader( cl );
|
|
||||||
taskObject = cl.loadClass( task.getName() ).asSubclass( EnhancerTestTask.class ).newInstance();
|
|
||||||
|
|
||||||
taskObject.prepare();
|
|
||||||
taskObject.execute();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new HibernateException( "could not execute task", e );
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
if ( taskObject != null ) {
|
|
||||||
taskObject.complete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
}
|
|
||||||
Thread.currentThread().setContextClassLoader( defaultCL );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setupClassLoader(ClassLoader cl, Class<?>... classesToLoad) {
|
|
||||||
for ( Class<?> classToLoad : classesToLoad ) {
|
|
||||||
try {
|
|
||||||
cl.loadClass( classToLoad.getName() );
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ClassLoader getEnhancerClassLoader(EnhancementContext context, String packageName) {
|
|
||||||
return new ClassLoader() {
|
|
||||||
|
|
||||||
private Enhancer enhancer = Environment.getBytecodeProvider().getEnhancer( context );
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
@Override
|
|
||||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
||||||
if ( !name.startsWith( packageName ) ) {
|
|
||||||
return getParent().loadClass( name );
|
|
||||||
}
|
|
||||||
Class c = findLoadedClass( name );
|
|
||||||
if ( c != null ) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream is = getResourceAsStream( name.replace( '.', '/' ) + ".class" );
|
|
||||||
if ( is == null ) {
|
|
||||||
throw new ClassNotFoundException( name + " not found" );
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] original = new byte[is.available()];
|
|
||||||
new BufferedInputStream( is ).read( original );
|
|
||||||
|
|
||||||
byte[] enhanced = enhancer.enhance( name, original );
|
|
||||||
|
|
||||||
if ( enhanced != null ) {
|
|
||||||
File f = new File( workingDir + File.separator + name.replace( ".", File.separator ) + ".class" );
|
|
||||||
f.getParentFile().mkdirs();
|
|
||||||
f.createNewFile();
|
|
||||||
FileOutputStream out = new FileOutputStream( f );
|
|
||||||
out.write( enhanced );
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
enhanced = original;
|
|
||||||
}
|
|
||||||
|
|
||||||
return defineClass( name, enhanced, 0, enhanced.length );
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
throw new ClassNotFoundException( name + " not found", t );
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
catch (IOException ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object getFieldByReflection(Object entity, String fieldName) {
|
public static Object getFieldByReflection(Object entity, String fieldName) {
|
||||||
try {
|
try {
|
||||||
|
@ -186,11 +34,8 @@ public abstract class EnhancerTestUtils extends BaseUnitTestCase {
|
||||||
field.setAccessible( true );
|
field.setAccessible( true );
|
||||||
return field.get( entity );
|
return field.get( entity );
|
||||||
}
|
}
|
||||||
catch (NoSuchFieldException e) {
|
catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
fail( "Fail to get field '" + fieldName + "' in entity " + entity );
|
fail( "Fail to get field '" + fieldName + "' in entity " + entity + ": " + e.getMessage() );
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
fail( "Fail to get field '" + fieldName + "' in entity " + entity );
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue