CtConstructor defaultConstructor = CtNewConstructor.make("public " + ctClass.getSimpleName() + "() {}", ctClass);
ctClass.addConstructor(defaultConstructor);
}
} catch (Exception e) {
Logger.error(e, "Error in PropertiesEnhancer");
throw new UnexpectedException("Error in PropertiesEnhancer", e);
}
if (isScala(applicationClass)) {
// Temporary hack for Scala. Done.
applicationClass.enhancedByteCode = ctClass.toBytecode();
ctClass.defrost();
return;
}
for (CtField ctField : ctClass.getDeclaredFields()) {
try {
if (isProperty(ctField)) {
// Property name
String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1);
String getter = "get" + propertyName;
String setter = "set" + propertyName;
try {
CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
if (ctMethod.getParameterTypes().length > 0 || Modifier.isStatic(ctMethod.getModifiers())) {
throw new NotFoundException("it's not a getter !");
}
} catch (NotFoundException noGetter) {
// Créé le getter
String code = "public " + ctField.getType().getName() + " " + getter + "() { return this." + ctField.getName() + "; }";
CtMethod getMethod = CtMethod.make(code, ctClass);
getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC);
ctClass.addMethod(getMethod);
}
try {
CtMethod ctMethod = ctClass.getDeclaredMethod(setter);
if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers())) {
throw new NotFoundException("it's not a setter !");
}
} catch (NotFoundException noSetter) {
// Créé le setter
CtMethod setMethod = CtMethod.make("public void " + setter + "(" + ctField.getType().getName() + " value) { this." + ctField.getName() + " = value; }", ctClass);
setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC);
ctClass.addMethod(setMethod);
createAnnotation(getAnnotations(setMethod), PlayPropertyAccessor.class);
}
}
} catch (Exception e) {
Logger.error(e, "Error in PropertiesEnhancer");
throw new UnexpectedException("Error in PropertiesEnhancer", e);
}
}
// Add a default constructor if needed
try {
boolean hasDefaultConstructor = false;
for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
if (constructor.getParameterTypes().length == 0) {
hasDefaultConstructor = true;
break;
}
}
if (!hasDefaultConstructor) {
CtConstructor defaultConstructor = CtNewConstructor.defaultConstructor(ctClass);
ctClass.addConstructor(defaultConstructor);
}
} catch (Exception e) {
Logger.error(e, "Error in PropertiesEnhancer");
throw new UnexpectedException("Error in PropertiesEnhancer", e);
}
// Intercept all fields access
for (final CtBehavior ctMethod : ctClass.getDeclaredBehaviors()) {
ctMethod.instrument(new ExprEditor() {
@Override
public void edit(FieldAccess fieldAccess) throws CannotCompileException {
try {
// Acces à une property ?
if (isProperty(fieldAccess.getField())) {
// TODO : vérifier que c'est bien un champ d'une classe de l'application (fieldAccess.getClassName())
// Si c'est un getter ou un setter
String propertyName = null;
if (fieldAccess.getField().getDeclaringClass().equals(ctMethod.getDeclaringClass())
|| ctMethod.getDeclaringClass().subclassOf(fieldAccess.getField().getDeclaringClass())) {
if ((ctMethod.getName().startsWith("get") || ctMethod.getName().startsWith("set")) && ctMethod.getName().length() > 3) {
propertyName = ctMethod.getName().substring(3);
propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
}
}
// On n'intercepte pas le getter de sa propre property
if (propertyName == null || !propertyName.equals(fieldAccess.getFieldName())) {
String invocationPoint = ctClass.getName() + "." + ctMethod.getName() + ", line " + fieldAccess.getLineNumber();
if (fieldAccess.isReader()) {
// Réécris l'accés en lecture à la property
fieldAccess.replace("$_ = ($r)play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeReadProperty($0, \"" + fieldAccess.getFieldName() + "\", \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");");
} else if (fieldAccess.isWriter()) {
// Réécris l'accés en ecriture à la property
fieldAccess.replace("play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeWriteProperty($0, \"" + fieldAccess.getFieldName() + "\", " + fieldAccess.getField().getType().getName() + ".class, $1, \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");");
}
}
}
} catch (Exception e) {
throw new UnexpectedException("Error in PropertiesEnhancer", e);
}
}
});
}