Author: davsclaus Date: Fri Nov 26 14:37:44 2010 New Revision: 1039384 URL: http://svn.apache.org/viewvc?rev=1039384&view=rev Log: CAMEL-3167: Constant fields from Exchange can now be referred as String in the DSL. Making it easier from Spring XML as you just use Exchange.FILE_NAME and it validates if the field exist or not.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeFailTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeFailTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeTest.java - copied, changed from r1039334, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringChoiceTest.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml - copied, changed from r1039334, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/choice.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java?rev=1039384&r1=1039383&r2=1039384&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java Fri Nov 26 14:37:44 2010 @@ -35,6 +35,7 @@ import javax.xml.bind.annotation.XmlTran import org.apache.camel.Channel; import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.Expression; import org.apache.camel.LoggingLevel; @@ -66,6 +67,7 @@ import org.apache.camel.spi.Policy; import org.apache.camel.spi.RouteContext; import org.apache.camel.spi.TransactedPolicy; import org.apache.camel.util.IntrospectionSupport; +import org.apache.camel.util.ObjectHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -389,6 +391,9 @@ public abstract class ProcessorDefinitio // resolve properties before we create the processor resolvePropertyPlaceholders(routeContext, this); + // resolve constant fields (eg Exchange.FILE_NAME) + resolveKnownConstantFields(this); + // at first use custom factory if (routeContext.getCamelContext().getProcessorFactory() != null) { processor = routeContext.getCamelContext().getProcessorFactory().createProcessor(routeContext, this); @@ -452,6 +457,56 @@ public abstract class ProcessorDefinitio } } + /** + * Inspects the given processor definition and resolves known fields + * <p/> + * This implementation will check all the getter/setter pairs on this instance and for all the values + * (which is a String type) will check if it refers to a known field (such as on Exchange). + * + * @param definition the processor definition + */ + protected void resolveKnownConstantFields(ProcessorDefinition definition) throws Exception { + if (log.isTraceEnabled()) { + log.trace("Resolving known fields for: " + definition); + } + + // find all String getter/setter + Map<Object, Object> properties = new HashMap<Object, Object>(); + IntrospectionSupport.getProperties(definition, properties, null); + + if (!properties.isEmpty()) { + if (log.isTraceEnabled()) { + log.trace("There are " + properties.size() + " properties on: " + definition); + } + + // lookup and resolve properties for String based properties + for (Map.Entry entry : properties.entrySet()) { + // the name is always a String + String name = (String) entry.getKey(); + Object value = entry.getValue(); + if (value instanceof String) { + // we can only resolve String typed values + String text = (String) value; + + // is the value a known field + if (text.startsWith("Exchange.")) { + String field = ObjectHelper.after(text, "Exchange."); + String constant = ObjectHelper.lookupConstantFieldValue(Exchange.class, field); + if (constant != null) { + // invoke setter as the text has changed + IntrospectionSupport.setProperty(definition, name, constant); + if (log.isDebugEnabled()) { + log.debug("Changed property [" + name + "] from: " + value + " to: " + constant); + } + } else { + throw new IllegalArgumentException("Constant field with name: " + field + " not found on Exchange.class"); + } + } + } + } + } + } + protected ErrorHandlerBuilder createErrorHandlerBuilder() { if (errorHandlerRef != null) { return new ErrorHandlerBuilderRef(errorHandlerRef); Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java?rev=1039384&r1=1039383&r2=1039384&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java Fri Nov 26 14:37:44 2010 @@ -22,6 +22,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; @@ -1270,6 +1271,32 @@ public final class ObjectHelper { return "0x" + Integer.toHexString(System.identityHashCode(object)); } + /** + * Lookup the constant field on the given class with the given name + * + * @param clazz the class + * @param name the name of the field to lookup + * @return the value of the constant field, or <tt>null</tt> if not found + */ + public static String lookupConstantFieldValue(Class clazz, String name) { + if (clazz == null) { + return null; + } + + for (Field field : clazz.getFields()) { + if (field.getName().equals(name)) { + try { + return (String) field.get(null); + } catch (IllegalAccessException e) { + // ignore + return null; + } + } + } + + return null; + } + private static final class ExceptionIterator implements Iterator<Throwable> { private List<Throwable> tree = new ArrayList<Throwable>(); private Iterator<Throwable> it; Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeFailTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeFailTest.java?rev=1039384&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeFailTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeFailTest.java Fri Nov 26 14:37:44 2010 @@ -0,0 +1,54 @@ +/** + * 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.processor; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.FailedToCreateRouteException; +import org.apache.camel.builder.RouteBuilder; + +/** + * @version $Revision$ + */ +public class RouteWithConstantFieldFromExchangeFailTest extends ContextTestSupport { + + public void testFail() throws Exception { + // noop as its tested that it fails on startup + } + + @Override + protected void setUp() throws Exception { + try { + super.setUp(); + fail("Should have thrown an exception"); + } catch (FailedToCreateRouteException e) { + IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause()); + assertEquals("Constant field with name: XXX not found on Exchange.class", iae.getMessage()); + } + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:bar") + .setHeader("Exchange.XXX", constant("bar")) + .to("mock:bar"); + } + }; + } +} Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeTest.java?rev=1039384&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RouteWithConstantFieldFromExchangeTest.java Fri Nov 26 14:37:44 2010 @@ -0,0 +1,48 @@ +/** + * 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.processor; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; + +/** + * @version $Revision$ + */ +public class RouteWithConstantFieldFromExchangeTest extends ContextTestSupport { + + public void testOk() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:result").expectedHeaderReceived(Exchange.FILE_NAME, "foo.txt"); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .setHeader("Exchange.FILE_NAME", constant("foo.txt")) + .to("mock:result"); + } + }; + } +} Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java?rev=1039384&r1=1039383&r2=1039384&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java Fri Nov 26 14:37:44 2010 @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import junit.framework.TestCase; +import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.impl.DefaultMessage; @@ -274,4 +275,11 @@ public class ObjectHelperTest extends Te assertEquals("Should get the right class name", "Integer[]", ObjectHelper.normalizeClassName("Integer[] \r")); assertEquals("Should get the right class name", "Hello_World", ObjectHelper.normalizeClassName("Hello_World")); } + + public void testLookupConstantFieldValue() { + assertEquals("CamelFileName", ObjectHelper.lookupConstantFieldValue(Exchange.class, "FILE_NAME")); + assertEquals(null, ObjectHelper.lookupConstantFieldValue(Exchange.class, "XXX")); + assertEquals(null, ObjectHelper.lookupConstantFieldValue(null, "FILE_NAME")); + } + } Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeFailTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeFailTest.java?rev=1039384&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeFailTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeFailTest.java Fri Nov 26 14:37:44 2010 @@ -0,0 +1,46 @@ +/** + * 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.spring.processor; + +import org.apache.camel.CamelContext; +import org.apache.camel.FailedToCreateRouteException; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.processor.RouteWithConstantFieldFromExchangeFailTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version $Revision: 630591 $ + */ +public class SpringRouteWithConstantFieldFromExchangeFailTest extends RouteWithConstantFieldFromExchangeFailTest { + + @Override + protected void setUp() throws Exception { + try { + super.setUp(); + fail("Should have thrown an exception"); + } catch (RuntimeCamelException e) { + FailedToCreateRouteException re = assertIsInstanceOf(FailedToCreateRouteException.class, e.getCause()); + IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, re.getCause()); + assertEquals("Constant field with name: XXX not found on Exchange.class", iae.getMessage()); + } + } + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml"); + } +} \ No newline at end of file Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeTest.java (from r1039334, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringChoiceTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringChoiceTest.java&r1=1039334&r2=1039384&rev=1039384&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringChoiceTest.java (original) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringRouteWithConstantFieldFromExchangeTest.java Fri Nov 26 14:37:44 2010 @@ -17,14 +17,16 @@ package org.apache.camel.spring.processor; import org.apache.camel.CamelContext; -import org.apache.camel.processor.ChoiceTest; +import org.apache.camel.processor.RouteWithConstantFieldFromExchangeTest; + import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; /** * @version $Revision$ */ -public class SpringChoiceTest extends ChoiceTest { +public class SpringRouteWithConstantFieldFromExchangeTest extends RouteWithConstantFieldFromExchangeTest { + protected CamelContext createCamelContext() throws Exception { - return createSpringCamelContext(this, "org/apache/camel/spring/processor/choice.xml"); + return createSpringCamelContext(this, "org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml"); } } \ No newline at end of file Added: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml?rev=1039384&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml (added) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeFailTest.xml Fri Nov 26 14:37:44 2010 @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:bar"/> + <setHeader headerName="Exchange.XXX"> + <constant>bar</constant> + </setHeader> + <to uri="mock:bar"/> + </route> + </camelContext> + +</beans> Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml (from r1039334, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/choice.xml) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/choice.xml&r1=1039334&r2=1039384&rev=1039384&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/choice.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/RouteWithConstantFieldFromExchangeTest.xml Fri Nov 26 14:37:44 2010 @@ -22,26 +22,17 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> - <!-- START SNIPPET: example --> - <camelContext xmlns="http://camel.apache.org/schema/spring"> - <route> - <from uri="direct:start"/> - <choice> - <when> - <xpath>$foo = 'bar'</xpath> - <to uri="mock:x"/> - </when> - <when> - <xpath>$foo = 'cheese'</xpath> - <to uri="mock:y"/> - </when> - <otherwise> - <to uri="mock:z"/> - </otherwise> - </choice> - <to uri="mock:end"/> - </route> - </camelContext> - <!-- END SNIPPET: example --> + <!-- START SNIPPET: example --> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <!-- we can refer to constant fields from Exchange like we do in Java DSL --> + <setHeader headerName="Exchange.FILE_NAME"> + <constant>foo.txt</constant> + </setHeader> + <to uri="mock:result"/> + </route> + </camelContext> + <!-- END SNIPPET: example --> </beans>