/*
* Copyright 2012-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;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepExecutionResult;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/** Creates a JAR file from a collection of directories/ZIP/JAR files. */
public class JarDirectoryStep implements Step {
private final ProjectFilesystem filesystem;
/** Where to write the new JAR file. */
private final Path pathToOutputFile;
/** A collection of directories/ZIP/JAR files to include in the generated JAR file. */
private final ImmutableSortedSet<Path> entriesToJar;
/** If specified, the Main-Class to list in the manifest of the generated JAR file. */
@Nullable private final String mainClass;
/** If specified, the Manifest file to use for the generated JAR file. */
@Nullable private final Path manifestFile;
/** Indicates that manifest merging should occur. Defaults to true. */
private final boolean mergeManifests;
/** Indicates that the manifest should contain hashes of the entries. Defaults to false. */
private final boolean hashEntries;
/** A set of regex. If a file matches one of the regex it will not be included in the Jar. */
private final ImmutableSet<Pattern> blacklist;
public JarDirectoryStep(
ProjectFilesystem filesystem,
Path pathToOutputFile,
ImmutableSortedSet<Path> entriesToJar,
@Nullable String mainClass,
@Nullable Path manifestFile) {
this(
filesystem,
pathToOutputFile,
entriesToJar,
mainClass,
manifestFile,
true,
ImmutableSet.of());
}
public JarDirectoryStep(
ProjectFilesystem filesystem,
Path pathToOutputFile,
ImmutableSortedSet<Path> entriesToJar,
@Nullable String mainClass,
@Nullable Path manifestFile,
boolean mergeManifests,
ImmutableSet<Pattern> blacklist) {
this(
filesystem,
pathToOutputFile,
entriesToJar,
mainClass,
manifestFile,
mergeManifests,
false,
blacklist);
}
/**
* Creates a JAR from the specified entries (most often, classpath entries).
*
* <p>If an entry is a directory, then its files are traversed and added to the generated JAR.
*
* <p>If an entry is a file, then it is assumed to be a ZIP/JAR file, and its entries will be read
* and copied to the generated JAR.
*
* @param pathToOutputFile The directory that contains this path must exist before this command is
* executed.
* @param entriesToJar Paths to directories/ZIP/JAR files.
* @param mainClass If specified, the value for the Main-Class attribute in the manifest of the
* generated JAR.
* @param manifestFile If specified, the path to the manifest file to use with this JAR.
*/
public JarDirectoryStep(
ProjectFilesystem filesystem,
Path pathToOutputFile,
ImmutableSortedSet<Path> entriesToJar,
@Nullable String mainClass,
@Nullable Path manifestFile,
boolean mergeManifests,
boolean hashEntries,
ImmutableSet<Pattern> blacklist) {
this.filesystem = filesystem;
this.pathToOutputFile = pathToOutputFile;
this.entriesToJar = entriesToJar;
this.mainClass = mainClass;
this.manifestFile = manifestFile;
this.mergeManifests = mergeManifests;
this.hashEntries = hashEntries;
this.blacklist = blacklist;
}
private String getJarArgs() {
String result = "cf";
if (manifestFile != null) {
result += "m";
}
return result;
}
@Override
public String getShortName() {
return "jar";
}
@Override
public String getDescription(ExecutionContext context) {
return String.format(
"jar %s %s %s %s",
getJarArgs(),
pathToOutputFile,
manifestFile != null ? manifestFile : "",
Joiner.on(' ').join(entriesToJar));
}
@Override
public StepExecutionResult execute(ExecutionContext context) throws IOException {
JavacEventSinkToBuckEventBusBridge eventSink =
new JavacEventSinkToBuckEventBusBridge(context.getBuckEventBus());
return StepExecutionResult.of(
new JarBuilder(filesystem)
.setObserver(new LoggingJarBuilderObserver(eventSink))
.setEntriesToJar(entriesToJar)
.setMainClass(Optional.ofNullable(mainClass).orElse(null))
.setManifestFile(Optional.ofNullable(manifestFile).orElse(null))
.setShouldMergeManifests(mergeManifests)
.setShouldHashEntries(hashEntries)
.setEntryPatternBlacklist(blacklist)
.createJarFile(filesystem.resolve(pathToOutputFile)));
}
}