| // 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.rules.java; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.lib.actions.Action; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.actions.ArtifactRoot; |
| import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoCollection; |
| import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory; |
| import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
| import com.google.devtools.build.lib.cmdline.RepositoryName; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
| import com.google.devtools.build.lib.collect.nestedset.Order; |
| import com.google.devtools.build.lib.rules.java.WriteBuildInfoPropertiesAction.TimestampFormatter; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| import java.time.Instant; |
| import java.time.ZoneOffset; |
| import java.time.format.DateTimeFormatter; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Java build info creation - generates properties file that contain the corresponding build-info |
| * data. |
| */ |
| public abstract class JavaBuildInfoFactory implements BuildInfoFactory { |
| public static final BuildInfoKey KEY = new BuildInfoKey("Java"); |
| |
| static final PathFragment BUILD_INFO_NONVOLATILE_PROPERTIES_NAME = |
| PathFragment.create("build-info-nonvolatile.properties"); |
| static final PathFragment BUILD_INFO_VOLATILE_PROPERTIES_NAME = |
| PathFragment.create("build-info-volatile.properties"); |
| static final PathFragment BUILD_INFO_REDACTED_PROPERTIES_NAME = |
| PathFragment.create("build-info-redacted.properties"); |
| |
| private static final DateTimeFormatter DEFAULT_TIME_FORMAT = |
| DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss yyyy"); |
| |
| // A default formatter that returns a date in UTC format. |
| @AutoCodec |
| @VisibleForSerialization |
| static class DefaultTimestampFormatter implements TimestampFormatter { |
| @Override |
| public String format(long timestamp) { |
| return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.UTC).format(DEFAULT_TIME_FORMAT) |
| + " (" |
| + timestamp / 1000 |
| + ')'; |
| } |
| } |
| |
| private static final TimestampFormatter DEFAULT_FORMATTER = new DefaultTimestampFormatter(); |
| |
| @Override |
| public final BuildInfoCollection create( |
| BuildInfoContext context, |
| BuildConfiguration config, |
| Artifact stableStatus, |
| Artifact volatileStatus, |
| RepositoryName repositoryName) { |
| WriteBuildInfoPropertiesAction redactedInfo = |
| getHeader( |
| context, |
| config, |
| BUILD_INFO_REDACTED_PROPERTIES_NAME, |
| NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| createRedactedTranslator(), |
| true, |
| true, |
| repositoryName); |
| WriteBuildInfoPropertiesAction nonvolatileInfo = |
| getHeader( |
| context, |
| config, |
| BUILD_INFO_NONVOLATILE_PROPERTIES_NAME, |
| NestedSetBuilder.create(Order.STABLE_ORDER, stableStatus), |
| createNonVolatileTranslator(), |
| false, |
| true, |
| repositoryName); |
| WriteBuildInfoPropertiesAction volatileInfo = |
| getHeader( |
| context, |
| config, |
| BUILD_INFO_VOLATILE_PROPERTIES_NAME, |
| NestedSetBuilder.create(Order.STABLE_ORDER, volatileStatus), |
| createVolatileTranslator(), |
| true, |
| false, |
| repositoryName); |
| List<Action> actions = new ArrayList<>(3); |
| actions.add(redactedInfo); |
| actions.add(nonvolatileInfo); |
| actions.add(volatileInfo); |
| return new BuildInfoCollection( |
| actions, |
| ImmutableList.of(nonvolatileInfo.getPrimaryOutput(), volatileInfo.getPrimaryOutput()), |
| ImmutableList.of(redactedInfo.getPrimaryOutput())); |
| } |
| |
| /** Creates a {@link BuildInfoPropertiesTranslator} to use for volatile keys. */ |
| protected abstract BuildInfoPropertiesTranslator createVolatileTranslator(); |
| |
| /** Creates a {@link BuildInfoPropertiesTranslator} to use for non-volatile keys. */ |
| protected abstract BuildInfoPropertiesTranslator createNonVolatileTranslator(); |
| |
| /** |
| * Creates a {@link BuildInfoPropertiesTranslator} to use for redacted version of the build |
| * informations. |
| */ |
| protected abstract BuildInfoPropertiesTranslator createRedactedTranslator(); |
| |
| /** Specifies the {@link TimestampFormatter} to use to output dates in the properties file. */ |
| protected TimestampFormatter getTimestampFormatter() { |
| return DEFAULT_FORMATTER; |
| } |
| |
| private WriteBuildInfoPropertiesAction getHeader( |
| BuildInfoContext context, |
| BuildConfiguration config, |
| PathFragment propertyFileName, |
| NestedSet<Artifact> inputs, |
| BuildInfoPropertiesTranslator translator, |
| boolean includeVolatile, |
| boolean includeNonVolatile, |
| RepositoryName repositoryName) { |
| ArtifactRoot outputPath = config.getIncludeDirectory(repositoryName); |
| final Artifact output = |
| context.getBuildInfoArtifact( |
| propertyFileName, |
| outputPath, |
| includeVolatile && !inputs.isEmpty() |
| ? BuildInfoType.NO_REBUILD |
| : BuildInfoType.FORCE_REBUILD_IF_CHANGED); |
| return new WriteBuildInfoPropertiesAction( |
| inputs, output, translator, includeVolatile, includeNonVolatile, getTimestampFormatter()); |
| } |
| |
| @Override |
| public final BuildInfoKey getKey() { |
| return KEY; |
| } |
| |
| @Override |
| public boolean isEnabled(BuildConfiguration config) { |
| return config.hasFragment(JavaConfiguration.class); |
| } |
| } |