Skip to content

Commit

Permalink
HHH-9806 - Bytecode-enhancement-based dirty tracking does not work be…
Browse files Browse the repository at this point in the history
…cause PersistentAttributeInterceptor is never injected
  • Loading branch information
sebersole committed May 20, 2015
1 parent 14fc885 commit acea523
Show file tree
Hide file tree
Showing 7 changed files with 614 additions and 453 deletions.
Expand Up @@ -37,11 +37,10 @@ public String buildInLineDirtyCheckingBodyFragment(EnhancementContext context, C
return "";
}
}
builder.append( String.format( "if (%s() != null", EnhancerConstants.INTERCEPTOR_GETTER_NAME ) );

// primitives || enums
if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) {
builder.append( String.format( " && %s != $1)", currentValue.getName()) );
builder.append( String.format( "if (%s != $1)", currentValue.getName()) );
}
// simple data types
else if ( currentValue.getType().getName().startsWith( "java.lang" )
Expand All @@ -50,7 +49,7 @@ else if ( currentValue.getType().getName().startsWith( "java.lang" )
|| currentValue.getType().getName().startsWith( "java.sql.Date" )
|| currentValue.getType().getName().startsWith( "java.util.Date" )
|| currentValue.getType().getName().startsWith( "java.util.Calendar" ) ) {
builder.append( String.format( " && ((%s == null) || (!%<s.equals($1))))", currentValue.getName() ) );
builder.append( String.format( "if (%s == null || !%<s.equals($1))", currentValue.getName() ) );
}
// all other objects
else {
Expand All @@ -64,7 +63,7 @@ else if ( currentValue.getType().getName().startsWith( "java.lang" )
}
}
// TODO: for now just call equals, should probably do something else here
builder.append( String.format( " && ((%s == null) || (!%<s.equals($1))))", currentValue.getName() ) );
builder.append( String.format( "if (%s == null || !%<s.equals($1))", currentValue.getName() ) );
}
builder.append( String.format( " { %s(\"%s\"); }", EnhancerConstants.TRACKER_CHANGER_NAME, currentValue.getName() ) );
}
Expand Down
Expand Up @@ -11,6 +11,7 @@
import javassist.CtField;
import javassist.Modifier;
import javassist.NotFoundException;

import org.hibernate.bytecode.enhance.internal.tracker.CollectionTracker;
import org.hibernate.bytecode.enhance.internal.tracker.SimpleDirtyTracker;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
Expand All @@ -22,6 +23,7 @@
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

/**
* enhancer for regular entities
Expand Down Expand Up @@ -54,49 +56,63 @@ public void enhance(CtClass managedCtClass) {
new PersistentAttributesEnhancer( enhancementContext ).enhance( managedCtClass );
}

/* -- */

private void addEntityInstanceHandling(CtClass managedCtClass) {
try {
MethodWriter.write( managedCtClass, "public Object %s() { return this; }", EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME );
MethodWriter.write(
managedCtClass,
"public Object %s() { return this; }",
EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME
);
}
catch (CannotCompileException cce) {
final String msg = String.format( "Could not enhance entity class [%s] to add EntityEntry getter", managedCtClass.getName() );
throw new EnhancementException(msg, cce);
throw new EnhancementException(
String.format(
Locale.ROOT,
"Could not enhance entity class [%s] to add EntityEntry getter",
managedCtClass.getName()
),
cce
);
}
}

/* -- */

private void addEntityEntryHandling(CtClass managedCtClass) {
FieldWriter.addFieldWithGetterAndSetter( managedCtClass, entityEntryCtClass,
FieldWriter.addFieldWithGetterAndSetter(
managedCtClass, entityEntryCtClass,
EnhancerConstants.ENTITY_ENTRY_FIELD_NAME,
EnhancerConstants.ENTITY_ENTRY_GETTER_NAME,
EnhancerConstants.ENTITY_ENTRY_SETTER_NAME );
EnhancerConstants.ENTITY_ENTRY_SETTER_NAME
);
}

private void addLinkedPreviousHandling(CtClass managedCtClass) {
FieldWriter.addFieldWithGetterAndSetter( managedCtClass, managedEntityCtClass,
FieldWriter.addFieldWithGetterAndSetter(
managedCtClass, managedEntityCtClass,
EnhancerConstants.PREVIOUS_FIELD_NAME,
EnhancerConstants.PREVIOUS_GETTER_NAME,
EnhancerConstants.PREVIOUS_SETTER_NAME );
EnhancerConstants.PREVIOUS_SETTER_NAME
);
}

private void addLinkedNextHandling(CtClass managedCtClass) {
FieldWriter.addFieldWithGetterAndSetter( managedCtClass, managedEntityCtClass,
FieldWriter.addFieldWithGetterAndSetter(
managedCtClass, managedEntityCtClass,
EnhancerConstants.NEXT_FIELD_NAME,
EnhancerConstants.NEXT_GETTER_NAME,
EnhancerConstants.NEXT_SETTER_NAME );
EnhancerConstants.NEXT_SETTER_NAME
);
}

/* --- */

private void addInLineDirtyHandling(CtClass managedCtClass) {
try {
managedCtClass.addInterface( classPool.get( SelfDirtinessTracker.class.getName() ) );

FieldWriter.addField( managedCtClass, classPool.get( TRACKER_IMPL ), EnhancerConstants.TRACKER_FIELD_NAME );
FieldWriter.addField( managedCtClass, classPool.get( CollectionTracker.class.getName() ), EnhancerConstants.TRACKER_COLLECTION_NAME );
FieldWriter.addField(
managedCtClass,
classPool.get( CollectionTracker.class.getName() ),
EnhancerConstants.TRACKER_COLLECTION_NAME
);

createDirtyTrackerMethods( managedCtClass );
}
Expand All @@ -107,24 +123,23 @@ private void addInLineDirtyHandling(CtClass managedCtClass) {

private void createDirtyTrackerMethods(CtClass managedCtClass) {
try {
MethodWriter.write( managedCtClass, "" +
MethodWriter.write(
managedCtClass, "" +
"public void %1$s(String name) {%n" +
" if (%2$s == null) { %2$s = new %3$s(); }%n" +
" %2$s.add(name);%n" +
"}",
EnhancerConstants.TRACKER_CHANGER_NAME,
EnhancerConstants.TRACKER_FIELD_NAME,
TRACKER_IMPL );

/* --- */
TRACKER_IMPL
);

createCollectionDirtyCheckMethod( managedCtClass );
createCollectionDirtyCheckGetFieldsMethod( managedCtClass );
createClearDirtyCollectionMethod( managedCtClass );

/* --- */

MethodWriter.write( managedCtClass, "" +
MethodWriter.write(
managedCtClass, "" +
"public java.util.Set %1$s() {%n" +
" if (%2$s == null) { %2$s = new %4$s(); }%n" +
" %3$s(%2$s);%n" +
Expand All @@ -133,32 +148,37 @@ private void createDirtyTrackerMethods(CtClass managedCtClass) {
EnhancerConstants.TRACKER_GET_NAME,
EnhancerConstants.TRACKER_FIELD_NAME,
EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME,
TRACKER_IMPL );
TRACKER_IMPL
);

MethodWriter.write( managedCtClass, "" +
MethodWriter.write(
managedCtClass,
"" +
"public boolean %1$s() {%n" +
" return (%2$s != null && !%2$s.isEmpty()) || %3$s();%n" +
"}",
EnhancerConstants.TRACKER_HAS_CHANGED_NAME,
EnhancerConstants.TRACKER_FIELD_NAME,
EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME );
EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME
);

MethodWriter.write( managedCtClass, "" +
MethodWriter.write(
managedCtClass,
"" +
"public void %1$s() {%n" +
" if (%2$s != null) { %2$s.clear(); }%n" +
" %3$s();%n" +
"}",
EnhancerConstants.TRACKER_CLEAR_NAME,
EnhancerConstants.TRACKER_FIELD_NAME,
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME );
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME
);
}
catch (CannotCompileException cce) {
cce.printStackTrace();
}
}

/* -- */

private List<CtField> collectCollectionFields(CtClass managedCtClass) {
final List<CtField> collectionList = new LinkedList<CtField>();
try {
Expand Down Expand Up @@ -186,21 +206,30 @@ private void createCollectionDirtyCheckMethod(CtClass managedCtClass) {
try {
final StringBuilder body = new StringBuilder();

body.append( String.format( "" +
"private boolean %1$s() {%n" +
" if (%2$s() == null || %3$s == null) { return false; }%n",
EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME ) );
body.append(
String.format(
"" +
"private boolean %1$s() {%n" +
" if (%2$s == null) {%n" +
" return false;%n" +
" }%n",
EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);

for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField )) {
body.append( String.format( "" +
" // collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { return true; }%n"+
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME ) );
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append(
String.format(
"" +
" // collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { return true; }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
}
body.append( " return false;%n}" );
Expand All @@ -216,21 +245,29 @@ private void createCollectionDirtyCheckGetFieldsMethod(CtClass managedCtClass) {
try {
final StringBuilder body = new StringBuilder();

body.append( String.format( "" +
"private void %1$s(%3$s tracker) {%n" +
" if (%2$s == null) { return; }%n",
EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
TRACKER_IMPL ) );
body.append(
String.format(
"" +
"private void %1$s(%3$s tracker) {%n" +
" if (%2$s == null) { return; }%n",
EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
TRACKER_IMPL
)
);

for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField )) {
body.append( String.format( "" +
" // Collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { tracker.add(\"%1$s\"); }%n"+
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME ) );
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append(
String.format(
"" +
" // Collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { tracker.add(\"%1$s\"); }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
}
body.append( "}" );
Expand All @@ -246,21 +283,29 @@ private void createClearDirtyCollectionMethod(CtClass managedCtClass) throws Can
try {
final StringBuilder body = new StringBuilder();

body.append( String.format( "" +
"private void %1$s() {%n" +
" if (%2$s == null) { %2$s = new %3$s(); }%n",
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
CollectionTracker.class.getName()) );
body.append(
String.format(
"" +
"private void %1$s() {%n" +
" if (%2$s == null) { %2$s = new %3$s(); }%n",
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
CollectionTracker.class.getName()
)
);

for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append( String.format( "" +
" // Collection field [%1$s]%n" +
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n"+
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME) );
body.append(
String.format(
"" +
" // Collection field [%1$s]%n" +
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
}
body.append( "}" );
Expand Down

0 comments on commit acea523

Please sign in to comment.