Search in sources :

Example 1 with ConditionalFieldAnnotationCopyTransformMemberDTO

use of org.broadleafcommerce.common.weave.ConditionalFieldAnnotationCopyTransformMemberDTO in project BroadleafCommerce by BroadleafCommerce.

the class ConditionalFieldAnnotationsClassTransformer method transform.

/**
 * Will return null if the Spring property value defined in {@link #propertyName} resolves to false, or if
 * an exception occurs while trying to determine the value for the property.
 *
 * @param loader
 * @param className
 * @param classBeingRedefined
 * @param protectionDomain
 * @param classfileBuffer
 * @return
 * @throws IllegalClassFormatException
 */
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    // Lambdas and anonymous methods in Java 8 do not have a class name defined and so no transformation should be done
    if (className == null) {
        return null;
    }
    String convertedClassName = className.replace('/', '.');
    ConditionalFieldAnnotationCopyTransformMemberDTO dto = manager.getTransformMember(convertedClassName);
    if (dto == null || dto.getTemplateNames() == null || dto.getTemplateNames().length < 1) {
        return null;
    }
    // Be careful with Apache library usage in this class (e.g. ArrayUtils). Usage will likely cause a ClassCircularityError
    // under JRebel. Favor not including outside libraries and unnecessary classes.
    CtClass clazz = null;
    try {
        String[] xformVals = dto.getTemplateNames();
        // Load the destination class and defrost it so it is eligible for modifications
        ClassPool classPool = ClassPool.getDefault();
        clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false);
        clazz.defrost();
        for (String xformVal : xformVals) {
            // Load the source class
            String trimmed = xformVal.trim();
            classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader()));
            CtClass template = classPool.get(trimmed);
            CtField[] fieldsToCopy = template.getDeclaredFields();
            // template annotations.  Otherwise, remove all annotations from the target.
            for (CtField field : fieldsToCopy) {
                ConstPool constPool = clazz.getClassFile().getConstPool();
                CtField fieldFromMainClass = clazz.getField(field.getName());
                AnnotationsAttribute copied = null;
                for (Object o : field.getFieldInfo().getAttributes()) {
                    if (o instanceof AnnotationsAttribute) {
                        AnnotationsAttribute templateAnnotations = (AnnotationsAttribute) o;
                        // have to make a copy of the annotations from the target
                        copied = (AnnotationsAttribute) templateAnnotations.copy(constPool, null);
                        break;
                    }
                }
                // add all the copied annotations into the target class's field.
                for (Object attribute : fieldFromMainClass.getFieldInfo().getAttributes()) {
                    if (attribute instanceof AnnotationsAttribute) {
                        Annotation[] annotations = null;
                        if (copied != null) {
                            // If we found annotations to copy, then use all of them
                            ArrayList<Annotation> annotationsList = new ArrayList<Annotation>();
                            for (Annotation annotation : copied.getAnnotations()) {
                                annotationsList.add(annotation);
                            }
                            annotations = new Annotation[annotationsList.size()];
                            int count = 0;
                            for (Annotation annotation : annotationsList) {
                                annotations[count] = annotation;
                                count++;
                            }
                            ((AnnotationsAttribute) attribute).setAnnotations(annotations);
                        } else {
                            // If no annotations were found on the template, then remove them entirely from the target.
                            ((AnnotationsAttribute) attribute).setAnnotations(new Annotation[] {});
                        }
                        break;
                    }
                }
            }
        }
        return clazz.toBytecode();
    } catch (ClassCircularityError error) {
        error.printStackTrace();
        throw error;
    } catch (Exception e) {
        throw new RuntimeException("Unable to transform class", e);
    } finally {
        if (clazz != null) {
            try {
                clazz.detach();
            } catch (Exception e) {
            // do nothing
            }
        }
    }
}
Also used : ConstPool(javassist.bytecode.ConstPool) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) ClassPool(javassist.ClassPool) ArrayList(java.util.ArrayList) LoaderClassPath(javassist.LoaderClassPath) Annotation(javassist.bytecode.annotation.Annotation) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) CtClass(javassist.CtClass) ByteArrayInputStream(java.io.ByteArrayInputStream) CtField(javassist.CtField) ConditionalFieldAnnotationCopyTransformMemberDTO(org.broadleafcommerce.common.weave.ConditionalFieldAnnotationCopyTransformMemberDTO)

Aggregations

ByteArrayInputStream (java.io.ByteArrayInputStream)1 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)1 ArrayList (java.util.ArrayList)1 ClassPool (javassist.ClassPool)1 CtClass (javassist.CtClass)1 CtField (javassist.CtField)1 LoaderClassPath (javassist.LoaderClassPath)1 AnnotationsAttribute (javassist.bytecode.AnnotationsAttribute)1 ConstPool (javassist.bytecode.ConstPool)1 Annotation (javassist.bytecode.annotation.Annotation)1 ConditionalFieldAnnotationCopyTransformMemberDTO (org.broadleafcommerce.common.weave.ConditionalFieldAnnotationCopyTransformMemberDTO)1