/******************************************************************************* * Copyright (c) 2006, 2007 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * wharley@bea.com - initial API and implementation * *******************************************************************************/ package org.eclipse.jdt.compiler.apt.tests.processors.genclass; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.Map; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; 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.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; @SupportedAnnotationTypes("org.eclipse.jdt.compiler.apt.tests.annotations.GenClass") @SupportedSourceVersion(SourceVersion.RELEASE_6) public class GenClassProc extends AbstractProcessor { private Messager _messager; private Filer _filer; private Elements _elementUtil; private TypeElement _annoDecl; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); _filer = processingEnv.getFiler(); _messager = processingEnv.getMessager(); _elementUtil = processingEnv.getElementUtils(); _annoDecl = _elementUtil.getTypeElement("org.eclipse.jdt.compiler.apt.tests.annotations.GenClass"); //System.out.println("Processor options are: "); //for (Map.Entry<String, String> option : processingEnv.getOptions().entrySet()) { // System.out.println(option.getKey() + " -> " + option.getValue()); //} } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (annotations == null || annotations.isEmpty()) { return true; } // sanity check if (!annotations.contains(_annoDecl)) { throw new IllegalArgumentException("process() called on an unexpected set of annotations"); } // get annotated declarations - could also use getElsAnnoWith(Class) form. for (Element d : roundEnv.getElementsAnnotatedWith(_annoDecl)) { // get annotations on the declaration String clazz = null; String method = null; for (AnnotationMirror am : d.getAnnotationMirrors()) { if (am.getAnnotationType().asElement().equals(_annoDecl)) { // query the annotation to get its values Map<? extends ExecutableElement, ? extends AnnotationValue> values = am.getElementValues(); // find the "clazz" and "msg" values for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : values.entrySet()) { // System.out.println("found a value named " + entry.getKey().getSimpleName() + " with value " + entry.getValue().getValue()); ExecutableElement key = entry.getKey(); AnnotationValue value = entry.getValue(); String keyName = key.getSimpleName().toString(); if ("clazz".equals(keyName)) { clazz = (String)(value.getValue()); } if ("method".equals(keyName)) { method = (String)(value.getValue()); } } if (null == clazz || clazz.length() > 40) { _messager.printMessage(Diagnostic.Kind.WARNING, "Long name for clazz()", d, am); clazz = null; break; } if (null == method || method.length() > 10) { _messager.printMessage(Diagnostic.Kind.WARNING, "Long name for method()", d, am); method = null; break; } } } if (null != clazz && null != method && !roundEnv.processingOver()) createSourceFile(d, clazz, method); } return true; } /** * Create a source file named 'name', with contents * that reflect 'method' and 'name'. * @param parent the parent element * @param clazz a fully qualified classname * @param method the name of a method that will be * added to the class */ private void createSourceFile(Element parent, String clazz, String method) { int lastDot = clazz.lastIndexOf('.'); if (lastDot <= 0 || clazz.length() == lastDot) return; String pkg = clazz.substring(0, lastDot); String lname = clazz.substring(lastDot + 1); Writer w = null; PrintWriter pw = null; try { JavaFileObject jfo = _filer.createSourceFile(clazz, parent); w = jfo.openWriter(); pw = new PrintWriter(w); pw.println("package " + pkg + ";"); pw.println("public class " + lname + " {"); pw.println("\tpublic String " + method + "() {"); // This compile error won't be reported if the -proc:only flag is set: // pw.println("\t\tb = a;"); pw.println("\t\treturn new String(\"" + clazz + "\");"); pw.println("\t}"); pw.println("}"); pw.close(); w.close(); } catch (IOException e) { e.printStackTrace(); } } }