You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2010/05/15 17:06:21 UTC

svn commit: r944656 - in /camel/trunk/components/camel-exec/src: main/java/org/apache/camel/component/exec/ main/java/org/apache/camel/component/exec/impl/ test/java/org/apache/camel/component/exec/

Author: davsclaus
Date: Sat May 15 15:06:21 2010
New Revision: 944656

URL: http://svn.apache.org/viewvc?rev=944656&view=rev
Log:
CAMEL-2706: Added option useStderrOnEmptyStdout

Modified:
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommandExecutor.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java
    camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java
    camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java Sat May 15 15:06:21 2010
@@ -26,6 +26,7 @@ import org.apache.camel.Exchange;
  * is an {@link ExecCommand} and the output is an {@link ExecResult}.
  */
 public interface ExecBinding {
+
     /**
      * The header value overrides the executable of the command, configured in
      * the exec endpoint URI. As executable is considered the remaining of the
@@ -35,6 +36,7 @@ public interface ExecBinding {
      * <code>C:/Program Files/jdk/java.exe<code> is the executable.
      */
     String EXEC_COMMAND_EXECUTABLE = "CamelExecCommandExecutable";
+
     /**
      * The header value overrides the existing command arguments in the
      * {@link ExecEndpoint} URI. The arguments may be a
@@ -60,6 +62,7 @@ public interface ExecBinding {
      * used.
      */
     String EXEC_COMMAND_WORKING_DIR = "CamelExecCommandWorkingDir";
+
     /**
      * Specifies the amount of time, in milliseconds, after which the process of
      * the executable should be terminated. The default value is
@@ -82,6 +85,12 @@ public interface ExecBinding {
     String EXEC_EXIT_VALUE = "CamelExecExitValue";
 
     /**
+     * The value of this header is a boolean which indicates whether or not
+     * to fallback and use stderr when stdout is empty.
+     */
+    String EXEC_USE_STDERR_ON_EMPTY_STDOUT = "CamelExecUseStderrOnEmptyStdout";
+
+    /**
      * Creates a {@link ExecCommand} from the headers in the
      * <code>exchange</code> and the settings of the <code>endpoint</code>.
      * 

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java Sat May 15 15:06:21 2010
@@ -35,33 +35,37 @@ public class ExecCommand implements Seri
     /**
      * @see ExecBinding#EXEC_COMMAND_EXECUTABLE
      */
-    private String executable;
+    private final String executable;
 
     /**
      * @see ExecBinding#EXEC_COMMAND_ARGS
      */
-    private List<String> args;
+    private final List<String> args;
 
     /**
      * @see ExecBinding#EXEC_COMMAND_WORKING_DIR
      */
-    private String workingDir;
+    private final String workingDir;
 
     /**
      * @see ExecBinding#EXEC_COMMAND_TIMEOUT
      */
-    private long timeout;
+    private final long timeout;
 
     /**
      * @see ExecBinding#EXEC_COMMAND_OUT_FILE
      */
-    private File outFile;
+    private final File outFile;
+
     /**
      * The input of the executable
      */
-    private InputStream input;
+    private final InputStream input;
+
+    private final boolean useStderrOnEmptyStdout;
 
-    public ExecCommand(String executable, List<String> args, String workingDir, Long timeout, InputStream input, File outFile) {
+    public ExecCommand(String executable, List<String> args, String workingDir, Long timeout,
+                       InputStream input, File outFile, boolean useStderrOnEmptyStdout) {
         notNull(executable, "command executable");
         this.executable = executable;
         this.args = unmodifiableOrEmptyList(args);
@@ -69,6 +73,7 @@ public class ExecCommand implements Seri
         this.timeout = timeout;
         this.input = input;
         this.outFile = outFile;
+        this.useStderrOnEmptyStdout = useStderrOnEmptyStdout;
     }
 
     public List<String> getArgs() {
@@ -95,11 +100,16 @@ public class ExecCommand implements Seri
         return workingDir;
     }
 
+    public boolean isUseStderrOnEmptyStdout() {
+        return useStderrOnEmptyStdout;
+    }
+
     @Override
     public String toString() {
         String dirToPrint = workingDir == null ? "null" : workingDir;
         String outFileToPrint = outFile == null ? "null" : outFile.getPath();
-        return "ExecCommand [args=" + args + ", executable=" + executable + ", timeout=" + timeout + ", outFile=" + outFileToPrint + ", workingDir=" + dirToPrint + "]";
+        return "ExecCommand [args=" + args + ", executable=" + executable + ", timeout=" + timeout + ", outFile="
+                + outFileToPrint + ", workingDir=" + dirToPrint + ", useStderrOnEmptyStdout=" + useStderrOnEmptyStdout + "]";
     }
 
     private <T> List<T> unmodifiableOrEmptyList(List<T> list) {

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommandExecutor.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommandExecutor.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommandExecutor.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommandExecutor.java Sat May 15 15:06:21 2010
@@ -18,8 +18,6 @@ package org.apache.camel.component.exec;
 
 import java.io.IOException;
 
-import org.apache.commons.exec.ExecuteException;
-
 /**
  * Executes {@link ExecCommand} instances.
  */
@@ -29,9 +27,9 @@ public interface ExecCommandExecutor {
      * Executes the <code>command</code> and returns a not-<code>null</code>
      * {@link ExecResult} instance.
      * 
-     * @param execCommand The command object, that describes the executable
-     *            application
-     * @throws ExecuteException if the execution failed
+     * @param execCommand The command object, that describes the executable application
+     * @return the result
+     * @throws ExecException if the execution failed
      * @throws IOException if there is an invalid path in the working directory,
      *             or if the absolute path of the command executable is invalid,
      *             or if the executable does not exist

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java Sat May 15 15:06:21 2010
@@ -17,7 +17,6 @@
 package org.apache.camel.component.exec;
 
 import org.apache.camel.Consumer;
-import org.apache.camel.Endpoint;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.component.exec.impl.DefaultExecBinding;
@@ -29,8 +28,7 @@ import org.apache.camel.util.ObjectHelpe
 /**
  * The endpoint utilizes an {@link ExecCommandExecutor} to execute a system
  * command when it receives message exchanges.
- * 
- * @see Endpoint
+ *
  * @see ExecBinding
  * @see ExecCommandExecutor
  * @see ExecCommand
@@ -57,6 +55,8 @@ public class ExecEndpoint extends Defaul
 
     private ExecBinding binding;
 
+    private boolean useStderrOnEmptyStdout;
+
     public ExecEndpoint(String uri, ExecComponent component) {
         super(uri, component);
         this.timeout = NO_TIMEOUT;
@@ -187,7 +187,7 @@ public class ExecEndpoint extends Defaul
 
     /**
      * @return The command executor used to execute commands. Defaults to
-     *         {@link DefaultExecCommandExecutror}
+     *         {@link org.apache.camel.component.exec.impl.DefaultExecCommandExecutor}
      */
     public ExecCommandExecutor getCommandExecutor() {
         return commandExecutor;
@@ -211,4 +211,12 @@ public class ExecEndpoint extends Defaul
         ObjectHelper.notNull(binding, "binding");
         this.binding = binding;
     }
+
+    public boolean isUseStderrOnEmptyStdout() {
+        return useStderrOnEmptyStdout;
+    }
+
+    public void setUseStderrOnEmptyStdout(boolean useStderrOnEmptyStdout) {
+        this.useStderrOnEmptyStdout = useStderrOnEmptyStdout;
+    }
 }

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java Sat May 15 15:06:21 2010
@@ -82,7 +82,14 @@ public final class ExecResultConverter {
      *             the file can not be found
      */
     public static <T> T convertTo(Class<T> type, Exchange exchange, ExecResult result) throws FileNotFoundException {
-        return exchange.getContext().getTypeConverter().convertTo(type, exchange, toInputStream(result));
+        InputStream is = toInputStream(result);
+        if (is != null) {
+            return exchange.getContext().getTypeConverter().convertTo(type, exchange, is);
+        } else {
+            // use Void to indicate we cannot convert it
+            // (prevents Camel from using a fallback converter which may convert a String from the instance name)  
+            return (T) Void.TYPE;
+        }
     }
 
     /**
@@ -114,11 +121,11 @@ public final class ExecResultConverter {
             result = new FileInputStream(execResult.getCommand().getOutFile());
         } else {
             // if the stdout is null, return the stderr.
-            if (execResult.getStdout() == null) {
+            if (execResult.getStdout() == null && execResult.getCommand().isUseStderrOnEmptyStdout()) {
                 LOG.warn("ExecResult has no stdout, will fallback to use stderr.");
                 result = execResult.getStderr();
             } else {
-                result = execResult.getStdout();
+                result = execResult.getStdout() != null ? execResult.getStdout() : null;
             }
         }
         // reset the stream if it was already read.

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java Sat May 15 15:06:21 2010
@@ -47,6 +47,7 @@ public class DefaultExecBinding implemen
         String dir = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_WORKING_DIR, endpoint.getWorkingDir(), String.class);
         long timeout = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_TIMEOUT, endpoint.getTimeout(), Long.class);
         String outFilePath = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_OUT_FILE, endpoint.getOutFile(), String.class);
+        boolean useStderrOnEmptyStdout = getAndRemoveHeader(exchange.getIn(), EXEC_USE_STDERR_ON_EMPTY_STDOUT, endpoint.isUseStderrOnEmptyStdout(), Boolean.class);
         InputStream input = exchange.getIn().getBody(InputStream.class);
 
         if (argsList == null) {
@@ -55,7 +56,7 @@ public class DefaultExecBinding implemen
         }
 
         File outFile = outFilePath == null ? null : new File(outFilePath);
-        return new ExecCommand(cmd, argsList, dir, timeout, input, outFile);
+        return new ExecCommand(cmd, argsList, dir, timeout, input, outFile, useStderrOnEmptyStdout);
     }
 
     public void writeOutput(Exchange exchange, ExecResult result) {

Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java (original)
+++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java Sat May 15 15:06:21 2010
@@ -73,11 +73,11 @@ public class DefaultExecCommandExecutor 
             return result;
 
         } catch (ExecuteException ee) {
-            LOG.error("ExecuteExeption while executing " + command.toString());
+            LOG.error("ExecException while executing command: " + command.toString() + " - " + ee.getMessage());
             throw new ExecException("Failed to execute command " + command, ee);
         } catch (IOException ioe) {
             // invalid working dir
-            LOG.error("IOException while executing " + command.toString());
+            LOG.error("IOException while executing command: " + command.toString() + " - " + ioe.getMessage());
             throw new ExecException("Unable to execute command " + command, ioe);
         } finally {
             // the inputStream must be closed after the execution

Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java?rev=944656&r1=944655&r2=944656&view=diff
==============================================================================
--- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java (original)
+++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java Sat May 15 15:06:21 2010
@@ -38,6 +38,7 @@ import static org.apache.camel.component
 import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_WORKING_DIR;
 import static org.apache.camel.component.exec.ExecBinding.EXEC_EXIT_VALUE;
 import static org.apache.camel.component.exec.ExecBinding.EXEC_STDERR;
+import static org.apache.camel.component.exec.ExecBinding.EXEC_USE_STDERR_ON_EMPTY_STDOUT;
 import static org.apache.camel.component.exec.ExecEndpoint.NO_TIMEOUT;
 import static org.apache.camel.component.exec.ExecTestUtils.buildJavaExecutablePath;
 import static org.apache.camel.component.exec.ExecutableJavaProgram.EXIT_WITH_VALUE_0;
@@ -133,7 +134,7 @@ public class ExecJavaProcessTest extends
         String commandArgument = PRINT_IN_STDERR;
         output.setExpectedMessageCount(1);
 
-        Exchange e = sendExchange(commandArgument, NO_TIMEOUT);
+        Exchange e = sendExchange(commandArgument, NO_TIMEOUT, null, true);
         ExecResult body = e.getIn().getBody(ExecResult.class);
 
         output.assertIsSatisfied();
@@ -145,6 +146,23 @@ public class ExecJavaProcessTest extends
     }
 
     @Test
+    public void testStdoutIsNull() throws Exception {
+        // this will be printed
+        String commandArgument = PRINT_IN_STDERR;
+        output.setExpectedMessageCount(1);
+
+        Exchange e = sendExchange(commandArgument, NO_TIMEOUT, null, false);
+        ExecResult body = e.getIn().getBody(ExecResult.class);
+
+        output.assertIsSatisfied();
+        assertNull("the test executable must not print anything in stdout", body.getStdout());
+        assertNotNull("the test executable must print in stderr", body.getStderr());
+        // the converter must fall back to the stderr, because stdout is null
+        String out = e.getIn().getBody(String.class);
+        assertNull("Should be null", out);
+    }
+
+    @Test
     public void testConvertResultToInputStream() throws Exception {
         String commandArgument = PRINT_IN_STDOUT;
         output.setExpectedMessageCount(1);
@@ -240,17 +258,17 @@ public class ExecJavaProcessTest extends
         String whiteSpaceSeparatedLines = builder.toString();
         String expected = builder.toString();
 
-        Exchange e = sendExchange(READ_INPUT_LINES_AND_PRINT_THEM, 20000, whiteSpaceSeparatedLines);
+        Exchange e = sendExchange(READ_INPUT_LINES_AND_PRINT_THEM, 20000, whiteSpaceSeparatedLines, false);
         ExecResult inBody = e.getIn().getBody(ExecResult.class);
         assertEquals(expected, IOUtils.toString(inBody.getStdout()));
 
     }
 
     protected Exchange sendExchange(final Object commandArgument, final long timeout) {
-        return sendExchange(commandArgument, timeout, "testBody");
+        return sendExchange(commandArgument, timeout, "testBody", false);
     }
 
-    protected Exchange sendExchange(final Object commandArgument, final long timeout, final String body) {
+    protected Exchange sendExchange(final Object commandArgument, final long timeout, final String body, final boolean useStderrOnEmptyStdout) {
         final List<String> args = buildArgs(commandArgument);
         final String javaAbsolutePath = buildJavaExecutablePath();
 
@@ -260,6 +278,9 @@ public class ExecJavaProcessTest extends
                 exchange.getIn().setHeader(EXEC_COMMAND_EXECUTABLE, javaAbsolutePath);
                 exchange.getIn().setHeader(EXEC_COMMAND_TIMEOUT, timeout);
                 exchange.getIn().setHeader(EXEC_COMMAND_ARGS, args);
+                if (useStderrOnEmptyStdout) {
+                    exchange.getIn().setHeader(EXEC_USE_STDERR_ON_EMPTY_STDOUT, true);
+                }
             }
         });
     }