@@ -63,8 +63,13 @@ public void enhance(CtClass managedCtClass) {
63
63
);
64
64
}
65
65
66
- // lastly, find all references to the transformed fields and replace with calls to the added reader/writer methods
66
+ // find all references to the transformed fields and replace with calls to the added reader/writer methods
67
67
enhanceAttributesAccess ( managedCtClass , attrDescriptorMap );
68
+
69
+ // same thing for direct access to fields of other entities
70
+ if ( this .enhancementContext .doFieldAccessEnhancement ( managedCtClass ) ) {
71
+ enhanceFieldAccess ( managedCtClass );
72
+ }
68
73
}
69
74
70
75
private CtField [] collectPersistentFields (CtClass managedCtClass ) {
@@ -74,6 +79,10 @@ private CtField[] collectPersistentFields(CtClass managedCtClass) {
74
79
if ( Modifier .isStatic ( ctField .getModifiers () ) || ctField .getName ().startsWith ( "$$_hibernate_" ) ) {
75
80
continue ;
76
81
}
82
+ // skip outer reference in inner classes
83
+ if ( "this$0" .equals ( ctField .getName () ) ) {
84
+ continue ;
85
+ }
77
86
if ( enhancementContext .isPersistentField ( ctField ) ) {
78
87
persistentFieldList .add ( ctField );
79
88
}
@@ -114,7 +123,6 @@ private CtMethod generateFieldReader(
114
123
return MethodWriter .addGetter ( managedCtClass , fieldName , readerName );
115
124
}
116
125
117
- // TODO: temporary solution...
118
126
try {
119
127
return MethodWriter .write (
120
128
managedCtClass , "public %s %s() {%n %s%n return this.%s;%n}" ,
@@ -520,4 +528,84 @@ private CtMethod getWriter() {
520
528
}
521
529
}
522
530
531
+ /**
532
+ * Replace access to fields of entities (for example, entity.field) with a call to the enhanced getter / setter
533
+ * (in this example, entity.$$_hibernate_read_field()). It's assumed that the target entity is enhanced as well.
534
+ *
535
+ * @param managedCtClass Class to enhance
536
+ */
537
+ public void enhanceFieldAccess (CtClass managedCtClass ) {
538
+ final ConstPool constPool = managedCtClass .getClassFile ().getConstPool ();
539
+
540
+ for ( Object oMethod : managedCtClass .getClassFile ().getMethods () ) {
541
+ final MethodInfo methodInfo = (MethodInfo ) oMethod ;
542
+ final String methodName = methodInfo .getName ();
543
+
544
+ // skip methods added by enhancement and abstract methods (methods without any code)
545
+ if ( methodName .startsWith ( "$$_hibernate_" ) || methodInfo .getCodeAttribute () == null ) {
546
+ continue ;
547
+ }
548
+
549
+ try {
550
+ final CodeIterator itr = methodInfo .getCodeAttribute ().iterator ();
551
+ while ( itr .hasNext () ) {
552
+ int index = itr .next ();
553
+ int op = itr .byteAt ( index );
554
+ if ( op != Opcode .PUTFIELD && op != Opcode .GETFIELD ) {
555
+ continue ;
556
+ }
557
+ String fieldName = constPool .getFieldrefName ( itr .u16bitAt ( index + 1 ) );
558
+ String fieldClassName = constPool .getClassInfo ( constPool .getFieldrefClass ( itr .u16bitAt ( index + 1 ) ) );
559
+ CtClass targetCtClass = this .classPool .getCtClass ( fieldClassName );
560
+
561
+ if ( !enhancementContext .isEntityClass ( targetCtClass ) && !enhancementContext .isCompositeClass ( targetCtClass ) ) {
562
+ continue ;
563
+ }
564
+ if ( targetCtClass == managedCtClass
565
+ || !enhancementContext .isPersistentField ( targetCtClass .getField ( fieldName ) )
566
+ || "this$0" .equals ( fieldName ) ) {
567
+ continue ;
568
+ }
569
+
570
+ log .debugf ( "Transforming access to field [%s] from method [%s]" , fieldName , methodName );
571
+
572
+ if ( op == Opcode .GETFIELD ) {
573
+ int fieldReaderMethodIndex = constPool .addMethodrefInfo (
574
+ constPool .addClassInfo ( fieldClassName ),
575
+ EnhancerConstants .PERSISTENT_FIELD_READER_PREFIX + fieldName ,
576
+ "()" + constPool .getFieldrefType ( itr .u16bitAt ( index + 1 ) )
577
+ );
578
+ itr .writeByte ( Opcode .INVOKEVIRTUAL , index );
579
+ itr .write16bit ( fieldReaderMethodIndex , index + 1 );
580
+ }
581
+ else {
582
+ int fieldWriterMethodIndex = constPool .addMethodrefInfo (
583
+ constPool .addClassInfo ( fieldClassName ),
584
+ EnhancerConstants .PERSISTENT_FIELD_WRITER_PREFIX + fieldName ,
585
+ "(" + constPool .getFieldrefType ( itr .u16bitAt ( index + 1 ) ) + ")V"
586
+ );
587
+ itr .writeByte ( Opcode .INVOKEVIRTUAL , index );
588
+ itr .write16bit ( fieldWriterMethodIndex , index + 1 );
589
+ }
590
+
591
+ }
592
+ methodInfo .getCodeAttribute ().setAttribute ( MapMaker .make ( classPool , methodInfo ) );
593
+ }
594
+ catch (BadBytecode bb ) {
595
+ final String msg = String .format (
596
+ "Unable to perform field access transformation in method [%s]" ,
597
+ methodName
598
+ );
599
+ throw new EnhancementException ( msg , bb );
600
+ }
601
+ catch (NotFoundException nfe ) {
602
+ final String msg = String .format (
603
+ "Unable to perform field access transformation in method [%s]" ,
604
+ methodName
605
+ );
606
+ throw new EnhancementException ( msg , nfe );
607
+ }
608
+ }
609
+ }
610
+
523
611
}
0 commit comments