in gshell-parser/src/main/java/org/apache/geronimo/gshell/parser/visitor/ExecutingVisitor.java [161:250]
private Object executePiped(final Object[][] commands) throws CommandLineExecutionFailed, InterruptedException, IOException {
assert commands != null;
// Prepare IOs
final IO[] ios = new IO[commands.length];
PipedOutputStream pos = null;
IO io = this.context.getIo();
for (int i = 0; i < ios.length; i++) {
InputStream is = (i == 0) ? io.inputStream : new PipedInputStream(pos);
OutputStream os;
if (i == ios.length - 1) {
os = io.outputStream;
}
else {
os = pos = new PipedOutputStream();
}
ios[i] = new IO(is, new PrintStream(os), io.errorStream);
}
final List<Throwable> errors = new CopyOnWriteArrayList<Throwable>();
final AtomicReference<Object> ref = new AtomicReference<Object>();
final CountDownLatch latch = new CountDownLatch(commands.length);
for (int i = 0; i < commands.length; i++) {
final int idx = i;
Runnable r = new Runnable() {
public void run() {
try {
ShellContext pipedContext = new ShellContext() {
public Shell getShell() {
return ExecutingVisitor.this.context.getShell();
}
public IO getIo() {
return ios[idx];
}
public Variables getVariables() {
return ExecutingVisitor.this.context.getVariables();
}
};
Object obj = executor.execute(pipedContext, String.valueOf(commands[idx][0]), Arguments.shift(commands[idx]));
if (idx == commands.length - 1) {
ref.set(obj);
}
}
catch (Throwable t) {
errors.add(t);
}
finally {
if (idx > 0) {
Closer.close(ios[idx].inputStream);
}
if (idx < commands.length - 1) {
Closer.close(ios[idx].outputStream);
}
latch.countDown();
}
}
};
if (idx != commands.length - 1) {
createThread(r).start();
} else {
r.run();
}
}
latch.await();
if (!errors.isEmpty()) {
Throwable t = errors.get(0);
// Always preserve the type of notication throwables, reguardless of the trace
if (t instanceof Notification) {
throw (Notification)t;
}
// Otherwise wrap to preserve the trace
throw new CommandLineExecutionFailed(t);
}
return ref.get();
}