Prepare JavaBuilder to accept an Aspect's name, in addition to a label, of the owner of a jar.

The motivation is strict-deps checking for Aspected rules such as java_proto_library. With this additional information, JavaBuilder will be able to better tell the user which rule is missing in the 'deps' attribute of the target being built.

Note that the AspectParameters aren't passed right now, because (1) serializing them adds complexity and (2) they're unneeded for JavaBuilder right now.

--
MOS_MIGRATED_REVID=127993845
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 c9c6b24..ee748b3 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
@@ -17,6 +17,10 @@
         "InvalidCommandLineException.java",
         "OptionsParser.java",
     ],
+    deps = [
+        ":JarOwner",
+        "//third_party:guava",
+    ],
 )
 
 java_library(
@@ -40,9 +44,11 @@
         ["*.java"],
         exclude = [
             "InvalidCommandLineException.java",
+            "JarOwner.java",
         ],
     ),
     deps = [
+        ":JarOwner",
         ":invalid_command_line_exception",
         ":javac",
         "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper",
@@ -86,6 +92,21 @@
     deps = [],
 )
 
+java_library(
+    name = "JarOwner",
+    srcs = ["JarOwner.java"],
+    visibility = [
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:__subpackages__",
+        "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine:__subpackages__",
+        "//src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine:__subpackages__",
+    ],
+    deps = [
+        "//third_party:auto_value",
+        "//third_party:guava",
+        "//third_party:jsr305",
+    ],
+)
+
 load("//tools/build_rules:java_rules_skylark.bzl", "bootstrap_java_library", "bootstrap_java_binary")
 
 bootstrap_java_library(
@@ -113,7 +134,10 @@
     name = "bootstrap",
     srcs = glob(
         ["**/*.java"],
-        exclude = ["java/com/google/devtools/build/buildjar/javac/testing/**"],
+        exclude = [
+            "java/com/google/devtools/build/buildjar/javac/testing/**",
+            "JarOwner.java",
+        ],
     ),
     main_class = "com.google.devtools.build.buildjar.BazelJavaBuilder",
     deps = [
@@ -123,6 +147,16 @@
     ],
 )
 
+bootstrap_java_library(
+    name = "bootstrap_JarOwner",
+    srcs = ["JarOwner.java"],
+    jars = [
+        "//third_party:jsr305-jars",
+        "//third_party:auto_value-jars",
+        "//third_party:guava-jars",
+    ],
+)
+
 filegroup(
     name = "srcs",
     srcs = glob(["**"]) + [
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JarOwner.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JarOwner.java
new file mode 100644
index 0000000..5c96d79
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JarOwner.java
@@ -0,0 +1,52 @@
+// 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.buildjar;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Function;
+import javax.annotation.Nullable;
+
+/**
+ * Holds information about the Bazel rule that created a certain jar.
+ *
+ * <p>Rules that use Aspects (http://www.bazel.io/docs/skylark/aspects.html) to compile jars will
+ * result in 'aspect()' being populated.
+ */
+@AutoValue
+public abstract class JarOwner {
+
+  /** A long way to say 'JarOwner::label'. */
+  public static final Function<JarOwner, String> LABEL =
+      new Function<JarOwner, String>() {
+        @Nullable
+        @Override
+        public String apply(@Nullable JarOwner jarOwner) {
+          return jarOwner == null ? null : jarOwner.label();
+        }
+      };
+
+  public abstract String label();
+
+  @Nullable
+  public abstract String aspect();
+
+  public static JarOwner create(String label) {
+    return new AutoValue_JarOwner(label, null);
+  }
+
+  public static JarOwner create(String label, String aspect) {
+    return new AutoValue_JarOwner(label, aspect);
+  }
+}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java
index 987b809..5b0a10d 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java
@@ -16,6 +16,8 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
@@ -36,10 +38,11 @@
  * command-line flags and options files and provides them via getters.
  */
 public final class OptionsParser {
+  private static final Splitter SPACE_SPLITTER = Splitter.on(' ');
   private final List<String> javacOpts = new ArrayList<>();
 
-  private final Map<String, String> directJarsToTargets = new HashMap<>();
-  private final Map<String, String> indirectJarsToTargets = new HashMap<>();
+  private final Map<String, JarOwner> directJarsToTargets = new HashMap<>();
+  private final Map<String, JarOwner> indirectJarsToTargets = new HashMap<>();
 
   private String strictJavaDeps;
 
@@ -108,15 +111,15 @@
         case "--direct_dependency":
           {
             String jar = getArgument(argQueue, arg);
-            String target = getArgument(argQueue, arg);
-            directJarsToTargets.put(jar, target);
+            JarOwner owner = parseJarOwner(getArgument(argQueue, arg));
+            directJarsToTargets.put(jar, owner);
             break;
           }
         case "--indirect_dependency":
           {
             String jar = getArgument(argQueue, arg);
-            String target = getArgument(argQueue, arg);
-            indirectJarsToTargets.put(jar, target);
+            JarOwner owner = parseJarOwner(getArgument(argQueue, arg));
+            indirectJarsToTargets.put(jar, owner);
             break;
           }
         case "--strict_java_deps":
@@ -204,6 +207,18 @@
     }
   }
 
+  private JarOwner parseJarOwner(String line) {
+    List<String> ownerStringParts = SPACE_SPLITTER.splitToList(line);
+    JarOwner owner;
+    Preconditions.checkState(ownerStringParts.size() == 1 || ownerStringParts.size() == 2);
+    if (ownerStringParts.size() == 1) {
+      owner = JarOwner.create(ownerStringParts.get(0));
+    } else {
+      owner = JarOwner.create(ownerStringParts.get(0), ownerStringParts.get(1));
+    }
+    return owner;
+  }
+
   /**
    * Pre-processes an argument list, expanding options @filename to read in
    * the content of the file and add it to the list of arguments.
@@ -302,11 +317,11 @@
     return javacOpts;
   }
 
-  public Map<String, String> getDirectMappings() {
+  public Map<String, JarOwner> getDirectMappings() {
     return directJarsToTargets;
   }
 
-  public Map<String, String> getIndirectMappings() {
+  public Map<String, JarOwner> getIndirectMappings() {
     return indirectJarsToTargets;
   }
 
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/BUILD
index 4ae7b1f..f3ae58e 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/BUILD
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/BUILD
@@ -25,6 +25,7 @@
     srcs = glob(["dependency/*.java"]),
     deps = [
         ":plugins",
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:JarOwner",
         "//src/main/protobuf:deps_java_proto",
         "//third_party:guava",
         "//third_party/java/jdk/langtools:javac",
@@ -76,6 +77,7 @@
         ["**/*.java"],
     ),
     deps = [
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:bootstrap_JarOwner",
         "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:bootstrap_invalid_command_line_exception",
         "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:skylark-deps",
     ],
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/DependencyModule.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/DependencyModule.java
index 974bec3..98f9f66 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/DependencyModule.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/DependencyModule.java
@@ -18,10 +18,10 @@
 import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
 import com.google.common.base.Verify;
+import com.google.devtools.build.buildjar.JarOwner;
 import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
 import com.google.devtools.build.lib.view.proto.Deps;
 import com.google.devtools.build.lib.view.proto.Deps.Dependency.Kind;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
@@ -68,8 +68,8 @@
   }
 
   private final StrictJavaDeps strictJavaDeps;
-  private final Map<String, String> directJarsToTargets;
-  private final Map<String, String> indirectJarsToTargets;
+  private final Map<String, JarOwner> directJarsToTargets;
+  private final Map<String, JarOwner> indirectJarsToTargets;
   private final boolean strictClasspathMode;
   private final Set<String> depsArtifacts;
   private final String ruleKind;
@@ -82,16 +82,17 @@
   private final String fixMessage;
   private final Set<String> exemptGenerators;
 
-  DependencyModule(StrictJavaDeps strictJavaDeps,
-                   Map<String, String> directJarsToTargets,
-                   Map<String, String> indirectJarsToTargets,
-                   boolean strictClasspathMode,
-                   Set<String> depsArtifacts,
-                   String ruleKind,
-                   String targetLabel,
-                   String outputDepsProtoFile,
-                   String fixMessage,
-                   Set<String> exemptGenerators) {
+  DependencyModule(
+      StrictJavaDeps strictJavaDeps,
+      Map<String, JarOwner> directJarsToTargets,
+      Map<String, JarOwner> indirectJarsToTargets,
+      boolean strictClasspathMode,
+      Set<String> depsArtifacts,
+      String ruleKind,
+      String targetLabel,
+      String outputDepsProtoFile,
+      String fixMessage,
+      Set<String> exemptGenerators) {
     this.strictJavaDeps = strictJavaDeps;
     this.directJarsToTargets = directJarsToTargets;
     this.indirectJarsToTargets = indirectJarsToTargets;
@@ -160,18 +161,18 @@
   }
 
   /**
-   * Returns the mapping for jars of direct dependencies. The keys are full
-   * paths (as seen on the classpath), and the values are build target names.
+   * Returns the mapping for jars of direct dependencies. The keys are full paths (as seen on the
+   * classpath), and the values are build target names.
    */
-  public Map<String, String> getDirectMapping() {
+  public Map<String, JarOwner> getDirectMapping() {
     return directJarsToTargets;
   }
 
   /**
-   * Returns the mapping for jars of indirect dependencies. The keys are full
-   * paths (as seen on the classpath), and the values are build target names.
+   * Returns the mapping for jars of indirect dependencies. The keys are full paths (as seen on the
+   * classpath), and the values are build target names.
    */
-  public Map<String, String> getIndirectMapping() {
+  public Map<String, JarOwner> getIndirectMapping() {
     return indirectJarsToTargets;
   }
 
@@ -315,8 +316,8 @@
   public static class Builder {
 
     private StrictJavaDeps strictJavaDeps = StrictJavaDeps.OFF;
-    private final Map<String, String> directJarsToTargets = new HashMap<>();
-    private final Map<String, String> indirectJarsToTargets = new HashMap<>();
+    private final Map<String, JarOwner> directJarsToTargets = new HashMap<>();
+    private final Map<String, JarOwner> indirectJarsToTargets = new HashMap<>();
     private final Set<String> depsArtifacts = new HashSet<>();
     private String ruleKind;
     private String targetLabel;
@@ -381,25 +382,13 @@
     }
 
     /**
-     * Adds a direct mapping to the existing map for direct dependencies.
-     *
-     * @param jar path of jar artifact, as seen on classpath.
-     * @param target full name of build target providing the jar.
-     * @return this Builder instance.
-     */
-    public Builder addDirectMapping(String jar, String target) {
-      directJarsToTargets.put(jar, target);
-      return this;
-    }
-
-    /**
      * Adds direct mappings to the existing map for direct dependencies.
      *
      * @param directMappings a map of paths of jar artifacts, as seen on classpath, to full names of
      *     build targets providing the jar.
      * @return this Builder instance
      */
-    public Builder addDirectMappings(Map<String, String> directMappings) {
+    public Builder addDirectMappings(Map<String, JarOwner> directMappings) {
       directJarsToTargets.putAll(directMappings);
       return this;
     }
@@ -411,7 +400,7 @@
      * @param target full name of build target providing the jar.
      * @return this Builder instance
      */
-    public Builder addIndirectMapping(String jar, String target) {
+    public Builder addIndirectMapping(String jar, JarOwner target) {
       indirectJarsToTargets.put(jar, target);
       return this;
     }
@@ -423,7 +412,7 @@
      *     of build targets providing the jar.
      * @return this Builder instance
      */
-    public Builder addIndirectMappings(Map<String, String> indirectMappings) {
+    public Builder addIndirectMappings(Map<String, JarOwner> indirectMappings) {
       indirectJarsToTargets.putAll(indirectMappings);
       return this;
     }
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
index d00bdd8..a32976e 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
@@ -18,11 +18,12 @@
 import static com.google.devtools.build.buildjar.javac.plugins.dependency.ImplicitDependencyExtractor.getPlatformJars;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.buildjar.JarOwner;
 import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
 import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule.StrictJavaDeps;
 import com.google.devtools.build.lib.view.proto.Deps;
 import com.google.devtools.build.lib.view.proto.Deps.Dependency;
-
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Kinds;
 import com.sun.tools.javac.code.Symbol;
@@ -35,7 +36,6 @@
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Log.WriterKind;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
@@ -44,8 +44,6 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.TreeSet;
-
 import javax.annotation.Generated;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
@@ -75,7 +73,7 @@
   private final Set<JCTree> trees;
 
   /** Computed missing dependencies */
-  private final Set<String> missingTargets;
+  private final Set<JarOwner> missingTargets;
 
   private static Properties targetMap;
 
@@ -100,7 +98,7 @@
     toplevels = new HashSet<>();
     trees = new HashSet<>();
     targetMap = new Properties();
-    missingTargets = new TreeSet<>();
+    missingTargets = new HashSet<>();
   }
 
   @Override
@@ -161,8 +159,9 @@
 
     if (!missingTargets.isEmpty()) {
       StringBuilder missingTargetsStr = new StringBuilder();
-      for (String target : missingTargets) {
-        missingTargetsStr.append(target);
+      for (JarOwner owner :
+          Ordering.natural().onResultOf(JarOwner.LABEL).immutableSortedCopy(missingTargets)) {
+        missingTargetsStr.append(canonicalizeTarget(owner.label()));
         missingTargetsStr.append(" ");
       }
       String canonicalizedLabel;
@@ -189,12 +188,12 @@
    */
   private static class CheckingTreeScanner extends TreeScanner {
 
-    private static final String transitiveDepMessage =
+    private static final String TRANSITIVE_DEP_MESSAGE =
         "[strict] Using type {0} from an indirect dependency (TOOL_INFO: \"{1}\"). "
             + "See command below **";
 
     /** Lookup for jars coming from transitive dependencies */
-    private final Map<String, String> indirectJarsToTargets;
+    private final Map<String, JarOwner> indirectJarsToTargets;
 
     /** All error reporting is done through javac's log, */
     private final Log log;
@@ -206,14 +205,14 @@
     private final StrictJavaDeps strictJavaDepsMode;
 
     /** Missing targets */
-    private final Set<String> missingTargets;
+    private final Set<JarOwner> missingTargets;
 
     /** Collect seen direct dependencies and their associated information */
     private final Map<String, Deps.Dependency> directDependenciesMap;
 
     /** We only emit one warning/error per class symbol */
     private final Set<ClassSymbol> seenClasses = new HashSet<>();
-    private final Set<String> seenTargets = new HashSet<>();
+    private final Set<JarOwner> seenTargets = new HashSet<>();
 
     /** The set of jars on the compilation bootclasspath. */
     private final Set<String> platformJars;
@@ -224,8 +223,12 @@
     /** Was the node being visited generated by an exempt annotation processor? */
     private boolean isStrictDepsExempt = false;
 
-    public CheckingTreeScanner(DependencyModule dependencyModule, Log log,
-        Set<String> missingTargets, Set<String> platformJars, JavaFileManager fileManager) {
+    public CheckingTreeScanner(
+        DependencyModule dependencyModule,
+        Log log,
+        Set<JarOwner> missingTargets,
+        Set<String> platformJars,
+        JavaFileManager fileManager) {
       this.indirectJarsToTargets = dependencyModule.getIndirectMapping();
       this.strictJavaDepsMode = dependencyModule.getStrictJavaDeps();
       this.log = log;
@@ -266,18 +269,27 @@
      */
     private void collectExplicitDependency(String jarName, JCTree node, Symbol.TypeSymbol sym) {
       if (strictJavaDepsMode.isEnabled() && !isStrictDepsExempt) {
-        // Does it make sense to emit a warning/error for this pair of (type, target)?
-        // We want to emit only one error/warning per target.
-        String target = indirectJarsToTargets.get(jarName);
-        if (target != null && seenTargets.add(target)) {
-          String canonicalTargetName = canonicalizeTarget(target);
-          missingTargets.add(canonicalTargetName);
+        // Does it make sense to emit a warning/error for this pair of (type, owner)?
+        // We want to emit only one error/warning per owner.
+        JarOwner owner = indirectJarsToTargets.get(jarName);
+        if (owner != null && seenTargets.add(owner)) {
+          // owner is of the form "//label/of:rule <Aspect name>" where <Aspect name> is optional.
+          String canonicalTargetName = canonicalizeTarget(owner.label());
+          missingTargets.add(owner);
+          String toolInfo =
+              owner.aspect() == null
+                  ? canonicalTargetName
+                  : String.format("%s with aspect %s", canonicalTargetName, owner.aspect());
           if (strictJavaDepsMode == ERROR) {
-            log.error(node.pos, "proc.messager",
-                MessageFormat.format(transitiveDepMessage, sym, canonicalTargetName));
+            log.error(
+                node.pos,
+                "proc.messager",
+                MessageFormat.format(TRANSITIVE_DEP_MESSAGE, sym, toolInfo));
           } else {
-            log.warning(node.pos, "proc.messager",
-                MessageFormat.format(transitiveDepMessage, sym, canonicalTargetName));
+            log.warning(
+                node.pos,
+                "proc.messager",
+                MessageFormat.format(TRANSITIVE_DEP_MESSAGE, sym, toolInfo));
           }
         }
       }
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/BUILD
index 567080e..5253ec4 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/BUILD
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/BUILD
@@ -18,6 +18,7 @@
     name = "turbine_options",
     srcs = ["TurbineOptions.java"],
     deps = [
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:JarOwner",
         "//third_party:guava",
         "//third_party:jsr305",
     ],
@@ -28,6 +29,7 @@
     srcs = ["TurbineOptionsParser.java"],
     deps = [
         ":turbine_options",
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:JarOwner",
         "//third_party:guava",
         "//third_party:jsr305",
     ],
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptions.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptions.java
index 84c7e7c..7aa4e7e 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptions.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptions.java
@@ -20,7 +20,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-
+import com.google.devtools.build.buildjar.JarOwner;
 import javax.annotation.Nullable;
 
 /** Header compilation options. */
@@ -36,8 +36,8 @@
   private final String tempDir;
   private final ImmutableList<String> sourceJars;
   private final Optional<String> outputDeps;
-  private final ImmutableMap<String, String> directJarsToTargets;
-  private final ImmutableMap<String, String> indirectJarsToTargets;
+  private final ImmutableMap<String, JarOwner> directJarsToTargets;
+  private final ImmutableMap<String, JarOwner> indirectJarsToTargets;
   private final Optional<String> targetLabel;
   private final ImmutableList<String> depsArtifacts;
   private final Optional<String> ruleKind;
@@ -54,8 +54,8 @@
       String tempDir,
       ImmutableList<String> sourceJars,
       @Nullable String outputDeps,
-      ImmutableMap<String, String> directJarsToTargets,
-      ImmutableMap<String, String> indirectJarsToTargets,
+      ImmutableMap<String, JarOwner> directJarsToTargets,
+      ImmutableMap<String, JarOwner> indirectJarsToTargets,
       @Nullable String targetLabel,
       ImmutableList<String> depsArtifacts,
       @Nullable String ruleKind,
@@ -135,12 +135,12 @@
   }
 
   /** The mapping from the path to a direct dependency to its build label. */
-  public ImmutableMap<String, String> directJarsToTargets() {
+  public ImmutableMap<String, JarOwner> directJarsToTargets() {
     return directJarsToTargets;
   }
 
   /** The mapping from the path to an indirect dependency to its build label. */
-  public ImmutableMap<String, String> indirectJarsToTargets() {
+  public ImmutableMap<String, JarOwner> indirectJarsToTargets() {
     return indirectJarsToTargets;
   }
 
@@ -181,8 +181,9 @@
     private final ImmutableList.Builder<String> sourceJars = ImmutableList.builder();
     private final ImmutableList.Builder<String> bootClassPath = ImmutableList.builder();
     private String outputDeps;
-    private final ImmutableMap.Builder<String, String> directJarsToTargets = ImmutableMap.builder();
-    private final ImmutableMap.Builder<String, String> indirectJarsToTargets =
+    private final ImmutableMap.Builder<String, JarOwner> directJarsToTargets =
+        ImmutableMap.builder();
+    private final ImmutableMap.Builder<String, JarOwner> indirectJarsToTargets =
         ImmutableMap.builder();
     @Nullable private String targetLabel;
     private final ImmutableList.Builder<String> depsArtifacts = ImmutableList.builder();
@@ -259,12 +260,12 @@
       return this;
     }
 
-    public Builder addDirectJarToTarget(String jar, String target) {
+    public Builder addDirectJarToTarget(String jar, JarOwner target) {
       directJarsToTargets.put(jar, target);
       return this;
     }
 
-    public Builder addIndirectJarToTarget(String jar, String target) {
+    public Builder addIndirectJarToTarget(String jar, JarOwner target) {
       indirectJarsToTargets.put(jar, target);
       return this;
     }
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptionsParser.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptionsParser.java
index a3b4723..5ef5bbe 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptionsParser.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/TurbineOptionsParser.java
@@ -17,20 +17,22 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.common.base.CharMatcher;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
-
+import com.google.devtools.build.buildjar.JarOwner;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayDeque;
 import java.util.Deque;
-
+import java.util.List;
 import javax.annotation.Nullable;
 
 /** A command line options parser for {@link TurbineOptions}. */
 public class TurbineOptionsParser {
+  private static final Splitter SPACE_SPLITTER = Splitter.on(' ');
 
   /**
    * Parses command line options into {@link TurbineOptions}, expanding any {@code @params}
@@ -115,14 +117,14 @@
           {
             String jar = readOne(argumentDeque);
             String target = readOne(argumentDeque);
-            builder.addDirectJarToTarget(jar, target);
+            builder.addDirectJarToTarget(jar, parseJarOwner(target));
             break;
           }
         case "--indirect_dependency":
           {
             String jar = readOne(argumentDeque);
             String target = readOne(argumentDeque);
-            builder.addIndirectJarToTarget(jar, target);
+            builder.addIndirectJarToTarget(jar, parseJarOwner(target));
             break;
           }
         case "--deps_artifacts":
@@ -142,6 +144,18 @@
     }
   }
 
+  private static JarOwner parseJarOwner(String line) {
+    List<String> ownerStringParts = SPACE_SPLITTER.splitToList(line);
+    JarOwner owner;
+    Preconditions.checkState(ownerStringParts.size() == 1 || ownerStringParts.size() == 2);
+    if (ownerStringParts.size() == 1) {
+      owner = JarOwner.create(ownerStringParts.get(0));
+    } else {
+      owner = JarOwner.create(ownerStringParts.get(0), ownerStringParts.get(1));
+    }
+    return owner;
+  }
+
   /** Returns the value of an option, or {@code null}. */
   @Nullable
   private static String readOne(Deque<String> argumentDeque) {
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/BUILD b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/BUILD
index 317b03b..32c3611 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/BUILD
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/BUILD
@@ -16,6 +16,7 @@
     srcs = ["TurbineOptionsTest.java"],
     tags = ["jdk8"],
     deps = [
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:JarOwner",
         "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine:turbine_options",
         "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine:turbine_options_parser",
         "//third_party:guava",
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/TurbineOptionsTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/TurbineOptionsTest.java
index a29ed27..ef2fa0e 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/TurbineOptionsTest.java
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/TurbineOptionsTest.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
 
+import com.google.devtools.build.buildjar.JarOwner;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
@@ -129,12 +130,13 @@
 
     assertThat(options.targetLabel()).hasValue("//java/com/google/test");
     assertThat(options.directJarsToTargets())
-        .containsExactlyEntriesIn(ImmutableMap.of("blaze-out/foo/libbar.jar", "//foo/bar"));
+        .containsExactlyEntriesIn(
+            ImmutableMap.of("blaze-out/foo/libbar.jar", JarOwner.create("//foo/bar")));
     assertThat(options.indirectJarsToTargets())
         .containsExactlyEntriesIn(
             ImmutableMap.of(
-                "blaze-out/foo/libbaz1.jar", "//foo/baz1",
-                "blaze-out/foo/libbaz2.jar", "//foo/baz2"));
+                "blaze-out/foo/libbaz1.jar", JarOwner.create("//foo/baz1"),
+                "blaze-out/foo/libbaz2.jar", JarOwner.create("//foo/baz2")));
     assertThat(options.depsArtifacts()).containsExactly("foo.jdeps", "bar.jdeps");
   }
 
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
index 2127783..9e2cd2b 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
@@ -16,6 +16,7 @@
     ],
     tags = ["jdk8"],
     deps = [
+        "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:JarOwner",
         "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine:turbine_options",
         "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac:javac_turbine",
         "//src/main/protobuf:deps_java_proto",
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
index 0f20f16..d657ab0 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
@@ -24,11 +24,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.io.ByteStreams;
+import com.google.devtools.build.buildjar.JarOwner;
 import com.google.devtools.build.java.turbine.TurbineOptions;
 import com.google.devtools.build.java.turbine.javac.JavacTurbine.Result;
 import com.google.devtools.build.lib.view.proto.Deps;
 import com.google.devtools.build.lib.view.proto.Deps.Dependency;
-
 import com.sun.source.tree.LiteralTree;
 import com.sun.source.util.JavacTask;
 import com.sun.source.util.TaskEvent;
@@ -39,17 +39,6 @@
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.util.Textifier;
-import org.objectweb.asm.util.TraceClassVisitor;
-
 import java.io.BufferedInputStream;
 import java.io.IOError;
 import java.io.IOException;
@@ -75,7 +64,6 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
-
 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.annotation.processing.RoundEnvironment;
@@ -88,6 +76,15 @@
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
 import javax.tools.StandardLocation;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.util.Textifier;
+import org.objectweb.asm.util.TraceClassVisitor;
 
 /** Unit tests for {@link JavacTurbine}. */
 @RunWith(JUnit4.class)
@@ -408,9 +405,9 @@
     optionsBuilder.addClassPathEntries(
         ImmutableList.of(libA.toString(), libB.toString(), libC.toString()));
     optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
-    optionsBuilder.addDirectJarToTarget(libA.toString(), "//lib:a");
-    optionsBuilder.addDirectJarToTarget(libB.toString(), "//lib:b");
-    optionsBuilder.addIndirectJarToTarget(libC.toString(), "//lib:c");
+    optionsBuilder.addDirectJarToTarget(libA.toString(), JarOwner.create("//lib:a"));
+    optionsBuilder.addDirectJarToTarget(libB.toString(), JarOwner.create("//lib:b"));
+    optionsBuilder.addIndirectJarToTarget(libC.toString(), JarOwner.create("//lib:c"));
     optionsBuilder.setTargetLabel("//my:target");
 
     addSourceLines(
@@ -543,10 +540,10 @@
     optionsBuilder.addClassPathEntries(
         ImmutableList.of(libA.toString(), libB.toString(), libC.toString(), libD.toString()));
     optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
-    optionsBuilder.addDirectJarToTarget(libA.toString(), "//lib:a");
-    optionsBuilder.addIndirectJarToTarget(libB.toString(), "//lib:b");
-    optionsBuilder.addIndirectJarToTarget(libC.toString(), "//lib:c");
-    optionsBuilder.addIndirectJarToTarget(libD.toString(), "//lib:d");
+    optionsBuilder.addDirectJarToTarget(libA.toString(), JarOwner.create("//lib:a"));
+    optionsBuilder.addIndirectJarToTarget(libB.toString(), JarOwner.create("//lib:b"));
+    optionsBuilder.addIndirectJarToTarget(libC.toString(), JarOwner.create("//lib:c"));
+    optionsBuilder.addIndirectJarToTarget(libD.toString(), JarOwner.create("//lib:d"));
     optionsBuilder.setTargetLabel("//my:target");
 
     addSourceLines(
@@ -635,10 +632,10 @@
     optionsBuilder.addClassPathEntries(
         ImmutableList.of(libA.toString(), libB.toString(), libC.toString(), libD.toString()));
     optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
-    optionsBuilder.addDirectJarToTarget(libA.toString(), "//lib:a");
-    optionsBuilder.addIndirectJarToTarget(libB.toString(), "//lib:b");
-    optionsBuilder.addIndirectJarToTarget(libC.toString(), "//lib:c");
-    optionsBuilder.addIndirectJarToTarget(libD.toString(), "//lib:d");
+    optionsBuilder.addDirectJarToTarget(libA.toString(), JarOwner.create("//lib:a"));
+    optionsBuilder.addIndirectJarToTarget(libB.toString(), JarOwner.create("//lib:b"));
+    optionsBuilder.addIndirectJarToTarget(libC.toString(), JarOwner.create("//lib:c"));
+    optionsBuilder.addIndirectJarToTarget(libD.toString(), JarOwner.create("//lib:d"));
     optionsBuilder.setTargetLabel("//my:target");
 
     addSourceLines(
@@ -1231,7 +1228,7 @@
         "}");
 
     optionsBuilder.addClassPathEntries(Collections.singleton(deps.toString()));
-    optionsBuilder.addDirectJarToTarget(deps.toString(), "//deps");
+    optionsBuilder.addDirectJarToTarget(deps.toString(), JarOwner.create("//deps"));
 
     compile();
     Map<String, byte[]> outputs = collectOutputs();
@@ -1252,7 +1249,7 @@
         "import " + Lib.class.getCanonicalName() + ";",
         "class Hello extends Lib {}");
 
-    optionsBuilder.addIndirectJarToTarget(lib.toString(), "//lib");
+    optionsBuilder.addIndirectJarToTarget(lib.toString(), JarOwner.create("//lib"));
     optionsBuilder.addClassPathEntries(ImmutableList.of(lib.toString()));
 
     optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));
diff --git a/third_party/BUILD b/third_party/BUILD
index 87c45bf..bedcb02 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -220,6 +220,12 @@
     jars = ["auto/auto-value-1.2.jar"],
 )
 
+# For bootstrapping JavaBuilder
+filegroup(
+    name = "auto_value-jars",
+    srcs = ["auto/auto-value-1.2.jar"],
+)
+
 java_library(
     name = "dagger",
     exported_plugins = [":dagger_plugin"],