Author: gnodet Date: Mon Nov 29 10:07:27 2010 New Revision: 1040053 URL: http://svn.apache.org/viewvc?rev=1040053&view=rev Log: [KARAF-282] The shell:exec may not capture the whole output
Added: karaf/trunk/util/src/main/java/org/apache/karaf/util/process/ karaf/trunk/util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java - copied, changed from r1040052, karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/PumpStreamHandler.java karaf/trunk/util/src/main/java/org/apache/karaf/util/process/StreamPumper.java - copied, changed from r1040052, karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/StreamPumper.java Removed: karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/PumpStreamHandler.java karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/StreamPumper.java Modified: karaf/trunk/itests/kittests/src/test/java/org/apache/karaf/kittests/Helper.java karaf/trunk/shell/commands/pom.xml karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/ExecuteAction.java karaf/trunk/shell/wrapper/pom.xml karaf/trunk/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java Modified: karaf/trunk/itests/kittests/src/test/java/org/apache/karaf/kittests/Helper.java URL: http://svn.apache.org/viewvc/karaf/trunk/itests/kittests/src/test/java/org/apache/karaf/kittests/Helper.java?rev=1040053&r1=1040052&r2=1040053&view=diff ============================================================================== --- karaf/trunk/itests/kittests/src/test/java/org/apache/karaf/kittests/Helper.java (original) +++ karaf/trunk/itests/kittests/src/test/java/org/apache/karaf/kittests/Helper.java Mon Nov 29 10:07:27 2010 @@ -24,9 +24,7 @@ import org.apache.commons.compress.compr import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.felix.utils.properties.InterpolationHelper; -import org.apache.karaf.admin.Instance; -import org.apache.karaf.admin.internal.InstanceImpl; -import org.apache.karaf.shell.commands.utils.StreamPumper; +import org.apache.karaf.util.process.PumpStreamHandler; import java.io.BufferedReader; import java.io.File; @@ -39,10 +37,7 @@ import java.io.OutputStream; import java.net.Socket; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; @@ -343,202 +338,4 @@ public final class Helper { } } - public static class PumpStreamHandler - { - private InputStream in; - - private OutputStream out; - - private OutputStream err; - - private Thread outputThread; - - private Thread errorThread; - - private StreamPumper inputPump; - - // - // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-( - // - - public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { - assert in != null; - assert out != null; - assert err != null; - - this.in = in; - this.out = out; - this.err = err; - } - - public PumpStreamHandler(final OutputStream out, final OutputStream err) { - this(null, out, err); - } - - public PumpStreamHandler(final OutputStream outAndErr) { - this(outAndErr, outAndErr); - } - - /** - * Set the input stream from which to read the standard output of the child. - */ - public void setChildOutputStream(final InputStream in) { - assert in != null; - - createChildOutputPump(in, out); - } - - /** - * Set the input stream from which to read the standard error of the child. - */ - public void setChildErrorStream(final InputStream in) { - assert in != null; - - if (err != null) { - createChildErrorPump(in, err); - } - } - - /** - * Set the output stream by means of which input can be sent to the child. - */ - public void setChildInputStream(final OutputStream out) { - assert out != null; - - if (in != null) { - inputPump = createInputPump(in, out, true); - } - else { - try { - out.close(); - } catch (IOException e) { } - } - } - - /** - * Attach to a child streams from the given process. - * - * @param p The process to attach to. - */ - public void attach(final Process p) { - assert p != null; - - setChildInputStream(p.getOutputStream()); - setChildOutputStream(p.getInputStream()); - setChildErrorStream(p.getErrorStream()); - } - /** - * Start pumping the streams. - */ - public void start() { - if (outputThread != null) { - outputThread.start(); - } - - if (errorThread != null) { - errorThread.start(); - } - - if (inputPump != null) { - Thread inputThread = new Thread(inputPump); - inputThread.setDaemon(true); - inputThread.start(); - } - } - - /** - * Stop pumping the streams. - */ - public void stop() { - if (outputThread != null) { - try { - outputThread.join(); - } - catch (InterruptedException e) { - // ignore - } - } - - if (errorThread != null) { - try { - errorThread.join(); - } - catch (InterruptedException e) { - // ignore - } - } - - if (inputPump != null) { - inputPump.stop(); - } - - try { - err.flush(); - } catch (IOException e) { } - try { - out.flush(); - } catch (IOException e) { } - } - - /** - * Create the pump to handle child output. - */ - protected void createChildOutputPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - outputThread = createPump(in, out); - } - - /** - * Create the pump to handle error output. - */ - protected void createChildErrorPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - errorThread = createPump(in, out); - } - - /** - * Creates a stream pumper to copy the given input stream to the given output stream. - */ - protected Thread createPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - return createPump(in, out, false); - } - - /** - * Creates a stream pumper to copy the given input stream to the - * given output stream. - * - * @param in The input stream to copy from. - * @param out The output stream to copy to. - * @param closeWhenExhausted If true close the inputstream. - * @return A thread object that does the pumping. - */ - protected Thread createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { - assert in != null; - assert out != null; - - final Thread result = new Thread(new StreamPumper(in, out, closeWhenExhausted)); - result.setDaemon(true); - return result; - } - - /** - * Creates a stream pumper to copy the given input stream to the - * given output stream. Used for standard input. - */ - protected StreamPumper createInputPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { - assert in != null; - assert out != null; - - StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted); - pumper.setAutoflush(true); - return pumper; - } - } } \ No newline at end of file Modified: karaf/trunk/shell/commands/pom.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/commands/pom.xml?rev=1040053&r1=1040052&r2=1040053&view=diff ============================================================================== --- karaf/trunk/shell/commands/pom.xml (original) +++ karaf/trunk/shell/commands/pom.xml Mon Nov 29 10:07:27 2010 @@ -49,6 +49,10 @@ <artifactId>org.apache.felix.gogo.runtime</artifactId> </dependency> <dependency> + <groupId>org.apache.karaf</groupId> + <artifactId>org.apache.karaf.util</artifactId> + </dependency> + <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.compendium</artifactId> <scope>provided</scope> @@ -89,6 +93,9 @@ org.apache.karaf.shell.console, * </Import-Package> + <Private-Package> + org.apache.karaf.util.process + </Private-Package> <_versionpolicy>${bnd.version.policy}</_versionpolicy> </instructions> </configuration> Modified: karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/ExecuteAction.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/ExecuteAction.java?rev=1040053&r1=1040052&r2=1040053&view=diff ============================================================================== --- karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/ExecuteAction.java (original) +++ karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/ExecuteAction.java Mon Nov 29 10:07:27 2010 @@ -20,8 +20,8 @@ import java.util.List; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; -import org.apache.karaf.shell.commands.utils.PumpStreamHandler; import org.apache.karaf.shell.console.AbstractAction; +import org.apache.karaf.util.process.PumpStreamHandler; /** * Execute system processes. @@ -37,7 +37,7 @@ public class ExecuteAction extends Abstr protected Object doExecute() throws Exception { ProcessBuilder builder = new ProcessBuilder(args); - PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err); + PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err, "Command" + args.toString()); log.info("Executing: {}", builder.command()); Process p = builder.start(); Modified: karaf/trunk/shell/wrapper/pom.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/wrapper/pom.xml?rev=1040053&r1=1040052&r2=1040053&view=diff ============================================================================== --- karaf/trunk/shell/wrapper/pom.xml (original) +++ karaf/trunk/shell/wrapper/pom.xml Mon Nov 29 10:07:27 2010 @@ -49,6 +49,10 @@ <artifactId>org.apache.karaf.main</artifactId> </dependency> <dependency> + <groupId>org.apache.karaf</groupId> + <artifactId>org.apache.karaf.util</artifactId> + </dependency> + <dependency> <groupId>tanukisoft</groupId> <artifactId>wrapper</artifactId> </dependency> @@ -99,7 +103,9 @@ org.apache.karaf.shell.console, * </Import-Package> - <Private-Package>!*</Private-Package> + <Private-Package> + org.apache.karaf.util.process + </Private-Package> <_versionpolicy>${bnd.version.policy}</_versionpolicy> </instructions> </configuration> Modified: karaf/trunk/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java?rev=1040053&r1=1040052&r2=1040053&view=diff ============================================================================== --- karaf/trunk/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java (original) +++ karaf/trunk/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java Mon Nov 29 10:07:27 2010 @@ -34,15 +34,17 @@ import java.io.IOException; */ public class PumpStreamHandler { - private InputStream in; + private final InputStream in; - private OutputStream out; + private final OutputStream out; - private OutputStream err; + private final OutputStream err; - private Thread outputThread; + private final String name; - private Thread errorThread; + private StreamPumper outputPump; + + private StreamPumper errorPump; private StreamPumper inputPump; @@ -50,14 +52,20 @@ public class PumpStreamHandler // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-( // - public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { + public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) { assert in != null; assert out != null; assert err != null; + assert name != null; this.in = in; this.out = out; this.err = err; + this.name = name; + } + + public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { + this(in, out, err, "<unknown>"); } public PumpStreamHandler(final OutputStream out, final OutputStream err) { @@ -120,18 +128,25 @@ public class PumpStreamHandler * Start pumping the streams. */ public void start() { - if (outputThread != null) { - outputThread.start(); + if (outputPump != null) { + Thread thread = new Thread(outputPump); + thread.setDaemon(true); + thread.setName("Output pump for " + this.name); + thread.start(); } - if (errorThread != null) { - errorThread.start(); + if (errorPump != null) { + Thread thread = new Thread(errorPump); + thread.setDaemon(true); + thread.setName("Error pump for " + this.name); + thread.start(); } if (inputPump != null) { - Thread inputThread = new Thread(inputPump); - inputThread.setDaemon(true); - inputThread.start(); + Thread thread = new Thread(inputPump); + thread.setDaemon(true); + thread.setName("Input pump for " + this.name); + thread.start(); } } @@ -139,18 +154,20 @@ public class PumpStreamHandler * Stop pumping the streams. */ public void stop() { - if (outputThread != null) { + if (outputPump != null) { try { - outputThread.join(); + outputPump.stop(); + outputPump.waitFor(); } catch (InterruptedException e) { // ignore } } - if (errorThread != null) { + if (errorPump != null) { try { - errorThread.join(); + errorPump.stop(); + errorPump.waitFor(); } catch (InterruptedException e) { // ignore @@ -176,7 +193,7 @@ public class PumpStreamHandler assert in != null; assert out != null; - outputThread = createPump(in, out); + outputPump = createPump(in, out); } /** @@ -186,13 +203,13 @@ public class PumpStreamHandler assert in != null; assert out != null; - errorThread = createPump(in, out); + errorPump = createPump(in, out); } /** * Creates a stream pumper to copy the given input stream to the given output stream. */ - protected Thread createPump(final InputStream in, final OutputStream out) { + protected StreamPumper createPump(final InputStream in, final OutputStream out) { assert in != null; assert out != null; @@ -208,13 +225,12 @@ public class PumpStreamHandler * @param closeWhenExhausted If true close the inputstream. * @return A thread object that does the pumping. */ - protected Thread createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { + protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { assert in != null; assert out != null; - final Thread result = new Thread(new StreamPumper(in, out, closeWhenExhausted)); - result.setDaemon(true); - return result; + StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted); + return pumper; } /** Copied: karaf/trunk/util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java (from r1040052, karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/PumpStreamHandler.java) URL: http://svn.apache.org/viewvc/karaf/trunk/util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java?p2=karaf/trunk/util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java&p1=karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/PumpStreamHandler.java&r1=1040052&r2=1040053&rev=1040053&view=diff ============================================================================== --- karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/PumpStreamHandler.java (original) +++ karaf/trunk/util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java Mon Nov 29 10:07:27 2010 @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.karaf.shell.commands.utils; +package org.apache.karaf.util.process; import java.io.InputStream; import java.io.OutputStream; @@ -34,15 +34,17 @@ import java.io.IOException; */ public class PumpStreamHandler { - private InputStream in; + private final InputStream in; - private OutputStream out; + private final OutputStream out; - private OutputStream err; + private final OutputStream err; - private Thread outputThread; + private final String name; - private Thread errorThread; + private StreamPumper outputPump; + + private StreamPumper errorPump; private StreamPumper inputPump; @@ -50,14 +52,20 @@ public class PumpStreamHandler // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-( // - public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { + public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) { assert in != null; assert out != null; assert err != null; + assert name != null; this.in = in; this.out = out; this.err = err; + this.name = name; + } + + public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { + this(in, out, err, "<unknown>"); } public PumpStreamHandler(final OutputStream out, final OutputStream err) { @@ -120,18 +128,25 @@ public class PumpStreamHandler * Start pumping the streams. */ public void start() { - if (outputThread != null) { - outputThread.start(); + if (outputPump != null) { + Thread thread = new Thread(outputPump); + thread.setDaemon(true); + thread.setName("Output pump for " + this.name); + thread.start(); } - if (errorThread != null) { - errorThread.start(); + if (errorPump != null) { + Thread thread = new Thread(errorPump); + thread.setDaemon(true); + thread.setName("Error pump for " + this.name); + thread.start(); } if (inputPump != null) { - Thread inputThread = new Thread(inputPump); - inputThread.setDaemon(true); - inputThread.start(); + Thread thread = new Thread(inputPump); + thread.setDaemon(true); + thread.setName("Input pump for " + this.name); + thread.start(); } } @@ -139,18 +154,20 @@ public class PumpStreamHandler * Stop pumping the streams. */ public void stop() { - if (outputThread != null) { + if (outputPump != null) { try { - outputThread.join(); + outputPump.stop(); + outputPump.waitFor(); } catch (InterruptedException e) { // ignore } } - if (errorThread != null) { + if (errorPump != null) { try { - errorThread.join(); + errorPump.stop(); + errorPump.waitFor(); } catch (InterruptedException e) { // ignore @@ -176,7 +193,7 @@ public class PumpStreamHandler assert in != null; assert out != null; - outputThread = createPump(in, out); + outputPump = createPump(in, out); } /** @@ -186,13 +203,13 @@ public class PumpStreamHandler assert in != null; assert out != null; - errorThread = createPump(in, out); + errorPump = createPump(in, out); } /** * Creates a stream pumper to copy the given input stream to the given output stream. */ - protected Thread createPump(final InputStream in, final OutputStream out) { + protected StreamPumper createPump(final InputStream in, final OutputStream out) { assert in != null; assert out != null; @@ -208,13 +225,12 @@ public class PumpStreamHandler * @param closeWhenExhausted If true close the inputstream. * @return A thread object that does the pumping. */ - protected Thread createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { + protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { assert in != null; assert out != null; - final Thread result = new Thread(new StreamPumper(in, out, closeWhenExhausted)); - result.setDaemon(true); - return result; + StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted); + return pumper; } /** Copied: karaf/trunk/util/src/main/java/org/apache/karaf/util/process/StreamPumper.java (from r1040052, karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/StreamPumper.java) URL: http://svn.apache.org/viewvc/karaf/trunk/util/src/main/java/org/apache/karaf/util/process/StreamPumper.java?p2=karaf/trunk/util/src/main/java/org/apache/karaf/util/process/StreamPumper.java&p1=karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/StreamPumper.java&r1=1040052&r2=1040053&rev=1040053&view=diff ============================================================================== --- karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/utils/StreamPumper.java (original) +++ karaf/trunk/util/src/main/java/org/apache/karaf/util/process/StreamPumper.java Mon Nov 29 10:07:27 2010 @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.karaf.shell.commands.utils; +package org.apache.karaf.util.process; import java.io.InputStream; import java.io.OutputStream; @@ -47,7 +47,7 @@ public class StreamPumper private boolean autoflush; - private Exception exception; + private Throwable exception; private int bufferSize = 128; @@ -106,7 +106,7 @@ public class StreamPumper int length; try { do { - while (in.available() > 0 && !finish) { + while (in.available() > 0) { length = in.read(buf); if (length < 1 ) { break; @@ -118,11 +118,11 @@ public class StreamPumper } out.flush(); Thread.sleep(200); // Pause to avoid tight loop if external proc is slow - } while (!finish && closeWhenExhausted); + } while (!finish); } - catch (Exception e) { + catch (Throwable t) { synchronized (this) { - exception = e; + exception = t; } } finally { @@ -187,7 +187,7 @@ public class StreamPumper * * @return The Exception encountered; or null if there was none. */ - public synchronized Exception getException() { + public synchronized Throwable getException() { return exception; }