Search in sources :

Example 1 with ByteArrayClassLoader

use of org.drools.wiring.api.util.ByteArrayClassLoader in project drools by kiegroup.

the class ClassFieldAccessorFactory method getClassFieldReader.

@Override
public BaseClassFieldReader getClassFieldReader(Class<?> clazz, String fieldName, CacheEntry cache) {
    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);
        } else {
            // otherwise, bytecode generate a specific extractor
            ClassFieldInspector inspector = getClassFieldInspector(clazz, cache);
            Method getterMethod = inspector.getGetterMethods().get(fieldName);
            Integer index = inspector.getFieldNames().get(fieldName);
            Class<?> fieldType = inspector.getFieldType(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 = inspector.getFieldType(altFieldName);
                if (fieldType != null) {
                    // it seems it is the corner case indeed.
                    getterMethod = inspector.getGetterMethods().get(altFieldName);
                    index = inspector.getFieldNames().get(altFieldName);
                }
            }
            if (fieldType != null && getterMethod != null) {
                final String className = ClassFieldAccessorFactory.BASE_PACKAGE + "/" + Type.getInternalName(clazz) + Math.abs((long) System.identityHashCode(clazz)) + "$" + getterMethod.getName();
                // generating byte array to create target class
                final byte[] bytes = dumpReader(clazz, className, getterMethod, fieldType);
                // use bytes to get a class
                ByteArrayClassLoader byteArrayClassLoader = cache.getByteArrayClassLoader();
                final Class<?> newClass = byteArrayClassLoader.defineClass(className.replace('/', '.'), bytes, PROTECTION_DOMAIN);
                // instantiating target class
                final ValueType valueType = ValueType.determineValueType(fieldType);
                final Object[] params = { index, fieldType, valueType };
                return (BaseClassFieldReader) newClass.getConstructors()[0].newInstance(params);
            } else {
                // must be a public field
                return null;
            }
        }
    } catch (final RuntimeException e) {
        throw e;
    } catch (final Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ValueType(org.drools.core.base.ValueType) ByteArrayClassLoader(org.drools.wiring.api.util.ByteArrayClassLoader) Method(java.lang.reflect.Method) BaseClassFieldReader(org.drools.core.base.BaseClassFieldReader) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) ClassFieldAccessorStore.getClassFieldInspector(org.drools.mvel.accessors.ClassFieldAccessorStore.getClassFieldInspector) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Example 2 with ByteArrayClassLoader

use of org.drools.wiring.api.util.ByteArrayClassLoader in project drools by kiegroup.

the class ClassGenerator method generateClass.

private Class<?> generateClass() {
    if (clazz == null) {
        byte[] bytecode = generateBytecode();
        if (ClassUtils.isAndroid()) {
            ByteArrayClassLoader cl = (ByteArrayClassLoader) ClassUtils.instantiateObject("org.drools.android.MultiDexClassLoader", null, writableClassLoader.asClassLoader());
            clazz = cl.defineClass(className, bytecode, null);
        } else {
            clazz = writableClassLoader.writeClass(className, bytecode);
        }
    }
    return clazz;
}
Also used : ByteArrayClassLoader(org.drools.wiring.api.util.ByteArrayClassLoader)

Example 3 with ByteArrayClassLoader

use of org.drools.wiring.api.util.ByteArrayClassLoader in project drools by kiegroup.

the class ClassFieldAccessorFactory method getClassFieldWriter.

@Override
public BaseClassFieldWriter getClassFieldWriter(Class<?> clazz, String fieldName, CacheEntry cache) {
    ByteArrayClassLoader byteArrayClassLoader = cache.getByteArrayClassLoader();
    Map<Class<?>, ClassFieldInspector> inspectors = cache.getInspectors();
    try {
        // otherwise, bytecode generate a specific extractor
        ClassFieldInspector inspector = inspectors.get(clazz);
        if (inspector == null) {
            inspector = new ClassFieldInspectorImpl(clazz);
            inspectors.put(clazz, inspector);
        }
        Method setterMethod = inspector.getSetterMethods().get(fieldName);
        Integer index = inspector.getFieldNames().get(fieldName);
        if (setterMethod == 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);
            setterMethod = inspector.getSetterMethods().get(altFieldName);
            index = inspector.getFieldNames().get(altFieldName);
        }
        if (setterMethod != null) {
            final Class<?> fieldType = setterMethod.getParameterTypes()[0];
            final String className = ClassFieldAccessorFactory.BASE_PACKAGE + "/" + Type.getInternalName(clazz) + Math.abs((long) System.identityHashCode(clazz)) + "$" + setterMethod.getName();
            // generating byte array to create target class
            final byte[] bytes = dumpWriter(clazz, className, setterMethod, fieldType);
            // 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);
            final Object[] params = { index, fieldType, valueType };
            return (BaseClassFieldWriter) newClass.getConstructors()[0].newInstance(params);
        } else {
            if (inspector.getFieldNames().containsKey(fieldName)) {
                return null;
            } else {
                throw new RuntimeException("Field/method '" + fieldName + "' not found for class '" + clazz.getName() + "'");
            }
        }
    } catch (final RuntimeException e) {
        throw e;
    } catch (final Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ValueType(org.drools.core.base.ValueType) ByteArrayClassLoader(org.drools.wiring.api.util.ByteArrayClassLoader) Method(java.lang.reflect.Method) BaseClassFieldWriter(org.drools.core.base.BaseClassFieldWriter) ClassFieldAccessorStore.getClassFieldInspector(org.drools.mvel.accessors.ClassFieldAccessorStore.getClassFieldInspector) ClassFieldInspector(org.drools.core.base.ClassFieldInspector)

Aggregations

ByteArrayClassLoader (org.drools.wiring.api.util.ByteArrayClassLoader)3 Method (java.lang.reflect.Method)2 ClassFieldInspector (org.drools.core.base.ClassFieldInspector)2 ValueType (org.drools.core.base.ValueType)2 ClassFieldAccessorStore.getClassFieldInspector (org.drools.mvel.accessors.ClassFieldAccessorStore.getClassFieldInspector)2 BaseClassFieldReader (org.drools.core.base.BaseClassFieldReader)1 BaseClassFieldWriter (org.drools.core.base.BaseClassFieldWriter)1 SelfReferenceClassFieldReader (org.drools.core.base.extractors.SelfReferenceClassFieldReader)1