Author: davsclaus Date: Thu Apr 15 06:35:26 2010 New Revision: 934297 URL: http://svn.apache.org/viewvc?rev=934297&view=rev Log: CAMEL-2549: Applied patch with thanks to Mitko Kolev.
Added: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java (with props) 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/ExecCommandExecutor.java camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecComponent.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/ExecProducer.java camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResult.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/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecJavaProcessTest.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecScriptTest.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecTestUtils.java camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecCommandExecutorMock.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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -16,8 +16,9 @@ */ package org.apache.camel.component.exec; +import java.io.InputStream; + import org.apache.camel.Exchange; -import org.apache.camel.component.exec.impl.ExecParseUtils; /** * Represents the binding of input and output types of a @@ -30,18 +31,17 @@ public interface ExecBinding { * the exec endpoint URI. As executable is considered the remaining of the * {...@link ExecEndpoint} URI; <br> * <br> - * e.g. in the URI <i> <code>exec:"C:/Program Files/jdk/java.exe"</code> - * </i>, <code>"C:/Program Files/jdk/java.exe"<code> is the executable, escaped by the " character. + * e.g. in the URI <i> <code>exec:C:/Program Files/jdk/java.exe</code> </i>, + * <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 one or many - * whitespace-separated tokens, and can be quoted with <code>"</code>, or with - * <code>""</code>. + * {...@link ExecEndpoint} URI. The arguments may be a + * <code>List<String></code>. In this case no parsing of the arguments is + * necessary. * * @see {...@link #EXEC_COMMAND_EXECUTABLE} - * @see ExecParseUtils#splitToWhiteSpaceSeparatedTokens(String) */ String EXEC_COMMAND_ARGS = "CamelExecCommandArgs"; @@ -62,18 +62,14 @@ public interface ExecBinding { String EXEC_COMMAND_WORKING_DIR = "CamelExecCommandWorkingDir"; /** * Specifies the amount of time, in milliseconds, after which the process of - * the executable should be terminated. + * the executable should be terminated. The default value is + * {...@link Long#MAX_VALUE}. */ String EXEC_COMMAND_TIMEOUT = "CamelExecCommandTimeout"; /** - * The value of this header is a String with the standard output stream of - * the executable. - */ - String EXEC_STDOUT = "CamelExecStdout"; - /** - * The value of this header is a String with the standard error stream of - * the executable. + * The value of this header is a {...@link InputStream} with the standard error + * stream of the executable. */ String EXEC_STDERR = "CamelExecStderr"; 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -26,7 +26,8 @@ import org.apache.commons.exec.ExecuteEx public interface ExecCommandExecutor { /** - * Executes the <code>command</code> and returns its exit value + * 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 Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecComponent.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecComponent.java (original) +++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecComponent.java Thu Apr 15 06:35:26 2010 @@ -23,7 +23,7 @@ import org.apache.camel.impl.DefaultComp /** * Represents the component that manages {...@link ExecEndpoint}. With the - * component it is possible to execute an system command. + * component it is possible to execute system commands. */ public class ExecComponent extends DefaultComponent { 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -22,6 +22,7 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.exec.impl.DefaultExecBinding; import org.apache.camel.component.exec.impl.DefaultExecCommandExecutor; +import org.apache.camel.component.exec.impl.ExecParseUtils; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.util.ObjectHelper; @@ -85,9 +86,10 @@ public class ExecEndpoint extends Defaul } /** - * Sets the executable to be executed + * Sets the executable to be executed. The executable must not be empty or + * <code>null</code>. * - * @param executable must not be empty or <code>null</code> + * @param executable Sets the executable to be executed. */ public void setExecutable(String executable) { ObjectHelper.notEmpty(executable, "executable"); @@ -95,9 +97,17 @@ public class ExecEndpoint extends Defaul } /** + * The arguments may be one or many whitespace-separated tokens, that can be + * quoted with ", e.g. <code>args="arg 1" arg2"</code> will use two arguments + * <code>arg 1</code> and <code>arg2</code>. To include the quotes use + * <code>""</code><br> + * , e.g. <code>args=""arg 1"" arg2</code> will use the arguments + * <code>"arg 1"</code> and <code>arg2</code>. + * * @return the arguments of the executable application, as configured from - * the endpoint URI + * the endpoint URI. * @see ExecBinding#EXEC_COMMAND_ARGS + * @see ExecParseUtils#splitToWhiteSpaceSeparatedTokens(String) */ public String getArgs() { return args; @@ -108,13 +118,16 @@ public class ExecEndpoint extends Defaul * * @param args Returns <code>null</code> value if no arguments are * configured in the endpoint URI + * @see #getArgs() + * @see ExecBinding#EXEC_COMMAND_ARGS */ public void setArgs(String args) { this.args = args; } /** - * @return the working directory of the executable, or <code>null</code> + * @return the working directory of the executable, or <code>null</code> is + * such is not set. * @see ExecBinding#EXEC_COMMAND_WORKING_DIR */ public String getWorkingDir() { @@ -122,7 +135,7 @@ public class ExecEndpoint extends Defaul } /** - * Sets the working directory of the executable application + * Sets the working directory of the executable. * * @param dir the working directory of the executable. <code>null</code> * values indicates that the current working directory will be Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecProducer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecProducer.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecProducer.java (original) +++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecProducer.java Thu Apr 15 06:35:26 2010 @@ -23,7 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Exec producer + * Exec producer. * * @see {link Producer} */ @@ -47,26 +47,15 @@ public class ExecProducer extends Defaul } ExecResult result = endpoint.getCommandExecutor().execute(execCommand); ObjectHelper.notNull(result, "The command executor must return a not-null result"); - log(result); + if (log.isInfoEnabled()) { + log.info("The command " + execCommand + " had exit value " + result.getExitValue()); + } else if (log.isErrorEnabled() && result.getExitValue() != 0) { + log.error("The command " + execCommand + " returned exit value " + result.getExitValue()); + } getBinding().writeOutput(exchange, result); } private ExecBinding getBinding() { return endpoint.getBinding(); } - - private void log(ExecResult result) { - String executable = result.getCommand().getExecutable(); - // 0 means no error, by convention - if (result.getExitValue() != 0) { - if (log.isErrorEnabled()) { - log.error(new StringBuilder(executable).append(" exit value: ").append(result.getExitValue())); - log.error(new StringBuilder(executable).append(" stderr: ").append(result.getStderr())); - } - } - if (log.isDebugEnabled()) { - log.debug(new StringBuilder(executable).append(" stdout: ").append(result.getStdout())); - } - - } } Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResult.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResult.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResult.java (original) +++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResult.java Thu Apr 15 06:35:26 2010 @@ -16,12 +16,13 @@ */ package org.apache.camel.component.exec; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Serializable; +import static org.apache.camel.util.ObjectHelper.notNull; + /** - * Represents the result of the execution of an {...@link ExecCommand} + * Value object, that represents the result of an {...@link ExecCommand} execution. */ public class ExecResult implements Serializable { @@ -29,56 +30,68 @@ public class ExecResult implements Seria private final ExecCommand command; - private int exitValue; + private final int exitValue; - private InputStream stdout; + private final InputStream stdout; - private InputStream stderr; + private final InputStream stderr; - public ExecResult(ExecCommand command) { + /** + * Creates a <code>ExecResult</code> instance. + * + * @param command A not-null reference of {...@link ExecCommand}, that produced + * the result. + * @param stdout InputStream with the stdout of the command executable. If + * there was no stdout, the value must be <code>null</code>. + * @param stderr InputStream with the stderr of the command executable. If + * there was no stderr, the value must be <code>null</code>. + * @param exitValue the exit value of the command executable. + */ + public ExecResult(ExecCommand command, InputStream stdout, InputStream stderr, int exitValue) { + notNull(command, "command"); this.command = command; - this.stdout = new ByteArrayInputStream(new byte[0]); - this.stderr = new ByteArrayInputStream(new byte[0]); + + this.stdout = stdout; + this.stderr = stderr; + this.exitValue = exitValue; } /** - * @return The command, that produced this result + * The executed command, that produced this result. The returned object is + * never <code>null</code>. + * + * @return The executed command, that produced this result. */ public ExecCommand getCommand() { return command; } /** + * The exit value of the command executable. + * * @return The exit value of the command executable */ public int getExitValue() { return exitValue; } - public void setExitValue(int exitValue) { - this.exitValue = exitValue; - } - /** - * @return The stdout of the command executable + * Returns the content of the standart output (stdout) of the executed + * command or <code>null</code>, if no output was produced in the stdout. + * + * @return The standart output (stdout) of the command executable. */ public InputStream getStdout() { return stdout; } - public void setStdout(InputStream stdout) { - this.stdout = stdout; - } - /** - * @return The stderr of the command executable + * Returns the content of the standart error output (stderr) of the executed + * command or <code>null</code>, if no output was produced in the stderr. + * + * @return The standart error output (stderr) of the command executable. */ public InputStream getStderr() { return stderr; } - - public void setStderr(InputStream stderr) { - this.stderr = stderr; - } - } 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -18,12 +18,14 @@ package org.apache.camel.component.exec; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import org.w3c.dom.Document; import org.apache.camel.Converter; import org.apache.camel.Exchange; +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -47,6 +49,11 @@ public final class ExecResultConverter { } @Converter + public static byte[] convertToByteArray(ExecResult result, Exchange exchange) throws FileNotFoundException, IOException { + return IOUtils.toByteArray(toInputStream(result)); + } + + @Converter public static String convertToString(ExecResult result, Exchange exchange) throws FileNotFoundException { return convertTo(String.class, exchange, result); } @@ -56,11 +63,6 @@ public final class ExecResultConverter { return convertTo(Document.class, exchange, result); } - @Converter - public static byte[] convertToByteArray(ExecResult result, Exchange exchange) throws FileNotFoundException { - return convertTo(byte[].class, exchange, result); - } - /** * Converts <code>ExecResult</code> to the type <code>T</code>. * @@ -86,23 +88,27 @@ public final class ExecResultConverter { * If the ExecResult contains out file, * <code>InputStream<code> with the output of the <code>execResult</code>. * If there is {...@link ExecCommand#getOutFile()}, its content is preferred to - * {...@link ExecResult#getStdout()} + * {...@link ExecResult#getStdout()}. Returns <code>null</code> if the stdout + * is null, or if the <code>execResult</code> is <code>null</code>. * * @param execResult ExecResult object. - * @return InputStream object - * @throws FileNotFoundException if the {...@link ExecResult#getOutFile()} is + * @return InputStream object if the output of the executable. + * @throws FileNotFoundException if the {...@link ExecCommand#getOutFile()} is * not <code>null</code>, but can not be found */ public static InputStream toInputStream(ExecResult execResult) throws FileNotFoundException { if (execResult == null) { - LOG.error("Unable to convert a null exec result!"); + LOG.warn("Received a null ExecResult instance to convert!"); return null; } - InputStream resultVal = execResult.getStdout(); // prefer generic file conversion if (execResult.getCommand().getOutFile() != null) { - resultVal = new FileInputStream(execResult.getCommand().getOutFile()); + return new FileInputStream(execResult.getCommand().getOutFile()); + } else { + if (execResult.getStdout() == null) { + LOG.warn("Received null stdout of the ExecResult for conversion!"); + } + return execResult.getStdout(); } - return resultVal; } } 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -37,18 +37,23 @@ import static org.apache.camel.component */ public class DefaultExecBinding implements ExecBinding { + @SuppressWarnings("unchecked") public ExecCommand readInput(Exchange exchange, ExecEndpoint endpoint) { ObjectHelper.notNull(exchange, "exchange"); ObjectHelper.notNull(endpoint, "endpoint"); String cmd = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_EXECUTABLE, endpoint.getExecutable(), String.class); - String args = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_ARGS, endpoint.getArgs(), String.class); + List<String> argsList = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_ARGS, null, List.class); 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); InputStream input = exchange.getIn().getBody(InputStream.class); - List<String> argsList = splitToWhiteSpaceSeparatedTokens(args); + if (argsList == null) { + // do the URI parsing, only if the arguments are not set + argsList = splitToWhiteSpaceSeparatedTokens(endpoint.getArgs()); + } + File outFile = outFilePath == null ? null : new File(outFilePath); return new ExecCommand(cmd, argsList, dir, timeout, input, outFile); } @@ -89,5 +94,4 @@ public class DefaultExecBinding implemen message.removeHeader(headerName); return h; } - } 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.List; import org.apache.camel.component.exec.ExecCommand; @@ -27,7 +28,6 @@ import org.apache.camel.component.exec.E import org.apache.camel.component.exec.ExecEndpoint; import org.apache.camel.component.exec.ExecException; import org.apache.camel.component.exec.ExecResult; -import org.apache.camel.util.ObjectHelper; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteException; @@ -38,9 +38,11 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import static org.apache.camel.util.ObjectHelper.notNull; + /** * Executes the command utilizing the <a - * href="http://commons.apache.org/exec/">Apache Commmons exec library</a>. Adds + * href="http://commons.apache.org/exec/">Apache Commons exec library</a>. Adds * a shutdown hook for every executed process. */ public class DefaultExecCommandExecutor implements ExecCommandExecutor { @@ -48,13 +50,11 @@ public class DefaultExecCommandExecutor private static final Log LOG = LogFactory.getLog(DefaultExecCommandExecutor.class); public ExecResult execute(ExecCommand command) { - ObjectHelper.notNull(command, "command"); + notNull(command, "command"); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); - ExecResult result = new ExecResult(command); - DefaultExecutor executor = prepareDefaultExecutor(command); // handle error and output of the process and write them to the given // out stream @@ -65,10 +65,11 @@ public class DefaultExecCommandExecutor try { int exitValue = executor.execute(cl); - - result.setExitValue(exitValue); - result.setStdout(new ByteArrayInputStream(out.toByteArray())); - result.setStderr(new ByteArrayInputStream(err.toByteArray())); + // if the size is zero, we have no output, so construct the result + // with null (required by ExecResult) + InputStream stdout = out.size() == 0 ? null : new ByteArrayInputStream(out.toByteArray()); + InputStream stderr = err.size() == 0 ? null : new ByteArrayInputStream(err.toByteArray()); + ExecResult result = new ExecResult(command, stdout, stderr, exitValue); return result; } catch (ExecuteException ee) { @@ -99,12 +100,14 @@ public class DefaultExecCommandExecutor } /** - * Transforms an exec command to a {...@link CommandLine} + * Transforms an {...@link ExecCommand} to a {...@link CommandLine}. No quoting fo + * the arguments is used. * - * @param execCommand - * @return a {...@link CommandLine} object + * @param execCommand a not-null <code>ExecCommand</code> instance. + * @return a {...@link CommandLine} object. */ protected CommandLine toCommandLine(ExecCommand execCommand) { + notNull(execCommand, "execCommand"); CommandLine cl = new CommandLine(execCommand.getExecutable()); List<String> args = execCommand.getArgs(); for (String arg : args) { Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java (original) +++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java Thu Apr 15 06:35:26 2010 @@ -21,7 +21,9 @@ import java.util.List; import java.util.StringTokenizer; /** - * Utility class for parsing, used by the Camel Exec component. + * Utility class for parsing, used by the Camel Exec component.<br> + * Note: the class should be dropped, when the the commons-exec library + * implements similar functionality. */ public final class ExecParseUtils { @@ -35,8 +37,9 @@ public final class ExecParseUtils { /** * Splits the input line string by {...@link #WHITESPACE}. Supports quoting the * white-spaces with a {...@link #QUOTE_CHAR}. A quote itself can also be - * quoted with another #...@link #QUOTE_CHAR}. More than two quotes in a - * sequence is not allowed<br> + * enclosed within #...@link #quote_char...@link #QUOTE_CHAR}. More than two + * double-quotes in a sequence is not allowed. Nested quotes are not + * allowed.<br> * E.g. The string * <code>"arg 1" arg2<code> will return the tokens <code>arg 1</code>, * <code>arg2</code><br> @@ -44,15 +47,15 @@ public final class ExecParseUtils { * <code>""arg 1"" "arg2" arg 3<code> will return the tokens <code>"arg 1"</code> * , <code>arg2</code>,<code>arg</code> and <code>3</code> <br> * - * @param input - * @return a list of {...@link #WHITESPACE} separated tokens + * @param input the input to split. + * @return a not-null list of tokens */ public static List<String> splitToWhiteSpaceSeparatedTokens(String input) { if (input == null) { return new ArrayList<String>(); } StringTokenizer tokenizer = new StringTokenizer(input.trim(), QUOTE_CHAR + WHITESPACE, true); - List<String> args = new ArrayList<String>(); + List<String> tokens = new ArrayList<String>(); StringBuilder quotedText = new StringBuilder(); @@ -64,7 +67,7 @@ public final class ExecParseUtils { quotedText.append(QUOTE_CHAR); String buffer = quotedText.toString(); if (isSingleQuoted(buffer) || isDoubleQuoted(buffer)) { - args.add(buffer.substring(1, buffer.length() - 1)); + tokens.add(buffer.substring(1, buffer.length() - 1)); quotedText = new StringBuilder(); } } else if (WHITESPACE.equals(token)) { @@ -77,21 +80,21 @@ public final class ExecParseUtils { if (quotedText.length() > 0) { quotedText.append(token); } else { - args.add(token); + tokens.add(token); } } } if (quotedText.length() > 0) { throw new IllegalArgumentException("Invalid quoting found in args " + quotedText); } - return args; + return tokens; } /** * Tests if the input is enclosed within {...@link #QUOTE_CHAR} characters * * @param input a not null String - * @return + * @return true if the regular expression is matched */ protected static boolean isSingleQuoted(String input) { if (input == null || input.trim().length() == 0) { Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java (original) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java Thu Apr 15 06:35:26 2010 @@ -157,7 +157,7 @@ public class ExecEndpointTest extends Ab @Test @DirtiesContext public void testCreateEndpointEscapedCommand() throws Exception { - String executable = "\"C:/Program Files/test/text.exe\""; + String executable = "C:/Program Files/test/text.exe"; String uri = "exec:" + executable; ExecEndpoint endpoint = createExecEndpoint(uri); 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=934297&r1=934296&r2=934297&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 Thu Apr 15 06:35:26 2010 @@ -17,6 +17,8 @@ package org.apache.camel.component.exec; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import org.apache.camel.EndpointInject; import org.apache.camel.Exchange; @@ -27,19 +29,18 @@ import org.apache.camel.builder.RouteBui import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.commons.io.IOUtils; - import org.junit.Test; import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_ARGS; import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_EXECUTABLE; import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_TIMEOUT; +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.ExecEndpoint.NO_TIMEOUT; import static org.apache.camel.component.exec.ExecTestUtils.buildJavaExecutablePath; import static org.apache.camel.component.exec.ExecutableJavaProgram.EXIT_WITH_VALUE_0; import static org.apache.camel.component.exec.ExecutableJavaProgram.EXIT_WITH_VALUE_1; -import static org.apache.camel.component.exec.ExecutableJavaProgram.PRINT_IN_STDERR; import static org.apache.camel.component.exec.ExecutableJavaProgram.PRINT_IN_STDOUT; import static org.apache.camel.component.exec.ExecutableJavaProgram.READ_INPUT_LINES_AND_PRINT_THEM; import static org.apache.camel.component.exec.ExecutableJavaProgram.SLEEP_WITH_TIMEOUT; @@ -106,7 +107,6 @@ public class ExecJavaProcessTest extends output.assertIsSatisfied(); String out = e.getIn().getBody(String.class); assertEquals(PRINT_IN_STDOUT, out); - } @Test @@ -133,14 +133,19 @@ public class ExecJavaProcessTest extends } @Test - public void testResultConverterString() throws Exception { - String commandArgument = PRINT_IN_STDERR; - output.setExpectedMessageCount(1); - output.expectedHeaderReceived(EXEC_STDERR, commandArgument); - output.expectedHeaderReceived(EXEC_EXIT_VALUE, 1); + public void testInvalidWorkingDir() throws Exception { + String commandArgument = PRINT_IN_STDOUT; + final List<String> args = buildArgs(commandArgument); + final String javaAbsolutePath = buildJavaExecutablePath(); - sendExchange(commandArgument, NO_TIMEOUT); - output.assertIsSatisfied(); + Exchange e = producerTemplate.send(new Processor() { + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(EXEC_COMMAND_EXECUTABLE, javaAbsolutePath); + exchange.getIn().setHeader(EXEC_COMMAND_WORKING_DIR, "\\cdd:///invalidWWorkginDir"); + exchange.getIn().setHeader(EXEC_COMMAND_ARGS, args); + } + }); + assertEquals(ExecException.class, e.getException().getClass()); } /** @@ -211,19 +216,29 @@ public class ExecJavaProcessTest extends } protected Exchange sendExchange(final Object commandArgument, final long timeout, final String body) { - final String classpath = "\"" + System.getProperty("java.class.path") + "\""; + final List<String> args = buildArgs(commandArgument); final String javaAbsolutePath = buildJavaExecutablePath(); - + return producerTemplate.send(new Processor() { public void process(Exchange exchange) throws Exception { exchange.getIn().setBody(body); exchange.getIn().setHeader(EXEC_COMMAND_EXECUTABLE, javaAbsolutePath); exchange.getIn().setHeader(EXEC_COMMAND_TIMEOUT, timeout); - exchange.getIn().setHeader(EXEC_COMMAND_ARGS, "-cp" + classpath + " " + EXECUTABLE_PROGRAM_ARG + " " + commandArgument.toString()); + exchange.getIn().setHeader(EXEC_COMMAND_ARGS, args); } }); } + private List<String> buildArgs(Object commandArgument) { + String classpath = System.getProperty("java.class.path"); + List<String> args = new ArrayList<String>(); + args.add("-cp"); + args.add(classpath); + args.add(EXECUTABLE_PROGRAM_ARG); + args.add(commandArgument.toString()); + return args; + } + @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java (original) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java Thu Apr 15 06:35:26 2010 @@ -17,6 +17,7 @@ package org.apache.camel.component.exec; import java.io.IOException; +import java.util.Arrays; import java.util.List; import org.apache.camel.Exchange; @@ -79,22 +80,24 @@ public class ExecProducerTest extends Ab assertEquals(command, execCommandExecutorMock.lastCommandResult.getCommand().getExecutable()); } + /** + * Tests that the args are set literally. + */ @Test @DirtiesContext public void testOverrideArgs() { - final String[] args = {"-version", "\"classpath:c:/program files/test/\""}; + final String[] args = {"-version", "classpath:c:/program files/test/"}; producerTemplate.send(new Processor() { public void process(Exchange exchange) throws Exception { exchange.getIn().setBody("noinput"); - exchange.getIn().setHeader(EXEC_COMMAND_ARGS, args[0] + " " + args[1]); + exchange.getIn().setHeader(EXEC_COMMAND_ARGS, Arrays.asList(args)); } }); List<String> commandArgs = execCommandExecutorMock.lastCommandResult.getCommand().getArgs(); assertEquals(args[0], commandArgs.get(0)); - String secondArgEscaped = args[1].substring(1, args[1].length() - 1); - assertEquals(secondArgEscaped, commandArgs.get(1)); + assertEquals(args[1], commandArgs.get(1)); } @Test @@ -139,6 +142,21 @@ public class ExecProducerTest extends Ab assertNotNull(result); assertNull(result.getCommand().getInput()); } + + @Test + @DirtiesContext + public void testNullInBody() throws IOException { + // Null body must also be supported + Exchange e = producerTemplate.send(new Processor() { + + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody(null); + } + }); + ExecResult result = e.getIn().getBody(ExecResult.class); + assertNotNull(result); + assertNull(result.getCommand().getInput()); + } @Test @DirtiesContext Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecScriptTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecScriptTest.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecScriptTest.java (original) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecScriptTest.java Thu Apr 15 06:35:26 2010 @@ -33,7 +33,6 @@ import static org.apache.camel.component import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_EXECUTABLE; import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_TIMEOUT; import static org.apache.camel.component.exec.ExecBinding.EXEC_STDERR; -import static org.apache.camel.component.exec.ExecBinding.EXEC_STDOUT; import static org.apache.camel.component.exec.ExecEndpoint.NO_TIMEOUT; import static org.apache.camel.component.exec.ExecTestUtils.getClasspathResourceFileOrNull; import static org.apache.camel.component.exec.ExecutableJavaProgram.PRINT_IN_STDOUT; @@ -67,7 +66,7 @@ public class ExecScriptTest extends Abst String classpathArg = getClasspathArg(); Exchange exchange = executeScript(scriptFile, NO_TIMEOUT, classpathArg, PRINT_IN_STDOUT); if (exchange != null) { - String out = (String)exchange.getIn().getHeader(EXEC_STDOUT); + String out = (String)exchange.getIn().getBody(String.class); String err = (String)exchange.getIn().getHeader(EXEC_STDERR); assertNotNull(out); Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecTestUtils.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecTestUtils.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecTestUtils.java (original) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecTestUtils.java Thu Apr 15 06:35:26 2010 @@ -19,7 +19,6 @@ package org.apache.camel.component.exec; import java.io.File; import java.io.IOException; -import org.apache.commons.exec.OS; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.io.ClassPathResource; Modified: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecCommandExecutorMock.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecCommandExecutorMock.java?rev=934297&r1=934296&r2=934297&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecCommandExecutorMock.java (original) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecCommandExecutorMock.java Thu Apr 15 06:35:26 2010 @@ -33,9 +33,7 @@ public class ExecCommandExecutorMock imp public ExecResult execute(ExecCommand command) { - lastCommandResult = new ExecResult(command); - lastCommandResult.setStdout(new ByteArrayInputStream(STD_OUT_VALUE.getBytes())); - lastCommandResult.setExitValue(0); + lastCommandResult = new ExecResult(command, new ByteArrayInputStream(STD_OUT_VALUE.getBytes()), null, 0); return lastCommandResult; } } Added: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java?rev=934297&view=auto ============================================================================== --- camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java (added) +++ camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java Thu Apr 15 06:35:26 2010 @@ -0,0 +1,193 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.exec.impl; + +import java.io.File; +import java.io.InputStream; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.Produce; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.exec.ExecResult; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import org.junit.Ignore; +import org.junit.Test; + +import static org.apache.camel.component.exec.ExecTestUtils.buildJavaExecutablePath; + +/** + * The tests are ignored by default, because they are OS-specific. On demand + * they can be run manually to validate the documentation examples for that OS. + */ + +public class ExecDocumentationExamplesTest extends CamelTestSupport { + + private static final String ANT_BUILD_FILE_NAME = "CamelExecTestAntBuildFile.xml"; + + private static final String ANT_OUT_FILE_NAME = "CamelExecOutFile.txt"; + + private static final String ANT_BUILD_FILE_CONTENT = buildAntFileContent(); + + private static final String TEST_MSG = "Hello Camel Exec!"; + + @Produce(uri = "direct:javaVersion") + protected ProducerTemplate templateJavaVersion; + + @Produce(uri = "direct:javaVersionWorkingDir") + protected ProducerTemplate templateJavaVersionWorkingDir; + + @Produce(uri = "direct:execAnt") + protected ProducerTemplate templateExecAnt; + + @Produce(uri = "direct:execAntWithOutFile") + protected ProducerTemplate templateExecAntWithOutFile; + + @Produce(uri = "direct:wordCount") + protected ProducerTemplate templateWordCount; + + @Test + @Ignore + public void testExecLinuxWordCount() throws Exception { + // use type conversion here + ExecResult body = templateWordCount.requestBody((Object)"test", ExecResult.class); + assertNotNull(body); + + } + + /** + * The test assumes, that java is in the system path + */ + @Test + @Ignore + public void testJavaVersion() throws Exception { + ExecResult body = templateJavaVersion.requestBody((Object)"test", ExecResult.class); + InputStream out = body.getStdout(); + InputStream err = body.getStderr(); + // Strange that Sun Java 1.5 writes the -version in the syserr + assertNull(out); + assertNotNull(err); + String outString = IOUtils.toString(err); + log.info("Received stdout: " + outString); + assertTrue(outString.contains("java version")); + } + + @Test + @Ignore + public void testWinJavaVersionWorkingDir() throws Exception { + ExecResult body = templateJavaVersionWorkingDir.requestBody((Object)"test", ExecResult.class); + InputStream out = body.getStdout(); + InputStream err = body.getStderr(); + // Strange that Sun Java 1.5 writes the -version in the syserr + assertNull(out); + assertNotNull(err); + String outerr = IOUtils.toString(err); + log.info("Received stderr: " + outerr); + assertTrue(outerr.contains("java version")); + } + + /** + * The test assumes that Apache ant is installed + */ + @Test + @Ignore + public void testExecWinAnt() throws Exception { + File f = new File(ANT_BUILD_FILE_NAME); + f.createNewFile(); + FileUtils.writeStringToFile(f, ANT_BUILD_FILE_CONTENT); + assertTrue("You must create a sample build file!", f.exists()); + ExecResult body = templateExecAnt.requestBody((Object)"test", ExecResult.class); + String stdout = IOUtils.toString(body.getStdout()); + assertNull(body.getStderr()); + assertTrue("The ant script should print" + TEST_MSG, stdout.contains(TEST_MSG)); + f.delete(); + } + + /** + * The test assumes that Apache ant is installed + */ + @Test + @Ignore + public void testExecWinAntWithOutFile() throws Exception { + File f = new File(ANT_BUILD_FILE_NAME); + f.createNewFile(); + FileUtils.writeStringToFile(f, ANT_BUILD_FILE_CONTENT); + assertTrue("You must create a sample build file!", f.exists()); + // use type conversion here + InputStream body = templateExecAntWithOutFile.requestBody((Object)"test", InputStream.class); + String bodyString = IOUtils.toString(body); + assertTrue("The ant script should print" + TEST_MSG, bodyString.contains(TEST_MSG)); + f.delete(); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + // word count + from("direct:wordCount").to("exec:wc?args=--words /usr/share/dict/words").process(new Processor() { + public void process(Exchange exchange) throws Exception { + // By default, the body is ExecResult instance + assertIsInstanceOf(ExecResult.class, exchange.getIn().getBody()); + // Use the Camel Exec String type converter to + // convert the ExecResult to String + // In this case, the stdout is considered as output + String wordCountOutput = exchange.getIn().getBody(String.class); + // do something with the output + log.info(wordCountOutput); + } + + }); + + // example 1 in the component docs + from("direct:javaVersion").to("exec:java?args=-version -server"); + // example 2 in the component docs + from("direct:javaVersionWorkingDir").to("exec:" + buildJavaExecutablePath() + "?args=-version -Duser.name=Camel&workingDir=C:/temp"); + + // advanced, test ant + from("direct:execAnt").to("exec:ant.bat?args=-f " + ANT_BUILD_FILE_NAME); + + // advanced, test ant with out file + from("direct:execAntWithOutFile").to("exec:ant.bat?args=-f " + ANT_BUILD_FILE_NAME + " -l " + ANT_OUT_FILE_NAME + "&outFile=" + ANT_OUT_FILE_NAME) + .process(new Processor() { + + public void process(Exchange exchange) throws Exception { + InputStream outFile = exchange.getIn().getBody(InputStream.class); + // do something with the out file here + log.info(IOUtils.toString(outFile)); + } + + }); + } + }; + } + + private static String buildAntFileContent() { + StringBuilder builder = new StringBuilder(); + builder.append("<project name=\"TestExec\" default=\"test\" basedir=\".\">"); + builder.append("<target name=\"test\">"); + builder.append("<echo message=\"" + TEST_MSG + "\"/>"); + builder.append("</target>"); + builder.append("</project>"); + return builder.toString(); + } + +} Propchange: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecDocumentationExamplesTest.java ------------------------------------------------------------------------------ svn:keywords = Rev Date