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