aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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(