// Copyright 2017 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.rules.java;
import static com.google.devtools.build.lib.util.Preconditions.checkNotNull;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.Builder;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.CustomMultiArgv;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.OneVersionEnforcementLevel;
/** Utility for generating a call to the one-version binary. */
public class OneVersionCheckActionBuilder {
public static void build(
RuleContext ruleContext,
NestedSet<Artifact> jarsToCheck,
Artifact oneVersionOutput,
OneVersionEnforcementLevel enforcementLevel) {
JavaToolchainProvider javaToolchain = JavaToolchainProvider.fromRuleContext(ruleContext);
Artifact oneVersionTool = javaToolchain.getOneVersionBinary();
Artifact oneVersionWhitelist = javaToolchain.getOneVersionWhitelist();
if (oneVersionTool == null || oneVersionWhitelist == null) {
ruleContext.ruleError(
String.format(
"one version enforcement was requested but it is not supported by the current "
+ "Java toolchain '%s'; see the "
+ "java_toolchain.oneversion and java_toolchain.oneversion_whitelist attributes",
javaToolchain.getToolchainLabel()));
return;
}
Builder oneVersionArgsBuilder =
CustomCommandLine.builder()
.addExecPath("--output", oneVersionOutput)
.addExecPath("--whitelist", oneVersionWhitelist);
if (enforcementLevel == OneVersionEnforcementLevel.WARNING) {
oneVersionArgsBuilder.add("--succeed_on_found_violations");
}
oneVersionArgsBuilder.add(new OneVersionJarMapArgv(jarsToCheck));
CustomCommandLine oneVersionArgs = oneVersionArgsBuilder.build();
ruleContext.registerAction(
new SpawnAction.Builder()
.addOutput(oneVersionOutput)
.addInput(oneVersionWhitelist)
.addTransitiveInputs(jarsToCheck)
.setExecutable(oneVersionTool)
.setCommandLine(oneVersionArgs)
.alwaysUseParameterFile(ParameterFileType.SHELL_QUOTED)
.setMnemonic("JavaOneVersion")
.setProgressMessage("Checking for one-version violations in " + ruleContext.getLabel())
.build(ruleContext));
}
private static class OneVersionJarMapArgv extends CustomMultiArgv {
private static final Joiner COMMA_JOINER = Joiner.on(',');
private final Iterable<Artifact> classPathJars;
private OneVersionJarMapArgv(Iterable<Artifact> classPathJars) {
this.classPathJars = classPathJars;
}
@Override
public Iterable<String> argv() {
ImmutableList.Builder<String> args = ImmutableList.builder();
args.add("--inputs");
for (Artifact classPathJar : classPathJars) {
args.add(
COMMA_JOINER.join(
classPathJar.getExecPathString(), getArtifactOwnerGeneralizedLabel(classPathJar)));
}
return args.build();
}
private static String getArtifactOwnerGeneralizedLabel(Artifact artifact) {
Label label = checkNotNull(artifact.getArtifactOwner(), artifact).getLabel();
return
label.getPackageIdentifier().getRepository().isDefault()
|| label.getPackageIdentifier().getRepository().isMain()
? label.toString()
// Escape '@' prefix for .params file.
: "@" + label;
}
}
}