diff --git a/README.md b/README.md index 363f02c..2681b6c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,27 @@ There are two modules in this project: - The processor (`processor/`) - The example using the processor (`example/`) -The `processor` project defines an annotation `@Version` that lets you specify a version number. When the annotation processor is run, it generates a source file `GeneratedVersion.java` with a static field containing that version number. +The `processor` project defines an annotation `@Version` that lets you specify a version number in two ways: + +- Either provide a `value` for the version. +- Or you provide a `fileName` pointing to a `Properties` file. This file contains the version number either with the default key `version` or with your own key, which you can specify with the `propertyName` attribute. + +For example: + +``` +@Version(fileName = "example/src/main/properties/version.properties", + propertyName = "example.version") +public class A { +// ... +``` + +And the content of the `version.properties` file: + +``` +example.version=1.4 +``` + +When the annotation processor is run, it generates a source file `GeneratedVersion.java` with a static field containing that version number. The `example` project has a single class `Example` which is annotated with `@Version` and which then displays the value of the version from the `GeneratedVersion` generated class. diff --git a/example/src/main/java/com/beust/apt/example/Example.java b/example/src/main/java/com/beust/apt/example/Example.java index 0d1624e..d2d51fa 100644 --- a/example/src/main/java/com/beust/apt/example/Example.java +++ b/example/src/main/java/com/beust/apt/example/Example.java @@ -4,24 +4,25 @@ import com.beust.apt.processor.Version; import java.io.File; -@Version("1.3") +@Version(fileName = "example/src/main/properties/version.properties", propertyName = "example.version") class Example { public Example() { System.out.println("Instantiating Example"); } public static void main(String[] argv) throws Exception { - // Uncomment these lines and launch this class to debug the annotation processor. -// String[] args = new String[] { -//// "-proc:only", -// "-classpath", "/Users/beust/home/java/java-apt-example/processor/kobaltBuild/libs/processor-0.1.jar", -// "-processor", "com.beust.apt.processor.MainProcessor", -// "/Users/beust/java/java-apt-example/example/src/main/java/com/beust/apt/example/Example.java" -// }; + String root = "/Users/cbeust/java/java-apt-example/"; + String[] args = new String[] { + "-classpath", + root + "processor/kobaltBuild/libs/processor-0.1.jar", + "-processor", "com.beust.apt.processor.VersionProcessor", + root + "example/src/main/java/com/beust/apt/example/Example.java" + }; + // Uncomment this line and launch this class to debug the annotation processor. // com.sun.tools.javac.Main.main(args); File file = new File("."); System.out.println("Version generated: " + GeneratedVersion.VERSION); - new Example(); +// new Example(); } } \ No newline at end of file diff --git a/example/src/main/properties/version.properties b/example/src/main/properties/version.properties new file mode 100644 index 0000000..f75d731 --- /dev/null +++ b/example/src/main/properties/version.properties @@ -0,0 +1 @@ +example.version=1.4 \ No newline at end of file diff --git a/processor/src/main/java/com/beust/apt/processor/MainProcessor.java b/processor/src/main/java/com/beust/apt/processor/MainProcessor.java deleted file mode 100644 index ed41889..0000000 --- a/processor/src/main/java/com/beust/apt/processor/MainProcessor.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.beust.apt.processor; - -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.JavaFileObject; -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - -public class MainProcessor extends AbstractProcessor { - private Types typeUtils; - private Elements elementUtils; - private Filer filer; - private Messager messager; - - public MainProcessor() { - log("Instantiating MainProcessor"); - } - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - typeUtils = processingEnv.getTypeUtils(); - elementUtils = processingEnv.getElementUtils(); - filer = processingEnv.getFiler(); - messager = processingEnv.getMessager(); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Version.class)) { - Version version = annotatedElement.getAnnotation(Version.class); - if (annotatedElement.getKind() == ElementKind.CLASS) { - Element enclosing = annotatedElement.getEnclosingElement(); - if (enclosing.getKind() == ElementKind.PACKAGE) { - PackageElement packageElement = (PackageElement) enclosing; - String packageName = packageElement.getQualifiedName().toString(); - JavaFileObject jfo = null; - try { - log("version = " + version.value()); - jfo = filer.createSourceFile(packageName + ".GeneratedVersion"); - BufferedWriter writer = new BufferedWriter(jfo.openWriter()); - writer.write("package " + packageName + ";\n\n"); - writer.write("public class GeneratedVersion {\n"); - writer.write(" public static final String VERSION = \"" + version.value() + "\";\n"); - writer.write("}\n"); - writer.close(); - log("Generated " + jfo.getName()); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - return true; - } - - public Set getSupportedAnnotationTypes() { - Set result = new HashSet<>(); - result.add(Version.class.getCanonicalName()); - return result; - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.RELEASE_7; - } - - private static void log(String s) { - System.out.println("[MainProcessor] " + s); - } -} diff --git a/processor/src/main/java/com/beust/apt/processor/Version.java b/processor/src/main/java/com/beust/apt/processor/Version.java index 470163b..15707b7 100644 --- a/processor/src/main/java/com/beust/apt/processor/Version.java +++ b/processor/src/main/java/com/beust/apt/processor/Version.java @@ -8,5 +8,7 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Version { - String value(); + String value() default ""; + String fileName() default "version.properties"; + String propertyName() default "version"; } diff --git a/processor/src/main/java/com/beust/apt/processor/VersionProcessor.java b/processor/src/main/java/com/beust/apt/processor/VersionProcessor.java new file mode 100644 index 0000000..72d68ae --- /dev/null +++ b/processor/src/main/java/com/beust/apt/processor/VersionProcessor.java @@ -0,0 +1,116 @@ +package com.beust.apt.processor; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +public class VersionProcessor extends AbstractProcessor { + private Types typeUtils; + private Elements elementUtils; + private Filer filer; + private Messager messager; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + typeUtils = processingEnv.getTypeUtils(); + elementUtils = processingEnv.getElementUtils(); + filer = processingEnv.getFiler(); + messager = processingEnv.getMessager(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Version.class)) { + Version version = annotatedElement.getAnnotation(Version.class); + if (annotatedElement.getKind() == ElementKind.CLASS) { + Element enclosing = annotatedElement.getEnclosingElement(); + if (enclosing.getKind() == ElementKind.PACKAGE) { + PackageElement packageElement = (PackageElement) enclosing; + String packageName = packageElement.getQualifiedName().toString(); + JavaFileObject jfo = null; + try { + String versionValue = findVersionValue(version); + if (versionValue != null) { + log("Version value found: " + versionValue); + jfo = filer.createSourceFile(packageName + ".GeneratedVersion"); + BufferedWriter writer = new BufferedWriter(jfo.openWriter()); + writer.write("package " + packageName + ";\n\n"); + writer.write("public class GeneratedVersion {\n"); + writer.write(" public static final String VERSION = \"" + versionValue + "\";\n"); + writer.write("}\n"); + writer.close(); + log("Generated " + jfo.getName()); + } else { + error("Need to specify either @Version(value) or @Version(fileName)"); + } + } catch (IOException e) { + error("IOException while running", e); + } + } + } + } + return true; + } + + private boolean isDefault(String s) { + return s.length() == 0; + } + + private String findVersionValue(Version version) throws IOException { + if (! isDefault(version.value())) { + return version.value(); + } else if (! isDefault(version.fileName())) { + File f = new File(version.fileName()); + if (f.exists()) { + log("Found " + f); + Properties p = new Properties(); + p.load(new FileReader(f)); + String result = p.getProperty(version.propertyName()); + return result; + } else { + error("Couldn't find " + version.fileName()); + } + } + + return null; + } + + public Set getSupportedAnnotationTypes() { + Set result = new HashSet<>(); + result.add(Version.class.getCanonicalName()); + return result; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_8; + } + + private void log(String s) { + messager.printMessage(Diagnostic.Kind.OTHER, "[VersionProcessor] " + s); +// System.out.println("[VersionProcessor] " + s); + } + + private void error(String s) { + error(s, null); + } + + private void error(String s, Throwable t) { + messager.printMessage(Diagnostic.Kind.ERROR, s + " " + (t != null ? t.getMessage() : "")); + } +} diff --git a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor index ac0fb56..51b3888 100644 --- a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1 @@ -com.beust.apt.processor.MainProcessor +com.beust.apt.processor.VersionProcessor