Author: davsclaus Date: Sun Sep 26 07:05:45 2010 New Revision: 1001371 URL: http://svn.apache.org/viewvc?rev=1001371&view=rev Log: CAMEL-3160: Added alternative start token for simple language to avoid clash with springs property placeholder feature.
Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.java - copied, changed from r1001363, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.xml - copied unchanged from r1001363, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileComponent.java camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/myprop.properties Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileComponent.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileComponent.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileComponent.java Sun Sep 26 07:05:45 2010 @@ -19,6 +19,8 @@ package org.apache.camel.component.file; import java.io.File; import java.util.Map; +import org.apache.camel.language.simple.SimpleLanguage; + /** * File component. */ @@ -36,7 +38,7 @@ public class FileComponent extends Gener protected GenericFileEndpoint<File> buildFileEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { // the starting directory must be a static (not containing dynamic expressions) - if (remaining.indexOf("${") != -1) { + if (SimpleLanguage.hasStartToken(remaining)) { throw new IllegalArgumentException("Invalid directory: " + remaining + ". Dynamic expressions with ${ } placeholders is not allowed." + " Use the fileName option to set the dynamic expression."); Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java Sun Sep 26 07:05:45 2010 @@ -31,6 +31,7 @@ import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.converter.IOConverter; import org.apache.camel.impl.ScheduledPollEndpoint; +import org.apache.camel.language.simple.SimpleLanguage; import org.apache.camel.processor.idempotent.MemoryIdempotentRepository; import org.apache.camel.spi.FactoryFinder; import org.apache.camel.spi.IdempotentRepository; @@ -534,7 +535,7 @@ public abstract class GenericFileEndpoin */ protected String configureMoveOrPreMoveExpression(String expression) { // if the expression already have ${ } placeholders then pass it unmodified - if (expression.indexOf("${") != -1) { + if (SimpleLanguage.hasStartToken(expression)) { return expression; } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java Sun Sep 26 07:05:45 2010 @@ -22,6 +22,7 @@ import java.io.InputStream; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.language.simple.SimpleLanguage; import org.apache.camel.spi.Language; import org.apache.camel.util.ExchangeHelper; import org.apache.camel.util.FileUtil; @@ -242,7 +243,7 @@ public class GenericFileProducer<T> exte if (name != null) { // the header name can be an expression too, that should override // whatever configured on the endpoint - if (name.indexOf("${") > -1) { + if (SimpleLanguage.hasStartToken(name)) { if (log.isDebugEnabled()) { log.debug(Exchange.FILE_NAME + " contains a Simple expression: " + name); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java Sun Sep 26 07:05:45 2010 @@ -32,7 +32,9 @@ import org.apache.camel.util.StringHelpe * <li>id to access the inbound message id</li> * <li>in.body or body to access the inbound body</li> * <li>in.body.OGNL or body.OGNL to access the inbound body using an OGNL expression</li> - * <li>bodyAs(<classname>) to convert the in body to the given type</li> + * <li>mandatoryBodyAs(<classname>) to convert the in body to the given type, will throw exception if not possible to convert</li> + * <li>bodyAs(<classname>) to convert the in body to the given type, will return null if not possible to convert</li> + * <li>headerAs(<key>, <classname>) to convert the in header to the given type, will return null if not possible to convert</li> * <li>out.body to access the inbound body</li> * <li>in.header.foo or header.foo to access an inbound header called 'foo'</li> * <li>in.header.foo[bar] or header.foo[bar] to access an inbound header called 'foo' as a Map and lookup the map with 'bar' as key</li> @@ -90,6 +92,20 @@ public class SimpleLanguage extends Simp private static final SimpleLanguage SIMPLE = new SimpleLanguage(); + /** + * Does the expression have the simple language start token? + * + * @param expression the expression + * @return <tt>true</tt> if the expression contains the start token, <tt>false</tt> otherwise + */ + public static boolean hasStartToken(String expression) { + if (expression == null) { + return false; + } + + return expression.indexOf("${") >= 0 || expression.indexOf("$simple{") >= 0; + } + public static Expression simple(String expression) { return SIMPLE.createExpression(expression); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java Sun Sep 26 07:05:45 2010 @@ -85,7 +85,7 @@ public abstract class SimpleLanguageSupp log.debug("Expression is evaluated as simple (with operator) expression: " + expression); } return createOperatorExpression(matcher, startMatcher, expression); - } else if (expression.indexOf("${") >= 0) { + } else if (SimpleLanguage.hasStartToken(expression)) { if (log.isDebugEnabled()) { log.debug("Expression is evaluated as simple (strict) expression: " + expression); } @@ -294,15 +294,21 @@ public abstract class SimpleLanguageSupp int pivot = 0; int size = expression.length(); while (pivot < size) { + // look for start tokens + int delta = 2; int idx = expression.indexOf("${", pivot); if (idx < 0) { + idx = expression.indexOf("$simple{", pivot); + delta = 8; + } + if (idx < 0) { results.add(createConstantExpression(expression, pivot, size)); break; } else { if (pivot < idx) { results.add(createConstantExpression(expression, pivot, idx)); } - pivot = idx + 2; + pivot = idx + delta; int endIdx = expression.indexOf('}', pivot); if (endIdx < 0) { throw new IllegalArgumentException("Expecting } but found end of string for simple expression: " + expression); @@ -328,6 +334,9 @@ public abstract class SimpleLanguageSupp protected Expression createSimpleOrConstantExpression(String text) { if (text != null) { String simple = ObjectHelper.between(text, "${", "}"); + if (simple == null) { + simple = ObjectHelper.between(text, "$simple{", "}"); + } if (simple != null) { return createSimpleExpression(simple, true); } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java Sun Sep 26 07:05:45 2010 @@ -78,6 +78,25 @@ public class FileLanguageTest extends La assertEquals(new Date(file.lastModified()), modified); } + public void testFileUsingAlternativeStartToken() throws Exception { + assertExpression("$simple{file:ext}", "txt"); + assertExpression("$simple{file:name.ext}", "txt"); + assertExpression("$simple{file:name}", "test" + File.separator + file.getName()); + assertExpression("$simple{file:name.noext}", "test" + File.separator + "hello"); + assertExpression("$simple{file:onlyname}", file.getName()); + assertExpression("$simple{file:onlyname.noext}", "hello"); + assertExpression("$simple{file:parent}", file.getParent()); + assertExpression("$simple{file:path}", file.getPath()); + assertExpression("$simple{file:absolute}", FileUtil.isAbsolute(file)); + assertExpression("$simple{file:absolute.path}", file.getAbsolutePath()); + assertExpression("$simple{file:length}", file.length()); + assertExpression("$simple{file:size}", file.length()); + + // modified is a Date object + Date modified = SimpleLanguage.simple("file:modified").evaluate(exchange, Date.class); + assertEquals(new Date(file.lastModified()), modified); + } + public void testDate() throws Exception { String now = new SimpleDateFormat("yyyyMMdd").format(new Date()); assertExpression("backup-${date:now:yyyyMMdd}", "backup-" + now); @@ -96,6 +115,24 @@ public class FileLanguageTest extends La } } + public void testDateUsingAlternativeStartToken() throws Exception { + String now = new SimpleDateFormat("yyyyMMdd").format(new Date()); + assertExpression("backup-$simple{date:now:yyyyMMdd}", "backup-" + now); + + String expected = new SimpleDateFormat("yyyyMMdd").format(new Date(file.lastModified())); + assertExpression("backup-$simple{date:file:yyyyMMdd}", "backup-" + expected); + + assertExpression("backup-$simple{date:header.birthday:yyyyMMdd}", "backup-19740420"); + assertExpression("hello-$simple{date:out.header.special:yyyyMMdd}", "hello-20080808"); + + try { + this.assertExpression("nodate-$simple{date:header.xxx:yyyyMMdd}", null); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + public void testSimpleAndFile() throws Exception { assertExpression("backup-${in.header.foo}-${file:name.noext}.bak", "backup-abc-test" + File.separator + "hello.bak"); assertExpression("backup-${in.header.foo}-${file:onlyname.noext}.bak", "backup-abc-hello.bak"); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java Sun Sep 26 07:05:45 2010 @@ -48,6 +48,11 @@ public class SimpleTest extends Language assertNotNull(exp); } + public void testBodyExpressionUsingAlternativeStartToken() throws Exception { + Expression exp = SimpleLanguage.simple("$simple{body}"); + assertNotNull(exp); + } + public void testBodyExpressionNotStringType() throws Exception { exchange.getIn().setBody(123); Expression exp = SimpleLanguage.simple("${body}"); @@ -141,6 +146,16 @@ public class SimpleTest extends Language assertExpression("${in.header.foo}!", "abc!"); } + public void testComplexExpressionsUsingAlternativeStartToken() throws Exception { + assertExpression("hey $simple{in.header.foo}", "hey abc"); + assertExpression("hey $simple{in.header.foo}!", "hey abc!"); + assertExpression("hey $simple{in.header.foo}-$simple{in.header.foo}!", "hey abc-abc!"); + assertExpression("hey $simple{in.header.foo}$simple{in.header.foo}", "hey abcabc"); + assertExpression("$simple{in.header.foo}$simple{in.header.foo}", "abcabc"); + assertExpression("$simple{in.header.foo}", "abc"); + assertExpression("$simple{in.header.foo}!", "abc!"); + } + public void testInvalidComplexExpression() throws Exception { try { assertExpression("hey ${foo", "bad expression!"); Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.java (from r1001363, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.java&r1=1001363&r2=1001371&rev=1001371&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.java (original) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/issues/SpringPropertyPlaceholderFileEndpointIssueTest.java Sun Sep 26 07:05:45 2010 @@ -16,6 +16,7 @@ */ package org.apache.camel.spring.issues; +import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.spring.SpringTestSupport; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -23,7 +24,7 @@ import org.springframework.context.suppo /** * @version $Revision$ */ -public class SpringPropertyPlaceholderIssueTest extends SpringTestSupport { +public class SpringPropertyPlaceholderFileEndpointIssueTest extends SpringTestSupport { @Override protected AbstractXmlApplicationContext createApplicationContext() { @@ -31,9 +32,13 @@ public class SpringPropertyPlaceholderIs } public void testSpring() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); + deleteDirectory("target/issue"); - template.sendBody("direct:start", "Hello World"); + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + mock.expectedFileExists("target/issue/foo.txt"); + + template.sendBodyAndHeader("direct:start", "Hello World", "foo", "foo.txt"); assertMockEndpointsSatisfied(); } Modified: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/SpringPropertyPlaceholderIssueTest.xml Sun Sep 26 07:05:45 2010 @@ -22,16 +22,25 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> + <!-- START SNIPPET: e1 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:org/apache/camel/spring/issues/myprop.properties"/> </bean> - <bean id="myRoute" class="org.apache.camel.spring.issues.MyCoolRoute"> - <property name="inputQueue" value="${inputQueue}"/> - </bean> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + + <!-- use $simple{ start token in the fileName parameter + to avoid clash with spring property placeholder. However we can still use + spring property placeholders for the output folder --> + <endpoint id="myFile" uri="file://${outputFolder}?fileName=$simple{header.foo}"/> + + <route> + <from uri="direct:start"/> + <to ref="myFile"/> + <to uri="mock:result"/> + </route> - <camelContext trace="true" xmlns="http://camel.apache.org/schema/spring"> - <routeBuilder ref="myRoute"/> </camelContext> + <!-- END SNIPPET: e1 --> </beans> Modified: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/myprop.properties URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/myprop.properties?rev=1001371&r1=1001370&r2=1001371&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/myprop.properties (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/myprop.properties Sun Sep 26 07:05:45 2010 @@ -15,4 +15,6 @@ ## limitations under the License. ## ------------------------------------------------------------------------ -inputQueue=direct:start \ No newline at end of file +inputQueue=direct:start + +outputFolder=target/issue \ No newline at end of file