aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java
blob: 7ca29596a04224ea6d7877e9a4665c74cd5142f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2007 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 com.google.common.collect.ImmutableList;
import com.google.devtools.build.buildjar.javac.JavacOptions;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.classloader.ClassLoaderMaskingPlugin;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
import com.google.devtools.build.buildjar.javac.plugins.errorprone.ErrorPronePlugin;
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.util.Arrays;
import java.util.List;

/**
 * The JavaBuilder main called by bazel.
 */
public abstract class BazelJavaBuilder {

  private static final String CMDNAME = "BazelJavaBuilder";

  /**
   * The main method of the BazelJavaBuilder.
   */
  public static void main(String[] args) {
    if (args.length == 1 && args[0].equals("--persistent_worker")) {
      System.exit(runPersistentWorker());
    } else {
      // This is a single invocation of JavaBuilder that exits after it processed the request.
      System.exit(processRequest(Arrays.asList(args)));
    }
  }

  private static int runPersistentWorker() {
    PrintStream originalStdOut = System.out;
    PrintStream originalStdErr = System.err;

    while (true) {
      try {
        WorkRequest request = WorkRequest.parseDelimitedFrom(System.in);

        if (request == null) {
          break;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos, true);
        // Make sure that we exit nonzero in case an exception occurs during processRequest.
        int exitCode = 1;
        // TODO(philwo) - change this so that a PrintWriter can be passed in and will be used
        // instead of redirect stdout / stderr.
        System.setOut(ps);
        System.setErr(ps);
        try {
          exitCode = processRequest(request.getArgumentsList());
        } finally {
          System.setOut(originalStdOut);
          System.setErr(originalStdErr);
        }

        WorkResponse.newBuilder()
            .setOutput(baos.toString())
            .setExitCode(exitCode)
            .build()
            .writeDelimitedTo(System.out);
        System.out.flush();
      } catch (IOException e) {
        e.printStackTrace();
        return 1;
      } finally {
        // JavaBuilder doesn't close certain file handles. We have to migrate to using the real
        // Jsr199 API instead of just calling the Main method of Javac in order to fix this, for
        // now let's just invoke GC.
        System.gc();
      }
    }

    return 0;
  }

  private static int processRequest(List<String> args) {
    try {
      JavaLibraryBuildRequest build = parse(args);
      AbstractJavaBuilder builder = build.getDependencyModule().reduceClasspath()
          ? new ReducedClasspathJavaLibraryBuilder()
          : new SimpleJavaLibraryBuilder();
      builder.run(build, System.err);
    } catch (JavacException | InvalidCommandLineException e) {
      System.err.println(CMDNAME + " threw exception: " + e.getMessage());
      return 1;
    } catch (Exception e) {
      e.printStackTrace();
      return 1;
    }
    return 0;
  }

  /**
   * Parses the list of arguments into a {@link JavaLibraryBuildRequest}. The returned
   * {@link JavaLibraryBuildRequest} object can be then used to configure the compilation itself.
   *
   * @throws IOException if the argument list contains a file (with the @ prefix) and reading that
   *         file failed
   * @throws InvalidCommandLineException on any command line error
   */
  private static JavaLibraryBuildRequest parse(List<String> args) throws IOException,
      InvalidCommandLineException {
    ImmutableList<BlazeJavaCompilerPlugin> plugins =
        ImmutableList.<BlazeJavaCompilerPlugin>of(
            new ClassLoaderMaskingPlugin(),
            new ErrorPronePlugin());
    JavaLibraryBuildRequest build =
        new JavaLibraryBuildRequest(args, plugins, new DependencyModule.Builder());
    build.setJavacOpts(JavacOptions.normalizeOptions(build.getJavacOpts()));
    return build;
  }
}