// Copyright 2014 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.lib.runtime.commands;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ProtoUtils;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.AllowedRuleClassInfo;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.AttributeDefinition;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.AttributeValue;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.BuildLanguage;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.RuleDefinition;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ProcessUtils;
import com.google.devtools.build.lib.util.StringUtilities;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * An item that is returned by <code>blaze info</code>.
 */
public abstract class InfoItem {
  protected final String name;
  protected final String description;
  protected final boolean hidden;

  protected InfoItem(String name,
      String description,
      boolean hidden) {
    this.name = name;
    this.description = description;
    this.hidden = hidden;
  }

  protected InfoItem(String name,
      String description) {
    this(name, description, false);
  }

  /**
   * The name of the info key.
   */
  public String getName() {
    return name;
  }

  /**
   * The help description of the info key.
   */
  public String getDescription() {
    return description;
  }

  /**
   * Whether the key is printed when "blaze info" is invoked without arguments.
   *
   * <p>This is usually true for info keys that take multiple lines, thus, cannot really be
   * included in the output of argumentless "blaze info".
   */
  public boolean isHidden() {
    return hidden;
  }

  /**
   * Returns the value of the info key. The return value is directly printed to stdout.
   */
  public abstract byte[] get(
      Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
      throws AbruptExitException, InterruptedException;

  protected static byte[] print(Object value) {
    if (value instanceof byte[]) {
      return (byte[]) value;
    }
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(
        outputStream, StandardCharsets.UTF_8));
    writer.print(value + "\n");
    writer.flush();
    return outputStream.toByteArray();
  }

  /**
   * Info item for the workspace directory.
   */
  public static final class WorkspaceInfoItem extends InfoItem {
    public WorkspaceInfoItem() {
      super("workspace",
          "The working directory of the server.");
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getWorkspace());
    }
  }

  /**
   * Info item for the install_base directory.
   */
  public static final class InstallBaseInfoItem extends InfoItem {
    public InstallBaseInfoItem() {
      super("install_base",
          "The installation base directory.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getInstallBase());
    }
  }

  /**
   * Info item for the output_base directory.
   */
  public static final class OutputBaseInfoItem extends InfoItem {
    public OutputBaseInfoItem(String productName) {
      super("output_base",
          "A directory for shared " + productName
          + " state as well as tool and strategy specific subdirectories.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getOutputBase());
    }
  }

  /**
   * Info item for the execution_root directory.
   */
  public static final class ExecutionRootInfoItem extends InfoItem {
    public ExecutionRootInfoItem() {
      super("execution_root",
          "A directory that makes all input and output files visible to the build.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getDirectories().getExecRoot(
          configurationSupplier.get().getMainRepositoryName()));
    }
  }

  /**
   * Info item for the output_path directory.
   */
  public static final class OutputPathInfoItem extends InfoItem {
    public OutputPathInfoItem() {
      super("output_path",
          "Output directory",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(
          env.getDirectories().getOutputPath(configurationSupplier.get().getMainRepositoryName()));
    }
  }

  /**
   * Info item for the {blaze,bazel}-bin directory.
   */
  public static final class BlazeBinInfoItem extends InfoItem {
    public BlazeBinInfoItem(String productName) {
      super(productName + "-bin",
          "Configuration dependent directory for binaries.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getBinDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /**
   * Info item for the {blaze,bazel}-genfiles directory.
   */
  public static final class BlazeGenfilesInfoItem extends InfoItem {
    public BlazeGenfilesInfoItem(String productName) {
      super(productName + "-genfiles",
          "Configuration dependent directory for generated files.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getGenfilesDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /**
   * Info item for the {blaze,bazel}-testlogs directory.
   */
  public static final class BlazeTestlogsInfoItem extends InfoItem {
    public BlazeTestlogsInfoItem(String productName) {
      super(productName + "-testlogs",
          "Configuration dependent directory for logs from a test run.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getTestLogsDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /** Info item for server_log path. */
  public static class ServerLogInfoItem extends InfoItem {
    private static final Logger logger = Logger.getLogger(ServerLogInfoItem.class.getName());

    /**
     * Constructs an info item for the server log path.
     *
     * @param productName name of the tool whose server log path will be queried
     */
    public ServerLogInfoItem(String productName) {
      super("server_log", productName + " server log path", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      try {
        Optional<Path> path = env.getRuntime().getServerLogPath();
        return print(path.map(Path::toString).orElse(""));
      } catch (IOException e) {
        logger.log(Level.WARNING, "Failed to determine server log location", e);
        return print("UNKNOWN LOG LOCATION");
      }
    }
  }

  /**
   * Info item for release
   */
  public static final class ReleaseInfoItem extends InfoItem {
    public ReleaseInfoItem(String productName) {
      super("release",
          productName + " release identifier",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(BlazeVersionInfo.instance().getReleaseName());
    }
  }

  /**
   * Info item for server_pid
   */
  public static final class ServerPidInfoItem extends InfoItem {
    public ServerPidInfoItem(String productName) {
      super("server_pid",
          productName + " process id",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(ProcessUtils.getpid());
    }
  }

  /**
   * Info item for package_path
   */
  public static final class PackagePathInfoItem extends InfoItem {
    private final OptionsParsingResult commandOptions;

    public PackagePathInfoItem(OptionsParsingResult commandOptions) {
      super("package_path",
          "The search path for resolving package labels.",
          false);
      this.commandOptions = commandOptions;
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(commandOptions);
      PackageCacheOptions packageCacheOptions =
          commandOptions.getOptions(PackageCacheOptions.class);
      return print(Joiner.on(":").join(packageCacheOptions.packagePath));
    }
  }

  private static MemoryUsage getMemoryUsage() {
    MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
    return memBean.getHeapMemoryUsage();
  }

  /**
   * Info item for the used heap size
   */
  public static final class UsedHeapSizeInfoItem extends InfoItem {
    public UsedHeapSizeInfoItem() {
      super("used-heap-size",
          "The amount of used memory in bytes. Note that this is not a "
          + "good indicator of the actual memory use, as it includes any remaining inaccessible "
          + "memory.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
    }
  }

  /**
   * Info item for the used heap size after garbage collection
   */
  public static final class UsedHeapSizeAfterGcInfoItem extends InfoItem {
    public UsedHeapSizeAfterGcInfoItem() {
      super("used-heap-size-after-gc",
          "The amount of used memory in bytes after a call to System.gc().",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      System.gc();
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
    }
  }

  /**
   * Info item for the committed heap size
   */
  public static final class CommitedHeapSizeInfoItem extends InfoItem {
    public CommitedHeapSizeInfoItem() {
      super("committed-heap-size",
          "The amount of memory in bytes that is committed for the Java virtual machine to use",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getCommitted()));
    }
  }

  /**
   * Info item for the max heap size
   */
  public static final class MaxHeapSizeInfoItem extends InfoItem {
    public MaxHeapSizeInfoItem() {
      super("max-heap-size",
          "The maximum amount of memory in bytes that can be used for memory management.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getMax()));
    }
  }

  /**
   * Info item for the gc-count
   */
  public static final class GcCountInfoItem extends InfoItem {
    public GcCountInfoItem() {
      super("gc-count",
          "Number of garbage collection runs.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      // The documentation is not very clear on what it means to have more than
      // one GC MXBean, so we just sum them up.
      long gcCount = 0;
      for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
        gcCount += gcBean.getCollectionCount();
      }
      return print(gcCount + "");
    }
  }

  /** Info item for the name and version of the Java runtime environment. */
  public static final class JavaRuntimeInfoItem extends InfoItem {
    public JavaRuntimeInfoItem() {
      super("java-runtime", "Name and version of the current Java runtime environment.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "%s (build %s) by %s",
              System.getProperty("java.runtime.name", "Unknown runtime"),
              System.getProperty("java.runtime.version", "unknown"),
              System.getProperty("java.vendor", "unknown")));
    }
  }

  /** Info item for the name and version of the Java VM. */
  public static final class JavaVirtualMachineInfoItem extends InfoItem {
    public JavaVirtualMachineInfoItem() {
      super("java-vm", "Name and version of the current Java virtual machine.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "%s (build %s, %s) by %s",
              System.getProperty("java.vm.name", "Unknown VM"),
              System.getProperty("java.vm.version", "unknown"),
              System.getProperty("java.vm.info", "unknown"),
              System.getProperty("java.vm.vendor", "unknown")));
    }
  }

  /** Info item for the location of the Java runtime. */
  public static final class JavaHomeInfoItem extends InfoItem {
    public JavaHomeInfoItem() {
      super("java-home", "Location of the current Java runtime.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      String javaHome = System.getProperty("java.home");
      if (javaHome == null) {
        return print("unknown");
      }
      // Tunnel through a Path object in order to normalize the representation of the path.
      Path javaHomePath = env.getRuntime().getFileSystem().getPath(javaHome);
      return print(javaHomePath.getPathString());
    }
  }

  /** Info item for the current character encoding settings. */
  public static final class CharacterEncodingInfoItem extends InfoItem {
    public CharacterEncodingInfoItem() {
      super(
          "character-encoding",
          "Information about the character encoding used by the running JVM.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "file.encoding = %s, defaultCharset = %s",
              System.getProperty("file.encoding", "unknown"), Charset.defaultCharset().name()));
    }
  }

  /** Info item for the gc-time */
  public static final class GcTimeInfoItem extends InfoItem {
    public GcTimeInfoItem() {
      super("gc-time",
          "The approximate accumulated time spend on garbage collection.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      // The documentation is not very clear on what it means to have more than
      // one GC MXBean, so we just sum them up.
      long gcTime = 0;
      for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
        gcTime += gcBean.getCollectionTime();
      }
      return print(gcTime + "ms");
    }
  }

  /** Info item for the effective current client environment. */
  public static final class ClientEnv extends InfoItem {
    public ClientEnv() {
      super(
          "client-env",
          "The specifications that need to be added to the project-specific rc file to freeze the"
              + " current client environment",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      String result = "";
      for (Map.Entry<String, String> entry : env.getWhitelistedActionEnv().entrySet()) {
        // TODO(bazel-team): as the syntax of our rc-files does not support to express new-lines in
        // values, we produce syntax errors if the value of the entry contains a newline character.
        result += "build --action_env=" + entry.getKey() + "=" + entry.getValue() + "\n";
      }
      for (Map.Entry<String, String> entry : env.getWhitelistedTestEnv().entrySet()) {
        // TODO(bazel-team): as the syntax of our rc-files does not support to express new-lines in
        // values, we produce syntax errors if the value of the entry contains a newline character.
        result += "build --test_env=" + entry.getKey() + "=" + entry.getValue() + "\n";
      }
      return print(result);
    }
  }

  /**
   * Info item for the effective current set of Starlark semantics option values.
   *
   * <p>This is hidden because its output is verbose and may be multiline.
   */
  public static final class StarlarkSemanticsInfoItem extends InfoItem {
    private final OptionsParsingResult commandOptions;

    StarlarkSemanticsInfoItem(OptionsParsingResult commandOptions) {
      super(
          /*name=*/ "starlark-semantics",
          /*description=*/ "The effective set of Starlark semantics option values.",
          /*hidden=*/ true);
      this.commandOptions = commandOptions;
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
      StarlarkSemanticsOptions starlarkSemanticsOptions =
          commandOptions.getOptions(StarlarkSemanticsOptions.class);
      SkyframeExecutor skyframeExecutor = env.getBlazeWorkspace().getSkyframeExecutor();
      StarlarkSemantics effectiveSkylarkSemantics =
          skyframeExecutor.getEffectiveStarlarkSemantics(starlarkSemanticsOptions);
      return print(effectiveSkylarkSemantics.toDeterministicString());
    }
  }

  /**
   * Info item for the default package. It is deprecated, it still works, when explicitly requested,
   * but are not shown by default. It prints multi-line messages and thus don't play well with grep.
   * We don't print them unless explicitly requested.
   *
   * @deprecated
   */
  // TODO(lberki): Try to remove this using an incompatible flag.
  @Deprecated
  public static final class DefaultsPackageInfoItem extends InfoItem {
    public DefaultsPackageInfoItem() {
      super("defaults-package", "Obsolete. Retained for backwards compatibility.", true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
      checkNotNull(env);
      return print("");
    }
  }

  private static AllowedRuleClassInfo getAllowedRuleClasses(
      Collection<RuleClass> ruleClasses, Attribute attr) {
    AllowedRuleClassInfo.Builder info = AllowedRuleClassInfo.newBuilder();
    info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.ANY);

    if (attr.isStrictLabelCheckingEnabled()
        && attr.getAllowedRuleClassesPredicate() != Predicates.<RuleClass>alwaysTrue()) {
      info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.SPECIFIED);
      Predicate<RuleClass> filter = attr.getAllowedRuleClassesPredicate();
      for (RuleClass otherClass : Iterables.filter(ruleClasses, filter)) {
        if (!isAbstractRule(otherClass)) {
          info.addAllowedRuleClass(otherClass.getName());
        }
      }
    }

    return info.build();
  }

  private static boolean isAbstractRule(RuleClass c) {
    return c.getName().startsWith("$");
  }

  /**
   * Returns a byte array containing a proto-buffer describing the build language.
   */
  private static byte[] getBuildLanguageDefinition(RuleClassProvider provider) {
    BuildLanguage.Builder resultPb = BuildLanguage.newBuilder();
    ImmutableList<RuleClass> sortedRuleClasses =
        ImmutableList.sortedCopyOf(
            Comparator.comparing(RuleClass::getName), provider.getRuleClassMap().values());
    for (RuleClass ruleClass : sortedRuleClasses) {
      if (isAbstractRule(ruleClass)) {
        continue;
      }

      RuleDefinition.Builder rulePb = RuleDefinition.newBuilder();
      rulePb.setName(ruleClass.getName());

      ImmutableList<Attribute> sortedAttributeDefinitions =
          ImmutableList.sortedCopyOf(
              Comparator.comparing(Attribute::getName), ruleClass.getAttributes());
      for (Attribute attr : sortedAttributeDefinitions) {
        Type<?> t = attr.getType();
        AttributeDefinition.Builder attrPb = AttributeDefinition.newBuilder();
        attrPb.setName(attr.getName());
        attrPb.setType(ProtoUtils.getDiscriminatorFromType(t));
        attrPb.setMandatory(attr.isMandatory());
        attrPb.setAllowEmpty(!attr.isNonEmpty());
        attrPb.setAllowSingleFile(attr.isSingleArtifact());
        attrPb.setConfigurable(attr.isConfigurable());
        attrPb.setCfgIsHost(attr.getTransitionFactory().isHost());

        // Encode default value, if simple.
        Object v = attr.getDefaultValueUnchecked();
        if (!(v == null
            || v instanceof Attribute.ComputedDefault
            || v instanceof Attribute.SkylarkComputedDefaultTemplate
            || v instanceof Attribute.LateBoundDefault
            || v == t.getDefaultValue())) {
          attrPb.setDefault(convertAttrValue(t, v));
        }
        attrPb.setExecutable(attr.isExecutable());
        if (BuildType.isLabelType(t)) {
          attrPb.setAllowedRuleClasses(getAllowedRuleClasses(sortedRuleClasses, attr));
          attrPb.setNodep(t.getLabelClass() == Type.LabelClass.NONDEP_REFERENCE);
        }
        rulePb.addAttribute(attrPb);
      }

      resultPb.addRule(rulePb);
    }

    return resultPb.build().toByteArray();
  }

  // convertAttrValue converts attribute value v of type to t an AttributeValue message.
  private static AttributeValue convertAttrValue(Type<?> t, Object v) {
    AttributeValue.Builder b = AttributeValue.newBuilder();
    if (v instanceof Map) {
      Type.DictType<?, ?> dictType = (Type.DictType<?, ?>) t;
      for (Map.Entry<?, ?> entry : ((Map<?, ?>) v).entrySet()) {
        b.addDictBuilder()
            .setKey(entry.getKey().toString())
            .setValue(convertAttrValue(dictType.getValueType(), entry.getValue()))
            .build();
      }
    } else if (v instanceof List) {
      for (Object elem : (List<?>) v) {
        b.addList(convertAttrValue(t.getListElementType(), elem));
      }
    } else if (t == BuildType.LICENSE) {
      // TODO(adonovan): need dual function of parseLicense.
      // Treat as empty list for now.
    } else if (t == BuildType.DISTRIBUTIONS) {
      // TODO(adonovan): need dual function of parseDistributions.
      // Treat as empty list for now.
    } else if (t == Type.STRING) {
      b.setString((String) v);
    } else if (t == Type.INTEGER) {
      b.setInt((Integer) v);
    } else if (t == Type.BOOLEAN) {
      b.setBool((Boolean) v);
    } else if (t == BuildType.TRISTATE) {
      b.setInt(((TriState) v).toInt());
    } else if (BuildType.isLabelType(t)) { // case order matters!
      b.setString(v.toString());
    } else {
      // No native rule attribute of this type (FilesetEntry?) has a default value.
      throw new IllegalStateException("unexpected type of attribute default value: " + t);
    }
    return b.build();
  }

  /**
   * Info item for the build language. It is deprecated, it still works, when
   * explicitly requested, but are not shown by default. It prints multi-line messages and thus
   * don't play well with grep. We don't print them unless explicitly requested.
   * @Deprecated
   */
  @Deprecated
  public static final class BuildLanguageInfoItem extends InfoItem {
    public BuildLanguageInfoItem() {
      super("build-language",
          "A protobuffer with the build language structure",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(getBuildLanguageDefinition(env.getRuntime().getRuleClassProvider()));
    }
  }

  /**
   * Info item for the default package path. It is deprecated, it still works, when
   * explicitly requested, but are not shown by default. It prints multi-line messages and thus
   * don't play well with grep. We don't print them unless explicitly requested.
   * @deprecated
   */
  @Deprecated
  public static final class DefaultPackagePathInfoItem extends InfoItem {
    private final OptionsParsingResult commandOptions;

    public DefaultPackagePathInfoItem(OptionsParsingResult commandOptions) {
      super("default-package-path",
          "The default package path",
          true);
      this.commandOptions = commandOptions;
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(commandOptions);
      return print(Joiner.on(":").join(
          commandOptions.getOptions(PackageCacheOptions.class).packagePath));
    }
  }

  /**
   * Info item for the make environment.
   */
  public static class MakeInfoItem extends InfoItem {
    public MakeInfoItem(String name, String description) {
      super(name, description, false);
    }
    @Override
    public String getDescription() {
      return "Make environment variable '" + name + "'";
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
      return print(description);
    }
  }
}
