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