/*
* Copyright 2016-present Facebook, Inc.
*
* 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.facebook.buck.jvm.java.autodeps;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildOutputInitializer;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.ExplicitBuildTargetSourcePath;
import com.facebook.buck.rules.InitializableFromDisk;
import com.facebook.buck.rules.OnDiskBuildInfo;
import com.facebook.buck.rules.RuleKeyAppendable;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepExecutionResult;
import com.facebook.buck.step.fs.MkdirStep;
import com.facebook.buck.util.ObjectMappers;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.List;
final class JavaSymbolsRule implements BuildRule, InitializableFromDisk<Symbols> {
interface SymbolsFinder extends RuleKeyAppendable {
Symbols extractSymbols() throws IOException;
}
private static final String TYPE = "java_symbols";
public static final Flavor JAVA_SYMBOLS = InternalFlavor.of(TYPE);
private final BuildTarget buildTarget;
@AddToRuleKey private final SymbolsFinder symbolsFinder;
private final ProjectFilesystem projectFilesystem;
private final Path outputPath;
private final BuildOutputInitializer<Symbols> outputInitializer;
JavaSymbolsRule(
BuildTarget javaLibraryBuildTarget,
SymbolsFinder symbolsFinder,
ProjectFilesystem projectFilesystem) {
this.buildTarget = javaLibraryBuildTarget.withFlavors(JAVA_SYMBOLS);
this.symbolsFinder = symbolsFinder;
this.projectFilesystem = projectFilesystem;
this.outputPath = BuildTargets.getGenPath(getProjectFilesystem(), buildTarget, "__%s__.json");
this.outputInitializer = new BuildOutputInitializer<>(buildTarget, this);
}
public Symbols getFeatures() {
return outputInitializer.getBuildOutput();
}
@Override
public Symbols initializeFromDisk(OnDiskBuildInfo onDiskBuildInfo) throws IOException {
List<String> lines = onDiskBuildInfo.getOutputFileContentsByLine(outputPath);
Preconditions.checkArgument(lines.size() == 1, "Should be one line of JSON: %s", lines);
return ObjectMappers.readValue(lines.get(0), Symbols.class);
}
@Override
public BuildOutputInitializer<Symbols> getBuildOutputInitializer() {
return outputInitializer;
}
@Override
public ImmutableList<Step> getBuildSteps(
BuildContext context, BuildableContext buildableContext) {
Step mkdirStep = MkdirStep.of(getProjectFilesystem(), outputPath.getParent());
Step extractSymbolsStep =
new AbstractExecutionStep("java-symbols") {
@Override
public StepExecutionResult execute(ExecutionContext context) throws IOException {
try (OutputStream output = getProjectFilesystem().newFileOutputStream(outputPath)) {
ObjectMappers.WRITER.writeValue(output, symbolsFinder.extractSymbols());
}
return StepExecutionResult.SUCCESS;
}
};
return ImmutableList.of(mkdirStep, extractSymbolsStep);
}
@Override
public BuildTarget getBuildTarget() {
return buildTarget;
}
@Override
public String toString() {
return getFullyQualifiedName();
}
@Override
public String getType() {
return TYPE;
}
@Override
public BuildableProperties getProperties() {
return BuildableProperties.NONE;
}
@Override
public ImmutableSortedSet<BuildRule> getBuildDeps() {
return ImmutableSortedSet.of();
}
@Override
public SourcePath getSourcePathToOutput() {
return new ExplicitBuildTargetSourcePath(getBuildTarget(), outputPath);
}
@Override
public ProjectFilesystem getProjectFilesystem() {
return projectFilesystem;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BuildRule)) {
return false;
}
BuildRule that = (BuildRule) obj;
return this.getBuildTarget().equals(that.getBuildTarget());
}
@Override
public int hashCode() {
return buildTarget.hashCode();
}
@Override
public boolean isCacheable() {
return true;
}
}