Java tutorial
/* * 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.cxx; import com.facebook.buck.event.ConsoleEvent; 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.facebook.buck.util.CommandSplitter; import com.facebook.buck.util.ProcessExecutor; import com.facebook.buck.util.ProcessExecutorParams; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; /** * Create an object archive with ar. */ public class ArchiveStep implements Step { private final ProjectFilesystem filesystem; private final ImmutableMap<String, String> environment; private final ImmutableList<String> archiverCommand; private final ImmutableList<String> archiverFlags; private final ImmutableList<String> archiverExtraFlags; private final Path output; private final ImmutableList<Path> inputs; private final Archiver archiver; public ArchiveStep(ProjectFilesystem filesystem, ImmutableMap<String, String> environment, ImmutableList<String> archiverCommand, ImmutableList<String> archiverFlags, ImmutableList<String> archiverExtraFlags, Path output, ImmutableList<Path> inputs, Archiver archiver) { Preconditions.checkArgument(!output.isAbsolute()); // Our current support for thin archives requires that all the inputs are relative paths from // the same cell as the output. for (Path input : inputs) { Preconditions.checkArgument(!input.isAbsolute()); } this.filesystem = filesystem; this.environment = environment; this.archiverCommand = archiverCommand; this.archiverFlags = archiverFlags; this.archiverExtraFlags = archiverExtraFlags; this.output = output; this.inputs = inputs; this.archiver = archiver; } private ImmutableList<String> getAllInputs() throws IOException { ImmutableList.Builder<String> allInputs = ImmutableList.builder(); // Inputs can either be files or directories. In the case of the latter, we add all files // found from a recursive search. for (Path input : inputs) { if (filesystem.isDirectory(input)) { // We make sure to sort the files we find under the directories so that we get // deterministic output. final Set<String> dirFiles = new TreeSet<>(); filesystem.walkFileTree(filesystem.resolve(input), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { dirFiles.add(file.toString()); return FileVisitResult.CONTINUE; } }); allInputs.addAll(dirFiles); } else { allInputs.add(input.toString()); } } return allInputs.build(); } private ProcessExecutor.Result runArchiver(ExecutionContext context, final ImmutableList<String> command) throws IOException, InterruptedException { Map<String, String> env = new HashMap<>(context.getEnvironment()); env.putAll(environment); ProcessExecutorParams params = ProcessExecutorParams.builder().setDirectory(filesystem.getRootPath()) .setEnvironment(env).setCommand(command).build(); ProcessExecutor.Result result = context.getProcessExecutor().launchAndExecute(params); if (result.getExitCode() != 0 && result.getStderr().isPresent()) { context.getBuckEventBus().post(ConsoleEvent.create(Level.SEVERE, result.getStderr().get())); } return result; } @Override public StepExecutionResult execute(ExecutionContext context) throws IOException, InterruptedException { ImmutableList<String> allInputs = getAllInputs(); if (allInputs.isEmpty()) { filesystem.writeContentsToPath("!<arch>\n", output); return StepExecutionResult.SUCCESS; } else { ImmutableList<String> archiveCommandPrefix = ImmutableList.<String>builder().addAll(archiverCommand) .addAll(archiverFlags).addAll(archiverExtraFlags).addAll(archiver.outputArgs(output.toString())) .build(); CommandSplitter commandSplitter = new CommandSplitter(archiveCommandPrefix); for (ImmutableList<String> command : commandSplitter.getCommandsForArguments(allInputs)) { ProcessExecutor.Result result = runArchiver(context, command); if (result.getExitCode() != 0) { return StepExecutionResult.of(result); } } return StepExecutionResult.SUCCESS; } } @Override public String getDescription(ExecutionContext context) { ImmutableList.Builder<String> command = ImmutableList.<String>builder().add("ar").addAll(archiverFlags) .addAll(archiverExtraFlags).addAll(archiver.outputArgs(output.toString())) .addAll(Iterables.transform(inputs, Object::toString)); return Joiner.on(' ').join(command.build()); } @Override public String getShortName() { return "archive"; } }