play.classloading.enhancers.SigEnhancer Maven / Gradle / Ivy
package play.classloading.enhancers;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.Opcode;
import javassist.bytecode.annotation.Annotation;
import play.classloading.ApplicationClasses.ApplicationClass;
/**
* Compute a unique hash for the class signature.
*/
public class SigEnhancer extends Enhancer {
@Override
public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {
if (isScala(applicationClass)) {
return;
}
final CtClass ctClass = makeClass(applicationClass);
if (isScalaObject(ctClass)) {
return;
}
StringBuilder sigChecksum = new StringBuilder();
sigChecksum.append("Class->" + ctClass.getName() + ":");
for (Annotation annotation : getAnnotations(ctClass).getAnnotations()) {
sigChecksum.append(annotation + ",");
}
for (CtField field : ctClass.getDeclaredFields()) {
sigChecksum.append(" Field->" + ctClass.getName() + " " + field.getSignature() + ":");
sigChecksum.append(field.getSignature());
for (Annotation annotation : getAnnotations(field).getAnnotations()) {
sigChecksum.append(annotation + ",");
}
}
for (CtMethod method : ctClass.getDeclaredMethods()) {
sigChecksum.append(" Method->" + method.getName() + method.getSignature() + ":");
for (Annotation annotation : getAnnotations(method).getAnnotations()) {
sigChecksum.append(annotation + " ");
}
// Signatures names
CodeAttribute codeAttribute = (CodeAttribute) method.getMethodInfo().getAttribute("Code");
if (codeAttribute == null || javassist.Modifier.isAbstract(method.getModifiers())) {
continue;
}
LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute("LocalVariableTable");
if (localVariableAttribute != null) {
for (int i = 0; i < localVariableAttribute.tableLength(); i++) {
sigChecksum.append(localVariableAttribute.variableName(i) + ",");
}
}
}
if (ctClass.getClassInitializer() != null) {
sigChecksum.append("Static Code->");
for (CodeIterator i = ctClass.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); i.hasNext();) {
int index = i.next();
int op = i.byteAt(index);
sigChecksum.append(op);
if (op == Opcode.LDC) {
sigChecksum.append("[" + i.get().getConstPool().getLdcValue(i.byteAt(index + 1)) + "]");
;
}
sigChecksum.append(".");
}
}
if (ctClass.getName().endsWith("$")) {
sigChecksum.append("Singletons->");
for (CodeIterator i = ctClass.getDeclaredConstructors()[0].getMethodInfo().getCodeAttribute().iterator(); i.hasNext();) {
int index = i.next();
int op = i.byteAt(index);
sigChecksum.append(op);
if (op == Opcode.LDC) {
sigChecksum.append("[" + i.get().getConstPool().getLdcValue(i.byteAt(index + 1)) + "]");
;
}
sigChecksum.append(".");
}
}
// Done.
applicationClass.sigChecksum = sigChecksum.toString().hashCode();
}
}