diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java')
-rw-r--r-- | mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java b/mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java new file mode 100644 index 0000000000..8db77eed0b --- /dev/null +++ b/mobile/android/annotations/src/main/java/org/mozilla/gecko/annotationProcessors/AnnotationProcessor.java @@ -0,0 +1,231 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.annotationProcessors; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.util.Arrays; +import java.util.Iterator; +import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity; +import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions; +import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader; +import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator; + +public class AnnotationProcessor { + private static final String NATIVES_NAME = "Natives"; + private static final String WRAPPERS_NAME = "Wrappers"; + private static final String EXPORT_PREFIX = "mozilla/java/"; + + public static final String GENERATED_COMMENT = + "// GENERATED CODE\n" + + "// Generated by the Java program at /build/annotationProcessors at compile time\n" + + "// from annotations on Java methods. To update, change the annotations on the\n" + + "// corresponding Java methods and rerun the build. Manually updating this file\n" + + "// will cause your build to fail.\n" + + "\n"; + + public static void main(String[] args) { + // We expect a list of jars on the commandline. If missing, whinge about it. + if (args.length < 2) { + System.err.println("Usage: java AnnotationProcessor outprefix jarfiles ..."); + System.exit(1); + } + + final String OUTPUT_PREFIX = args[0]; + final String QUALIFIER = OUTPUT_PREFIX + "JNI"; + + (new File(QUALIFIER)).mkdir(); + + System.out.println("Processing annotations..."); + + // We want to produce the same output as last time as often as possible. Ordering of + // generated statements, therefore, needs to be consistent. + final String[] jars = Arrays.copyOfRange(args, 1, args.length); + Arrays.sort(jars); + + // Start the clock! + long s = System.currentTimeMillis(); + + int ret = 0; + + // Get an iterator over the classes in the jar files given... + Iterator<ClassWithOptions> jarClassIterator = + IterableJarLoadingURLClassLoader.getIteratorOverJars(jars); + + while (jarClassIterator.hasNext()) { + final ClassWithOptions annotatedClass = jarClassIterator.next(); + if (!annotatedClass.hasGenerated()) { + continue; + } + + final String sourceFileName = + QUALIFIER + annotatedClass.generatedName + WRAPPERS_NAME + ".cpp"; + final String headerFileName = + QUALIFIER + File.separator + annotatedClass.generatedName + WRAPPERS_NAME + ".h"; + final String headerExportedFileName = + EXPORT_PREFIX + annotatedClass.generatedName + WRAPPERS_NAME + ".h"; + final String nativesFileName = + QUALIFIER + File.separator + annotatedClass.generatedName + NATIVES_NAME + ".h"; + final String nativesExportedFileName = + EXPORT_PREFIX + annotatedClass.generatedName + NATIVES_NAME + ".h"; + + final StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT); + final StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT); + final StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT); + + headerFile.append( + "#ifndef " + + getHeaderGuardName(headerExportedFileName) + + "\n" + + "#define " + + getHeaderGuardName(headerExportedFileName) + + "\n" + + "\n" + + "#ifndef MOZ_PREPROCESSOR\n" + + "#include \"mozilla/jni/Refs.h\"\n" + + "#endif\n" + + "\n" + + "namespace mozilla {\n" + + "namespace java {\n" + + "\n"); + + implementationFile.append( + "#ifndef MOZ_PREPROCESSOR\n" + + "#include \"" + + headerExportedFileName + + "\"\n" + + "#include \"mozilla/jni/Accessors.h\"\n" + + "#endif\n" + + "\n" + + "namespace mozilla {\n" + + "namespace java {\n" + + "\n"); + + nativesFile.append( + "#ifndef " + + getHeaderGuardName(nativesExportedFileName) + + "\n" + + "#define " + + getHeaderGuardName(nativesExportedFileName) + + "\n" + + "\n" + + "#ifndef MOZ_PREPROCESSOR\n" + + "#include \"" + + headerExportedFileName + + "\"\n" + + "#include \"mozilla/jni/Natives.h\"\n" + + "#endif\n" + + "\n" + + "namespace mozilla {\n" + + "namespace java {\n" + + "\n"); + + generateClass(annotatedClass, headerFile, implementationFile, nativesFile); + + implementationFile.append("} /* java */\n" + "} /* mozilla */\n"); + + headerFile.append( + "} /* java */\n" + + "} /* mozilla */\n\n" + + "#endif // " + + getHeaderGuardName(headerExportedFileName) + + "\n"); + + nativesFile.append( + "} /* java */\n" + + "} /* mozilla */\n\n" + + "#endif // " + + getHeaderGuardName(nativesExportedFileName) + + "\n"); + + ret |= writeOutputFile(sourceFileName, implementationFile); + ret |= writeOutputFile(headerFileName, headerFile); + ret |= writeOutputFile(nativesFileName, nativesFile); + } + long e = System.currentTimeMillis(); + System.out.println("Annotation processing complete in " + (e - s) + "ms"); + + System.exit(ret); + } + + private static void generateClass( + final ClassWithOptions annotatedClass, + final StringBuilder headerFile, + final StringBuilder implementationFile, + final StringBuilder nativesFile) { + // Get an iterator over the appropriately generated methods of this class + final GeneratableElementIterator methodIterator = + new GeneratableElementIterator(annotatedClass); + final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses(); + + final CodeGenerator generatorInstance = new CodeGenerator(annotatedClass); + generatorInstance.generateClasses(innerClasses); + + // Iterate all annotated members in this class.. + while (methodIterator.hasNext()) { + AnnotatableEntity aElementTuple = methodIterator.next(); + switch (aElementTuple.mEntityType) { + case METHOD: + generatorInstance.generateMethod(aElementTuple); + break; + case NATIVE: + generatorInstance.generateNative(aElementTuple); + break; + case FIELD: + generatorInstance.generateField(aElementTuple); + break; + case CONSTRUCTOR: + generatorInstance.generateConstructor(aElementTuple); + break; + } + } + + headerFile.append(generatorInstance.getHeaderFileContents()); + implementationFile.append(generatorInstance.getWrapperFileContents()); + nativesFile.append(generatorInstance.getNativesFileContents()); + + for (ClassWithOptions innerClass : innerClasses) { + generateClass(innerClass, headerFile, implementationFile, nativesFile); + } + } + + private static String getHeaderGuardName(final String name) { + return name.replaceAll("\\W", "_"); + } + + private static int writeOutputFile(final String name, final StringBuilder content) { + final byte[] contentBytes = content.toString().getBytes(StandardCharsets.UTF_8); + + try { + final byte[] existingBytes = Files.readAllBytes(new File(name).toPath()); + if (Arrays.equals(contentBytes, existingBytes)) { + return 0; + } + } catch (FileNotFoundException e) { + // Pass. + } catch (NoSuchFileException e) { + // Pass. + } catch (IOException e) { + System.err.println("Unable to read " + name + ". Perhaps a permissions issue?"); + e.printStackTrace(System.err); + return 1; + } + + try (FileOutputStream outStream = new FileOutputStream(name)) { + outStream.write(contentBytes); + } catch (IOException e) { + System.err.println("Unable to write " + name + ". Perhaps a permissions issue?"); + e.printStackTrace(System.err); + return 1; + } + + return 0; + } +} |