jnr.posix.util.ExecIt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cassandra-driver Show documentation
Show all versions of cassandra-driver Show documentation
Shaded version of DataStax Java Driver for Apache Cassandra
/***** BEGIN LICENSE BLOCK *****
* Version: CPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Common Public
* License Version 1.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.eclipse.org/legal/cpl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2008 JRuby Community
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the CPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the CPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package jnr.posix.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import jnr.posix.POSIXHandler;
public class ExecIt {
protected final POSIXHandler handler;
/** Creates a new instance of ShellLauncher */
public ExecIt(POSIXHandler handler) {
this.handler = handler;
}
public int runAndWait(String... args) throws IOException, InterruptedException {
return runAndWait(handler.getOutputStream(), args);
}
public int runAndWait(OutputStream output, String... args) throws IOException, InterruptedException {
return runAndWait(output, handler.getErrorStream(), args);
}
public int runAndWait(OutputStream output, OutputStream error, String... args) throws IOException, InterruptedException {
Process process = run(args);
handleStreams(process, handler.getInputStream(), output, error);
return process.waitFor();
}
public Process run(String... args) throws IOException {
File cwd = handler.getCurrentWorkingDirectory();
return Runtime.getRuntime().exec(args, handler.getEnv(), cwd);
}
private static class StreamPumper extends Thread {
private InputStream in;
private OutputStream out;
private boolean onlyIfAvailable;
private volatile boolean quit;
private final Object waitLock = new Object();
StreamPumper(InputStream in, OutputStream out, boolean avail) {
this.in = in;
this.out = out;
this.onlyIfAvailable = avail;
}
public void run() {
byte[] buf = new byte[1024];
int numRead;
boolean hasReadSomething = false;
try {
while (!quit) {
// The problem we trying to solve below: STDIN in Java is blocked and
// non-interruptible, so if we invoke read on it, we might never be able to
// interrupt such thread. So, we use in.available() to see if there is any
// input ready, and only then read it. But this approach can't tell whether
// the end of stream reached or not, so we might end up looping right at the
// end of the stream. Well, at least, we can improve the situation by checking
// if some input was ever available, and if so, not checking for available
// anymore, and just go to read.
if (onlyIfAvailable && !hasReadSomething) {
if (in.available() == 0) {
synchronized (waitLock) {
waitLock.wait(10);
}
continue;
} else {
hasReadSomething = true;
}
}
if ((numRead = in.read(buf)) == -1) {
break;
}
out.write(buf, 0, numRead);
}
} catch (Exception e) {
} finally {
if (onlyIfAvailable) {
// We need to close the out, since some
// processes would just wait for the stream
// to be closed before they process its content,
// and produce the output. E.g.: "cat".
try { out.close(); } catch (IOException ioe) {}
}
}
}
public void quit() {
this.quit = true;
synchronized (waitLock) {
waitLock.notify();
}
}
}
private void handleStreams(Process p, InputStream in, OutputStream out, OutputStream err) throws IOException {
InputStream pOut = p.getInputStream();
InputStream pErr = p.getErrorStream();
OutputStream pIn = p.getOutputStream();
StreamPumper t1 = new StreamPumper(pOut, out, false);
StreamPumper t2 = new StreamPumper(pErr, err, false);
StreamPumper t3 = new StreamPumper(in, pIn, true);
t1.start();
t2.start();
t3.start();
try { t1.join(); } catch (InterruptedException ie) {}
try { t2.join(); } catch (InterruptedException ie) {}
t3.quit();
try { err.flush(); } catch (IOException io) {}
try { out.flush(); } catch (IOException io) {}
try { pIn.close(); } catch (IOException io) {}
try { pOut.close(); } catch (IOException io) {}
try { pErr.close(); } catch (IOException io) {}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy