private void transformFieldAccessesIntoReadsAndWrites(
CtClass managedCtClass,
IdentityHashMap<String, PersistentAttributeDescriptor> attributeDescriptorMap) {
final ConstPool constPool = managedCtClass.getClassFile().getConstPool();
for ( Object oMethod : managedCtClass.getClassFile().getMethods() ) {
final MethodInfo methodInfo = (MethodInfo) oMethod;
final String methodName = methodInfo.getName();
// skip methods added by enhancement
if ( methodName.startsWith( EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX )
|| methodName.startsWith( EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX )
|| methodName.equals( EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME )
|| methodName.equals( EnhancerConstants.ENTITY_ENTRY_GETTER_NAME )
|| methodName.equals( EnhancerConstants.ENTITY_ENTRY_SETTER_NAME )
|| methodName.equals( EnhancerConstants.PREVIOUS_GETTER_NAME )
|| methodName.equals( EnhancerConstants.PREVIOUS_SETTER_NAME )
|| methodName.equals( EnhancerConstants.NEXT_GETTER_NAME )
|| methodName.equals( EnhancerConstants.NEXT_SETTER_NAME ) ) {
continue;
}
final CodeAttribute codeAttr = methodInfo.getCodeAttribute();
if ( codeAttr == null ) {
// would indicate an abstract method, continue to next method
continue;
}
try {
final CodeIterator itr = codeAttr.iterator();
while ( itr.hasNext() ) {
final int index = itr.next();
final int op = itr.byteAt( index );
if ( op != Opcode.PUTFIELD && op != Opcode.GETFIELD ) {
continue;
}
final int constIndex = itr.u16bitAt( index + 1 );
final String fieldName = constPool.getFieldrefName( constIndex );
final PersistentAttributeDescriptor attributeDescriptor = attributeDescriptorMap.get( fieldName );
if ( attributeDescriptor == null ) {
// its not a field we have enhanced for interception, so skip it
continue;
}
log.tracef(
"Transforming access to field [%s] from method [%s]",
fieldName,
methodName
);
if ( op == Opcode.GETFIELD ) {
final int readMethodIndex = constPool.addMethodrefInfo(
constPool.getThisClassInfo(),
attributeDescriptor.getReader().getName(),
attributeDescriptor.getReader().getSignature()
);
itr.writeByte( Opcode.INVOKESPECIAL, index );
itr.write16bit( readMethodIndex, index + 1 );
}
else {
final int writeMethodIndex = constPool.addMethodrefInfo(
constPool.getThisClassInfo(),
attributeDescriptor.getWriter().getName(),
attributeDescriptor.getWriter().getSignature()
);
itr.writeByte( Opcode.INVOKESPECIAL, index );
itr.write16bit( writeMethodIndex, index + 1 );