
com.maxifier.mxcache.transform.JavaSourceFactory 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.transform;
import com.maxifier.mxcache.MxCacheException;
import com.maxifier.mxcache.tuple.Tuple;
import com.maxifier.mxcache.tuple.TupleFactory;
import com.maxifier.mxcache.tuple.TupleGenerator;
import gnu.trove.map.hash.THashMap;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author Alexander Kochurov ([email protected])
*/
public class JavaSourceFactory implements TransformFactory {
private static final TupleFactory KEY_FACTORY = TupleGenerator.getTupleFactory(Object.class, Object.class);
private static final String CLASS_NAME = "$$$TransformHolder$$$";
private static final Map METHOD_HOLDERS = new THashMap();
static String generateSource(Annotation instance, Class param) throws InvocationTargetException, IllegalAccessException {
Class extends Annotation> annotationType = instance.annotationType();
SourceCode sourceCode = annotationType.getAnnotation(SourceCode.class);
if (sourceCode == null) {
throw new IllegalStateException("Source-based custom transform annotations should have @SourceCode annotation");
}
StringBuilder definition = new StringBuilder();
definition.append("public class " + CLASS_NAME + " {\n");
definition.append("\tpublic static ").append(sourceCode.target().getCanonicalName()).append(" transform(").append(param.getCanonicalName()).append(" key) {\n");
for (Method method : annotationType.getDeclaredMethods()) {
definition.append("\t\t").append(method.getReturnType().getCanonicalName()).append(" ").append(method.getName()).append(" = ").append(toSourceString(method.invoke(instance))).append(";\n");
}
definition.append("\t\treturn ").append(sourceCode.value()).append(";\n");
definition.append("\t}\n");
definition.append("}");
return definition.toString();
}
private static String toSourceString(Object o) {
if (o instanceof String) {
return ((String) o).replace("\"", "\\\"").replace("\n", "\\n");
} else if (o instanceof Class) {
return ((Class) o).getCanonicalName() + ".class";
} else if (o instanceof Enum) {
Enum e = (Enum) o;
return e.getDeclaringClass().getCanonicalName() + "." + e.name();
} else if (o.getClass().isArray()) {
StringBuilder b = new StringBuilder();
b.append("new ").append(o.getClass().getComponentType().getCanonicalName()).append("[] {");
int length = Array.getLength(o);
for (int i = 0; i annotationType = a.annotationType();
Tuple t0 = KEY_FACTORY.create(annotationType, param);
Class gen = METHOD_HOLDERS.get(t0);
if (gen != null) {
return gen;
}
Tuple t = KEY_FACTORY.create(a, param);
Class res = METHOD_HOLDERS.get(t);
if (res == null) {
res = generateMethodHolderFor(a, param);
METHOD_HOLDERS.put(annotationType.getDeclaredMethods().length == 0 ? t0 : t, res);
}
return res;
}
private static Class generateMethodHolderFor(Annotation a, Class param) {
try {
String source = generateSource(a, param);
return CompileHelper.compile(CLASS_NAME, source);
} catch (Exception e) {
throw new MxCacheException(e);
}
}
@Override
public TransformGenerator create(Annotation annotation, Annotation[] allAnnotations, Class paramType) {
return TransformGeneratorFactoryImpl.getInstance().getTransformator(paramType, getMethodHolderFor(annotation, paramType), "transform");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy