package org.argeo.slc.maven.plugin; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import org.apache.commons.io.IOUtils; public class SystemCall implements Runnable { private String execDir; private String cmd = null; private String[] command = null; private boolean synchronous = true; private boolean captureStdIn = false; public SystemCall() { } public SystemCall(String execDir, String cmd, boolean captureStdIn) { super(); this.execDir = execDir; this.cmd = cmd; this.synchronous = true; this.captureStdIn = captureStdIn; } public SystemCall(String execDir, String[] command, boolean captureStdIn) { super(); this.execDir = execDir; this.command = command; this.synchronous = true; this.captureStdIn = captureStdIn; } public void run() { try { // Execution directory File dir = null; if (execDir != null) { // Replace '/' by local file separator, for portability execDir.replace('/', File.separatorChar); dir = new File(execDir).getCanonicalFile(); } final Process process; if (cmd != null) { process = Runtime.getRuntime().exec(cmd, null, dir); } else if (command != null) { process = Runtime.getRuntime().exec(command, null, dir); ; } else { throw new RuntimeException("No command specified"); } Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { if (process != null) { try { process.exitValue(); } catch (Exception e) { process.destroy(); System.err.println("Killed process " + process); } } } }); // Manage standard streams StreamReaderThread stdOutThread = new StreamReaderThread(process .getInputStream(), false); stdOutThread.start(); // TODO: understand why streams are not properly flushed StreamReaderThread stdErrThread = new StreamReaderThread(process .getInputStream(), false); stdErrThread.start(); if (captureStdIn) new StdInThread(process.getOutputStream()).start(); // Wait for the end of the process if (synchronous) { int exitCode = process.waitFor(); if (exitCode != 0) { Thread.sleep(5000);// leave the process a chance to log System.err.println("Process return exit code " + exitCode); } } else { // asynchronous: return } } catch (Exception e) { throw new RuntimeException("Could not execute command " + cmd, e); } } /** * Shortcut method returning the current exec dir if the specified one is * null. */ private String getUsedDir(File dir) { if (dir == null) return System.getProperty("user.dir"); else return dir.getPath(); } public void setCmd(String command) { this.cmd = command; } public void setExecDir(String execdir) { this.execDir = execdir; } public void setCommand(String[] command) { this.command = command; } protected synchronized void write(String str, boolean isErr) { if (isErr) { System.err.print(str); System.err.flush(); } else { System.out.print(str); System.out.flush(); } notifyAll(); } protected class StreamReaderThread extends Thread { private final InputStream stream; private final boolean isErr; public StreamReaderThread(InputStream stream, boolean isErr) { this.stream = stream; this.isErr = isErr; } public void run() { // BufferedReader in = null; InputStreamReader isr = null; try { isr = new InputStreamReader(stream); int c; StringBuffer buf = new StringBuffer(256); char lastCr = '\n'; while ((c = isr.read()) != -1) { char cr = (char) c; buf.append(cr); boolean write = false; if (lastCr == '>' && cr == ' ') write = true; else if (cr == '\n') write = true; lastCr = cr; if (write) { write(buf.toString(), isErr); buf = new StringBuffer(256); } // if (isErr) { // System.err.print(cr); // if (cr == '\n' || cr == '>') // System.err.flush(); // } else { // System.out.print(cr); // if (cr == '\n' || cr == '>') // System.out.flush(); // } } // String line = null; // while ((line = in.readLine()) != null) { // stdOutCallback(line); // System.out. // } } catch (IOException e) { // catch silently // because the other methods // to check whether the stream // is closed would probably // be to costly } finally { if (synchronous) IOUtils.closeQuietly(isr); } } } protected class StdInThread extends Thread { private final OutputStream stream; public StdInThread(OutputStream stream) { this.stream = stream; } public void run() { // BufferedReader in = null; // Writer out = null; InputStreamReader isr = null; try { // out = new OutputStreamWriter(stream); isr = new InputStreamReader(System.in); int c; while ((c = isr.read()) != -1) { stream.write(c); stream.flush(); } /* * in = new BufferedReader(new InputStreamReader(System.in)); * String line = null; while ((line = in.readLine()) != null) { * out.write(line); out.write("\n"); out.flush(); } */ } catch (IOException e) { throw new RuntimeException("Could not write to stdin stream", e); } finally { if (synchronous) { IOUtils.closeQuietly(isr); // IOUtils.closeQuietly(in); // IOUtils.closeQuietly(out); } } } } }