build/annotationProcessors/AnnotationProcessor.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/build/annotationProcessors/AnnotationProcessor.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,161 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +package org.mozilla.gecko.annotationProcessors;
     1.9 +
    1.10 +import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
    1.11 +import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
    1.12 +import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
    1.13 +import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
    1.14 +
    1.15 +import java.io.FileOutputStream;
    1.16 +import java.io.IOException;
    1.17 +import java.util.Arrays;
    1.18 +import java.util.Iterator;
    1.19 +
    1.20 +public class AnnotationProcessor {
    1.21 +    public static final String OUTFILE = "GeneratedJNIWrappers.cpp";
    1.22 +    public static final String HEADERFILE = "GeneratedJNIWrappers.h";
    1.23 +
    1.24 +    public static final String GENERATED_COMMENT =
    1.25 +            "// GENERATED CODE\n" +
    1.26 +            "// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
    1.27 +            "// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
    1.28 +            "// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
    1.29 +
    1.30 +    public static void main(String[] args) {
    1.31 +        // We expect a list of jars on the commandline. If missing, whinge about it.
    1.32 +        if (args.length <= 1) {
    1.33 +            System.err.println("Usage: java AnnotationProcessor jarfiles ...");
    1.34 +            System.exit(1);
    1.35 +        }
    1.36 +
    1.37 +        System.out.println("Processing annotations...");
    1.38 +
    1.39 +        // We want to produce the same output as last time as often as possible. Ordering of
    1.40 +        // generated statements, therefore, needs to be consistent.
    1.41 +        Arrays.sort(args);
    1.42 +
    1.43 +        // Start the clock!
    1.44 +        long s = System.currentTimeMillis();
    1.45 +
    1.46 +        // Get an iterator over the classes in the jar files given...
    1.47 +        Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
    1.48 +
    1.49 +        StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
    1.50 +        headerFile.append("#ifndef GeneratedJNIWrappers_h__\n" +
    1.51 +                          "#define GeneratedJNIWrappers_h__\n\n" +
    1.52 +                          "#include \"nsXPCOMStrings.h\"\n" +
    1.53 +                          "#include \"AndroidJavaWrappers.h\"\n" +
    1.54 +                          "\n" +
    1.55 +                          "namespace mozilla {\n" +
    1.56 +                          "namespace widget {\n" +
    1.57 +                          "namespace android {\n" +
    1.58 +                          "void InitStubs(JNIEnv *jEnv);\n\n");
    1.59 +
    1.60 +        StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
    1.61 +        implementationFile.append("#include \"GeneratedJNIWrappers.h\"\n" +
    1.62 +                                  "#include \"AndroidBridgeUtilities.h\"\n" +
    1.63 +                                  "#include \"nsXPCOMStrings.h\"\n" +
    1.64 +                                  "#include \"AndroidBridge.h\"\n" +
    1.65 +                                  "\n" +
    1.66 +                                  "namespace mozilla {\n" +
    1.67 +                                  "namespace widget {\n" +
    1.68 +                                  "namespace android {\n");
    1.69 +
    1.70 +        // Used to track the calls to the various class-specific initialisation functions.
    1.71 +        StringBuilder stubInitialiser = new StringBuilder();
    1.72 +        stubInitialiser.append("void InitStubs(JNIEnv *jEnv) {\n");
    1.73 +
    1.74 +        while (jarClassIterator.hasNext()) {
    1.75 +            ClassWithOptions aClassTuple = jarClassIterator.next();
    1.76 +
    1.77 +            CodeGenerator generatorInstance;
    1.78 +
    1.79 +            // Get an iterator over the appropriately generated methods of this class
    1.80 +            Iterator<AnnotatableEntity> methodIterator = new GeneratableElementIterator(aClassTuple.wrappedClass);
    1.81 +
    1.82 +            if (!methodIterator.hasNext()) {
    1.83 +                continue;
    1.84 +            }
    1.85 +            generatorInstance = new CodeGenerator(aClassTuple.wrappedClass, aClassTuple.generatedName);
    1.86 +
    1.87 +            stubInitialiser.append("    ").append(aClassTuple.generatedName).append("::InitStubs(jEnv);\n");
    1.88 +
    1.89 +            // Iterate all annotated members in this class..
    1.90 +            while (methodIterator.hasNext()) {
    1.91 +                AnnotatableEntity aElementTuple = methodIterator.next();
    1.92 +                switch (aElementTuple.mEntityType) {
    1.93 +                    case METHOD:
    1.94 +                        generatorInstance.generateMethod(aElementTuple);
    1.95 +                        break;
    1.96 +                    case FIELD:
    1.97 +                        generatorInstance.generateField(aElementTuple);
    1.98 +                        break;
    1.99 +                    case CONSTRUCTOR:
   1.100 +                        generatorInstance.generateConstructor(aElementTuple);
   1.101 +                        break;
   1.102 +                }
   1.103 +            }
   1.104 +
   1.105 +            headerFile.append(generatorInstance.getHeaderFileContents());
   1.106 +            implementationFile.append(generatorInstance.getWrapperFileContents());
   1.107 +        }
   1.108 +
   1.109 +        implementationFile.append('\n');
   1.110 +        stubInitialiser.append("}");
   1.111 +        implementationFile.append(stubInitialiser);
   1.112 +
   1.113 +        implementationFile.append("\n} /* android */\n" +
   1.114 +                                    "} /* widget */\n" +
   1.115 +                                    "} /* mozilla */\n");
   1.116 +
   1.117 +        headerFile.append("\n} /* android */\n" +
   1.118 +                            "} /* widget */\n" +
   1.119 +                            "} /* mozilla */\n" +
   1.120 +                            "#endif\n");
   1.121 +
   1.122 +        writeOutputFiles(headerFile, implementationFile);
   1.123 +        long e = System.currentTimeMillis();
   1.124 +        System.out.println("Annotation processing complete in " + (e - s) + "ms");
   1.125 +    }
   1.126 +
   1.127 +    private static void writeOutputFiles(StringBuilder aHeaderFile, StringBuilder aImplementationFile) {
   1.128 +        FileOutputStream headerStream = null;
   1.129 +        try {
   1.130 +            headerStream = new FileOutputStream(OUTFILE);
   1.131 +            headerStream.write(aImplementationFile.toString().getBytes());
   1.132 +        } catch (IOException e) {
   1.133 +            System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?");
   1.134 +            e.printStackTrace(System.err);
   1.135 +        } finally {
   1.136 +            if (headerStream != null) {
   1.137 +                try {
   1.138 +                    headerStream.close();
   1.139 +                } catch (IOException e) {
   1.140 +                    System.err.println("Unable to close headerStream due to "+e);
   1.141 +                    e.printStackTrace(System.err);
   1.142 +                }
   1.143 +            }
   1.144 +        }
   1.145 +
   1.146 +        FileOutputStream outStream = null;
   1.147 +        try {
   1.148 +            outStream = new FileOutputStream(HEADERFILE);
   1.149 +            outStream.write(aHeaderFile.toString().getBytes());
   1.150 +        } catch (IOException e) {
   1.151 +            System.err.println("Unable to write " + HEADERFILE + ". Perhaps a permissions issue?");
   1.152 +            e.printStackTrace(System.err);
   1.153 +        } finally {
   1.154 +            if (outStream != null) {
   1.155 +                try {
   1.156 +                    outStream.close();
   1.157 +                } catch (IOException e) {
   1.158 +                    System.err.println("Unable to close outStream due to "+e);
   1.159 +                    e.printStackTrace(System.err);
   1.160 +                }
   1.161 +            }
   1.162 +        }
   1.163 +    }
   1.164 +}
   1.165 \ No newline at end of file

mercurial