Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.zodiac.injection.graal.processor.GraalInjectionProcessor Maven / Gradle / Ivy
package org.zodiac.injection.graal.processor;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.EXPOSE_MANY_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.EXPOSE_TYPES_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.GUICE_INJECT_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.JAVAX_INJECT_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.JSON_CREATOR_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.JSON_PROPERTY_ANNOTATION;
import static org.zodiac.injection.graal.processor.GraalInjectionProcessor.REFLECTION_INFO_ANNOTATION;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.processing.Processor;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import org.zodiac.injection.graal.processor.GraalEntryIndexFactory.GraalEntry;
import org.zodiac.sdk.annotation.processors.service.ServiceProvider;
import org.zodiac.sdk.annotation.tools.AnnotationUtils;
import org.zodiac.sdk.annotation.tools.registries.AbstractRegistrationAnnotationProcessor;
import java.util.Arrays;
@ServiceProvider(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({GUICE_INJECT_ANNOTATION, JAVAX_INJECT_ANNOTATION, REFLECTION_INFO_ANNOTATION, JSON_CREATOR_ANNOTATION, JSON_PROPERTY_ANNOTATION, EXPOSE_TYPES_ANNOTATION, EXPOSE_MANY_ANNOTATION})
public final class GraalInjectionProcessor extends AbstractRegistrationAnnotationProcessor {
static final String GUICE_INJECT_ANNOTATION = "com.google.inject.Inject";
static final String JAVAX_INJECT_ANNOTATION = "javax.inject.Inject";
static final String REFLECTION_INFO_ANNOTATION = "org.zodiac.injection.graal.annotation.Expose";
static final String EXPOSE_MANY_ANNOTATION = "org.zodiac.injection.graal.annotation.ExposeMany";
static final String EXPOSE_TYPES_ANNOTATION = "org.zodiac.injection.graal.annotation.ExposeAllMethods";
static final String JSON_CREATOR_ANNOTATION = "com.fasterxml.jackson.annotation.JsonCreator";
static final String JSON_PROPERTY_ANNOTATION = "com.fasterxml.jackson.annotation.JsonProperty";
//static final String GUICE_MODULE_ANNOTATION = "org.zodiac.acteur.annotations.GuiceModule";
public static final String JAR_PATH_JSON_FILE = "META-INF/injection/reflective.json";
public GraalInjectionProcessor() {
super(new GraalEntryIndexFactory());
}
private Boolean verbose;
boolean verbose() {
if (verbose == null) {
String val = processingEnv.getOptions().get("verbose");
if (val == null) {
val = System.getenv("GRAAL_PROCESSOR_VERBOSE");
}
if (val == null) {
val = System.getProperty("graal.processor.verbose");
}
verbose = "1".equals(val) || "true".equals(val);
}
return verbose;
}
private TypeMirror enclosingType(Element el) {
while (!(el instanceof TypeElement) && el != null) {
el = el.getEnclosingElement();
}
return el == null ? null : el.asType();
}
private ExecutableElement enclosingMethod(Element el) {
while (!(el instanceof ExecutableElement) && el != null) {
el = el.getEnclosingElement();
}
return el instanceof ExecutableElement ? ((ExecutableElement) el) : null;
}
private void note(String msg, Element e, AnnotationMirror me) {
if (!verbose()) {
return;
}
processingEnv.getMessager().printMessage(Diagnostic.Kind.OTHER, msg, e, me);
}
private void handleReflectionInfo(Element e, String typeName, AnnotationMirror anno, AnnotationUtils utils) {
String name = utils.annotationValue(anno, "type", String.class);
name = name == null || name.isEmpty() ? typeName : name;
int memberCount = 0;
for (AnnotationMirror me : utils.annotationValues(anno, "methods", AnnotationMirror.class)) {
List params = utils.annotationValues(me, "parameterTypes", String.class);
String methodName = utils.annotationValue(me, "name", String.class);
GraalEntry infoEntry = new GraalEntry(name, methodName, params, e);
if (indexer.add(JAR_PATH_JSON_FILE, infoEntry, processingEnv, e)) {
note("[reflective-method-access] " + infoEntry, e, me);
memberCount++;
}
}
List fieldDefs = utils.annotationValues(anno, "fields", String.class);
if (fieldDefs.size() == 1 && Arrays.asList("*").equals(fieldDefs)) {
TypeElement el = processingEnv.getElementUtils().getTypeElement(name);
if (el == null) {
fail("Cannot resolve " + name + " on compiler classpath to fill in all fields to expose '*'", e, anno);
} else {
for (Element member : el.getEnclosedElements()) {
switch (member.getKind()) {
case FIELD:
String nm = member.getSimpleName().toString();
GraalEntry fieldEntry = new GraalEntry(name, nm, e);
if (indexer.add(JAR_PATH_JSON_FILE, fieldEntry, processingEnv, e)) {
memberCount++;
note("[reflective-field-access] " + fieldEntry, e, anno);
}
}
}
}
} else {
for (String fieldName : fieldDefs) {
GraalEntry infoEntry = new GraalEntry(name, fieldName, e);
if (indexer.add(JAR_PATH_JSON_FILE, infoEntry, processingEnv, e)) {
note("[reflective-field-access] " + infoEntry, e, anno);
memberCount++;
}
}
}
if (memberCount == 0) {
GraalEntry allEntry = new GraalEntry(name, e);
if (indexer.add(JAR_PATH_JSON_FILE, allEntry, processingEnv, e)) {
note("[reflective-all-access] " + allEntry, e, anno);
memberCount++;
}
}
}
private void handleExposeTypesAnnotation(Element e, AnnotationMirror anno, AnnotationUtils utils) {
List typesToExpose = utils.typeList(anno, "value");
utils.warn("Handle expose types: " + anno);
if (typesToExpose != null) {
for (String type : typesToExpose) {
utils.warn("Expose type " + type, e, anno);
GraalEntry allEntry = new GraalEntry(type, e);
indexer.add(JAR_PATH_JSON_FILE, allEntry, processingEnv, e);
}
}
}
@Override
protected void handleOne(Element e, AnnotationMirror anno, int order, AnnotationUtils utils) {
try {
if (EXPOSE_TYPES_ANNOTATION.equals(anno.getAnnotationType().toString())) {
handleExposeTypesAnnotation(e, anno, utils);
return;
}
if (EXPOSE_MANY_ANNOTATION.equals(anno.getAnnotationType().toString())) {
List exposeAnnotations = utils.annotationValues(anno, "value", AnnotationMirror.class);
for (AnnotationMirror expose : exposeAnnotations) {
handleOne(e, expose, order, utils);
}
return;
}
if (e.getKind() == ElementKind.PARAMETER) {
Element orig = e;
e = enclosingMethod(e);
if (e == null) {
super.fail("Could not find an enclosing method for " + orig, e, anno);
return;
}
}
TypeMirror type = enclosingType(e);
if (type == null) {
super.fail("Could not find enclosing type for " + e, e, anno);
return;
}
String typeName = utils.canonicalize(type);
if (anno.getAnnotationType().toString().equals(REFLECTION_INFO_ANNOTATION)) {
handleReflectionInfo(e, typeName, anno, utils);
return;
}
// if (GUICE_MODULE_ANNOTATION.equals(anno.getAnnotationType().toString())) {
// GraalEntry allEntry = new GraalEntry(utils.canonicalize(e.asType()), e);
// indexer.add(JAR_PATH_JSON_FILE, allEntry, processingEnv, e);
// return;
// }
if (e.getKind() != ElementKind.FIELD && !(e instanceof ExecutableElement)) {
utils.fail("Not a field or ExecutableElement (method, constructor): " + e, e, anno);
return;
}
switch (e.getKind()) {
case CONSTRUCTOR:
case METHOD:
if (!(e instanceof ExecutableElement)) {
/*Broken sources can do strange things.*/
fail("Not an executable element (method, constructor): " + e, e, anno);
return;
}
ExecutableElement ex = (ExecutableElement) e;
List params = new ArrayList<>();
for (VariableElement v : ex.getParameters()) {
TypeMirror ptype = v.asType();
String paramTypeName = utils.canonicalize(ptype);
if (paramTypeName == null) {
fail("Could not canonicalize " + v, v);
break;
}
params.add(paramTypeName);
}
GraalEntry methodOrConstructorEntry = new GraalEntry(typeName, ex.getSimpleName().toString(), params, e);
indexer.add(JAR_PATH_JSON_FILE, methodOrConstructorEntry, processingEnv, e);
String noteKey = e.getKind() == ElementKind.CONSTRUCTOR
? "[reflective-constructor-access] " : "[reflective-method-access] ";
note(noteKey + methodOrConstructorEntry, e, anno);
break;
case FIELD:
if (!(e instanceof VariableElement)) {
fail("Not a variable element (field): " + e, e, anno);
return;
}
// if (e.getModifiers().contains(Modifier.PUBLIC)) {
// // No need to record reflection access for a field which is already
// // public
// return;
// }
VariableElement ve = (VariableElement) e;
GraalEntry fieldEntry = new GraalEntry(typeName, ve.getSimpleName().toString(), e);
note("[reflective-field-access] " + fieldEntry, e, anno);
indexer.add(JAR_PATH_JSON_FILE, fieldEntry, processingEnv, ve);
break;
default:
throw new IllegalArgumentException("Unprocessable element kind " + e.getKind() + " on " + type);
}
} catch (java.lang.annotation.IncompleteAnnotationException inc) {
fail(inc.getMessage(), e, anno);
}
}
}