aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java')
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java516
1 files changed, 516 insertions, 0 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
new file mode 100644
index 0000000000..9b899e50ef
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
@@ -0,0 +1,516 @@
+// Copyright 2014 Google Inc. 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 com.google.common.collect.ImmutableList;
+import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
+import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * All the information needed to perform a single Java library build operation.
+ */
+public final class JavaLibraryBuildRequest {
+ private boolean compressJar;
+
+ private final List<String> sourceFiles;
+ private final ImmutableList<String> sourceJars;
+ private final ImmutableList<String> messageFiles;
+ private final ImmutableList<String> resourceFiles;
+ private final ImmutableList<String> resourceJars;
+ /** Resource files that should be put in the root of the output jar. */
+ private final ImmutableList<String> rootResourceFiles;
+
+ private final String classPath;
+
+ private final String processorPath;
+ private final List<String> processorNames;
+
+ private final String classDir;
+ private final String tempDir;
+
+ private final String outputJar;
+
+ // Post processors
+ private final ImmutableList<AbstractPostProcessor> postProcessors;
+
+ private final ImmutableList<String> javacOpts;
+
+ /**
+ * Where to store source files generated by annotation processors.
+ */
+ private final String sourceGenDir;
+
+ /**
+ * The path to an output jar for source files generated by annotation processors.
+ */
+ private final String generatedSourcesOutputJar;
+
+ /**
+ * Repository for all dependency-related information.
+ */
+ private final DependencyModule dependencyModule;
+
+ /**
+ * List of plugins that are given to javac.
+ */
+ private final ImmutableList<BlazeJavaCompilerPlugin> plugins;
+
+ private JavaLibraryBuildRequest(
+ boolean compressJar,
+ List<String> sourceFiles, ImmutableList<String> sourceJars,
+ ImmutableList<String> messageFiles, ImmutableList<String> resourceFiles,
+ ImmutableList<String> resourceJars, ImmutableList<String> rootResourceFiles,
+ String classPath, String processorPath, List<String> processorNames, String classDir,
+ String tempDir, String outputJar, ImmutableList<AbstractPostProcessor> postProcessors,
+ ImmutableList<String> javacOpts, String sourceGenDir, String generatedSourcesOutputJar,
+ DependencyModule dependencyModule, ImmutableList<BlazeJavaCompilerPlugin> plugins) {
+ this.compressJar = compressJar;
+ this.sourceFiles = sourceFiles;
+ this.sourceJars = sourceJars;
+ this.messageFiles = messageFiles;
+ this.resourceFiles = resourceFiles;
+ this.resourceJars = resourceJars;
+ this.rootResourceFiles = rootResourceFiles;
+ this.classPath = classPath;
+ this.processorPath = processorPath;
+ this.processorNames = processorNames;
+ this.classDir = classDir;
+ this.tempDir = tempDir;
+ this.outputJar = outputJar;
+ this.postProcessors = postProcessors;
+ this.javacOpts = javacOpts;
+ this.sourceGenDir = sourceGenDir;
+ this.generatedSourcesOutputJar = generatedSourcesOutputJar;
+ this.dependencyModule = dependencyModule;
+ this.plugins = plugins;
+ }
+
+ public boolean compressJar() {
+ return compressJar;
+ }
+
+ public List<String> getSourceFiles() {
+ // TODO(bazel-team): This is being modified after parsing to add files from source jars.
+ return sourceFiles;
+ }
+
+ public ImmutableList<String> getSourceJars() {
+ return sourceJars;
+ }
+
+ public ImmutableList<String> getMessageFiles() {
+ return messageFiles;
+ }
+
+ public ImmutableList<String> getResourceFiles() {
+ return resourceFiles;
+ }
+
+ public ImmutableList<String> getResourceJars() {
+ return resourceJars;
+ }
+
+ public ImmutableList<String> getRootResourceFiles() {
+ return rootResourceFiles;
+ }
+
+ public String getClassPath() {
+ return classPath;
+ }
+
+ public String getProcessorPath() {
+ return processorPath;
+ }
+
+ public List<String> getProcessors() {
+ // TODO(bazel-team): This might be modified by a JavaLibraryBuilder to enable specific
+ // annotation processors.
+ return processorNames;
+ }
+
+ public String getClassDir() {
+ return classDir;
+ }
+
+ public String getTempDir() {
+ return tempDir;
+ }
+
+ public String getOutputJar() {
+ return outputJar;
+ }
+
+ public ImmutableList<String> getJavacOpts() {
+ return javacOpts;
+ }
+
+ public String getSourceGenDir() {
+ return sourceGenDir;
+ }
+
+ public String getGeneratedSourcesOutputJar() {
+ return generatedSourcesOutputJar;
+ }
+
+ public ImmutableList<AbstractPostProcessor> getPostProcessors() {
+ return postProcessors;
+ }
+
+ public ImmutableList<BlazeJavaCompilerPlugin> getPlugins() {
+ return plugins;
+ }
+
+ public DependencyModule getDependencyModule() {
+ return dependencyModule;
+ }
+
+ /**
+ * 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 file (with the @ prefix) and reading that
+ * file failed.
+ * @throws InvalidCommandLineException on any command line error
+ */
+ public static JavaLibraryBuildRequest parse(List<String> args) throws IOException,
+ InvalidCommandLineException {
+ return new JavaLibraryBuildRequest.Builder(args).build();
+ }
+
+ /**
+ * Builds a {@link JavaLibraryBuildRequest}.
+ */
+ public static final class Builder {
+ private boolean compressJar;
+
+ private final ImmutableList.Builder<String> sourceFiles = ImmutableList.builder();
+ private final ImmutableList.Builder<String> sourceJars = ImmutableList.builder();
+ private final ImmutableList.Builder<String> messageFiles = ImmutableList.builder();
+ private final ImmutableList.Builder<String> resourceFiles = ImmutableList.builder();
+ private final ImmutableList.Builder<String> resourceJars = ImmutableList.builder();
+ private final ImmutableList.Builder<String> rootResourceFiles = ImmutableList.builder();
+
+ private String classPath;
+
+ private String processorPath = "";
+ private final List<String> processorNames = new ArrayList<>();
+
+ // Since the default behavior of this tool with no arguments is
+ // "rm -fr <classDir>", let's not default to ".", shall we?
+ private String classDir = "classes";
+ private String tempDir = "_tmp";
+
+ private String outputJar;
+
+ private final ImmutableList.Builder<AbstractPostProcessor> postProcessors =
+ ImmutableList.builder();
+
+ private String ruleKind;
+ private String targetLabel;
+
+ private ImmutableList.Builder<String> javacOpts = ImmutableList.builder();
+
+ private String sourceGenDir;
+
+ private String generatedSourcesOutputJar;
+
+ private final DependencyModule dependencyModule;
+
+ private final ImmutableList.Builder<BlazeJavaCompilerPlugin> plugins = ImmutableList.builder();
+
+ /**
+ * Constructs a build from a list of command args. Sets the same JavacRunner
+ * for both compilation and annotation processing.
+ *
+ * @param args the list of command line args
+ * @throws InvalidCommandLineException on any command line error
+ */
+ public Builder(List<String> args) throws InvalidCommandLineException, IOException {
+ dependencyModule = processCommandlineArgs(expandArguments(args));
+ plugins.add(dependencyModule.getPlugin());
+ }
+
+ /**
+ * Constructs a build from a list of command args. Sets the same JavacRunner
+ * for both compilation and annotation processing.
+ *
+ * @param args the list of command line args
+ * @param extraPlugins extraneous plugins to use in addition to the strict dependency module.
+ * @throws InvalidCommandLineException on any command line error
+ */
+ public Builder(List<String> args, List<BlazeJavaCompilerPlugin> extraPlugins)
+ throws InvalidCommandLineException, IOException {
+ this(args);
+ plugins.addAll(extraPlugins);
+ }
+
+ public ImmutableList<String> getJavacOpts() {
+ return javacOpts.build();
+ }
+
+ public void setJavacOpts(List<String> javacOpts) {
+ this.javacOpts = ImmutableList.<String>builder().addAll(javacOpts);
+ }
+
+ public JavaLibraryBuildRequest build() {
+ ArrayList<String> sourceFiles = new ArrayList<>(this.sourceFiles.build());
+ ImmutableList<String> sourceJars = this.sourceJars.build();
+ ImmutableList<String> messageFiles = this.messageFiles.build();
+ ImmutableList<String> resourceFiles = this.resourceFiles.build();
+ ImmutableList<String> resourceJars = this.resourceJars.build();
+ ImmutableList<String> rootResourceFiles = this.rootResourceFiles.build();
+ ImmutableList<AbstractPostProcessor> postProcessors = this.postProcessors.build();
+ ImmutableList<String> javacOpts = this.javacOpts.build();
+ ImmutableList<BlazeJavaCompilerPlugin> plugins = this.plugins.build();
+ return new JavaLibraryBuildRequest(compressJar, sourceFiles, sourceJars, messageFiles,
+ resourceFiles, resourceJars, rootResourceFiles, classPath, processorPath, processorNames,
+ classDir, tempDir, outputJar, postProcessors, javacOpts, sourceGenDir,
+ generatedSourcesOutputJar, dependencyModule, plugins);
+ }
+
+ /**
+ * Processes the command line arguments.
+ *
+ * @throws InvalidCommandLineException on an invalid option being passed.
+ */
+ private DependencyModule processCommandlineArgs(Deque<String> argQueue)
+ throws InvalidCommandLineException {
+ DependencyModule.Builder builder = new DependencyModule.Builder();
+ for (String arg = argQueue.pollFirst(); arg != null; arg = argQueue.pollFirst()) {
+ switch (arg) {
+ case "--javacopts":
+ // Collect additional arguments to javac.
+ // Assumes that javac options do not start with "--".
+ // otherwise we have to do something like adding a "--"
+ // terminator to the passed arguments.
+ collectFlagArguments(javacOpts, argQueue, "--");
+ break;
+ case "--direct_dependency": {
+ String jar = getArgument(argQueue, arg);
+ String target = getArgument(argQueue, arg);
+ builder.addDirectMapping(jar, target);
+ break;
+ }
+ case "--indirect_dependency": {
+ String jar = getArgument(argQueue, arg);
+ String target = getArgument(argQueue, arg);
+ builder.addIndirectMapping(jar, target);
+ break;
+ }
+ case "--strict_java_deps":
+ builder.setStrictJavaDeps(getArgument(argQueue, arg));
+ break;
+ case "--output_deps":
+ builder.setOutputDepsFile(getArgument(argQueue, arg));
+ break;
+ case "--output_deps_proto":
+ builder.setOutputDepsProtoFile(getArgument(argQueue, arg));
+ break;
+ case "--deps_artifacts":
+ ImmutableList.Builder<String> depsArtifacts = ImmutableList.builder();
+ collectFlagArguments(depsArtifacts, argQueue, "--");
+ builder.addDepsArtifacts(depsArtifacts.build());
+ break;
+ case "--reduce_classpath":
+ builder.setReduceClasspath();
+ break;
+ case "--sourcegendir":
+ sourceGenDir = getArgument(argQueue, arg);
+ break;
+ case "--generated_sources_output":
+ generatedSourcesOutputJar = getArgument(argQueue, arg);
+ break;
+ default:
+ processArg(arg, argQueue);
+ }
+ }
+ builder.setRuleKind(ruleKind);
+ builder.setTargetLabel(targetLabel);
+ return builder.build();
+ }
+
+ /**
+ * Pre-processes an argument list, expanding options &at;filename to read in
+ * the content of the file and add it to the list of arguments.
+ *
+ * @param args the List of arguments to pre-process.
+ * @return the List of pre-processed arguments.
+ * @throws IOException if one of the files containing options cannot be read.
+ */
+ private static Deque<String> expandArguments(List<String> args) throws IOException {
+ Deque<String> expanded = new ArrayDeque<>(args.size());
+ for (String arg : args) {
+ expandArgument(expanded, arg);
+ }
+ return expanded;
+ }
+
+ /**
+ * Expands a single argument, expanding options &at;filename to read in the content of the file
+ * and add it to the list of processed arguments. The &at; itself can be escaped with &at;&at;.
+ *
+ * @param arg the argument to pre-process.
+ * @return the list of pre-processed arguments.
+ * @throws IOException if one of the files containing options cannot be read.
+ */
+ private static void expandArgument(Deque<String> expanded, String arg)
+ throws IOException {
+ if (arg.startsWith("@") && !arg.startsWith("@@")) {
+ for (String line : Files.readAllLines(Paths.get(arg.substring(1)), UTF_8)) {
+ if (line.length() > 0) {
+ expandArgument(expanded, line);
+ }
+ }
+ } else {
+ expanded.add(arg);
+ }
+ }
+
+ /**
+ * Collects the arguments for a command line flag until it finds a flag that starts with the
+ * terminatorPrefix.
+ *
+ * @param output where to put the collected flag arguments.
+ * @param args
+ * @param terminatorPrefix the terminator prefix to stop collecting of argument flags.
+ */
+ private static void collectFlagArguments(
+ ImmutableList.Builder<String> output, Deque<String> args, String terminatorPrefix) {
+ for (String arg = args.pollFirst(); arg != null; arg = args.pollFirst()) {
+ if (arg.startsWith(terminatorPrefix)) {
+ args.addFirst(arg);
+ break;
+ }
+ output.add(arg);
+ }
+ }
+
+ /**
+ * Collects the arguments for the --processors command line flag until it finds a flag that
+ * starts with the terminatorPrefix.
+ *
+ * @param output where to put the collected flag arguments.
+ * @param args
+ * @param terminatorPrefix the terminator prefix to stop collecting of argument flags.
+ */
+ private static void collectProcessorArguments(
+ List<String> output, Deque<String> args, String terminatorPrefix)
+ throws InvalidCommandLineException {
+ for (String arg = args.pollFirst(); arg != null; arg = args.pollFirst()) {
+ if (arg.startsWith(terminatorPrefix)) {
+ args.addFirst(arg);
+ break;
+ }
+ if (arg.contains(",")) {
+ throw new InvalidCommandLineException("processor argument may not contain commas: "
+ + arg);
+ }
+ output.add(arg);
+ }
+ }
+
+ private static String getArgument(Deque<String> args, String arg)
+ throws InvalidCommandLineException {
+ try {
+ return args.remove();
+ } catch (NoSuchElementException e) {
+ throw new InvalidCommandLineException(arg + ": missing argument");
+ }
+ }
+
+ private void processArg(String arg, Deque<String> args)
+ throws InvalidCommandLineException {
+ switch (arg) {
+ case "--sources":
+ collectFlagArguments(sourceFiles, args, "-");
+ break;
+ case "--source_jars":
+ collectFlagArguments(sourceJars, args, "-");
+ break;
+ case "--messages":
+ collectFlagArguments(messageFiles, args, "-");
+ break;
+ case "--resources":
+ collectFlagArguments(resourceFiles, args, "-");
+ break;
+ case "--resource_jars":
+ collectFlagArguments(resourceJars, args, "-");
+ break;
+ case "--classpath_resources":
+ collectFlagArguments(rootResourceFiles, args, "-");
+ break;
+ case "--classpath":
+ classPath = getArgument(args, arg);
+ break;
+ case "--processorpath":
+ processorPath = getArgument(args, arg);
+ break;
+ case "--processors":
+ collectProcessorArguments(processorNames, args, "-");
+ break;
+ case "--output":
+ outputJar = getArgument(args, arg);
+ break;
+ case "--classdir":
+ classDir = getArgument(args, arg);
+ break;
+ case "--tempdir":
+ tempDir = getArgument(args, arg);
+ break;
+ case "--gendir":
+ // TODO(bazel-team) - remove when Bazel no longer passes this flag to buildjar.
+ getArgument(args, arg);
+ break;
+ case "--post_processor":
+ addExternalPostProcessor(postProcessors, args, arg);
+ break;
+ case "--compress_jar":
+ compressJar = true;
+ break;
+ case "--rule_kind":
+ ruleKind = getArgument(args, arg);
+ break;
+ case "--target_label":
+ targetLabel = getArgument(args, arg);
+ break;
+ default:
+ throw new InvalidCommandLineException("unknown option : '" + arg + "'");
+ }
+ }
+
+ private void addExternalPostProcessor(ImmutableList.Builder<AbstractPostProcessor> output,
+ Deque<String> args, String arg) throws InvalidCommandLineException {
+ String processorName = getArgument(args, arg);
+ ImmutableList.Builder<String> arguments = ImmutableList.builder();
+ collectFlagArguments(arguments, args, "--");
+ // TODO(bazel-team): there is no check than the same post processor is not added twice.
+ // We should either forbid multiple add of the same post processor or use a processor factory
+ // to allow multiple add of the same post processor. Anyway, this binary is invoked by Blaze
+ // and not manually.
+ output.add(AbstractPostProcessor.create(processorName, arguments.build()));
+ }
+ }
+}