kitaev@213: /* kitaev@213: * Copyright (c) 2011 TMate Software Ltd kitaev@213: * kitaev@213: * This program is free software; you can redistribute it and/or modify kitaev@213: * it under the terms of the GNU General Public License as published by kitaev@213: * the Free Software Foundation; version 2 of the License. kitaev@213: * kitaev@213: * This program is distributed in the hope that it will be useful, kitaev@213: * but WITHOUT ANY WARRANTY; without even the implied warranty of kitaev@213: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the kitaev@213: * GNU General Public License for more details. kitaev@213: * kitaev@213: * For information on how to redistribute this software under kitaev@213: * the terms of a license other than GNU General Public License kitaev@213: * contact TMate Software at support@hg4j.com kitaev@213: */ kitaev@213: package org.tmatesoft.hg.test; kitaev@213: kitaev@213: import java.io.File; kitaev@213: import java.io.IOException; kitaev@213: import java.io.InputStreamReader; kitaev@213: import java.nio.CharBuffer; kitaev@213: import java.util.ArrayList; kitaev@213: import java.util.Arrays; kitaev@213: import java.util.LinkedList; kitaev@213: import java.util.StringTokenizer; kitaev@213: kitaev@213: /** kitaev@213: * kitaev@213: * @author Artem Tikhomirov kitaev@213: * @author TMate Software Ltd. kitaev@213: */ kitaev@213: public class ExecHelper { kitaev@213: kitaev@213: private final OutputParser parser; kitaev@213: private File dir; kitaev@213: private int exitValue; kitaev@213: kitaev@213: public ExecHelper(OutputParser outParser, File workingDir) { kitaev@213: parser = outParser; kitaev@213: dir = workingDir; kitaev@213: } kitaev@213: kitaev@213: public void run(String... cmd) throws IOException, InterruptedException { kitaev@213: ProcessBuilder pb = null; kitaev@213: if (System.getProperty("os.name").startsWith("Windows")) { kitaev@213: StringTokenizer st = new StringTokenizer(System.getenv("PATH"), ";"); kitaev@213: while (st.hasMoreTokens()) { kitaev@213: File pe = new File(st.nextToken()); kitaev@213: if (new File(pe, cmd[0] + ".exe").exists()) { kitaev@213: break; kitaev@213: } kitaev@213: // PATHEXT controls precedence of .exe, .bat and .cmd files, ususlly .exe wins kitaev@213: if (new File(pe, cmd[0] + ".bat").exists() || new File(pe, cmd[0] + ".cmd").exists()) { kitaev@213: ArrayList command = new ArrayList(); kitaev@213: command.add("cmd.exe"); kitaev@213: command.add("/C"); kitaev@213: command.addAll(Arrays.asList(cmd)); kitaev@213: pb = new ProcessBuilder(command); kitaev@213: break; kitaev@213: } kitaev@213: } kitaev@213: } kitaev@213: if (pb == null) { kitaev@213: pb = new ProcessBuilder(cmd); kitaev@213: } kitaev@213: Process p = pb.directory(dir).redirectErrorStream(true).start(); kitaev@213: InputStreamReader stdOut = new InputStreamReader(p.getInputStream()); kitaev@213: LinkedList l = new LinkedList(); kitaev@213: int r = -1; kitaev@213: CharBuffer b = null; kitaev@213: do { kitaev@213: if (b == null || b.remaining() < b.capacity() / 3) { kitaev@213: b = CharBuffer.allocate(512); kitaev@213: l.add(b); kitaev@213: } kitaev@213: r = stdOut.read(b); kitaev@213: } while (r != -1); kitaev@213: int total = 0; kitaev@213: for (CharBuffer cb : l) { kitaev@213: total += cb.position(); kitaev@213: cb.flip(); kitaev@213: } kitaev@213: CharBuffer res = CharBuffer.allocate(total); kitaev@213: for (CharBuffer cb : l) { kitaev@213: res.put(cb); kitaev@213: } kitaev@213: res.flip(); kitaev@213: p.waitFor(); kitaev@213: exitValue = p.exitValue(); kitaev@213: parser.parse(res); kitaev@213: } kitaev@213: kitaev@213: public int getExitValue() { kitaev@213: return exitValue; kitaev@213: } kitaev@213: kitaev@213: public void cwd(File wd) { kitaev@213: dir = wd; kitaev@213: } kitaev@213: }