use of org.drools.core.base.ClassFieldInspector 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);
}
}
use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.
the class ClassDefinitionFactory method populateDefinitionFromClass.
public static void populateDefinitionFromClass(ClassDefinition def, Resource resource, Class<?> concrete, boolean asTrait) {
try {
def.setClassName(concrete.getName());
if (concrete.getSuperclass() != null) {
def.setSuperClass(concrete.getSuperclass().getName());
}
ClassFieldInspector inspector = CoreComponentsBuilder.get().createClassFieldInspector(concrete);
Map<String, Method> methods = inspector.getGetterMethods();
Map<String, Method> setters = inspector.getSetterMethods();
Map<String, TypeFieldDescr> fields = new HashMap<>();
for (String fieldName : methods.keySet()) {
if (asTrait && ("core".equals(fieldName) || "fields".equals(fieldName))) {
continue;
}
if (!inspector.isNonGetter(fieldName) && setters.containsKey(fieldName)) {
Position position = null;
if (!concrete.isInterface()) {
try {
Field fld = concrete.getDeclaredField(fieldName);
position = fld.getAnnotation(Position.class);
} catch (NoSuchFieldException nsfe) {
// @Position can only annotate fields. This x means that a getter/setter pair was found with no field
}
}
Class ret = methods.get(fieldName).getReturnType();
TypeFieldDescr field = new TypeFieldDescr();
field.setResource(resource);
field.setFieldName(fieldName);
field.setPattern(new PatternDescr(ret.getName()));
field.setIndex(position != null ? position.value() : -1);
fields.put(fieldName, field);
}
}
if (!fields.isEmpty()) {
List<FieldDefinition> fieldDefs = sortFields(fields, null, null);
int i = 0;
for (FieldDefinition fieldDef : fieldDefs) {
fieldDef.setIndex(i++);
def.addField(fieldDef);
}
}
Set<String> interfaces = new HashSet<>();
Collections.addAll(interfaces, def.getInterfaces());
for (Class iKlass : ClassUtils.getAllImplementedInterfaceNames(concrete)) {
interfaces.add(iKlass.getName());
}
def.setInterfaces(interfaces.toArray(new String[interfaces.size()]));
def.setDefinedClass(concrete);
} catch (IOException e) {
e.printStackTrace();
}
}
use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.
the class ClassHierarchyManager method buildDescrsFromFields.
private static void buildDescrsFromFields(Class klass, TypeDeclarationDescr typeDescr, Map<String, TypeFieldDescr> fieldMap) {
ClassFieldInspector inspector;
try {
inspector = CoreComponentsBuilder.get().createClassFieldInspector(klass);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (String name : inspector.getGetterMethods().keySet()) {
// classFieldAccessor requires both getter and setter
if (inspector.getSetterMethods().containsKey(name)) {
if (!inspector.isNonGetter(name) && !"class".equals(name)) {
Resource resource = typeDescr.getResource();
PatternDescr patternDescr = new PatternDescr(inspector.getFieldType(name).getName());
patternDescr.setResource(resource);
TypeFieldDescr inheritedFlDescr = new TypeFieldDescr(name, patternDescr);
inheritedFlDescr.setResource(resource);
inheritedFlDescr.setInherited(!Modifier.isAbstract(inspector.getGetterMethods().get(name).getModifiers()));
if (!fieldMap.containsKey(inheritedFlDescr.getFieldName()))
fieldMap.put(inheritedFlDescr.getFieldName(), inheritedFlDescr);
}
}
}
}
use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.
the class TypeDeclarationFactory method checkRedeclaration.
protected void checkRedeclaration(AbstractClassTypeDeclarationDescr typeDescr, TypeDeclaration type, PackageRegistry pkgRegistry) {
TypeDeclaration previousTypeDeclaration = kbuilder.getPackageRegistry(typeDescr.getNamespace()).getPackage().getTypeDeclaration(typeDescr.getTypeName());
try {
// to the behavior previous these changes
if (!type.isDefinition()) {
// new declarations of a POJO can't declare new fields,
// except if the POJO was previously generated/compiled and saved into the kjar
Class<?> existingDeclarationClass = TypeDeclarationUtils.getExistingDeclarationClass(typeDescr, pkgRegistry);
if (!kbuilder.getBuilderConfiguration().isPreCompiled() && !GeneratedFact.class.isAssignableFrom(existingDeclarationClass) && !type.getTypeClassDef().getFields().isEmpty()) {
try {
Class existingClass = pkgRegistry.getPackage().getTypeResolver().resolveType(typeDescr.getType().getFullName());
ClassFieldInspector cfi = CoreComponentsBuilder.get().createClassFieldInspector(existingClass);
int fieldCount = 0;
for (String existingFieldName : cfi.getFieldTypesField().keySet()) {
if (!cfi.isNonGetter(existingFieldName) && !"class".equals(existingFieldName) && cfi.getSetterMethods().containsKey(existingFieldName) && cfi.getGetterMethods().containsKey(existingFieldName)) {
if (!typeDescr.getFields().containsKey(existingFieldName)) {
type.setValid(false);
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "New declaration of " + typeDescr.getType().getFullName() + " does not include field " + existingFieldName));
} else {
String fldType = cfi.getFieldType(existingFieldName).getName();
fldType = TypeDeclarationUtils.toBuildableType(fldType, kbuilder.getRootClassLoader());
TypeFieldDescr declaredField = typeDescr.getFields().get(existingFieldName);
if (!fldType.equals(type.getTypeClassDef().getField(existingFieldName).getTypeName())) {
type.setValid(false);
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "New declaration of " + typeDescr.getType().getFullName() + " redeclared field " + existingFieldName + " : \n" + "existing : " + fldType + " vs declared : " + declaredField.getPattern().getObjectType()));
} else {
fieldCount++;
}
}
}
}
if (fieldCount != typeDescr.getFields().size()) {
kbuilder.addBuilderResult(reportDeclarationDiff(cfi, typeDescr));
}
} catch (IOException e) {
e.printStackTrace();
type.setValid(false);
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Unable to redeclare " + typeDescr.getType().getFullName() + " : " + e.getMessage()));
} catch (ClassNotFoundException e) {
type.setValid(false);
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Unable to redeclare " + typeDescr.getType().getFullName() + " : " + e.getMessage()));
}
}
} else if (previousTypeDeclaration != null) {
// previous declaration can be null during an incremental compilation
int typeComparisonResult = this.compareTypeDeclarations(previousTypeDeclaration, type);
if (typeComparisonResult < 0) {
// oldDeclaration is "less" than newDeclaration -> error
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, typeDescr.getType().getFullName() + " declares more fields than the already existing version"));
type.setValid(false);
} else if (typeComparisonResult > 0 && !type.getTypeClassDef().getFields().isEmpty()) {
// oldDeclaration is "grater" than newDeclaration -> error
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, typeDescr.getType().getFullName() + " declares less fields than the already existing version"));
type.setValid(false);
}
// fields present in the previous declaration
if (type.getNature() == TypeDeclaration.Nature.DECLARATION) {
mergeTypeDeclarations(previousTypeDeclaration, type);
}
}
} catch (IncompatibleClassChangeError error) {
// if the types are incompatible -> error
kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, error.getMessage()));
}
}
use of org.drools.core.base.ClassFieldInspector in project drools by kiegroup.
the class TypeDeclarationUtils method isCompatible.
public static boolean isCompatible(Class<?> typeClass, AbstractClassTypeDeclarationDescr typeDescr) {
try {
if (typeDescr.getFields().isEmpty()) {
return true;
}
Class<?> sup = typeClass.getSuperclass();
if (sup == null) {
return true;
}
if (!sup.getName().equals(typeDescr.getSupertTypeFullName())) {
return false;
}
ClassFieldInspector cfi = CoreComponentsBuilder.get().createClassFieldInspector(typeClass, false);
if (cfi.getGetterMethods().size() != typeDescr.getFields().size()) {
return false;
}
for (String fieldName : cfi.getFieldTypes().keySet()) {
if (!typeDescr.getFields().containsKey(fieldName)) {
return false;
}
String fieldTypeName = typeDescr.getFields().get(fieldName).getPattern().getObjectType();
Class fieldType = cfi.getFieldTypes().get(fieldName);
if (!fieldTypeName.equals(fieldType.getName()) || !fieldTypeName.equals(fieldType.getSimpleName())) {
return false;
}
}
} catch (IOException e) {
return false;
}
return true;
}
Aggregations