}
public BaseClassFieldReader getClassFieldReader(final Class< ? > clazz,
final String fieldName,
CacheEntry cache) {
ByteArrayClassLoader byteArrayClassLoader = cache.getByteArrayClassLoader();
Map<Class< ? >, ClassFieldInspector> inspectors = cache.getInspectors();
// if ( byteArrayClassLoader == null || byteArrayClassLoader.getParent() != classLoader ) {
// if ( classLoader == null ) {
// throw new RuntimeDroolsException( "ClassFieldAccessorFactory cannot have a null parent ClassLoader" );
// }
// byteArrayClassLoader = new ByteArrayClassLoader( classLoader );
// }
try {
// if it is a self reference
if ( SELF_REFERENCE_FIELD.equals( fieldName ) ) {
// then just create an instance of the special class field extractor
return new SelfReferenceClassFieldReader( clazz,
fieldName );
} else {
// otherwise, bytecode generate a specific extractor
ClassFieldInspector inspector = inspectors.get( clazz );
if ( inspector == null ) {
inspector = new ClassFieldInspector( clazz );
inspectors.put( clazz,
inspector );
}
Class< ? > fieldType = (Class< ? >) inspector.getFieldTypes().get( fieldName );
Method getterMethod = (Method) inspector.getGetterMethods().get( fieldName );
Integer index = (Integer) inspector.getFieldNames().get( fieldName );
if ( fieldType == null && fieldName.length() > 1 && Character.isLowerCase( fieldName.charAt( 0 ) ) && Character.isUpperCase( fieldName.charAt(1) ) ) {
// it might be that odd case of javabeans naming conventions that does not use lower case first letters if the second is uppercase
String altFieldName = Character.toUpperCase( fieldName.charAt( 0 ) ) + fieldName.substring( 1 );
fieldType = (Class< ? >) inspector.getFieldTypes().get( altFieldName );
if( fieldType != null ) {
// it seems it is the corner case indeed.
getterMethod = (Method) inspector.getGetterMethods().get( altFieldName );
index = (Integer) inspector.getFieldNames().get( altFieldName );
}
}
if ( fieldType != null && getterMethod != null ) {
final String className = ClassFieldAccessorFactory.BASE_PACKAGE + "/" + Type.getInternalName( clazz ) + Math.abs( System.identityHashCode( clazz ) ) + "$" + getterMethod.getName();
// generating byte array to create target class
final byte[] bytes = dumpReader( clazz,
className,
getterMethod,
fieldType,
clazz.isInterface() );
// use bytes to get a class
final Class< ? > newClass = byteArrayClassLoader.defineClass( className.replace( '/',
'.' ),
bytes,
PROTECTION_DOMAIN );
// instantiating target class
final ValueType valueType = ValueType.determineValueType( fieldType );