From 6ba3b6fc452265fb595b7f32055423c606ed77fd Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 1 Aug 2013 22:26:13 +0200 Subject: o Initial import. --- .../io/trygvis/container/compiler/MyProcessor.java | 246 +++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java (limited to 'container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java') diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java new file mode 100644 index 0000000..0ec7001 --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java @@ -0,0 +1,246 @@ +package io.trygvis.container.compiler; + +import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.FieldRef; +import io.trygvis.container.compiler.model.ParameterRef; +import io.trygvis.container.compiler.model.TypeRef; +import io.trygvis.container.log.Log; +import io.trygvis.container.tx.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.processing.Completion; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.JavaFileObject; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; +import static javax.lang.model.util.ElementFilter.constructorsIn; +import static org.springframework.util.StringUtils.collectionToDelimitedString; + +public class MyProcessor implements Processor { + + private ProcessingEnvironment processingEnv; + private Elements elements; + private Types types; + + @Override + public Set getSupportedOptions() { + return emptySet(); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_5; + } + + @Override + public void init(ProcessingEnvironment processingEnv) { + this.processingEnv = processingEnv; + elements = processingEnv.getElementUtils(); + types = processingEnv.getTypeUtils(); + } + + @Override + public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) { + return emptyList(); + } + + @Override + public Set getSupportedAnnotationTypes() { + return new HashSet<>(asList(Transactional.class.getName(), Log.class.getName())); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + Set transactional = roundEnv.getElementsAnnotatedWith(Transactional.class); + + TypeElement tx = elements.getTypeElement(Transactional.class.getCanonicalName()); + TypeElement log = elements.getTypeElement(Transactional.class.getCanonicalName()); + + for (Element element : transactional) { + try { + System.out.println("Processing: " + element); + for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { + + System.out.println("annotationMirror.getAnnotationType().asElement().getSimpleName() = " + annotationMirror.getAnnotationType().asElement().getSimpleName()); + + if (types.isSameType(tx.asType(), annotationMirror.getAnnotationType())) { + processTransactional((TypeElement) element); + } +// if (types.isSameType(log.asType(), annotationMirror.getAnnotationType())) { +// processLog((TypeElement) element); +// } + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return true; + } + + private void processTransactional(TypeElement element) throws IOException { + Name targetClassName = element.getSimpleName(); + System.out.println("Processing @Transactional " + targetClassName); + + Transactional transactional = element.getAnnotation(Transactional.class); + + String p = elements.getPackageOf(element).getQualifiedName().toString(); + + String className = targetClassName + "_Transactional"; + + JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(p + "." + className, element); + + try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { + ClassG g = new ClassG(p, className, targetClassName.toString()); +// writer.println("package " + p + ";"); +// writer.println(); +// writer.println("import io.trygvis.container.tx.PlatformTransactionManager;"); +// writer.println(); +// writer.println("public class " + className + " extends " + targetClassName + " {"); +// writer.println(" private final PlatformTransactionManager transactionManager;"); +// writer.println(); + + TypeRef platformTransactionManager = g.addImport(PlatformTransactionManager.class); + FieldRef transactionManager = g.addField(PlatformTransactionManager.class, "transactionManager"); + + for (ExecutableElement constructor : constructorsIn(elements.getAllMembers(element))) { + if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + + constructor(g, constructor); + } + +// System.out.println("elements.getTypeElement(\"Object\") = " + elements.getTypeElement("java.lang.Object")); + Name javaLangObjectName = elements.getTypeElement("java.lang.Object").getQualifiedName(); + + for (Element e : elements.getAllMembers(element)) { + if (!(e instanceof ExecutableElement)) { + continue; + } + + ExecutableElement ee = (ExecutableElement) e; + + TypeElement enclosingElement = (TypeElement) ee.getEnclosingElement(); + + if (enclosingElement.getQualifiedName().equals(javaLangObjectName)) { + continue; + } + + if (ee.getSimpleName().toString().equals("")) { + continue; + } + +// System.out.println("ee.getSimpleName() = " + ee.getSimpleName()); +// System.out.println("ee.getEnclosingElement() = " + enclosingElement); +// System.out.println("ee.getEnclosingElement().getQualifiedName() = " + enclosingElement.getQualifiedName()); +// System.out.println("ee.getEnclosingElement().asType().getKind().getDeclaringClass() = " + enclosingElement.asType().getKind().getDeclaringClass()); + + TypeMirror returnTypeMirror = ee.getReturnType(); + + TypeKind kind = returnTypeMirror.getKind(); + + boolean isVoid = kind == TypeKind.VOID; + TypeRef returnType = isVoid ? TypeRef.VOID : g.addImport(returnTypeMirror); +// String returnString; +// if (isVoid) { +// returnString = "void"; +// } else { +// returnString = returnTypeMirror.toString(); +// } + + List parameters = new ArrayList<>(); + List arguments = new ArrayList<>(); + for (VariableElement ve : ee.getParameters()) { +// parameters.add("final " + ve.asType().toString() + " " + ve.getSimpleName().toString()); + TypeRef k = g.addImport(ve.asType()); + parameters.add(new ParameterRef(k, ve.getSimpleName().toString())); + arguments.add(ve.getSimpleName().toString()); + } + + CharArrayWriter buffer = new CharArrayWriter(); + PrintWriter m = new PrintWriter(buffer); + g.addMethod(buffer.toString(), returnType, ee.getSimpleName().toString(), parameters.toArray(new ParameterRef[arguments.size()])); + +// writer.println(); +// writer.println(" public " + returnString + " " + ee.getSimpleName() + "(" + collectionToDelimitedString(parameters, ", ") + ") {"); + +/* + writer.println(" " + (isVoid ? "" : "return ") + "transactionManager.doInTransaction("); + writer.println(" PlatformTransactionManager.TransactionIsolation.ISOLATION_" + transactional.isolation() + ","); + writer.println(" PlatformTransactionManager.TransactionPropagation.PROPAGATION_" + transactional.propagation() + ","); + writer.println(" new PlatformTransactionManager.TransactionTemplate<" + (isVoid ? "Object" : returnTypeMirror) + ">() {"); + writer.println(" @Override"); + writer.println(" public " + (isVoid ? "Object" : returnTypeMirror) + " doInTransaction() {"); + String targetInvocation = className + ".super." + ee.getSimpleName() + "(" + collectionToDelimitedString(arguments, ", ") + ");"; + + if (isVoid) { + writer.println(" " + targetInvocation); + writer.println(" return null;"); + } else { + writer.print(" return "); + writer.println(targetInvocation); + } + + writer.println(" }"); + writer.println(" });"); + writer.println(" }"); +*/ + + elements.printElements(new PrintWriter(System.out), ee); + } +// writer.println("}"); + g.write(w); + } + } + + private void constructor(ClassG g, ExecutableElement constructor) { + List parameters = new ArrayList<>(); + List goesToSuper = new ArrayList<>(); + + TypeRef k = g.addImport(PlatformTransactionManager.class); + parameters.add(new ParameterRef(k, "_transactionManager_")); + + for (VariableElement p : constructor.getParameters()) { +// parameters.add(p.asType().toString() + " " + p.getSimpleName().toString()); +// arguments.add(p.getSimpleName().toString()); + k = g.addImport(p.asType()); + String name = p.getSimpleName().toString(); + parameters.add(new ParameterRef(k, name)); + goesToSuper.add(name); + } + +// String params = parameters.size() == 0 ? "" : ", " + collectionToDelimitedString(parameters, ", "); + + g.simpleConstructor(parameters, goesToSuper); + +// writer.println(" public " + className + "(PlatformTransactionManager _transactionManager_" + params + ") {"); +// writer.println(" super(" + collectionToDelimitedString(arguments, ", ") + ");"); +// writer.println(" this.transactionManager = _transactionManager_;"); +// writer.println(" }"); + } +} -- cgit v1.2.3