build/annotationProcessors/AnnotationProcessor.java

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:4fabbffd7841
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 package org.mozilla.gecko.annotationProcessors;
6
7 import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
8 import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
9 import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
10 import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
11
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.util.Arrays;
15 import java.util.Iterator;
16
17 public class AnnotationProcessor {
18 public static final String OUTFILE = "GeneratedJNIWrappers.cpp";
19 public static final String HEADERFILE = "GeneratedJNIWrappers.h";
20
21 public static final String GENERATED_COMMENT =
22 "// GENERATED CODE\n" +
23 "// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
24 "// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
25 "// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
26
27 public static void main(String[] args) {
28 // We expect a list of jars on the commandline. If missing, whinge about it.
29 if (args.length <= 1) {
30 System.err.println("Usage: java AnnotationProcessor jarfiles ...");
31 System.exit(1);
32 }
33
34 System.out.println("Processing annotations...");
35
36 // We want to produce the same output as last time as often as possible. Ordering of
37 // generated statements, therefore, needs to be consistent.
38 Arrays.sort(args);
39
40 // Start the clock!
41 long s = System.currentTimeMillis();
42
43 // Get an iterator over the classes in the jar files given...
44 Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
45
46 StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
47 headerFile.append("#ifndef GeneratedJNIWrappers_h__\n" +
48 "#define GeneratedJNIWrappers_h__\n\n" +
49 "#include \"nsXPCOMStrings.h\"\n" +
50 "#include \"AndroidJavaWrappers.h\"\n" +
51 "\n" +
52 "namespace mozilla {\n" +
53 "namespace widget {\n" +
54 "namespace android {\n" +
55 "void InitStubs(JNIEnv *jEnv);\n\n");
56
57 StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
58 implementationFile.append("#include \"GeneratedJNIWrappers.h\"\n" +
59 "#include \"AndroidBridgeUtilities.h\"\n" +
60 "#include \"nsXPCOMStrings.h\"\n" +
61 "#include \"AndroidBridge.h\"\n" +
62 "\n" +
63 "namespace mozilla {\n" +
64 "namespace widget {\n" +
65 "namespace android {\n");
66
67 // Used to track the calls to the various class-specific initialisation functions.
68 StringBuilder stubInitialiser = new StringBuilder();
69 stubInitialiser.append("void InitStubs(JNIEnv *jEnv) {\n");
70
71 while (jarClassIterator.hasNext()) {
72 ClassWithOptions aClassTuple = jarClassIterator.next();
73
74 CodeGenerator generatorInstance;
75
76 // Get an iterator over the appropriately generated methods of this class
77 Iterator<AnnotatableEntity> methodIterator = new GeneratableElementIterator(aClassTuple.wrappedClass);
78
79 if (!methodIterator.hasNext()) {
80 continue;
81 }
82 generatorInstance = new CodeGenerator(aClassTuple.wrappedClass, aClassTuple.generatedName);
83
84 stubInitialiser.append(" ").append(aClassTuple.generatedName).append("::InitStubs(jEnv);\n");
85
86 // Iterate all annotated members in this class..
87 while (methodIterator.hasNext()) {
88 AnnotatableEntity aElementTuple = methodIterator.next();
89 switch (aElementTuple.mEntityType) {
90 case METHOD:
91 generatorInstance.generateMethod(aElementTuple);
92 break;
93 case FIELD:
94 generatorInstance.generateField(aElementTuple);
95 break;
96 case CONSTRUCTOR:
97 generatorInstance.generateConstructor(aElementTuple);
98 break;
99 }
100 }
101
102 headerFile.append(generatorInstance.getHeaderFileContents());
103 implementationFile.append(generatorInstance.getWrapperFileContents());
104 }
105
106 implementationFile.append('\n');
107 stubInitialiser.append("}");
108 implementationFile.append(stubInitialiser);
109
110 implementationFile.append("\n} /* android */\n" +
111 "} /* widget */\n" +
112 "} /* mozilla */\n");
113
114 headerFile.append("\n} /* android */\n" +
115 "} /* widget */\n" +
116 "} /* mozilla */\n" +
117 "#endif\n");
118
119 writeOutputFiles(headerFile, implementationFile);
120 long e = System.currentTimeMillis();
121 System.out.println("Annotation processing complete in " + (e - s) + "ms");
122 }
123
124 private static void writeOutputFiles(StringBuilder aHeaderFile, StringBuilder aImplementationFile) {
125 FileOutputStream headerStream = null;
126 try {
127 headerStream = new FileOutputStream(OUTFILE);
128 headerStream.write(aImplementationFile.toString().getBytes());
129 } catch (IOException e) {
130 System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?");
131 e.printStackTrace(System.err);
132 } finally {
133 if (headerStream != null) {
134 try {
135 headerStream.close();
136 } catch (IOException e) {
137 System.err.println("Unable to close headerStream due to "+e);
138 e.printStackTrace(System.err);
139 }
140 }
141 }
142
143 FileOutputStream outStream = null;
144 try {
145 outStream = new FileOutputStream(HEADERFILE);
146 outStream.write(aHeaderFile.toString().getBytes());
147 } catch (IOException e) {
148 System.err.println("Unable to write " + HEADERFILE + ". Perhaps a permissions issue?");
149 e.printStackTrace(System.err);
150 } finally {
151 if (outStream != null) {
152 try {
153 outStream.close();
154 } catch (IOException e) {
155 System.err.println("Unable to close outStream due to "+e);
156 e.printStackTrace(System.err);
157 }
158 }
159 }
160 }
161 }

mercurial