package de.twenty11.skysail.server.ext.osgi.monitor.agent;
import java.util.ArrayList;
import java.util.List;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.twenty11.skysail.server.ext.osgi.monitor.agent.descriptors.Param;
public abstract class MethodInstrumentation {
private static final Logger logger = LoggerFactory.getLogger(MethodInstrumentation.class);
private CtMethod m;
private ClassPool classPool;
protected String callbackMethodName;
protected String callbackClassName;
public MethodInstrumentation(String callbackClassName, String callbackMethodName) {
this.callbackClassName = callbackClassName;
this.callbackMethodName = callbackMethodName;
}
public void instrument(CtMethod m, ClassPool classPool) {
this.m = m;
this.classPool = classPool;
}
protected String defaultBeforeCode(String callbackClassName, CtMethod m) {
List<String> params = new ArrayList<String>();
try {
CtClass[] parameterTypes = m.getParameterTypes();
// CtClass returnType = m.getReturnType();
boolean isStatic = Modifier.isStatic(m.getModifiers());
int i = 0;
if (isStatic) {
i = 1;
} else {
params.add("$0");
}
for (CtClass param : parameterTypes) {
params.add("$" + (++i));
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return getInsertBefore(callbackClassName, m.getName(), params);
}
protected String defaultCatchCode(CtMethod m, String callbackMethodName, ClassPool classPool) {
// return getCatch(
// ServiceRegistrationCallback.class.getSimpleName(),
// Param.fromObject("this"),
// Param.fromString(m.getDeclaringClass().getName()),
// Param.fromString(m.getName())
// );
// StringBuilder sb = new StringBuilder("{").append(className).append(".catchMe(");
// handleParams(sb, params);
// sb.append(", $e); throw new RuntimeException($e);}");
// return sb.toString();
List<String> params = new ArrayList<String>();
try {
CtClass[] parameterTypes = m.getParameterTypes();
// CtClass returnType = m.getReturnType();
boolean isStatic = Modifier.isStatic(m.getModifiers());
int i = 0;
if (isStatic) {
i = 1;
} else {
params.add("$0");
}
for (CtClass param : parameterTypes) {
params.add("$" + (++i));
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// return get(callbackClassName, m.getName(), params);
return "{" + callbackClassName + ".catchMe(\"" + m.getName() + "\", $e); throw new RuntimeException($e);}";
}
protected void insertBeforeMethod(String code) {
logger.info(code);
try {
m.insertBefore(code);
} catch (CannotCompileException e) {
logger.error("Problem with code {} in method {}", code, m, e);
}
}
protected void insertCatchMethod(String code) {
logger.info(code);
try {
m.addCatch(code, classPool.get("java.lang.RuntimeException"));
} catch (Exception e) {
logger.error("Problem with code {} in method {}", code, m, e);
}
}
protected void insertAfterMethod(String code) {
logger.info(code);
try {
m.insertAfter(code);
} catch (Exception e) {
logger.error("Problem with code {} in method {}", code, m, e);
}
}
// public static String getInsertBefore(String className, String callbackMethodName, Param... params) {
// StringBuilder sb = new StringBuilder("{").append(className).append(".").append(callbackMethodName).append("(");
// handleParams(sb, params);
// sb.append(");}");
// return sb.toString();
// }
protected String getInsertBefore(String className, String callbackMethodName, List<String> params) {
StringBuilder sb = new StringBuilder("{").append(className).append(".").append(callbackMethodName).append("(");
handleParams(sb, params);
sb.append(");}");
return sb.toString();
}
private static StringBuilder handleParams(StringBuilder sb, List<String> params) {
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).toString());
if (i < params.size() - 1) {
sb.append(",");
}
}
return sb;
}
protected static StringBuilder handleParams(StringBuilder sb, Param[] params) {
for (int i = 0; i < params.length; i++) {
sb.append(params[i].toString());
if (i < params.length - 1) {
sb.append(",");
}
}
return sb;
}
public static String getCatch(String className, Param... params) {
StringBuilder sb = new StringBuilder("{").append(className).append(".catchMe(");
handleParams(sb, params);
sb.append(", $e); throw new RuntimeException($e);}");
return sb.toString();
}
}