/* * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package toolbox; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import static toolbox.ToolBox.lineSeparator; /** * The supertype for tasks. * Complex operations are modeled by building and running a "Task" object. * Tasks are typically configured in a fluent series of calls. */ public interface Task { /** * Returns the name of the task. * @return the name of the task */ String name(); /** * Executes the task as currently configured. * @return a Result object containing the results of running the task * @throws TaskError if the outcome of the task was not as expected */ Result run() throws TaskError; /** * Exception thrown by {@code Task.run} when the outcome is not as * expected. */ public static class TaskError extends Error { /** * Creates a TaskError object with the given message. * @param message the message */ public TaskError(String message) { super(message); } } /** * An enum to indicate the mode a task should use it is when executed. */ public enum Mode { /** * The task should use the interface used by the command * line launcher for the task. * For example, for javac: com.sun.tools.javac.Main.compile */ CMDLINE, /** * The task should use a publicly defined API for the task. * For example, for javac: javax.tools.JavaCompiler */ API, /** * The task should use the standard launcher for the task. * For example, $JAVA_HOME/bin/javac */ EXEC } /** * An enum to indicate the expected success or failure of executing a task. */ public enum Expect { /** It is expected that the task will complete successfully. */ SUCCESS, /** It is expected that the task will not complete successfully. */ FAIL } /** * An enum to identify the streams that may be written by a {@code Task}. */ public enum OutputKind { /** Identifies output written to {@code System.out} or {@code stdout}. */ STDOUT, /** Identifies output written to {@code System.err} or {@code stderr}. */ STDERR, /** Identifies output written to a stream provided directly to the task. */ DIRECT }; /** * The results from running a {@link Task}. * The results contain the exit code returned when the tool was invoked, * and a map containing the output written to any streams during the * execution of the tool. * All tools support "stdout" and "stderr". * Tools that take an explicit PrintWriter save output written to that * stream as "main". */ public static class Result { final ToolBox toolBox; final Task task; final int exitCode; final Map<OutputKind, String> outputMap; Result(ToolBox toolBox, Task task, int exitCode, Map<OutputKind, String> outputMap) { this.toolBox = toolBox; this.task = task; this.exitCode = exitCode; this.outputMap = outputMap; } /** * Returns the content of a specified stream. * @param outputKind the kind of the selected stream * @return the content that was written to that stream when the tool * was executed. */ public String getOutput(OutputKind outputKind) { return outputMap.get(outputKind); } /** * Returns the content of named streams as a list of lines. * @param outputKinds the kinds of the selected streams * @return the content that was written to the given streams when the tool * was executed. */ public List<String> getOutputLines(OutputKind... outputKinds) { List<String> result = new ArrayList<>(); for (OutputKind outputKind : outputKinds) { result.addAll(Arrays.asList(outputMap.get(outputKind).split(lineSeparator))); } return result; } /** * Writes the content of the specified stream to the log. * @param kind the kind of the selected stream * @return this Result object */ public Result write(OutputKind kind) { PrintStream out = toolBox.out; String text = getOutput(kind); if (text == null || text.isEmpty()) out.println("[" + task.name() + ":" + kind + "]: empty"); else { out.println("[" + task.name() + ":" + kind + "]:"); out.print(text); } return this; } /** * Writes the content of all streams with any content to the log. * @return this Result object */ public Result writeAll() { PrintStream out = toolBox.out; outputMap.forEach((name, text) -> { if (!text.isEmpty()) { out.println("[" + name + "]:"); out.print(text); } }); return this; } } }