change priority of ; and | to match bash. resolves FELIX-1500.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@892356 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java
index c205775..8ab4dc1 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java
@@ -18,11 +18,15 @@
*/
package org.apache.felix.gogo.runtime.shell;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
import org.osgi.service.command.CommandSession;
import org.osgi.service.command.Function;
-import java.util.*;
-
public class Closure extends Reflective implements Function
{
private static final long serialVersionUID = 1L;
@@ -42,65 +46,75 @@
{
parms = values;
Parser parser = new Parser(source);
- ArrayList<Pipe> pipes = new ArrayList<Pipe>();
List<List<List<CharSequence>>> program = parser.program();
+ Pipe last = null;
- for (List<List<CharSequence>> statements : program)
+ for (List<List<CharSequence>> pipeline : program)
{
- Pipe current = new Pipe(this, statements);
+ ArrayList<Pipe> pipes = new ArrayList<Pipe>();
- if (pipes.isEmpty())
- {
- if (current.out == null)
+ for (List<CharSequence> statement : pipeline)
+ {
+ Pipe current = new Pipe(this, statement);
+
+ if (pipes.isEmpty())
{
- current.setIn(session.in);
- current.setOut(session.out);
- current.setErr(session.err);
+ if (current.out == null)
+ {
+ current.setIn(session.in);
+ current.setOut(session.out);
+ current.setErr(session.err);
+ }
}
- }
- else
- {
- Pipe previous = pipes.get(pipes.size() - 1);
- previous.connect(current);
- }
- pipes.add(current);
- }
- if (pipes.size() == 0)
- {
- return null;
- }
+ else
+ {
+ Pipe previous = pipes.get(pipes.size() - 1);
+ previous.connect(current);
+ }
+ pipes.add(current);
+ }
- if (pipes.size() == 1)
- {
- pipes.get(0).run();
- }
- else
- {
- for (Pipe pipe : pipes)
- {
- pipe.start();
- }
- for (Pipe pipe : pipes)
- {
- pipe.join();
- }
- }
+ if (pipes.size() == 1)
+ {
+ pipes.get(0).run();
+ }
+ else if (pipes.size() > 1)
+ {
+ for (Pipe pipe : pipes)
+ {
+ pipe.start();
+ }
+ for (Pipe pipe : pipes)
+ {
+ pipe.join();
+ }
+ }
- Pipe last = pipes.remove(pipes.size() - 1);
+ last = pipes.remove(pipes.size() - 1);
- for (Pipe pipe : pipes)
- {
- if (pipe.exception != null)
- {
- // can't throw exception, as result is defined by last pipe
- session.err.println("pipe: " + pipe.exception);
- }
- }
+ for (Pipe pipe : pipes)
+ {
+ if (pipe.exception != null)
+ {
+ // can't throw exception, as result is defined by last pipe
+ session.err.println("pipe: " + pipe.exception);
+ session.put("pipe-exception", pipe.exception);
+ }
+ }
- if (last.exception != null)
- {
- throw last.exception;
- }
+ if (last.exception != null)
+ {
+ Pipe.reset();
+ throw last.exception;
+ }
+ }
+
+ Pipe.reset(); // reset IO in case sshd uses same thread for new client
+
+ if (last == null)
+ {
+ return null;
+ }
if (last.result instanceof Object[])
{
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java
index 60d09ba..930a3ab 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java
@@ -137,11 +137,15 @@
ws();
if (!eof())
{
- program.add(statements());
- while (peek() == '|')
+ program.add(pipeline());
+ while (peek() == ';')
{
current++;
- program.add(statements());
+ List<List<CharSequence>> pipeline = pipeline();
+ if (pipeline.get(0).get(0).length() != 0)
+ {
+ program.add(pipeline);
+ }
}
}
if (!eof())
@@ -157,19 +161,22 @@
return text.subSequence(Math.max(0, current - 20), Math.min(text.length(), current + 4));
}
- public List<List<CharSequence>> statements()
+ public List<List<CharSequence>> pipeline()
{
List<List<CharSequence>> statements = new ArrayList<List<CharSequence>>();
statements.add(statement());
- while (peek() == ';')
+ while (peek() == '|')
{
current++;
- // derek: BUGFIX: allow trailing ;
ws();
if (!eof())
{
statements.add(statement());
}
+ else
+ {
+ throw new RuntimeException("Eof found after pipe |");
+ }
}
return statements;
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Pipe.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Pipe.java
index 5b8dca5..f3608cf 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Pipe.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Pipe.java
@@ -39,18 +39,29 @@
Closure closure;
Exception exception;
Object result;
- List<List<CharSequence>> statements;
-
- public Pipe(Closure closure, List<List<CharSequence>> statements)
+ List<CharSequence> statement;
+
+ public static void reset()
{
- super("pipe-" + statements);
+ tIn.set(null);
+ tOut.set(null);
+ tErr.set(null);
+ }
+
+ public Pipe(Closure closure, List<CharSequence> statement)
+ {
+ super("pipe-" + statement);
this.closure = closure;
- this.statements = statements;
+ this.statement = statement;
in = tIn.get();
out = tOut.get();
err = tErr.get();
}
+
+ public String toString() {
+ return "pipe<" + statement + "> out=" + out;
+ }
public void setIn(InputStream in)
{
@@ -86,13 +97,10 @@
try
{
- for (List<CharSequence> statement : statements)
+ result = closure.executeStatement(statement);
+ if (result != null && pout != null)
{
- result = closure.executeStatement(statement);
- if (result != null && pout != null)
- {
- out.println(closure.session.format(result, Converter.INSPECT));
- }
+ out.println(closure.session.format(result, Converter.INSPECT));
}
}
catch (Exception e)
@@ -119,11 +127,6 @@
{
e.printStackTrace();
}
-
- tIn.set(null);
- tOut.set(null);
- tErr.set(null);
-
}
}
}
diff --git a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java
index bc521a1..18aa183 100644
--- a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java
+++ b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java
@@ -113,9 +113,10 @@
assertEquals("def", c.execute("echo def|grep d.*|capture"));
assertEquals("def", c.execute("echoout def|grep d.*|capture"));
assertEquals("def", c.execute("myecho def|grep d.*|capture"));
- assertEquals("def", c.execute("echo abc; echo def; echo ghi|grep d.*|capture"));
+ assertEquals("def", c.execute("(echoout abc; echoout def; echoout ghi)|grep d.*|capture"));
+ assertEquals("", c.execute("echoout def; echoout ghi | grep d.* | capture"));
assertEquals("hello world", c.execute("echo hello world|capture"));
- assertEquals("defghi", c.execute("echo abc; echo def; echo ghi|grep 'def|ghi'|capture"));
+ assertEquals("defghi", c.execute("(echoout abc; echoout def; echoout ghi)|grep 'def|ghi'|capture"));
}
public void testAssignment() throws Exception
@@ -320,17 +321,17 @@
List<List<List<CharSequence>>> x = new Parser("abc def|ghi jkl;mno pqr|stu vwx").program();
assertEquals("abc", x.get(0).get(0).get(0));
assertEquals("def", x.get(0).get(0).get(1));
- assertEquals("ghi", x.get(1).get(0).get(0));
- assertEquals("jkl", x.get(1).get(0).get(1));
- assertEquals("mno", x.get(1).get(1).get(0));
- assertEquals("pqr", x.get(1).get(1).get(1));
- assertEquals("stu", x.get(2).get(0).get(0));
- assertEquals("vwx", x.get(2).get(0).get(1));
+ assertEquals("ghi", x.get(0).get(1).get(0));
+ assertEquals("jkl", x.get(0).get(1).get(1));
+ assertEquals("mno", x.get(1).get(0).get(0));
+ assertEquals("pqr", x.get(1).get(0).get(1));
+ assertEquals("stu", x.get(1).get(1).get(0));
+ assertEquals("vwx", x.get(1).get(1).get(1));
}
public void testStatements()
{
- List<List<CharSequence>> x = new Parser("abc def;ghi jkl;mno pqr").statements();
+ List<List<CharSequence>> x = new Parser("abc def|ghi jkl|mno pqr").pipeline();
assertEquals("abc", x.get(0).get(0));
assertEquals("def", x.get(0).get(1));
assertEquals("ghi", x.get(1).get(0));