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); + } } }); }