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
}
}
}
}
Aggregations