|
|
@ -110,7 +110,54 @@ public abstract class FS { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final static Logger LOG = LoggerFactory.getLogger(FS.class); |
|
|
|
/** |
|
|
|
|
|
|
|
* Result of an executed process. The caller is responsible to close the |
|
|
|
|
|
|
|
* contained {@link TemporaryBuffer}s |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @since 4.2 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static class ExecutionResult { |
|
|
|
|
|
|
|
private TemporaryBuffer stdout; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private TemporaryBuffer stderr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int rc; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @param stdout |
|
|
|
|
|
|
|
* @param stderr |
|
|
|
|
|
|
|
* @param rc |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public ExecutionResult(TemporaryBuffer stdout, TemporaryBuffer stderr, |
|
|
|
|
|
|
|
int rc) { |
|
|
|
|
|
|
|
this.stdout = stdout; |
|
|
|
|
|
|
|
this.stderr = stderr; |
|
|
|
|
|
|
|
this.rc = rc; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @return buffered standard output stream |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public TemporaryBuffer getStdout() { |
|
|
|
|
|
|
|
return stdout; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @return buffered standard error stream |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public TemporaryBuffer getStderr() { |
|
|
|
|
|
|
|
return stderr; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @return the return code of the process |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getRc() { |
|
|
|
|
|
|
|
return rc; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final static Logger LOG = LoggerFactory.getLogger(FS.class); |
|
|
|
|
|
|
|
|
|
|
|
/** The auto-detected implementation selected for this operating system and JRE. */ |
|
|
|
/** The auto-detected implementation selected for this operating system and JRE. */ |
|
|
|
public static final FS DETECTED = detect(); |
|
|
|
public static final FS DETECTED = detect(); |
|
|
@ -1004,10 +1051,10 @@ public abstract class FS { |
|
|
|
pool.shutdown(); // Disable new tasks from being submitted
|
|
|
|
pool.shutdown(); // Disable new tasks from being submitted
|
|
|
|
try { |
|
|
|
try { |
|
|
|
// Wait a while for existing tasks to terminate
|
|
|
|
// Wait a while for existing tasks to terminate
|
|
|
|
if (!pool.awaitTermination(5, TimeUnit.SECONDS)) { |
|
|
|
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { |
|
|
|
pool.shutdownNow(); // Cancel currently executing tasks
|
|
|
|
pool.shutdownNow(); // Cancel currently executing tasks
|
|
|
|
// Wait a while for tasks to respond to being canceled
|
|
|
|
// Wait a while for tasks to respond to being canceled
|
|
|
|
if (!pool.awaitTermination(5, TimeUnit.SECONDS)) |
|
|
|
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) |
|
|
|
hasShutdown = false; |
|
|
|
hasShutdown = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (InterruptedException ie) { |
|
|
|
} catch (InterruptedException ie) { |
|
|
@ -1034,6 +1081,31 @@ public abstract class FS { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public abstract ProcessBuilder runInShell(String cmd, String[] args); |
|
|
|
public abstract ProcessBuilder runInShell(String cmd, String[] args); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Execute a command defined by a {@link ProcessBuilder}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param pb |
|
|
|
|
|
|
|
* The command to be executed |
|
|
|
|
|
|
|
* @param in |
|
|
|
|
|
|
|
* The standard input stream passed to the process |
|
|
|
|
|
|
|
* @return The result of the executed command |
|
|
|
|
|
|
|
* @throws InterruptedException |
|
|
|
|
|
|
|
* @throws IOException |
|
|
|
|
|
|
|
* @since 4.2 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public ExecutionResult execute(ProcessBuilder pb, InputStream in) |
|
|
|
|
|
|
|
throws IOException, InterruptedException { |
|
|
|
|
|
|
|
TemporaryBuffer stdout = new TemporaryBuffer.LocalFile(null); |
|
|
|
|
|
|
|
TemporaryBuffer stderr = new TemporaryBuffer.Heap(1024, 1024 * 1024); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
int rc = runProcess(pb, stdout, stderr, in); |
|
|
|
|
|
|
|
return new ExecutionResult(stdout, stderr, rc); |
|
|
|
|
|
|
|
} finally { |
|
|
|
|
|
|
|
stdout.close(); |
|
|
|
|
|
|
|
stderr.close(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static class Holder<V> { |
|
|
|
private static class Holder<V> { |
|
|
|
final V value; |
|
|
|
final V value; |
|
|
|
|
|
|
|
|
|
|
|