1 /* 2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package toolbox; 25 26 import java.io.PrintStream; 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.List; 30 import java.util.Map; 31 import static toolbox.ToolBox.lineSeparator; 32 33 /** 34 * The supertype for tasks. 35 * Complex operations are modeled by building and running a "Task" object. 36 * Tasks are typically configured in a fluent series of calls. 37 */ 38 public interface Task { 39 /** 40 * Returns the name of the task. 41 * @return the name of the task 42 */ name()43 String name(); 44 45 /** 46 * Executes the task as currently configured. 47 * @return a Result object containing the results of running the task 48 * @throws TaskError if the outcome of the task was not as expected 49 */ run()50 Result run() throws TaskError; 51 52 /** 53 * Exception thrown by {@code Task.run} when the outcome is not as 54 * expected. 55 */ 56 public static class TaskError extends Error { 57 /** 58 * Creates a TaskError object with the given message. 59 * @param message the message 60 */ TaskError(String message)61 public TaskError(String message) { 62 super(message); 63 } 64 } 65 66 /** 67 * An enum to indicate the mode a task should use it is when executed. 68 */ 69 public enum Mode { 70 /** 71 * The task should use the interface used by the command 72 * line launcher for the task. 73 * For example, for javac: com.sun.tools.javac.Main.compile 74 */ 75 CMDLINE, 76 /** 77 * The task should use a publicly defined API for the task. 78 * For example, for javac: javax.tools.JavaCompiler 79 */ 80 API, 81 /** 82 * The task should use the standard launcher for the task. 83 * For example, $JAVA_HOME/bin/javac 84 */ 85 EXEC 86 } 87 88 /** 89 * An enum to indicate the expected success or failure of executing a task. 90 */ 91 public enum Expect { 92 /** It is expected that the task will complete successfully. */ 93 SUCCESS, 94 /** It is expected that the task will not complete successfully. */ 95 FAIL 96 } 97 98 /** 99 * An enum to identify the streams that may be written by a {@code Task}. 100 */ 101 public enum OutputKind { 102 /** Identifies output written to {@code System.out} or {@code stdout}. */ 103 STDOUT, 104 /** Identifies output written to {@code System.err} or {@code stderr}. */ 105 STDERR, 106 /** Identifies output written to a stream provided directly to the task. */ 107 DIRECT 108 }; 109 110 /** 111 * The results from running a {@link Task}. 112 * The results contain the exit code returned when the tool was invoked, 113 * and a map containing the output written to any streams during the 114 * execution of the tool. 115 * All tools support "stdout" and "stderr". 116 * Tools that take an explicit PrintWriter save output written to that 117 * stream as "main". 118 */ 119 public static class Result { 120 final ToolBox toolBox; 121 final Task task; 122 final int exitCode; 123 final Map<OutputKind, String> outputMap; 124 Result(ToolBox toolBox, Task task, int exitCode, Map<OutputKind, String> outputMap)125 Result(ToolBox toolBox, Task task, int exitCode, Map<OutputKind, String> outputMap) { 126 this.toolBox = toolBox; 127 this.task = task; 128 this.exitCode = exitCode; 129 this.outputMap = outputMap; 130 } 131 132 /** 133 * Returns the content of a specified stream. 134 * @param outputKind the kind of the selected stream 135 * @return the content that was written to that stream when the tool 136 * was executed. 137 */ getOutput(OutputKind outputKind)138 public String getOutput(OutputKind outputKind) { 139 return outputMap.get(outputKind); 140 } 141 142 /** 143 * Returns the content of named streams as a list of lines. 144 * @param outputKinds the kinds of the selected streams 145 * @return the content that was written to the given streams when the tool 146 * was executed. 147 */ getOutputLines(OutputKind... outputKinds)148 public List<String> getOutputLines(OutputKind... outputKinds) { 149 List<String> result = new ArrayList<>(); 150 for (OutputKind outputKind : outputKinds) { 151 result.addAll(Arrays.asList(outputMap.get(outputKind).split(lineSeparator))); 152 } 153 return result; 154 } 155 156 /** 157 * Writes the content of the specified stream to the log. 158 * @param kind the kind of the selected stream 159 * @return this Result object 160 */ write(OutputKind kind)161 public Result write(OutputKind kind) { 162 PrintStream out = toolBox.out; 163 String text = getOutput(kind); 164 if (text == null || text.isEmpty()) 165 out.println("[" + task.name() + ":" + kind + "]: empty"); 166 else { 167 out.println("[" + task.name() + ":" + kind + "]:"); 168 out.print(text); 169 } 170 return this; 171 } 172 173 /** 174 * Writes the content of all streams with any content to the log. 175 * @return this Result object 176 */ writeAll()177 public Result writeAll() { 178 PrintStream out = toolBox.out; 179 outputMap.forEach((name, text) -> { 180 if (!text.isEmpty()) { 181 out.println("[" + name + "]:"); 182 out.print(text); 183 } 184 }); 185 return this; 186 } 187 } 188 } 189 190