HHH-8354 added new dirty-checking options to newly cherry-picked plugins
This commit is contained in:
parent
a0e242992b
commit
492ea5d2a5
|
@ -29,7 +29,6 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -37,17 +36,20 @@ import javassist.ClassPool;
|
||||||
import javassist.CtClass;
|
import javassist.CtClass;
|
||||||
import javassist.CtField;
|
import javassist.CtField;
|
||||||
|
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
|
|
||||||
import org.hibernate.bytecode.enhance.spi.Enhancer;
|
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
|
||||||
|
import org.hibernate.bytecode.enhance.spi.Enhancer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This plugin will enhance Entity objects.
|
* This plugin will enhance Entity objects.
|
||||||
|
@ -55,13 +57,14 @@ import org.apache.maven.plugins.annotations.Parameter;
|
||||||
* @author Jeremy Whiting
|
* @author Jeremy Whiting
|
||||||
*/
|
*/
|
||||||
@Mojo(name = "enhance")
|
@Mojo(name = "enhance")
|
||||||
public class MavenEnhancePlugin extends AbstractMojo {
|
public class MavenEnhancePlugin extends AbstractMojo implements EnhancementContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contexts to use during enhancement.
|
* The contexts to use during enhancement.
|
||||||
*/
|
*/
|
||||||
private List<File> classes = new ArrayList<File>();
|
private List<File> classes = new ArrayList<File>();
|
||||||
private ClassPool pool = new ClassPool( false );
|
private ClassPool pool = new ClassPool( false );
|
||||||
|
private final Enhancer enhancer = new Enhancer( this);
|
||||||
|
|
||||||
private static final String CLASS_EXTENSION = ".class";
|
private static final String CLASS_EXTENSION = ".class";
|
||||||
|
|
||||||
|
@ -74,57 +77,9 @@ public class MavenEnhancePlugin extends AbstractMojo {
|
||||||
File root = new File( this.dir );
|
File root = new File( this.dir );
|
||||||
walkDir( root );
|
walkDir( root );
|
||||||
|
|
||||||
Enhancer enhancer = new Enhancer( new EnhancementContext() {
|
|
||||||
|
|
||||||
private ClassLoader overridden;
|
|
||||||
|
|
||||||
public ClassLoader getLoadingClassLoader() {
|
|
||||||
if ( null == this.overridden ) {
|
|
||||||
return getClass().getClassLoader();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return this.overridden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClassLoader(ClassLoader loader) {
|
|
||||||
this.overridden = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEntityClass(CtClass classDescriptor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasLazyLoadableAttributes(CtClass classDescriptor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLazyLoadable(CtField field) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCompositeClass(CtClass classDescriptor) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CtField[] order(CtField[] fields) {
|
|
||||||
// TODO: load ordering from configuration.
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPersistentField(CtField ctField) {
|
|
||||||
return !ctField.hasAnnotation( Transient.class );
|
|
||||||
}
|
|
||||||
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( 0 < classes.size() ) {
|
if ( 0 < classes.size() ) {
|
||||||
for ( File file : classes ) {
|
for ( File file : classes ) {
|
||||||
enhanceClass( enhancer, file );
|
processClassFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +107,7 @@ public class MavenEnhancePlugin extends AbstractMojo {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void walkDir(File dir, FileFilter classesFilter, FileFilter dirFilter) {
|
private void walkDir(File dir, FileFilter classesFilter, FileFilter dirFilter) {
|
||||||
|
|
||||||
File[] dirs = dir.listFiles( dirFilter );
|
File[] dirs = dir.listFiles( dirFilter );
|
||||||
for ( int i = 0; i < dirs.length; i++ ) {
|
for ( int i = 0; i < dirs.length; i++ ) {
|
||||||
walkDir( dirs[i], classesFilter, dirFilter );
|
walkDir( dirs[i], classesFilter, dirFilter );
|
||||||
|
@ -163,67 +119,82 @@ public class MavenEnhancePlugin extends AbstractMojo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enhanceClass(Enhancer enhancer, File file) {
|
|
||||||
byte[] enhancedBytecode = null;
|
/**
|
||||||
InputStream is = null;
|
* Atm only process files annotated with either @Entity or @Embeddable
|
||||||
CtClass clas = null;
|
* @param javaClassFile
|
||||||
|
*/
|
||||||
|
private void processClassFile(File javaClassFile)
|
||||||
|
throws MojoExecutionException {
|
||||||
try {
|
try {
|
||||||
is = new FileInputStream( file.toString() );
|
final CtClass ctClass = getClassPool().makeClass( new FileInputStream( javaClassFile ) );
|
||||||
clas = getClassPool().makeClass( is );
|
if(this.isEntityClass(ctClass))
|
||||||
if ( !clas.hasAnnotation( Entity.class ) ) {
|
processEntityClassFile(javaClassFile, ctClass);
|
||||||
getLog().debug( "Class $file not an annotated Entity class. skipping..." );
|
else if(this.isCompositeClass(ctClass))
|
||||||
}
|
processCompositeClassFile(javaClassFile, ctClass);
|
||||||
else {
|
|
||||||
enhancedBytecode = enhancer.enhance( clas.getName(), clas.toBytecode() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
getLog().error( "Unable to enhance class [${file.toString()}]", e );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
if ( null != is )
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
if ( null != enhancedBytecode ) {
|
|
||||||
if ( file.delete() ) {
|
|
||||||
try {
|
|
||||||
if ( !file.createNewFile() ) {
|
|
||||||
getLog().error( "Unable to recreate class file [" + clas.getName() + "]" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException ioe) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
getLog().error( "Unable to delete class file [" + clas.getName() + "]" );
|
|
||||||
}
|
|
||||||
FileOutputStream outputStream = null;
|
|
||||||
try {
|
|
||||||
outputStream = new FileOutputStream( file, false );
|
|
||||||
outputStream.write( enhancedBytecode );
|
|
||||||
outputStream.flush();
|
|
||||||
}
|
|
||||||
catch (IOException ioe) {
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
if ( outputStream != null )
|
|
||||||
outputStream.close();
|
|
||||||
clas.detach();// release memory
|
|
||||||
}
|
|
||||||
catch (IOException ignore) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new MojoExecutionException(
|
||||||
|
String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDir(String dir) {
|
private void processEntityClassFile(File javaClassFile, CtClass ctClass ) {
|
||||||
if ( null != dir && !"".equals( dir.trim() ) ) {
|
try {
|
||||||
this.dir = dir;
|
byte[] result = enhancer.enhance( ctClass.getName(), ctClass.toBytecode() );
|
||||||
|
if(result != null)
|
||||||
|
writeEnhancedClass(javaClassFile, result);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCompositeClassFile(File javaClassFile, CtClass ctClass) {
|
||||||
|
try {
|
||||||
|
byte[] result = enhancer.enhanceComposite(ctClass.getName(), ctClass.toBytecode());
|
||||||
|
if(result != null)
|
||||||
|
writeEnhancedClass(javaClassFile, result);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeEnhancedClass(File javaClassFile, byte[] result)
|
||||||
|
throws MojoExecutionException {
|
||||||
|
try {
|
||||||
|
if ( javaClassFile.delete() ) {
|
||||||
|
if ( ! javaClassFile.createNewFile() ) {
|
||||||
|
getLog().error( "Unable to recreate class file [" + javaClassFile.getName() + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getLog().error( "Unable to delete class file [" + javaClassFile.getName() + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
FileOutputStream outputStream = new FileOutputStream( javaClassFile, false );
|
||||||
|
try {
|
||||||
|
outputStream.write( result);
|
||||||
|
outputStream.flush();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
catch ( IOException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException ignore) {
|
||||||
|
// should not ever happen because of explicit checks
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new MojoExecutionException(
|
||||||
|
String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,4 +202,63 @@ public class MavenEnhancePlugin extends AbstractMojo {
|
||||||
return this.pool;
|
return this.pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldInclude(CtClass ctClass) {
|
||||||
|
// we currently only handle entity enhancement
|
||||||
|
return ctClass.hasAnnotation( Entity.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader getLoadingClassLoader() {
|
||||||
|
return getClass().getClassLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEntityClass(CtClass classDescriptor) {
|
||||||
|
return classDescriptor.hasAnnotation(Entity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCompositeClass(CtClass classDescriptor) {
|
||||||
|
return classDescriptor.hasAnnotation(Embeddable.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLazyLoadableAttributes(CtClass classDescriptor) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLazyLoadable(CtField field) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPersistentField(CtField ctField) {
|
||||||
|
// current check is to look for @Transient
|
||||||
|
return ! ctField.hasAnnotation( Transient.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMappedCollection(CtField field) {
|
||||||
|
try {
|
||||||
|
return (field.getAnnotation(OneToMany.class) != null ||
|
||||||
|
field.getAnnotation(ManyToMany.class) != null ||
|
||||||
|
field.getAnnotation(ElementCollection.class) != null);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CtField[] order(CtField[] persistentFields) {
|
||||||
|
// for now...
|
||||||
|
return persistentFields;
|
||||||
|
// eventually needs to consult the Hibernate metamodel for proper ordering
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,19 +23,22 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.bytecode.enhance.plugins
|
package org.hibernate.bytecode.enhance.plugins
|
||||||
|
|
||||||
import org.hibernate.bytecode.enhance.spi.Enhancer
|
|
||||||
import org.hibernate.bytecode.enhance.spi.EnhancementContext
|
|
||||||
import javassist.ClassPool
|
import javassist.ClassPool
|
||||||
import javassist.CtClass
|
import javassist.CtClass
|
||||||
import javassist.CtField
|
import javassist.CtField
|
||||||
import javax.persistence.Transient
|
|
||||||
|
import javax.persistence.ElementCollection
|
||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
import java.io.FileInputStream
|
import javax.persistence.ManyToMany
|
||||||
import java.io.FileOutputStream
|
import javax.persistence.OneToMany
|
||||||
|
import javax.persistence.Transient
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.FileTree
|
||||||
import org.gradle.api.plugins.Convention
|
import org.gradle.api.plugins.Convention
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.gradle.api.file.FileTree
|
import org.hibernate.bytecode.enhance.spi.EnhancementContext
|
||||||
|
import org.hibernate.bytecode.enhance.spi.Enhancer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin to enhance Entities using the context(s) to determine
|
* Plugin to enhance Entities using the context(s) to determine
|
||||||
|
@ -136,7 +139,7 @@ public class EnhanceTask extends DefaultTask implements EnhancementContext {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CtField[] order(CtField[] fields) {
|
public CtField[] order(CtField[] fields) {
|
||||||
|
@ -144,6 +147,17 @@ public class EnhanceTask extends DefaultTask implements EnhancementContext {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMappedCollection(CtField field) {
|
||||||
|
try {
|
||||||
|
return (field.getAnnotation(OneToMany.class) != null ||
|
||||||
|
field.getAnnotation(ManyToMany.class) != null ||
|
||||||
|
field.getAnnotation(ElementCollection.class) != null);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPersistentField(CtField ctField) {
|
public boolean isPersistentField(CtField ctField) {
|
||||||
return !ctField.hasAnnotation( Transient.class );
|
return !ctField.hasAnnotation( Transient.class );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue