Update from Google.

--
MOE_MIGRATED_REVID=85702957
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
new file mode 100644
index 0000000..2f2272b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
@@ -0,0 +1,654 @@
+// 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.lib.actions;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.syntax.SkylarkCallable;
+import com.google.devtools.build.lib.syntax.SkylarkModule;
+import com.google.devtools.build.lib.util.FileType;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * An Artifact represents a file used by the build system, whether it's a source
+ * file or a derived (output) file. Not all Artifacts have a corresponding
+ * FileTarget object in the <code>build.packages</code> API: for example,
+ * low-level intermediaries internal to a given rule, such as a Java class files
+ * or C++ object files. However all FileTargets have a corresponding Artifact.
+ *
+ * <p>In any given call to Builder#buildArtifacts(), no two Artifacts in the
+ * action graph may refer to the same path.
+ *
+ * <p>Artifacts generally fall into two classifications, source and derived, but
+ * there exist a few other cases that are fuzzy and difficult to classify. The
+ * following cases exist:
+ * <ul>
+ * <li>Well-formed source Artifacts will have null generating Actions and a root
+ * that is orthogonal to execRoot. (With the root coming from the package path.)
+ * <li>Well-formed derived Artifacts will have non-null generating Actions, and
+ * a root that is below execRoot.
+ * <li>Symlinked include source Artifacts under the output/include tree will
+ * appear to be derived artifacts with null generating Actions.
+ * <li>Some derived Artifacts, mostly in the genfiles tree and mostly discovered
+ * during include validation, will also have null generating Actions.
+ * </ul>
+ *
+ * <p>This class is "theoretically" final; it should not be subclassed except by
+ * {@link SpecialArtifact}.
+ */
+@Immutable
+@SkylarkModule(name = "File",
+    doc = "This type represents a file used by the build system. It can be "
+        + "either a source file or a derived file produced by a rule.")
+public class Artifact implements FileType.HasFilename, Comparable<Artifact>, ActionInput {
+
+  /** An object that can expand middleman artifacts. */
+  public interface MiddlemanExpander {
+
+    /**
+     * Expands the middleman artifact "mm", and populates "output" with the result.
+     *
+     * <p>{@code mm.isMiddlemanArtifact()} must be true. Only aggregating middlemen are expanded.
+     */
+    void expand(Artifact mm, Collection<? super Artifact> output);
+  }
+
+  public static final ImmutableList<Artifact> NO_ARTIFACTS = ImmutableList.of();
+
+  /**
+   * A Predicate that evaluates to true if the Artifact is not a middleman artifact.
+   */
+  public static final Predicate<Artifact> MIDDLEMAN_FILTER = new Predicate<Artifact>() {
+    @Override
+    public boolean apply(Artifact input) {
+      return !input.isMiddlemanArtifact();
+    }
+  };
+
+  private final Path path;
+  private final Root root;
+  private final PathFragment execPath;
+  private final PathFragment rootRelativePath;
+  // Non-final only for use when dealing with deserialized artifacts.
+  private ArtifactOwner owner;
+
+  /**
+   * Constructs an artifact for the specified path, root and execPath. The root must be an ancestor
+   * of path, and execPath must be a non-absolute tail of path. Outside of testing, this method
+   * should only be called by ArtifactFactory. The ArtifactOwner may be null.
+   *
+   * <p>In a source Artifact, the path tail after the root will be identical to the execPath, but
+   * the root will be orthogonal to execRoot.
+   * <pre>
+   *  [path] == [/root/][execPath]
+   * </pre>
+   *
+   * <p>In a derived Artifact, the execPath will overlap with part of the root, which in turn will
+   * be below of the execRoot.
+   * <pre>
+   *  [path] == [/root][pathTail] == [/execRoot][execPath] == [/execRoot][rootPrefix][pathTail]
+   * <pre>
+   */
+  @VisibleForTesting
+  public Artifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner) {
+    if (root == null || !path.startsWith(root.getPath())) {
+      throw new IllegalArgumentException(root + ": illegal root for " + path);
+    }
+    if (execPath == null || execPath.isAbsolute() || !path.asFragment().endsWith(execPath)) {
+      throw new IllegalArgumentException(execPath + ": illegal execPath for " + path);
+    }
+    this.path = path;
+    this.root = root;
+    this.execPath = execPath;
+    // These two lines establish the invariant that
+    // execPath == rootRelativePath <=> execPath.equals(rootRelativePath)
+    // This is important for isSourceArtifact.
+    PathFragment rootRel = path.relativeTo(root.getPath());
+    if (!execPath.endsWith(rootRel)) {
+      throw new IllegalArgumentException(execPath + ": illegal execPath doesn't end with "
+          + rootRel + " at " + path + " with root " + root);
+    }
+    this.rootRelativePath = rootRel.equals(execPath) ? execPath : rootRel;
+    this.owner = Preconditions.checkNotNull(owner, path);
+  }
+
+  /**
+   * Constructs an artifact for the specified path, root and execPath. The root must be an ancestor
+   * of path, and execPath must be a non-absolute tail of path. Should only be called for testing.
+   *
+   * <p>In a source Artifact, the path tail after the root will be identical to the execPath, but
+   * the root will be orthogonal to execRoot.
+   * <pre>
+   *  [path] == [/root/][execPath]
+   * </pre>
+   *
+   * <p>In a derived Artifact, the execPath will overlap with part of the root, which in turn will
+   * be below of the execRoot.
+   * <pre>
+   *  [path] == [/root][pathTail] == [/execRoot][execPath] == [/execRoot][rootPrefix][pathTail]
+   * <pre>
+   */
+  @VisibleForTesting
+  public Artifact(Path path, Root root, PathFragment execPath) {
+    this(path, root, execPath, ArtifactOwner.NULL_OWNER);
+  }
+
+  /**
+   * Constructs a source or derived Artifact for the specified path and specified root. The root
+   * must be an ancestor of the path.
+   */
+  @VisibleForTesting  // Only exists for testing.
+  public Artifact(Path path, Root root) {
+    this(path, root, root.getExecPath().getRelative(path.relativeTo(root.getPath())),
+        ArtifactOwner.NULL_OWNER);
+  }
+
+  /**
+   * Constructs a source or derived Artifact for the specified root-relative path and root.
+   */
+  @VisibleForTesting  // Only exists for testing.
+  public Artifact(PathFragment rootRelativePath, Root root) {
+    this(root.getPath().getRelative(rootRelativePath), root,
+        root.getExecPath().getRelative(rootRelativePath), ArtifactOwner.NULL_OWNER);
+  }
+
+  /**
+   * Returns the location of this Artifact on the filesystem.
+   */
+  public final Path getPath() {
+    return path;
+  }
+
+  /**
+   * Returns the base file name of this artifact.
+   */
+  @Override
+  public final String getFilename() {
+    return getExecPath().getBaseName();
+  }
+
+  /**
+   * Returns the artifact owner. May be null.
+   */
+  @Nullable public final Label getOwner() {
+    return owner.getLabel();
+  }
+
+  /**
+   * Get the {@code LabelAndConfiguration} of the {@code ConfiguredTarget} that owns this artifact,
+   * if it was set. Otherwise, this should be a dummy value -- either {@link
+   * ArtifactOwner#NULL_OWNER} or a dummy owner set in tests. Such a dummy value should only occur
+   * for source artifacts if created without specifying the owner, or for special derived artifacts,
+   * such as target completion middleman artifacts, build info artifacts, and the like.
+   *
+   * When deserializing artifacts we end up with a dummy owner. In that case, it must be set using
+   * {@link #setArtifactOwner} before this method is called.
+   */
+  public final ArtifactOwner getArtifactOwner() {
+    Preconditions.checkState(owner != DESERIALIZED_MARKER_OWNER, this);
+    return owner;
+  }
+
+  /**
+   * Sets the artifact owner of this artifact. Should only be called for artifacts that were created
+   * through deserialization, and so their owner was unknown at the time of creation.
+   */
+  public final void setArtifactOwner(ArtifactOwner owner) {
+    if (this.owner == DESERIALIZED_MARKER_OWNER) {
+      // We tolerate multiple calls of this method to accommodate shared actions.
+      this.owner = Preconditions.checkNotNull(owner, this);
+    }
+  }
+
+  /**
+   * Returns the root beneath which this Artifact resides, if any. This may be one of the
+   * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs
+   * (for derived Artifacts). It will always be an ancestor of getPath().
+   */
+  public final Root getRoot() {
+    return root;
+  }
+
+  /**
+   * Returns the exec path of this Artifact. The exec path is a relative path
+   * that is suitable for accessing this artifact relative to the execution
+   * directory for this build.
+   */
+  public final PathFragment getExecPath() {
+    return execPath;
+  }
+
+  /**
+   * Returns true iff this is a source Artifact as determined by its path and
+   * root relationships. Note that this will report all Artifacts in the output
+   * tree, including in the include symlink tree, as non-source.
+   */
+  public final boolean isSourceArtifact() {
+    return execPath == rootRelativePath;
+  }
+
+  /**
+   * Returns true iff this is a middleman Artifact as determined by its root.
+   */
+  public final boolean isMiddlemanArtifact() {
+    return getRoot().isMiddlemanRoot();
+  }
+
+  /**
+   * Returns whether the artifact represents a Fileset.
+   */
+  public boolean isFileset() {
+    return false;
+  }
+
+  /**
+   * Returns true iff metadata cache must return constant metadata for the
+   * given artifact.
+   */
+  public boolean isConstantMetadata() {
+    return false;
+  }
+
+  /**
+   * Special artifact types.
+   *
+   * @see SpecialArtifact
+   */
+  static enum SpecialArtifactType {
+    FILESET,
+    CONSTANT_METADATA,
+  }
+
+  /**
+   * A special kind of artifact that either is a fileset or needs special metadata caching behavior.
+   *
+   * <p>We subclass {@link Artifact} instead of storing the special attributes inside in order
+   * to save memory. The proportion of artifacts that are special is very small, and by not having
+   * to keep around the attribute for the rest we save some memory.
+   */
+  @Immutable
+  @VisibleForTesting
+  public static final class SpecialArtifact extends Artifact {
+    private final SpecialArtifactType type;
+
+    SpecialArtifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner,
+        SpecialArtifactType type) {
+      super(path, root, execPath, owner);
+      this.type = type;
+    }
+
+    @Override
+    public final boolean isFileset() {
+      return type == SpecialArtifactType.FILESET;
+    }
+
+    @Override
+    public boolean isConstantMetadata() {
+      return type == SpecialArtifactType.CONSTANT_METADATA;
+    }
+  }
+
+  /**
+   * Returns the relative path to this artifact relative to its root.  (Useful
+   * when deriving output filenames from input files, etc.)
+   */
+  public final PathFragment getRootRelativePath() {
+    return rootRelativePath;
+  }
+
+  /**
+   * Returns this.getExecPath().getPathString().
+   */
+  @Override
+  @SkylarkCallable(name = "path", structField = true,
+      doc = "The execution path of this file, relative to the execution directory.")
+  public final String getExecPathString() {
+    return getExecPath().getPathString();
+  }
+
+  @SkylarkCallable(name = "short_path", structField = true,
+      doc = "The path of this file relative to its root.")
+  public final String getRootRelativePathString() {
+    return getRootRelativePath().getPathString();
+  }
+
+  /**
+   * Returns a pretty string representation of the path denoted by this artifact, suitable for use
+   * in user error messages.  Artifacts beneath a root will be printed relative to that root; other
+   * artifacts will be printed as an absolute path.
+   *
+   * <p>(The toString method is intended for developer messages since its more informative.)
+   */
+  public final String prettyPrint() {
+    // toDetailString would probably be more useful to users, but lots of tests rely on the
+    // current values.
+    return rootRelativePath.toString();
+  }
+
+  @Override
+  public final boolean equals(Object other) {
+    if (!(other instanceof Artifact)) {
+      return false;
+    }
+    // We don't bother to check root in the equivalence relation, because we
+    // assume that 'root' is an ancestor of 'path', and that all possible roots
+    // are disjoint, so unless things are really screwed up, it's ok.
+    Artifact that = (Artifact) other;
+    return this.path.equals(that.path);
+  }
+
+  @Override
+  public final int compareTo(Artifact o) {
+    // The artifact factory ensures that there is a unique artifact for a given path.
+    return this.path.compareTo(o.path);
+  }
+
+  @Override
+  public final int hashCode() {
+    return path.hashCode();
+  }
+
+  @Override
+  public final String toString() {
+    return "Artifact:" + toDetailString();
+  }
+
+  /**
+   * Returns the root-part of a given path by trimming off the end specified by
+   * a given tail. Assumes that the tail is known to match, and simply relies on
+   * the segment lengths.
+   */
+  private static PathFragment trimTail(PathFragment path, PathFragment tail) {
+    return path.subFragment(0, path.segmentCount() - tail.segmentCount());
+  }
+
+  /**
+   * Returns a string representing the complete artifact path information.
+   */
+  public final String toDetailString() {
+    if (isSourceArtifact()) {
+      // Source Artifact: relPath == execPath, & real path is not under execRoot
+      return "[" + root + "]" + rootRelativePath;
+    } else {
+      // Derived Artifact: path and root are under execRoot
+      PathFragment execRoot = trimTail(path.asFragment(), execPath);
+      return "[[" + execRoot + "]" + root.getPath().asFragment().relativeTo(execRoot) + "]"
+          + rootRelativePath;
+    }
+  }
+
+  /**
+   * Serializes this artifact to a string that has enough data to reconstruct the artifact.
+   */
+  public final String serializeToString() {
+    // In theory, it should be enough to serialize execPath and rootRelativePath (which is a suffix
+    // of execPath). However, in practice there is code around that uses other attributes which
+    // needs cleaning up.
+    String result = execPath + " /" + rootRelativePath.toString().length();
+    if (getOwner() != null) {
+      result += " " + getOwner();
+    }
+    return result;
+  }
+
+  //---------------------------------------------------------------------------
+  // Static methods to assist in working with Artifacts
+
+  /**
+   * Formatter for execPath PathFragment output.
+   */
+  private static final Function<Artifact, PathFragment> EXEC_PATH_FORMATTER =
+      new Function<Artifact, PathFragment>() {
+        @Override
+        public PathFragment apply(Artifact input) {
+          return input.getExecPath();
+        }
+      };
+
+  private static final Function<Artifact, String> ROOT_RELATIVE_PATH_STRING =
+      new Function<Artifact, String>() {
+        @Override
+        public String apply(Artifact artifact) {
+          return artifact.getRootRelativePath().getPathString();
+        }
+      };
+
+  /**
+   * Converts a collection of artifacts into execution-time path strings, and
+   * adds those to a given collection. Middleman artifacts are ignored by this
+   * method.
+   */
+  public static void addExecPaths(Iterable<Artifact> artifacts, Collection<String> output) {
+    addNonMiddlemanArtifacts(artifacts, output, ActionInputHelper.EXEC_PATH_STRING_FORMATTER);
+  }
+
+  /**
+   * Converts a collection of artifacts into the outputs computed by
+   * outputFormatter and adds them to a given collection. Middleman artifacts
+   * are ignored.
+   */
+  static <E> void addNonMiddlemanArtifacts(Iterable<Artifact> artifacts,
+      Collection<? super E> output, Function<? super Artifact, E> outputFormatter) {
+    for (Artifact artifact : artifacts) {
+      if (MIDDLEMAN_FILTER.apply(artifact)) {
+        output.add(outputFormatter.apply(artifact));
+      }
+    }
+  }
+
+  /**
+   * Lazily converts artifacts into root-relative path strings. Middleman artifacts are ignored by
+   * this method.
+   */
+  public static Iterable<String> toRootRelativePaths(Iterable<Artifact> artifacts) {
+    return Iterables.transform(
+        Iterables.filter(artifacts, MIDDLEMAN_FILTER),
+        ROOT_RELATIVE_PATH_STRING);
+  }
+
+  /**
+   * Lazily converts artifacts into execution-time path strings. Middleman artifacts are ignored by
+   * this method.
+   */
+  public static Iterable<String> toExecPaths(Iterable<Artifact> artifacts) {
+    return ActionInputHelper.toExecPaths(Iterables.filter(artifacts, MIDDLEMAN_FILTER));
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path strings, and
+   * returns those as an immutable list. Middleman artifacts are ignored by this method.
+   */
+  public static List<String> asExecPaths(Iterable<Artifact> artifacts) {
+    return ImmutableList.copyOf(toExecPaths(artifacts));
+  }
+
+  /**
+   * Renders a collection of artifacts as execution-time paths and joins
+   * them into a single string. Middleman artifacts are ignored by this method.
+   */
+  public static String joinExecPaths(String delimiter, Iterable<Artifact> artifacts) {
+    return Joiner.on(delimiter).join(toExecPaths(artifacts));
+  }
+
+  /**
+   * Renders a collection of artifacts as root-relative paths and joins
+   * them into a single string. Middleman artifacts are ignored by this method.
+   */
+  public static String joinRootRelativePaths(String delimiter, Iterable<Artifact> artifacts) {
+    return Joiner.on(delimiter).join(toRootRelativePaths(artifacts));
+  }
+
+  /**
+   * Adds a collection of artifacts to a given collection, with
+   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions expanded once.
+   */
+  public static void addExpandedArtifacts(Iterable<Artifact> artifacts,
+      Collection<? super Artifact> output, MiddlemanExpander middlemanExpander) {
+    addExpandedArtifacts(artifacts, output, Functions.<Artifact>identity(), middlemanExpander);
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path strings, and
+   * adds those to a given collection. Middleman artifacts for
+   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions are expanded
+   * once.
+   */
+  @VisibleForTesting
+  public static void addExpandedExecPathStrings(Iterable<Artifact> artifacts,
+                                                 Collection<String> output,
+                                                 MiddlemanExpander middlemanExpander) {
+    addExpandedArtifacts(artifacts, output, ActionInputHelper.EXEC_PATH_STRING_FORMATTER,
+        middlemanExpander);
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path fragments, and
+   * adds those to a given collection. Middleman artifacts for
+   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions are expanded
+   * once.
+   */
+  public static void addExpandedExecPaths(Iterable<Artifact> artifacts,
+      Collection<PathFragment> output, MiddlemanExpander middlemanExpander) {
+    addExpandedArtifacts(artifacts, output, EXEC_PATH_FORMATTER, middlemanExpander);
+  }
+
+  /**
+   * Converts a collection of artifacts into the outputs computed by
+   * outputFormatter and adds them to a given collection. Middleman artifacts
+   * are expanded once.
+   */
+  private static <E> void addExpandedArtifacts(Iterable<Artifact> artifacts,
+                                               Collection<? super E> output,
+                                               Function<? super Artifact, E> outputFormatter,
+                                               MiddlemanExpander middlemanExpander) {
+    for (Artifact artifact : artifacts) {
+      if (artifact.isMiddlemanArtifact()) {
+        expandMiddlemanArtifact(artifact, output, outputFormatter, middlemanExpander);
+      } else {
+        output.add(outputFormatter.apply(artifact));
+      }
+    }
+  }
+
+  private static <E> void expandMiddlemanArtifact(Artifact middleman,
+                                                  Collection<? super E> output,
+                                                  Function<? super Artifact, E> outputFormatter,
+                                                  MiddlemanExpander middlemanExpander) {
+    Preconditions.checkArgument(middleman.isMiddlemanArtifact());
+    List<Artifact> artifacts = new ArrayList<>();
+    middlemanExpander.expand(middleman, artifacts);
+    for (Artifact artifact : artifacts) {
+      output.add(outputFormatter.apply(artifact));
+    }
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path strings, and
+   * returns those as a list. Middleman artifacts are expanded once. The
+   * returned list is mutable.
+   */
+  public static List<String> asExpandedExecPathStrings(Iterable<Artifact> artifacts,
+                                                       MiddlemanExpander middlemanExpander) {
+    List<String> result = new ArrayList<>();
+    addExpandedExecPathStrings(artifacts, result, middlemanExpander);
+    return result;
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path fragments, and
+   * returns those as a list. Middleman artifacts are expanded once. The
+   * returned list is mutable.
+   */
+  public static List<PathFragment> asExpandedExecPaths(Iterable<Artifact> artifacts,
+                                                       MiddlemanExpander middlemanExpander) {
+    List<PathFragment> result = new ArrayList<>();
+    addExpandedExecPaths(artifacts, result, middlemanExpander);
+    return result;
+  }
+
+  /**
+   * Converts a collection of artifacts into execution-time path strings with
+   * the root-break delimited with a colon ':', and adds those to a given list.
+   * <pre>
+   * Source: sourceRoot/rootRelative => :rootRelative
+   * Derived: execRoot/rootPrefix/rootRelative => rootPrefix:rootRelative
+   * </pre>
+   */
+  public static void addRootPrefixedExecPaths(Iterable<Artifact> artifacts,
+      List<String> output) {
+    for (Artifact artifact : artifacts) {
+      output.add(asRootPrefixedExecPath(artifact));
+    }
+  }
+
+  /**
+   * Convenience method to filter the files to build for a certain filetype.
+   *
+   * @param artifacts the files to filter
+   * @param allowedType the allowed filetype
+   * @return all members of filesToBuild that are of one of the
+   *     allowed filetypes
+   */
+  public static List<Artifact> filterFiles(Iterable<Artifact> artifacts, FileType allowedType) {
+    List<Artifact> filesToBuild = new ArrayList<>();
+    for (Artifact artifact : artifacts) {
+      if (allowedType.matches(artifact.getFilename())) {
+        filesToBuild.add(artifact);
+      }
+    }
+    return filesToBuild;
+  }
+
+  @VisibleForTesting
+  static String asRootPrefixedExecPath(Artifact artifact) {
+    PathFragment execPath = artifact.getExecPath();
+    PathFragment rootRel = artifact.getRootRelativePath();
+    if (execPath.equals(rootRel)) {
+      return ":" + rootRel.getPathString();
+    } else { //if (execPath.endsWith(rootRel)) {
+      PathFragment rootPrefix = trimTail(execPath, rootRel);
+      return rootPrefix.getPathString() + ":" + rootRel.getPathString();
+    }
+  }
+
+  /**
+   * Converts artifacts into their exec paths. Returns an immutable list.
+   */
+  public static List<PathFragment> asPathFragments(Iterable<Artifact> artifacts) {
+    return ImmutableList.copyOf(Iterables.transform(artifacts, EXEC_PATH_FORMATTER));
+  }
+
+  static final ArtifactOwner DESERIALIZED_MARKER_OWNER = new ArtifactOwner() {
+    @Override
+    public Label getLabel() {
+      return null;
+    }};
+}