package io.github.proxyhotswap.cglib; import io.github.proxyhotswap.AbstractProxyTransformer; import io.github.proxyhotswap.TransformationState; import io.github.proxyhotswap.TransformationUtils; import io.github.proxyhotswap.javassist.CtClass; import io.github.proxyhotswap.javassist.CtMethod; import java.lang.instrument.Instrumentation; import java.lang.reflect.Method; import java.util.concurrent.ConcurrentHashMap; /** * @author Erki Ehtla * */ public class EnhancerTransformer extends AbstractProxyTransformer { public EnhancerTransformer(Instrumentation inst) { super(inst, new ConcurrentHashMap<Class<?>, TransformationState>()); } @Override protected boolean isProxy(String className, Class<?> classBeingRedefined, byte[] classfileBuffer) { return GeneratorSpyTransformer.getGeneratorParams().containsKey(className.replaceAll("/", ".")); } @Override protected String getInitCall(CtClass cc, String random) throws Exception { CtMethod[] methods = cc.getDeclaredMethods(); StringBuilder strB = new StringBuilder(); for (CtMethod ctMethod : methods) { if (ctMethod.getName().startsWith("CGLIB$STATICHOOK")) { ctMethod.insertAfter(INIT_FIELD_PREFIX + random + "=true;"); strB.insert(0, ctMethod.getName() + "();"); break; } } if (strB.length() == 0) throw new RuntimeException("Could not find CGLIB$STATICHOOK method"); return strB.toString() + ";CGLIB$BIND_CALLBACKS(this);"; } @Override protected byte[] getNewByteCode(ClassLoader loader, String className, Class<?> classBeingRedefined) throws Exception { GeneratorParams param = GeneratorSpyTransformer.getGeneratorParams().get( TransformationUtils.getClassName(className)); if (param == null) throw new RuntimeException("No Parameters found for redefinition!"); Method genMethod = getGenerateMethod(param.getGenerator()); if (genMethod == null) throw new RuntimeException("No generation Method found for redefinition!"); byte[] invoke = (byte[]) genMethod.invoke(param.getGenerator(), param.getParam()); return invoke; } @Override protected CtClass getCtClass(byte[] newByteCode, String className) throws Exception { // can use get because generator parameter spy has already loaded it to the clas pool return classPool.get(TransformationUtils.getClassName(className)); } private Method getGenerateMethod(Object generator) { Method generateMethod = null; Method[] methods = generator.getClass().getMethods(); for (Method method : methods) { if (method.getName().equals("generate") && method.getReturnType().getSimpleName().equals("byte[]")) { generateMethod = method; break; } } return generateMethod; } }