aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java_tools/singlejar/BUILD8
-rw-r--r--src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJar.java46
-rw-r--r--src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJarWorker.java97
3 files changed, 146 insertions, 5 deletions
diff --git a/src/java_tools/singlejar/BUILD b/src/java_tools/singlejar/BUILD
index e9a9a6d4b2..24c9ff50c1 100644
--- a/src/java_tools/singlejar/BUILD
+++ b/src/java_tools/singlejar/BUILD
@@ -19,6 +19,7 @@ java_library(
deps = [
"//src/java_tools/singlejar/java/com/google/devtools/build/zip",
"//src/main/java/com/google/devtools/build/lib:shell",
+ "//src/main/protobuf:worker_protocol_java_proto",
"//third_party:jsr305",
],
)
@@ -75,7 +76,12 @@ bootstrap_java_library(
bootstrap_java_binary(
name = "bootstrap",
- srcs = glob(["java/**/*.java"]) + ["//src/java_tools/singlejar/java/com/google/devtools/build/zip:java-srcs"],
+ srcs = glob(
+ ["java/**/*.java"],
+ exclude = ["java/**/SingleJarWorker.java"],
+ ) + [
+ "//src/java_tools/singlejar/java/com/google/devtools/build/zip:java-srcs",
+ ],
main_class = "com.google.devtools.build.singlejar.SingleJar",
visibility = ["//visibility:public"],
deps = [
diff --git a/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJar.java b/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJar.java
index 6dd20a4803..d99d84b7f6 100644
--- a/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJar.java
+++ b/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJar.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.singlejar;
import com.google.devtools.build.singlejar.DefaultJarEntryFilter.PathFilter;
import com.google.devtools.build.singlejar.ZipCombiner.OutputMode;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -31,7 +30,6 @@ import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
-
import javax.annotation.concurrent.NotThreadSafe;
/**
@@ -377,13 +375,53 @@ public class SingleJar {
allowedPaths = new PrefixListPathFilter(prefixes);
}
+ static int singleRun(String[] args) throws IOException {
+ SingleJar singlejar = new SingleJar(new JavaIoFileSystem());
+ return singlejar.run(Arrays.asList(args));
+ }
+
public static void main(String[] args) {
+ if (shouldRunInWorker(args)) {
+ if (!canRunInWorker()) {
+ System.err.println("Asked to run in a worker, but no worker support");
+ System.exit(1);
+ }
+ try {
+ runWorker(args);
+ } catch (Exception e) {
+ System.err.println("Error running worker : " + e.getMessage());
+ System.exit(1);
+ }
+ return;
+ }
+
try {
- SingleJar singlejar = new SingleJar(new JavaIoFileSystem());
- System.exit(singlejar.run(Arrays.asList(args)));
+ System.exit(singleRun(args));
} catch (IOException e) {
System.err.println("SingleJar threw exception : " + e.getMessage());
System.exit(1);
}
}
+
+ private static void runWorker(String[] args) throws Exception {
+ // Invocation is done through reflection so that this code will work in bazel open source
+ // as well. SingleJar is used for bootstrap and thus can not depend on protos (used in
+ // SingleJarWorker).
+ Class<?> workerClass = Class.forName("com.google.devtools.build.singlejar.SingleJarWorker");
+ workerClass.getMethod("main", String[].class).invoke(null, (Object) args);
+ }
+
+ private static boolean shouldRunInWorker(String[] args) {
+ return Arrays.asList(args).contains("--persistent_worker");
+ }
+
+ private static boolean canRunInWorker() {
+ try {
+ Class.forName("com.google.devtools.build.singlejar.SingleJarWorker");
+ return true;
+ } catch (ClassNotFoundException e1) {
+ return false;
+ }
+ }
+
}
diff --git a/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJarWorker.java b/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJarWorker.java
new file mode 100644
index 0000000000..499192fada
--- /dev/null
+++ b/src/java_tools/singlejar/java/com/google/devtools/build/singlejar/SingleJarWorker.java
@@ -0,0 +1,97 @@
+// Copyright 2016 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.singlejar;
+
+import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest;
+import com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * A blaze worker to run {@link SingleJar} in a warm JVM process.
+ */
+public class SingleJarWorker {
+
+ public static void main(String[] args) {
+ new SingleJarWorker().runWorker();
+ }
+
+ private PrintStream originalStdout;
+ private PrintStream originalSterr;
+ private ByteArrayOutputStream stdoutAndStderr;
+
+ private void runWorker() {
+ trapOutputs();
+
+ try {
+ dispatchWorkRequestsForever();
+ } catch (IOException e) {
+ // IOException will only occur if System.in has been closed
+ // In that case we silently exit our process
+ }
+ }
+
+ private void trapOutputs() {
+ originalStdout = System.out;
+ originalSterr = System.err;
+ stdoutAndStderr = new ByteArrayOutputStream();
+ System.setErr(new PrintStream(stdoutAndStderr, true));
+ System.setOut(new PrintStream(stdoutAndStderr, true));
+ }
+
+ private void dispatchWorkRequestsForever() throws IOException {
+ while (true) {
+ WorkRequest workRequest = WorkRequest.parseDelimitedFrom(System.in);
+
+ String[] args = workRequest.getArgumentsList().toArray(new String[0]);
+
+ int returnCode = runSingleJar(args);
+
+ outputResult(returnCode);
+ }
+ }
+
+ private void outputResult(int returnCode) throws IOException {
+ WorkResponse.newBuilder()
+ .setExitCode(returnCode)
+ .setOutput(new String(stdoutAndStderr.toByteArray(), StandardCharsets.UTF_8))
+ .build()
+ .writeDelimitedTo(originalStdout);
+
+ // Reset output streams, we are not simply calling reset on the BAOS since this will
+ // still keep the full buffer allocated.
+ stdoutAndStderr = new ByteArrayOutputStream();
+ System.setErr(new PrintStream(stdoutAndStderr, true));
+ System.setOut(new PrintStream(stdoutAndStderr, true));
+ }
+
+ private int runSingleJar(String[] args) {
+ try {
+ return SingleJar.singleRun(args);
+ } catch (IOException e) {
+ // Some IO failures are okay no need to quit the worker
+ System.err.println("SingleJar threw exception : " + e.getMessage());
+ return 1;
+ } catch (Exception e) {
+ // We had an actual unexpected error, lets quit the worker
+ originalSterr.println("SingleJar threw an unexpected exception : " + e.getMessage());
+ e.printStackTrace(originalSterr);
+ System.exit(1);
+ return 1;
+ }
+ }
+}