Author: davsclaus
Date: Tue Feb 22 15:09:31 2011
New Revision: 1073359
URL: http://svn.apache.org/viewvc?rev=1073359&view=rev
Log:
CAMEL-3210: Property placeholders can now be used for any attribute in XML DSL.
Using the xs:any for otherAttributes.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslTest.java
camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.java
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml
- copied, changed from r1073309,
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/model/Constants.java
camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
camel/trunk/camel-core/src/test/resources/org/apache/camel/component/properties/myproperties.properties
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/myprop.properties
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/model/Constants.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/Constants.java?rev=1073359&r1=1073358&r2=1073359&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/Constants.java
(original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/Constants.java
Tue Feb 22 15:09:31 2011
@@ -31,6 +31,7 @@ public final class Constants {
+ "org.apache.camel.model.language:"
+ "org.apache.camel.model.loadbalancer";
+ public static final String PLACEHOLDER_QNAME =
"http://camel.apache.org/schema/placeholder";
private Constants() {
}
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=1073359&r1=1073358&r2=1073359&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
Tue Feb 22 15:09:31 2011
@@ -19,7 +19,6 @@ package org.apache.camel.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
@@ -30,8 +29,10 @@ import java.util.concurrent.ExecutorServ
import java.util.concurrent.TimeUnit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.namespace.QName;
import org.apache.camel.Channel;
import org.apache.camel.Endpoint;
@@ -48,6 +49,7 @@ import org.apache.camel.builder.ErrorHan
import org.apache.camel.builder.ExpressionBuilder;
import org.apache.camel.builder.ExpressionClause;
import org.apache.camel.builder.ProcessorBuilder;
+import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.model.language.ConstantExpression;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.model.language.LanguageExpression;
@@ -89,6 +91,9 @@ public abstract class ProcessorDefinitio
private ProcessorDefinition<?> parent;
private final List<InterceptStrategy> interceptStrategies = new
ArrayList<InterceptStrategy>();
+ // use xs:any to support optional property placeholders
+ private Map<QName, Object> otherAttributes;
+
// else to use an optional attribute in JAXB2
public abstract List<ProcessorDefinition> getOutputs();
@@ -427,10 +432,34 @@ public abstract class ProcessorDefinitio
log.trace("Resolving property placeholders for: " + definition);
}
- // find all String getter/setter
+ // find all getter/setter which we can use for property placeholders
Map<Object, Object> properties = new HashMap<Object, Object>();
IntrospectionSupport.getProperties(definition, properties, null);
+ // include additional properties which have the Camel placeholder QName
+ // and when the definition parameter is this (otherAttributes belong
to this)
+ if (definition.getOtherAttributes() != null) {
+ for (Object key : definition.getOtherAttributes().keySet()) {
+ QName qname = (QName) key;
+ if
(Constants.PLACEHOLDER_QNAME.equals(qname.getNamespaceURI())) {
+ String local = qname.getLocalPart();
+ Object value = definition.getOtherAttributes().get(key);
+ if (value != null && value instanceof String ) {
+ // value must be enclosed with placeholder tokens
+ String s = (String) value;
+ if (!s.startsWith(PropertiesComponent.PREFIX_TOKEN)) {
+ s = PropertiesComponent.PREFIX_TOKEN + s;
+ }
+ if (!s.endsWith(PropertiesComponent.SUFFIX_TOKEN)) {
+ s = s + PropertiesComponent.SUFFIX_TOKEN;
+ }
+ value = s;
+ }
+ properties.put(local, value);
+ }
+ }
+ }
+
if (!properties.isEmpty()) {
if (log.isTraceEnabled()) {
log.trace("There are " + properties.size() + " properties on:
" + definition);
@@ -442,12 +471,15 @@ public abstract class ProcessorDefinitio
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof String) {
- // we can only resolve String typed values
+ // value must be a String, as a String is the key for a
property placeholder
String text = (String) value;
text =
routeContext.getCamelContext().resolvePropertyPlaceholders(text);
if (text != value) {
// invoke setter as the text has changed
- IntrospectionSupport.setProperty(definition, name,
text);
+ boolean changed =
IntrospectionSupport.setProperty(routeContext.getCamelContext().getTypeConverter(),
definition, name, text);
+ if (!changed) {
+ throw new IllegalArgumentException("No setter to
set property: " + name + " to: " + text + " on: " + definition);
+ }
if (log.isDebugEnabled()) {
log.debug("Changed property [" + name + "] from: "
+ value + " to: " + text);
}
@@ -525,6 +557,35 @@ public abstract class ProcessorDefinitio
//
-------------------------------------------------------------------------
/**
+ * Adds a placeholder for the given option
+ * <p/>
+ * Requires using the {@link
org.apache.camel.component.properties.PropertiesComponent}
+ *
+ * @param option the name of the option
+ * @param key the placeholder key
+ * @return the builder
+ */
+ public Type placeholder(String option, String key) {
+ QName name = new QName(Constants.PLACEHOLDER_QNAME, option);
+ return attribute(name, key);
+ }
+
+ /**
+ * Adds an optional attribute
+ *
+ * @param name the name of the attribute
+ * @param value the value
+ * @return the builder
+ */
+ public Type attribute(QName name, Object value) {
+ if (otherAttributes == null) {
+ otherAttributes = new HashMap<QName, Object>();
+ }
+ otherAttributes.put(name, value);
+ return (Type) this;
+ }
+
+ /**
* Sends the exchange to the given endpoint
*
* @param uri the endpoint to send to
@@ -2922,6 +2983,15 @@ public abstract class ProcessorDefinitio
this.inheritErrorHandler = inheritErrorHandler;
}
+ public Map<QName, Object> getOtherAttributes() {
+ return otherAttributes;
+ }
+
+ @XmlAnyAttribute
+ public void setOtherAttributes(Map<QName, Object> otherAttributes) {
+ this.otherAttributes = otherAttributes;
+ }
+
/**
* Returns a label to describe this node such as the expression if some
kind of expression node
*/
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java?rev=1073359&view=auto
==============================================================================
---
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
(added)
+++
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
Tue Feb 22 15:09:31 2011
@@ -0,0 +1,77 @@
+/**
+ * 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.properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.FailedToCreateRouteException;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Test that placeholder DSL is working as expected.
+ */
+public class OptionalPropertiesDslInvalidSyntaxTest extends ContextTestSupport
{
+
+ public void testPlaceholderDslKeyNotFoundTest() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .multicast().placeholder("stopOnException", "xxx")
+ .to("mock:a").throwException(new
IllegalAccessException("Damn")).to("mock:b");
+ }
+ });
+ try {
+ context.start();
+ fail("Should have thrown exception");
+ } catch (FailedToCreateRouteException e) {
+ IllegalArgumentException cause =
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+ assertEquals("Property with key [xxx] not found in properties for
uri: {{xxx}}", cause.getMessage());
+ }
+ }
+
+ public void testPlaceholderDslSetterNotFoundTest() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .multicast().placeholder("xxx", "stop")
+ .to("mock:a").throwException(new
IllegalAccessException("Damn")).to("mock:b");
+ }
+ });
+ try {
+ context.start();
+ fail("Should have thrown exception");
+ } catch (FailedToCreateRouteException e) {
+ IllegalArgumentException cause =
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+ assertEquals("No setter to set property: xxx to: true on:
Multicast[[To[mock:a], ThrowException[java.lang.IllegalAccessException],
To[mock:b]]]", cause.getMessage());
+ }
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.addComponent("properties", new
PropertiesComponent("classpath:org/apache/camel/component/properties/myproperties.properties"));
+ return context;
+ }
+
+}
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslTest.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslTest.java?rev=1073359&view=auto
==============================================================================
---
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslTest.java
(added)
+++
camel/trunk/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslTest.java
Tue Feb 22 15:09:31 2011
@@ -0,0 +1,65 @@
+/**
+ * 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.properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Test that placeholder DSL is working as expected.
+ */
+public class OptionalPropertiesDslTest extends ContextTestSupport {
+
+ public void testPlaceholderDslTest() throws Exception {
+ getMockEndpoint("mock:a").expectedMessageCount(1);
+ getMockEndpoint("mock:b").expectedMessageCount(0);
+
+ try {
+ template.sendBody("direct:start", "Hello World");
+ fail("Should have thrown an exception");
+ } catch (Exception e) {
+ // expected
+ }
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // START SNIPPET: e1
+ from("direct:start")
+ // use a property placeholder for the option
stopOnException on the Multicast EIP
+ // which should have the value of {{stop}} key being
looked up in the properties file
+ .multicast().placeholder("stopOnException", "stop")
+ .to("mock:a").throwException(new
IllegalAccessException("Damn")).to("mock:b");
+ // END SNIPPET: e1
+ }
+ };
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.addComponent("properties", new
PropertiesComponent("classpath:org/apache/camel/component/properties/myproperties.properties"));
+ return context;
+ }
+
+}
Modified:
camel/trunk/camel-core/src/test/resources/org/apache/camel/component/properties/myproperties.properties
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/resources/org/apache/camel/component/properties/myproperties.properties?rev=1073359&r1=1073358&r2=1073359&view=diff
==============================================================================
---
camel/trunk/camel-core/src/test/resources/org/apache/camel/component/properties/myproperties.properties
(original)
+++
camel/trunk/camel-core/src/test/resources/org/apache/camel/component/properties/myproperties.properties
Tue Feb 22 15:09:31 2011
@@ -30,3 +30,5 @@ cool.mock=mock
myCoolCharset=iso-8859-1
slipDelimiter=##
+
+stop=true
\ No newline at end of file
Added:
camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.java
URL:
http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.java?rev=1073359&view=auto
==============================================================================
---
camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.java
(added)
+++
camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.java
Tue Feb 22 15:09:31 2011
@@ -0,0 +1,32 @@
+/**
+ * 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.properties;
+
+import org.apache.camel.CamelContext;
+
+import static
org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+
+/**
+ * Spring placeholder DSL test
+ */
+public class SpringOptionalPropertiesDslTest extends OptionalPropertiesDslTest
{
+
+ protected CamelContext createCamelContext() throws Exception {
+ return createSpringCamelContext(this,
"org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml");
+ }
+
+}
Copied:
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml
(from r1073309,
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml)
URL:
http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml&r1=1073309&r2=1073359&rev=1073359&view=diff
==============================================================================
---
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml
(original)
+++
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringOptionalPropertiesDslTest.xml
Tue Feb 22 15:09:31 2011
@@ -15,38 +15,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<!-- START SNIPPET: e1 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:prop="http://camel.apache.org/schema/placeholder"
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
">
+ <!-- Notice in the declaration above, we have defined the prop prefix as
the Camel placeholder namespace -->
+
+ <bean id="damn" class="java.lang.IllegalArgumentException">
+ <constructor-arg index="0" value="Damn"/>
+ </bean>
+
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties"
-
location="classpath:org/apache/camel/component/properties/cheese.properties"
+
location="classpath:org/apache/camel/component/properties/myprop.properties"
xmlns="http://camel.apache.org/schema/spring"/>
<route>
<from uri="direct:start"/>
- <to uri="properties:{{cool.end}}"/>
- </route>
-
- <route>
- <from uri="direct:bar"/>
- <to uri="properties:mock:{{cool.bar}}"/>
+ <!-- use prop namespace, to define a property placeholder, which
maps to
+ option stopOnException={{stop}} -->
+ <multicast prop:stopOnException="stop">
+ <to uri="mock:a"/>
+ <throwException ref="damn"/>
+ <to uri="mock:b"/>
+ </multicast>
</route>
- <route>
- <from uri="direct:start2"/>
- <to uri="{{cool.end}}"/>
- </route>
-
- <route>
- <from uri="direct:bar2"/>
- <to uri="mock:{{cool.bar}}"/>
- </route>
</camelContext>
</beans>
+<!-- END SNIPPET: e1 -->
Modified:
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/myprop.properties
URL:
http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/myprop.properties?rev=1073359&r1=1073358&r2=1073359&view=diff
==============================================================================
---
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/myprop.properties
(original)
+++
camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/myprop.properties
Tue Feb 22 15:09:31 2011
@@ -20,4 +20,6 @@ routescan=component.properties.route
routeincludes=*Simple*
result=mock:result
-mybuilder=simpleRoute
\ No newline at end of file
+mybuilder=simpleRoute
+
+stop=true
\ No newline at end of file