Bug 1444546 - Part 4b: Make AnnotationProcessor avoid writing, like Python's FileAvoidWrite. r=jchen
This allows us to invoke AnnotationProcessor more than is strictly
necessary and not trigger expensive native code compilations unless
the native code has actually evolved.
MozReview-Commit-ID: H1BIzJsdyIh
--- 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
@@ -4,18 +4,24 @@
package org.mozilla.gecko.annotationProcessors;
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;
+import java.io.File;
+import java.io.FileInputStream;
+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;
public class AnnotationProcessor {
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" +
@@ -100,22 +106,25 @@ public class AnnotationProcessor {
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(HEADER_FILE) + "\n");
nativesFile.append(
"} /* java */\n" +
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n");
- writeOutputFile(SOURCE_FILE, implementationFile);
- writeOutputFile(HEADER_FILE, headerFile);
- writeOutputFile(NATIVES_FILE, nativesFile);
+ int ret = 0;
+ ret |= writeOutputFile(SOURCE_FILE, implementationFile);
+ ret |= writeOutputFile(HEADER_FILE, headerFile);
+ ret |= writeOutputFile(NATIVES_FILE, 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) {
// Get an iterator over the appropriately generated methods of this class
final GeneratableElementIterator methodIterator
= new GeneratableElementIterator(annotatedClass);
final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses();
@@ -153,29 +162,37 @@ public class AnnotationProcessor {
generateClass(innerClass);
}
}
private static String getHeaderGuardName(final String name) {
return name.replaceAll("\\W", "_");
}
- private static void writeOutputFile(final String name,
- final StringBuilder content) {
- FileOutputStream outStream = null;
+ private static int writeOutputFile(final String name, final StringBuilder content) {
+ final byte[] contentBytes = content.toString().getBytes(StandardCharsets.UTF_8);
+
try {
- outStream = new FileOutputStream(name);
- outStream.write(content.toString().getBytes());
+ 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);
- } finally {
- if (outStream != null) {
- try {
- outStream.close();
- } catch (IOException e) {
- System.err.println("Unable to close outStream due to "+e);
- e.printStackTrace(System.err);
- }
- }
+ return 1;
}
+
+ return 0;
}
}