/* * Copyright 2011 Jesper Terkelsen. * * 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 dk.deck.localconsole; import dk.deck.console.CommandResult; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.concurrent.CountDownLatch; /** * * @author jester */ public class ProcessLocalConsole implements LocalConsole { private File directory; public ProcessLocalConsole(File directory) { this.directory = directory; } public ProcessLocalConsole() { this.directory = new File(System.getProperty("user.dir")); } @Override public String executeCommand(String command) throws IOException { return executeCommand(command, true); } @Override public String executeCommand(String command, boolean failOnExitNotZero) throws IOException { CommandResult result = executeCommandResult(command, failOnExitNotZero); return result.getOutput(); } @Override public CommandResult executeCommandResult(String command) throws IOException { return executeCommandResult(command, true); } @Override public CommandResult executeCommandResult(String command, boolean failOnExitNotZero) throws IOException { System.out.println("> " + command); CommandResult result = new CommandResult(); // This can cause problems if we escape spaces, we need a better splitter here. String[] commandAndArguments = command.split(" "); // We do not consider path currently ProcessBuilder builder = new ProcessBuilder(commandAndArguments); builder.directory(directory); builder.environment().put("LOCAL_CONSOLE", "true"); Process process = builder.start(); final InputStream errorOutput = process.getErrorStream(); final InputStream output = process.getInputStream(); CountDownLatch readLatch = new CountDownLatch(2); OutputReader outputReader = new OutputReader(output, readLatch); new Thread(outputReader).start(); OutputReader errprReader = new OutputReader(errorOutput, readLatch); new Thread(errprReader).start(); try { int exitCode = process.waitFor(); // Wait for process to finish readLatch.await(); // Wait for output to be consumed result.setExitCode(exitCode); result.setOutput(outputReader.getOutputBuffer().toString()); result.setErrorOutput(errprReader.getOutputBuffer().toString()); } catch (InterruptedException ex) { ex.printStackTrace(System.err); } return result; } /** * Read the output from a command. */ private static class OutputReader implements Runnable { private final InputStream output; private final StringBuilder outputBuffer = new StringBuilder(); private final Charset charset = Charset.forName("UTF-8"); private final CountDownLatch readLatch; public OutputReader(InputStream output, CountDownLatch readLatch) { this.output = output; this.readLatch = readLatch; } @Override public void run() { try { InputStreamReader reader = new InputStreamReader(output, charset); char[] buffer = new char[1024]; int length = reader.read(buffer); while (length != -1){ outputBuffer.append(buffer, 0, length); length = reader.read(buffer); } readLatch.countDown(); } catch (IOException ex) { ex.printStackTrace(System.err); } } public StringBuilder getOutputBuffer() { return outputBuffer; } } }