/* * 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.
*/
/** * A utility base class to simplify the implementation of tasks. * Provides support for running the task in a process and for * capturing output written by the task to stdout, stderr and * other writers where applicable. * @param <T> the implementing subclass
*/ abstractclass AbstractTask<T extends AbstractTask<T>> implements Task { protectedfinal ToolBox toolBox; protectedfinal Mode mode; privatefinal Map<OutputKind, String> redirects = new EnumMap<>(OutputKind.class); privatefinal Map<String, String> envVars = new HashMap<>(); private Expect expect = Expect.SUCCESS; int expectedExitCode = 0;
/** * Create a task that will execute in the specified mode. * @param mode the mode
*/ protected AbstractTask(ToolBox tb, Mode mode) {
toolBox = tb; this.mode = mode;
}
/** * Sets the expected outcome of the task and calls {@code run()}. * @param expect the expected outcome * @return the result of calling {@code run()}
*/ public Result run(Expect expect) {
expect(expect, Integer.MIN_VALUE); return run();
}
/** * Sets the expected outcome of the task and calls {@code run()}. * @param expect the expected outcome * @param exitCode the expected exit code if the expected outcome * is {@code FAIL} * @return the result of calling {@code run()}
*/ public Result run(Expect expect, int exitCode) {
expect(expect, exitCode); return run();
}
/** * Sets the expected outcome and expected exit code of the task. * The exit code will not be checked if the outcome is * {@code Expect.SUCCESS} or if the exit code is set to * {@code Integer.MIN_VALUE}. * @param expect the expected outcome * @param exitCode the expected exit code
*/ protectedvoid expect(Expect expect, int exitCode) { this.expect = expect; this.expectedExitCode = exitCode;
}
/** * Checks the exit code contained in a {@code Result} against the * expected outcome and exit value * @param result the result object * @return the result object * @throws TaskError if the exit code stored in the result object * does not match the expected outcome and exit code.
*/ protected Result checkExit(Result result) throws TaskError { switch (expect) { case SUCCESS: if (result.exitCode != 0) {
result.writeAll(); thrownew TaskError("Task " + name() + " failed: rc=" + result.exitCode);
} break;
case FAIL: if (result.exitCode == 0) {
result.writeAll(); thrownew TaskError("Task " + name() + " succeeded unexpectedly");
}
/** * Sets an environment variable to be used by this task. * @param name the name of the environment variable * @param value the value for the environment variable * @return this task object * @throws IllegalStateException if the task mode is not {@code EXEC}
*/ public T envVar(String name, String value) { if (mode != Mode.EXEC) thrownew IllegalStateException();
envVars.put(name, value); return (T) this;
}
/** * Redirects output from an output stream to a file. * @param outputKind the name of the stream to be redirected. * @param path the file * @return this task object * @throws IllegalStateException if the task mode is not {@code EXEC}
*/ public T redirect(OutputKind outputKind, String path) { if (mode != Mode.EXEC) thrownew IllegalStateException();
redirects.put(outputKind, path); return (T) this;
}
/** * Returns a {@code ProcessBuilder} initialized with any * redirects and environment variables that have been set. * @return a {@code ProcessBuilder}
*/ protected ProcessBuilder getProcessBuilder() { if (mode != Mode.EXEC) thrownew IllegalStateException();
ProcessBuilder pb = new ProcessBuilder(); if (redirects.get(OutputKind.STDOUT) != null)
pb.redirectOutput(new File(redirects.get(OutputKind.STDOUT))); if (redirects.get(OutputKind.STDERR) != null)
pb.redirectError(new File(redirects.get(OutputKind.STDERR)));
pb.environment().putAll(envVars); return pb;
}
/** * Collects the output from a process and saves it in a {@code Result}. * @param tb the {@code ToolBox} containing the task {@code t} * @param t the task initiating the process * @param p the process * @return a Result object containing the output from the process and its * exit value. * @throws InterruptedException if the thread is interrupted
*/ protected Result runProcess(ToolBox tb, Task t, Process p) throws InterruptedException { if (mode != Mode.EXEC) thrownew IllegalStateException();
ProcessOutput sysOut = new ProcessOutput(p.getInputStream()).start();
ProcessOutput sysErr = new ProcessOutput(p.getErrorStream()).start();
sysOut.waitUntilDone();
sysErr.waitUntilDone(); int rc = p.waitFor();
Map<OutputKind, String> outputMap = new EnumMap<>(OutputKind.class);
outputMap.put(OutputKind.STDOUT, sysOut.getOutput());
outputMap.put(OutputKind.STDERR, sysErr.getOutput()); return checkExit(new Result(toolBox, t, rc, outputMap));
}
/** * Thread-friendly class to read the output from a process until the stream * is exhausted.
*/ staticclass ProcessOutput implements Runnable {
ProcessOutput(InputStream from) {
in = new BufferedReader(new InputStreamReader(from));
out = new StringBuilder();
}
/** * Utility class to simplify the handling of temporarily setting a * new stream for System.out or System.err.
*/ staticclass StreamOutput { // Functional interface to set a stream. // Expected use: System::setOut, System::setErr interface Initializer { void set(PrintStream s);
}
privatefinal ByteArrayOutputStream baos = new ByteArrayOutputStream(); privatefinal PrintStream ps = new PrintStream(baos); privatefinal PrintStream prev; privatefinal Initializer init;
/** * Closes the stream and returns the contents that were written to it. * @return the contents that were written to it.
*/
String close() {
init.set(prev);
ps.close(); return baos.toString();
}
}
/** * Utility class to simplify the handling of creating an in-memory PrintWriter.
*/ staticclass WriterOutput { privatefinal StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw);
/** * Closes the stream and returns the contents that were written to it. * @return the contents that were written to it.
*/
String close() {
pw.close(); return sw.toString();
}
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.