use of org.apache.felix.gogo.runtime.Pipe.Result in project felix by apache.
the class Closure method execute.
@SuppressWarnings("unchecked")
private Object execute(List<Object> values, Channel capturingOutput) throws Exception {
if (null != values) {
parmv = new ArrayList<>(values);
parms = new ArgList(parmv);
} else if (null != parent) {
// inherit parent closure parameters
parmv = parent.parmv != null ? new ArrayList<>(parent.parmv) : null;
parms = parmv != null ? new ArgList(parmv) : null;
} else {
// inherit session parameters
Object args = session.get("args");
if (null != args && args instanceof List<?>) {
parmv = new ArrayList<>((List<Object>) args);
parms = new ArgList(parmv);
}
}
Result last = null;
Operator operator = null;
for (Iterator<Executable> iterator = program.tokens().iterator(); iterator.hasNext(); ) {
Operator prevOperator = operator;
Executable executable = iterator.next();
if (iterator.hasNext()) {
operator = (Operator) iterator.next();
} else {
operator = null;
}
if (prevOperator != null) {
if (Token.eq("&&", prevOperator)) {
if (!last.isSuccess()) {
continue;
}
} else if (Token.eq("||", prevOperator)) {
if (last.isSuccess()) {
continue;
}
}
}
Channel[] streams;
boolean[] toclose = new boolean[10];
if (Pipe.getCurrentPipe() != null) {
streams = Pipe.getCurrentPipe().streams.clone();
} else {
streams = new Channel[10];
System.arraycopy(session.channels, 0, streams, 0, 3);
}
if (capturingOutput != null) {
streams[1] = capturingOutput;
toclose[1] = true;
}
CommandSessionImpl.JobImpl job;
if (executable instanceof Pipeline) {
Pipeline pipeline = (Pipeline) executable;
List<Executable> exec = pipeline.tokens();
Token s = exec.get(0);
Token e = exec.get(exec.size() - 1);
Token t = program.subSequence(s.start - program.start, e.start + e.length - program.start);
job = session().createJob(t);
for (int i = 0; i < exec.size(); i++) {
Statement ex = (Statement) exec.get(i);
Operator op = i < exec.size() - 1 ? (Operator) exec.get(++i) : null;
Channel[] nstreams;
boolean[] ntoclose;
boolean endOfPipe;
if (i == exec.size() - 1) {
nstreams = streams;
ntoclose = toclose;
endOfPipe = true;
} else if (Token.eq("|", op)) {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
nstreams = streams.clone();
nstreams[1] = Channels.newChannel(pos);
ntoclose = toclose.clone();
ntoclose[1] = true;
streams[0] = Channels.newChannel(pis);
toclose[0] = true;
endOfPipe = false;
} else if (Token.eq("|&", op)) {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
nstreams = streams.clone();
nstreams[1] = nstreams[2] = Channels.newChannel(pos);
ntoclose = toclose.clone();
ntoclose[1] = ntoclose[2] = true;
streams[0] = Channels.newChannel(pis);
toclose[0] = true;
endOfPipe = false;
} else {
throw new IllegalStateException("Unrecognized pipe operator: '" + op + "'");
}
Pipe pipe = new Pipe(this, job, ex, nstreams, ntoclose, endOfPipe);
job.addPipe(pipe);
}
} else {
job = session().createJob(executable);
Pipe pipe = new Pipe(this, job, (Statement) executable, streams, toclose, true);
job.addPipe(pipe);
}
// Start pipe in background
if (operator != null && Token.eq("&", operator)) {
job.start(Status.Background);
last = new Result((Object) null);
} else // Start in foreground and wait for results
{
last = job.start(Status.Foreground);
if (last == null) {
last = new Result((Object) null);
} else if (last.exception != null) {
throw last.exception;
}
}
}
return last == null ? null : last.result;
}
use of org.apache.felix.gogo.runtime.Pipe.Result in project felix by apache.
the class Pipe method doCall.
private Result doCall() {
// The errChannel will be used to print errors to the error stream
// Before the command is actually executed (i.e. during the initialization,
// including the redirection processing), it will be the original error stream.
// This value may be modified by redirections and the redirected error stream
// will be effective just before actually running the command.
WritableByteChannel errChannel = (WritableByteChannel) streams[2];
ThreadIO threadIo = closure.session().threadIO();
try {
List<Token> tokens = statement.redirections();
for (int i = 0; i < tokens.size(); i++) {
Token t = tokens.get(i);
Matcher m;
if ((m = Pattern.compile("(?:([0-9])?|(&)?)>(>)?").matcher(t)).matches()) {
int fd;
if (m.group(1) != null) {
fd = Integer.parseInt(m.group(1));
} else if (m.group(2) != null) {
// both 1 and 2
fd = -1;
} else {
fd = 1;
}
boolean append = m.group(3) != null;
Set<StandardOpenOption> options = new HashSet<>();
options.add(StandardOpenOption.WRITE);
options.add(StandardOpenOption.CREATE);
options.add(append ? StandardOpenOption.APPEND : StandardOpenOption.TRUNCATE_EXISTING);
Token tok = tokens.get(++i);
Object val = Expander.expand(tok, closure);
for (Path p : toPaths(val)) {
p = closure.session().redirect(p, WRITE);
Channel ch = Files.newByteChannel(p, options);
if (fd >= 0) {
setStream(ch, fd, WRITE);
} else {
setStream(ch, 1, WRITE);
setStream(ch, 2, WRITE);
}
}
} else if ((m = Pattern.compile("([0-9])?>&([0-9])").matcher(t)).matches()) {
int fd0 = 1;
if (m.group(1) != null) {
fd0 = Integer.parseInt(m.group(1));
}
int fd1 = Integer.parseInt(m.group(2));
if (streams[fd0] != null && toclose[fd0]) {
streams[fd0].close();
}
// If the stream has to be closed, close it when both streams are closed
if (toclose[fd1]) {
Channel channel = streams[fd1];
AtomicInteger references = new AtomicInteger();
streams[fd0] = new RefByteChannel(channel, references);
streams[fd1] = new RefByteChannel(channel, references);
toclose[fd0] = true;
} else {
streams[fd0] = streams[fd1];
toclose[fd0] = false;
}
} else if ((m = Pattern.compile("([0-9])?<(>)?").matcher(t)).matches()) {
int fd = 0;
if (m.group(1) != null) {
fd = Integer.parseInt(m.group(1));
}
boolean output = m.group(2) != null;
Set<StandardOpenOption> options = new HashSet<>();
options.add(StandardOpenOption.READ);
if (output) {
options.add(StandardOpenOption.WRITE);
options.add(StandardOpenOption.CREATE);
}
Token tok = tokens.get(++i);
Object val = Expander.expand(tok, closure);
for (Path p : toPaths(val)) {
p = closure.session().redirect(p, READ + (output ? WRITE : 0));
Channel ch = Files.newByteChannel(p, options);
setStream(ch, fd, READ + (output ? WRITE : 0));
}
} else if ((m = Pattern.compile("<<-?").matcher(t)).matches()) {
final Token hereDoc = tokens.get(++i);
final boolean stripLeadingTabs = t.charAt(t.length() - 1) == '-';
InputStream doc = new InputStream() {
final byte[] bytes = hereDoc.toString().getBytes();
int index = 0;
boolean nl = true;
@Override
public int read() throws IOException {
if (nl && stripLeadingTabs) {
while (index < bytes.length && bytes[index] == '\t') {
index++;
}
}
if (index < bytes.length) {
int ch = bytes[index++];
nl = ch == '\n';
return ch;
}
return -1;
}
};
Channel ch = Channels.newChannel(doc);
setStream(ch, 0, READ);
} else if (Token.eq("<<<", t)) {
Token word = tokens.get(++i);
Object val = Expander.expand("\"" + word + "\"", closure);
String str = val != null ? String.valueOf(val) : "";
Channel ch = Channels.newChannel(new ByteArrayInputStream(str.getBytes()));
setStream(ch, 0, READ);
}
}
for (int i = 0; i < streams.length; i++) {
streams[i] = wrap(streams[i]);
}
// Create streams
in = Channels.newInputStream((ReadableByteChannel) streams[0]);
out = new PrintStream(Channels.newOutputStream((WritableByteChannel) streams[1]), true);
err = new PrintStream(Channels.newOutputStream((WritableByteChannel) streams[2]), true);
// Change the error stream to the redirected one, now that
// the command is about to be executed.
errChannel = (WritableByteChannel) streams[2];
if (threadIo != null) {
threadIo.setStreams(in, out, err);
}
Pipe previous = setCurrentPipe(this);
try {
Object result;
// Very special case for empty statements with redirection
if (statement.tokens().isEmpty() && toclose[0]) {
ByteBuffer bb = ByteBuffer.allocate(1024);
while (((ReadableByteChannel) streams[0]).read(bb) >= 0 || bb.position() != 0) {
bb.flip();
((WritableByteChannel) streams[1]).write(bb);
bb.compact();
}
result = null;
} else {
result = closure.execute(statement);
}
// If an error has been set
if (error != 0) {
return new Result(error);
}
// We don't print the result if we're at the end of the pipe
if (result != null && !endOfPipe && !Boolean.FALSE.equals(closure.session().get(".FormatPipe"))) {
out.println(closure.session().format(result, Converter.INSPECT));
}
return new Result(result);
} finally {
setCurrentPipe(previous);
}
} catch (Exception e) {
if (!endOfPipe) {
String msg = "gogo: " + e.getClass().getSimpleName() + ": " + e.getMessage() + "\n";
try {
errChannel.write(ByteBuffer.wrap(msg.getBytes()));
} catch (IOException ioe) {
e.addSuppressed(ioe);
}
}
return new Result(e);
} finally {
if (out != null) {
out.flush();
}
if (err != null) {
err.flush();
}
if (threadIo != null) {
threadIo.close();
}
try {
for (int i = 0; i < 10; i++) {
if (toclose[i] && streams[i] != null) {
streams[i].close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Aggregations