aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/buildjar
diff options
context:
space:
mode:
authorGravatar Liam Miller-Cushon <cushon@google.com>2017-02-11 03:06:31 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2017-02-13 11:34:16 +0000
commit19cdec0dbd900c534df35d8da47843521c96f64d (patch)
tree9b0693d78f0cf5ee928043b11773abfbe313bd09 /src/java_tools/buildjar
parent3a6f6297917b9d97d83d8384e346e2c725819c3d (diff)
Create a 'vanilla' JavaBuilder
that is portable across JDK versions, and doesn't depend on the javac distributed with Bazel. There is no support for Error Prone, strict Java deps, header compilation, Android desugaring, or any other features that depend on the Bazel javac. -- PiperOrigin-RevId: 147224490 MOS_MIGRATED_REVID=147224490
Diffstat (limited to 'src/java_tools/buildjar')
-rw-r--r--src/java_tools/buildjar/BUILD19
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD38
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/VanillaJavaBuilder.java340
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/BUILD21
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarBuilder.java12
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarOptions.java2
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/BUILD18
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/VanillaJavaBuilderTest.java135
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar/BUILD2
9 files changed, 579 insertions, 8 deletions
diff --git a/src/java_tools/buildjar/BUILD b/src/java_tools/buildjar/BUILD
index b47b17ccc3..80d70e957f 100644
--- a/src/java_tools/buildjar/BUILD
+++ b/src/java_tools/buildjar/BUILD
@@ -7,10 +7,17 @@ java_binary(
runtime_deps = ["//src/java_tools/buildjar/java/com/google/devtools/build/buildjar"],
)
+java_binary(
+ name = "VanillaJavaBuilder",
+ main_class = "com.google.devtools.build.buildjar.VanillaJavaBuilder",
+ visibility = ["//visibility:public"],
+ runtime_deps = ["//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:vanilla_java_builder"],
+)
+
filegroup(
name = "JavaBuilderDeploy",
srcs = select({
- "//tools/jdk:jdk7": ["//third_party/java/jdk/javabuilder:JavaBuilder_0.1.0"],
+ "//tools/jdk:jdk7": [":VanillaJavaBuilder_deploy.jar"],
"//conditions:default": [":JavaBuilder_deploy.jar"],
}),
)
@@ -22,6 +29,12 @@ filegroup(
)
filegroup(
+ name = "bootstrap_VanillaJavaBuilder_deploy.jar",
+ srcs = ["//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:bootstrap_VanillaJavaBuilder_deploy.jar"],
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
name = "bootstrap_genclass_deploy.jar",
srcs = ["//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:bootstrap_genclass_deploy.jar"],
visibility = ["//visibility:public"],
@@ -43,7 +56,7 @@ filegroup(
"//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine:srcs",
"//src/java_tools/buildjar/javatests/com/google/devtools/build/java/bazel:srcs",
"//src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine:srcs",
- "//src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar:srcs",
+ "//src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar:srcs",
],
visibility = ["//src:__pkg__"],
)
@@ -74,7 +87,7 @@ java_toolchain(
extclasspath = ["//tools/jdk:extdir"],
genclass = ["bootstrap_genclass_deploy.jar"],
ijar = ["//third_party/ijar"],
- javabuilder = ["//third_party/java/jdk/javabuilder:JavaBuilder_0.1.0"],
+ javabuilder = [":bootstrap_VanillaJavaBuilder_deploy.jar"],
javac = ["//third_party/java/jdk/langtools:javac7_jar"],
jvm_opts = [
"-XX:+TieredCompilation",
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD
index d05bdeec40..961904114f 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD
@@ -55,6 +55,7 @@ java_library(
exclude = [
"InvalidCommandLineException.java",
"JarOwner.java",
+ "VanillaJavaBuilder.java",
],
),
deps = [
@@ -154,6 +155,7 @@ bootstrap_java_binary(
exclude = [
"java/com/google/devtools/build/buildjar/javac/testing/**",
"JarOwner.java",
+ "VanillaJavaBuilder.java",
],
),
main_class = "com.google.devtools.build.buildjar.BazelJavaBuilder",
@@ -174,6 +176,42 @@ bootstrap_java_library(
],
)
+bootstrap_java_binary(
+ name = "bootstrap_VanillaJavaBuilder",
+ srcs = [
+ "InvalidCommandLineException.java",
+ "JarOwner.java",
+ "OptionsParser.java",
+ "VanillaJavaBuilder.java",
+ ],
+ main_class = "com.google.devtools.build.buildjar.VanillaJavaBuilder",
+ deps = [
+ ":skylark-deps",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper:bootstrap_jarhelper",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar:bootstrap_resourcejar",
+ ],
+)
+
+java_binary(
+ name = "VanillaJavaBuilder",
+ main_class = "com.google.devtools.build.buildjar.VanillaJavaBuilder",
+ runtime_deps = [":vanilla_java_builder"],
+)
+
+java_library(
+ name = "vanilla_java_builder",
+ srcs = ["VanillaJavaBuilder.java"],
+ deps = [
+ ":optionsparser",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar",
+ "//src/main/protobuf:deps_java_proto",
+ "//src/main/protobuf:java_compilation_java_proto",
+ "//src/main/protobuf:worker_protocol_java_proto",
+ "//third_party:guava",
+ ],
+)
+
filegroup(
name = "srcs",
srcs = glob(["**"]) + [
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/VanillaJavaBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/VanillaJavaBuilder.java
new file mode 100644
index 0000000000..77620674a7
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/VanillaJavaBuilder.java
@@ -0,0 +1,340 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.buildjar;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Locale.ENGLISH;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.buildjar.jarhelper.JarCreator;
+import com.google.devtools.build.buildjar.proto.JavaCompilation.Manifest;
+import com.google.devtools.build.buildjar.resourcejar.ResourceJarBuilder;
+import com.google.devtools.build.buildjar.resourcejar.ResourceJarOptions;
+import com.google.devtools.build.lib.view.proto.Deps;
+import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest;
+import com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.processing.Processor;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * A JavaBuilder that supports non-standard JDKs and unmodified javac's.
+ *
+ * <p>Does not support:
+ *
+ * <ul>
+ * <li>Error Prone
+ * <li>strict Java deps
+ * <li>header compilation
+ * <li>Android desugaring
+ * <li>coverage instrumentation
+ * <li>genclass handling for IDEs
+ * </ul>
+ */
+public class VanillaJavaBuilder implements Closeable {
+
+ /** Cache of opened zip filesystems. */
+ private final Map<Path, FileSystem> filesystems = new HashMap<>();
+
+ private FileSystem getJarFileSystem(Path sourceJar) throws IOException {
+ FileSystem fs = filesystems.get(sourceJar);
+ if (fs == null) {
+ filesystems.put(sourceJar, fs = FileSystems.newFileSystem(sourceJar, null));
+ }
+ return fs;
+ }
+
+ public static void main(String[] args) throws IOException {
+ if (args.length == 1 && args[0].equals("--persistent_worker")) {
+ System.exit(runPersistentWorker());
+ } else {
+ try (VanillaJavaBuilder builder = new VanillaJavaBuilder()) {
+ VanillaJavaBuilderResult result = builder.run(ImmutableList.copyOf(args));
+ System.err.print(result.output());
+ System.exit(result.ok() ? 0 : 1);
+ }
+ }
+ }
+
+ private static int runPersistentWorker() {
+ while (true) {
+ try {
+ WorkRequest request = WorkRequest.parseDelimitedFrom(System.in);
+ if (request == null) {
+ break;
+ }
+ try (VanillaJavaBuilder builder = new VanillaJavaBuilder()) {
+ VanillaJavaBuilderResult result = builder.run(request.getArgumentsList());
+ WorkResponse response =
+ WorkResponse.newBuilder()
+ .setOutput(result.output())
+ .setExitCode(result.ok() ? 0 : 1)
+ .build();
+ response.writeDelimitedTo(System.out);
+ }
+ System.out.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /** Return result of a {@link VanillaJavaBuilder} build. */
+ public static class VanillaJavaBuilderResult {
+ private final boolean ok;
+ private final String output;
+
+ public VanillaJavaBuilderResult(boolean ok, String output) {
+ this.ok = ok;
+ this.output = output;
+ }
+
+ /** True if the compilation was succesfull. */
+ public boolean ok() {
+ return ok;
+ }
+
+ /** Log output from the compilation. */
+ public String output() {
+ return output;
+ }
+ }
+
+ public VanillaJavaBuilderResult run(List<String> args) throws IOException {
+ OptionsParser optionsParser;
+ try {
+ optionsParser = new OptionsParser(args);
+ } catch (InvalidCommandLineException e) {
+ return new VanillaJavaBuilderResult(false, e.getMessage());
+ }
+ DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
+ StringWriter output = new StringWriter();
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fileManager =
+ javaCompiler.getStandardFileManager(diagnosticCollector, ENGLISH, UTF_8);
+ setLocations(optionsParser, fileManager);
+ ImmutableList<JavaFileObject> sources = getSources(optionsParser, fileManager);
+ boolean ok;
+ if (sources.isEmpty()) {
+ ok = true;
+ } else {
+ CompilationTask task =
+ javaCompiler.getTask(
+ new PrintWriter(output, true),
+ fileManager,
+ diagnosticCollector,
+ optionsParser.getJavacOpts(),
+ ImmutableList.<String>of() /*classes*/,
+ sources);
+ setProcessors(optionsParser, fileManager, task);
+ ok = task.call();
+ }
+ if (ok) {
+ writeOutput(optionsParser);
+ }
+ writeGeneratedSourceOutput(optionsParser);
+ // the jdeps output doesn't include any information about dependencies, but Bazel still expects
+ // the file to be created
+ if (optionsParser.getOutputDepsProtoFile() != null) {
+ try (OutputStream os =
+ Files.newOutputStream(Paths.get(optionsParser.getOutputDepsProtoFile()))) {
+ Deps.Dependencies.newBuilder()
+ .setRuleLabel(optionsParser.getTargetLabel())
+ .setSuccess(ok)
+ .build()
+ .writeTo(os);
+ }
+ }
+ // TODO(cushon): support manifest protos & genjar
+ if (optionsParser.getManifestProtoPath() != null) {
+ try (OutputStream os =
+ Files.newOutputStream(Paths.get(optionsParser.getManifestProtoPath()))) {
+ Manifest.getDefaultInstance().writeTo(os);
+ }
+ }
+
+ for (Diagnostic<? extends JavaFileObject> diagnostic : diagnosticCollector.getDiagnostics()) {
+ StringBuilder message = new StringBuilder(diagnostic.getSource().getName());
+ if (diagnostic.getLineNumber() != -1) {
+ message.append(':').append(diagnostic.getLineNumber());
+ }
+ message.append(": ").append(diagnostic.getKind().toString().toLowerCase(ENGLISH));
+ message.append(": ").append(diagnostic.getMessage(ENGLISH)).append(System.lineSeparator());
+ output.write(message.toString());
+ }
+ return new VanillaJavaBuilderResult(ok, output.toString());
+ }
+
+ /** Returns the sources to compile, including any source jar entries. */
+ private ImmutableList<JavaFileObject> getSources(
+ OptionsParser optionsParser, StandardJavaFileManager fileManager) throws IOException {
+ final ImmutableList.Builder<JavaFileObject> sources = ImmutableList.builder();
+ sources.addAll(fileManager.getJavaFileObjectsFromStrings(optionsParser.getSourceFiles()));
+ for (String sourceJar : optionsParser.getSourceJars()) {
+ for (final Path root : getJarFileSystem(Paths.get(sourceJar)).getRootDirectories()) {
+ Files.walkFileTree(
+ root,
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)
+ throws IOException {
+ if (path.getFileName().toString().endsWith(".java")) {
+ sources.add(new SourceJarFileObject(root, path));
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ }
+ return sources.build();
+ }
+
+ /** Sets the compilation search paths and output directories. */
+ private static void setLocations(OptionsParser optionsParser, StandardJavaFileManager fileManager)
+ throws IOException {
+ fileManager.setLocation(StandardLocation.CLASS_PATH, toFiles(optionsParser.getClassPath()));
+ fileManager.setLocation(
+ StandardLocation.PLATFORM_CLASS_PATH,
+ Iterables.concat(
+ toFiles(optionsParser.getBootClassPath()), toFiles(optionsParser.getExtdir())));
+ fileManager.setLocation(
+ StandardLocation.ANNOTATION_PROCESSOR_PATH, toFiles(optionsParser.getProcessorPath()));
+ if (optionsParser.getSourceGenDir() != null) {
+ Path sourceGenDir = Paths.get(optionsParser.getSourceGenDir());
+ Files.createDirectories(sourceGenDir);
+ fileManager.setLocation(
+ StandardLocation.SOURCE_OUTPUT, ImmutableList.of(sourceGenDir.toFile()));
+ }
+ Path classDir = Paths.get(optionsParser.getClassDir());
+ Files.createDirectories(classDir);
+ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, ImmutableList.of(classDir.toFile()));
+ }
+
+ /** Sets the compilation's annotation processors. */
+ private static void setProcessors(
+ OptionsParser optionsParser, StandardJavaFileManager fileManager, CompilationTask task) {
+ ClassLoader processorLoader =
+ fileManager.getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_PATH);
+ Builder<Processor> processors = ImmutableList.builder();
+ for (String processor : optionsParser.getProcessorNames()) {
+ try {
+ processors.add(
+ (Processor) processorLoader.loadClass(processor).getConstructor().newInstance());
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+ }
+ task.setProcessors(processors.build());
+ }
+
+ /** Writes a jar containing any sources generated by annotation processors. */
+ private static void writeGeneratedSourceOutput(OptionsParser optionsParser) throws IOException {
+ if (optionsParser.getGeneratedSourcesOutputJar() == null) {
+ return;
+ }
+ JarCreator jar = new JarCreator(optionsParser.getGeneratedSourcesOutputJar());
+ jar.setNormalize(true);
+ jar.setCompression(optionsParser.compressJar());
+ jar.addDirectory(optionsParser.getSourceGenDir());
+ jar.execute();
+ }
+
+ /** Writes the class output jar, including any resource entries. */
+ private static void writeOutput(OptionsParser optionsParser) throws IOException {
+ JarCreator jar = new JarCreator(optionsParser.getOutputJar());
+ jar.setNormalize(true);
+ jar.setCompression(optionsParser.compressJar());
+ jar.addDirectory(optionsParser.getClassDir());
+ // TODO(cushon): kill this once resource jar creation is decoupled from JavaBuilder
+ try (ResourceJarBuilder resourceBuilder =
+ new ResourceJarBuilder(
+ ResourceJarOptions.builder()
+ .setMessages(ImmutableList.copyOf(optionsParser.getMessageFiles()))
+ .setResourceJars(ImmutableList.copyOf(optionsParser.getResourceJars()))
+ .setResources(ImmutableList.copyOf(optionsParser.getResourceFiles()))
+ .setClasspathResources(ImmutableList.copyOf(optionsParser.getRootResourceFiles()))
+ .build())) {
+ resourceBuilder.build(jar);
+ }
+ jar.execute();
+ }
+
+ private static ImmutableList<File> toFiles(String classPath) {
+ if (classPath == null) {
+ return ImmutableList.of();
+ }
+ ImmutableList.Builder<File> files = ImmutableList.builder();
+ for (String path : Splitter.on(File.pathSeparatorChar).split(classPath)) {
+ files.add(new File(path));
+ }
+ return files.build();
+ }
+
+ @Override
+ public void close() throws IOException {
+ for (FileSystem fs : filesystems.values()) {
+ fs.close();
+ }
+ }
+
+ /**
+ * Wraps a {@link Path} as a {@link JavaFileObject}; used to avoid extracting source jar entries
+ * to disk when using file managers that don't support nio.
+ */
+ private static class SourceJarFileObject extends SimpleJavaFileObject {
+ private final Path path;
+
+ public SourceJarFileObject(Path root, Path path) {
+ super(URI.create("file:/" + root + "!" + root.resolve(path)), Kind.SOURCE);
+ this.path = path;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return new String(Files.readAllBytes(path), UTF_8);
+ }
+ }
+}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/BUILD
index 5ef3e21919..e40f339d9d 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/BUILD
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/BUILD
@@ -18,6 +18,7 @@ java_library(
"ResourceJarOptionsParser.java",
],
visibility = [
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:__pkg__",
"//src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar:__pkg__",
],
deps = [
@@ -25,3 +26,23 @@ java_library(
"//third_party:guava",
],
)
+
+#
+## Bootstrapping using Skylark rules
+#
+
+load("//tools/build_rules:java_rules_skylark.bzl", "bootstrap_java_library", "bootstrap_java_binary")
+
+bootstrap_java_library(
+ name = "bootstrap_resourcejar",
+ srcs = [
+ "ResourceJarBuilder.java",
+ "ResourceJarOptions.java",
+ "ResourceJarOptionsParser.java",
+ ],
+ visibility = ["//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:__pkg__"],
+ deps = [
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:skylark-deps",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper:bootstrap_jarhelper",
+ ],
+)
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarBuilder.java
index 480f929b82..89ec82bfe5 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarBuilder.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarBuilder.java
@@ -14,6 +14,8 @@
package com.google.devtools.build.buildjar.resourcejar;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.buildjar.jarhelper.JarCreator;
@@ -52,12 +54,18 @@ public class ResourceJarBuilder implements Closeable {
private final ResourceJarOptions options;
- private ResourceJarBuilder(ResourceJarOptions options) {
+ public ResourceJarBuilder(ResourceJarOptions options) {
this.options = options;
}
public void build() throws IOException {
+ requireNonNull(options.output());
final JarCreator jar = new JarCreator(options.output());
+ build(jar);
+ jar.execute();
+ }
+
+ public void build(JarCreator jar) throws IOException {
jar.setNormalize(true);
jar.setCompression(true);
@@ -65,8 +73,6 @@ public class ResourceJarBuilder implements Closeable {
jar.addRootEntries(options.classpathResources());
addResourceEntries(jar, options.resources());
addMessageEntries(jar, options.messages());
-
- jar.execute();
}
private void addResourceJars(final JarCreator jar, ImmutableList<String> resourceJars)
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarOptions.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarOptions.java
index bf1afe47c4..923148c6f1 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarOptions.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/resourcejar/ResourceJarOptions.java
@@ -32,7 +32,7 @@ public class ResourceJarOptions {
ImmutableList<String> resources,
ImmutableList<String> resourceJars,
ImmutableList<String> classpathResources) {
- this.output = checkNotNull(output);
+ this.output = output;
this.messages = messages;
this.resources = resources;
this.resourceJars = resourceJars;
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/BUILD b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/BUILD
new file mode 100644
index 0000000000..65ca6bd977
--- /dev/null
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/BUILD
@@ -0,0 +1,18 @@
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]) + [
+ "//src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar:srcs",
+ ],
+ visibility = ["//src/java_tools/buildjar:__pkg__"],
+)
+
+java_test(
+ name = "VanillaJavaBuilderTest",
+ srcs = ["VanillaJavaBuilderTest.java"],
+ deps = [
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:vanilla_java_builder",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/VanillaJavaBuilderTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/VanillaJavaBuilderTest.java
new file mode 100644
index 0000000000..71a702ed05
--- /dev/null
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/VanillaJavaBuilderTest.java
@@ -0,0 +1,135 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.buildjar;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.buildjar.VanillaJavaBuilder.VanillaJavaBuilderResult;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** {@link VanillaJavaBuilder}Test */
+@RunWith(JUnit4.class)
+public class VanillaJavaBuilderTest {
+ @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ VanillaJavaBuilderResult run(List<String> args) throws Exception {
+ try (VanillaJavaBuilder builder = new VanillaJavaBuilder()) {
+ return builder.run(args);
+ }
+ }
+
+ ImmutableMap<String, byte[]> readJar(File file) throws IOException {
+ ImmutableMap.Builder<String, byte[]> result = ImmutableMap.builder();
+ try (JarFile jf = new JarFile(file)) {
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry je = entries.nextElement();
+ result.put(je.getName(), ByteStreams.toByteArray(jf.getInputStream(je)));
+ }
+ }
+ return result.build();
+ }
+
+ @Test
+ public void hello() throws Exception {
+ Path source = temporaryFolder.newFile("Test.java").toPath();
+ Path output = temporaryFolder.newFile("out.jar").toPath();
+ Files.write(
+ source,
+ ImmutableList.of(
+ "class A {", //
+ "}"),
+ UTF_8);
+ Path sourceJar = temporaryFolder.newFile("src.srcjar").toPath();
+ try (OutputStream os = Files.newOutputStream(sourceJar);
+ JarOutputStream jos = new JarOutputStream(os)) {
+ jos.putNextEntry(new JarEntry("B.java"));
+ jos.write("class B {}".getBytes(UTF_8));
+ }
+ Path resource = temporaryFolder.newFile("resource.properties").toPath();
+ Files.write(resource, "hello".getBytes(UTF_8));
+
+ VanillaJavaBuilderResult result =
+ run(
+ ImmutableList.of(
+ "--sources",
+ source.toString(),
+ "--source_jars",
+ sourceJar.toString(),
+ "--output",
+ output.toString(),
+ "--classpath_resources",
+ resource.toString(),
+ "--bootclasspath",
+ Paths.get(System.getProperty("java.home")).resolve("lib/rt.jar").toString(),
+ "--classdir",
+ temporaryFolder.newFolder().toString()));
+
+ assertThat(result.output()).isEmpty();
+ assertThat(result.ok()).isTrue();
+
+ ImmutableMap<String, byte[]> outputEntries = readJar(output.toFile());
+ assertThat(outputEntries.keySet())
+ .containsExactly(
+ "META-INF/", "META-INF/MANIFEST.MF", "A.class", "B.class", "resource.properties");
+ }
+
+ @Test
+ public void error() throws Exception {
+ Path source = temporaryFolder.newFile("Test.java").toPath();
+ Path output = temporaryFolder.newFolder().toPath().resolve("out.jar");
+ Files.write(
+ source,
+ ImmutableList.of(
+ "class A {", //
+ "}}"),
+ UTF_8);
+
+ VanillaJavaBuilderResult result =
+ run(
+ ImmutableList.of(
+ "--sources",
+ source.toString(),
+ "--output",
+ output.toString(),
+ "--bootclasspath",
+ Paths.get(System.getProperty("java.home")).resolve("lib/rt.jar").toString(),
+ "--classdir",
+ temporaryFolder.newFolder().toString()));
+
+ assertThat(result.output()).contains("class, interface, or enum expected");
+ assertThat(result.ok()).isFalse();
+ assertThat(Files.exists(output)).isFalse();
+ }
+}
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar/BUILD b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar/BUILD
index a587c7cb73..743a4933bd 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar/BUILD
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar/resourcejar/BUILD
@@ -1,7 +1,7 @@
filegroup(
name = "srcs",
srcs = glob(["**"]),
- visibility = ["//src/java_tools/buildjar:__pkg__"],
+ visibility = ["//src/java_tools/buildjar/javatests/com/google/devtools/build/buildjar:__pkg__"],
)
java_test(