com.maxifier.mxcache.proxy.ResolvableGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mxcache-runtime Show documentation
Show all versions of mxcache-runtime Show documentation
Constains all classes necessary for launching a MxCache-instrumentated application
/*
* Copyright (c) 2008-2014 Maxifier Ltd. All Rights Reserved.
*/
package com.maxifier.mxcache.proxy;
import com.maxifier.mxcache.CacheFactory;
import com.maxifier.mxcache.asm.Type;
import com.maxifier.mxcache.asm.commons.Method;
import com.maxifier.mxcache.context.CacheContext;
import com.maxifier.mxcache.transform.TransformGenerator;
import com.maxifier.mxcache.transform.TransformGeneratorFactory;
import com.maxifier.mxcache.transform.TransformGeneratorFactoryImpl;
import com.maxifier.mxcache.util.ClassGenerator;
import com.maxifier.mxcache.util.CodegenHelper;
import com.maxifier.mxcache.util.MxConstructorGenerator;
import com.maxifier.mxcache.util.MxGeneratorAdapter;
import java.lang.annotation.Annotation;
import static com.maxifier.mxcache.asm.Opcodes.*;
import static com.maxifier.mxcache.asm.Type.getType;
import static com.maxifier.mxcache.util.CodegenHelper.*;
/**
* @author Alexander Kochurov ([email protected])
*/
public final class ResolvableGenerator {
public static final Type RESOLVABLE_TYPE = getType(Resolvable.class);
private static final Type CACHE_CONTEXT_TYPE = getType(CacheContext.class);
private static final Method GET_VALUE_METHOD = Method.getMethod("Object getValue()");
private static final String OWNER_FIELD_NAME = "owner";
public static final String NON_PROXIED_POSTFIX = "$nonproxied$";
private ResolvableGenerator() {
}
public static void generateResolvable(Class ownerClass, int id, String name, String desc, boolean isStatic) {
generateResolvable(ownerClass, id, new Method(name, desc), isStatic);
}
public static void generateResolvable(Class ownerClass, int id, Method method, boolean isStatic) {
Method nonProxiedMethod = new Method(getNonProxiedMethodName(method), method.getDescriptor());
generateResolvable(ownerClass.getClassLoader(), getResolvableName(id, Type.getType(ownerClass)), ownerClass, nonProxiedMethod, nonProxiedMethod.getArgumentTypes(), isStatic, getKeyTransformers(ownerClass, method));
}
public static void generateResolvable(ClassLoader classLoader, String resolvableName, Class ownerClass, Method nonProxiedMethod, Type[] genericArguments, boolean isStatic, TransformGenerator[] tg) {
Type ownerType = Type.getType(ownerClass);
ClassGenerator w = new ClassGenerator(ACC_PUBLIC | ACC_SUPER | ACC_SYNTHETIC, resolvableName, OBJECT_TYPE, RESOLVABLE_TYPE);
Type resolvableType = w.getThisType();
if (tg != null) {
int index = 0;
for (TransformGenerator generator : tg) {
generator.generateFields(resolvableType, index, w);
index += generator.getFieldCount();
}
}
Type[] arguments = nonProxiedMethod.getArgumentTypes();
if (!isStatic) {
w.defineField(ACC_PRIVATE | ACC_FINAL, OWNER_FIELD_NAME, ownerType);
}
Type[] stored = new Type[arguments.length];
for (int i = 0; i < arguments.length; i++) {
Type arg = genericArguments[i];
if (tg != null) {
stored[i] = Type.getType(tg[i].getOutType());
} else {
stored[i] = arg;
}
w.defineField(ACC_PRIVATE | ACC_FINAL, "arg" + i, stored[i]);
}
Type[] ctorArguments = isStatic ? arguments : CodegenHelper.insertFirst(arguments, ownerType);
MxConstructorGenerator ctor = w.defineConstructor(ACC_PUBLIC, ctorArguments);
generateResolvableCtor(ownerType, resolvableType, arguments, genericArguments, ctor, isStatic, tg, stored);
MxGeneratorAdapter getValue = w.defineMethod(ACC_PUBLIC, GET_VALUE_METHOD);
generateGetValue(ownerClass, ownerType, nonProxiedMethod, isStatic, resolvableType, arguments, getValue, tg, stored);
w.toClass(classLoader);
}
private static TransformGenerator[] getKeyTransformers(Class ownerClass, Method method) {
TransformGeneratorFactory tgf = TransformGeneratorFactoryImpl.getInstance();
Class[] params = CodegenHelper.getClasses(ownerClass.getClassLoader(), method.getArgumentTypes());
Annotation[][] annotations;
try {
annotations = ownerClass.getDeclaredMethod(method.getName(), params).getParameterAnnotations();
} catch (NoSuchMethodException e) {
throw new IllegalStateException(e);
}
TransformGenerator[] tg = new TransformGenerator[params.length];
for (int i = 0; i