com.googlecode.gwt.test.internal.GwtPatcherUtils Maven / Gradle / Ivy
package com.googlecode.gwt.test.internal;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
/**
* Some patching utility methods. Bytecode manipulation relies on javassist API. For
* internal use only.
*
* @author Bertrand Paquet
* @author Gael Lazzari
*/
public class GwtPatcherUtils {
public static void patch(CtClass c, Patcher patcher) throws Exception {
c.setModifiers(Modifier.PUBLIC);
if (patcher != null) {
patcher.initClass(c);
}
for (CtMethod m : c.getDeclaredMethods()) {
boolean wasAbstract = false;
String newBody = null;
if (Modifier.isAbstract(m.getModifiers())) {
m.setModifiers(m.getModifiers() - Modifier.ABSTRACT);
wasAbstract = true;
}
if (patcher != null) {
newBody = patcher.getNewBody(m);
}
if (newBody != null) {
if (Modifier.isNative(m.getModifiers())) {
m.setModifiers(m.getModifiers() - Modifier.NATIVE);
}
replaceImplementation(m, newBody);
} else if (wasAbstract) {
if (patcher != null) {
m.setBody("{ throw new " + UnsupportedOperationException.class.getName()
+ "(\"Abstract method '" + c.getSimpleName() + "." + m.getName()
+ "()' is not patched by " + patcher.getClass().getName() + "\"); }");
} else {
m.setBody("{ throw new " + UnsupportedOperationException.class.getName()
+ "(\"Abstract method '" + c.getSimpleName() + "." + m.getName()
+ "()' is not patched by any declared " + Patcher.class.getSimpleName()
+ " instance\"); }");
}
}
}
if (patcher != null) {
patcher.finalizeClass(c);
}
}
private static void replaceImplementation(CtMethod m, String src) throws Exception {
if (src == null || src.trim().length() == 0) {
m.setBody(null);
} else {
src = src.trim();
if (!src.startsWith("{")) {
if (!m.getReturnType().equals(CtClass.voidType) && !src.startsWith("return")) {
src = "{ return ($r)($w) " + src;
} else {
src = "{ " + src;
}
}
if (!src.endsWith("}")) {
if (!src.endsWith(";")) {
src = src + "; }";
} else {
src = src + " }";
}
}
try {
m.setBody(src);
} catch (CannotCompileException e) {
throw new CannotCompileException("Unable to compile new body for method '"
+ m.getLongName() + "' : " + src, e);
}
}
}
private GwtPatcherUtils() {
}
}