You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/09/26 04:59:59 UTC

[camel] 04/10: CAMEL-13947: PropertiesComponent should be a static service and resolved like other similar features.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-13947
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 106a6e451f1d70640018800d30b1c53dec6a0cd3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Sep 25 19:46:05 2019 +0200

    CAMEL-13947: PropertiesComponent should be a static service and resolved like other similar features.
---
 core/camel-base/src/main/docs/simple-language.adoc | 13 ++++
 .../simple/ast/SimpleFunctionExpression.java       | 15 +++++
 .../camel/builder/xml/XPathFunctionsTest.java      |  2 +-
 ...opertiesComponentConcatenatePropertiesTest.java |  4 +-
 .../PropertiesComponentEIPChoiceSimpleTest.java    |  2 +-
 .../PropertiesComponentEndpointMandatoryTest.java  | 50 ----------------
 .../PropertiesComponentNestPropertiesTest.java     | 70 ----------------------
 .../PropertiesComponentSimpleLanguageTest.java     | 66 --------------------
 .../camel/impl/MultipleLifecycleStrategyTest.java  |  2 +-
 .../camel/support/builder/ExpressionBuilder.java   | 24 ++++++++
 10 files changed, 57 insertions(+), 191 deletions(-)

diff --git a/core/camel-base/src/main/docs/simple-language.adoc b/core/camel-base/src/main/docs/simple-language.adoc
index 5fc83b4..0c6e3c0 100644
--- a/core/camel-base/src/main/docs/simple-language.adoc
+++ b/core/camel-base/src/main/docs/simple-language.adoc
@@ -179,6 +179,10 @@ Specifying a method name you must use dot as separator. We also support
 the ?method=methodname syntax that is used by the xref:components::bean-component.adoc[Bean]
 component.
 
+|`properties:key:default` |String |Lookup a property with the given key. If the key does
+not exists or has no value, then an optional default value can be
+specified.
+
 |routeId |String |Returns the id of the current route the
 Exchange is being routed.
 
@@ -775,6 +779,15 @@ a `java.util.Map` and we then lookup with the key `gold` and return the
 value. If the header is not convertible to Map an exception is thrown. If the
 header with name `type` does not exist `null` is returned.
 
+You can nest functions, such as shown below:
+
+[source,xml]
+----
+<setHeader name="myHeader">
+  <simple>${properties:${header.someKey}}</simple>
+</setHeader>
+----
+
 == Referring to constants or enums
 
 Suppose you have an enum for customers
diff --git a/core/camel-base/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/core/camel-base/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index d6eab1f..adabcdc 100644
--- a/core/camel-base/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++ b/core/camel-base/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -208,6 +208,21 @@ public class SimpleFunctionExpression extends LiteralExpression {
             return ExpressionBuilder.beanExpression(remainder);
         }
 
+        // properties: prefix
+        remainder = ifStartsWithReturnRemainder("properties:", function);
+        if (remainder != null) {
+            String[] parts = remainder.split(":");
+            if (parts.length > 2) {
+                throw new SimpleParserException("Valid syntax: ${properties:key[:default]} was: " + function, token.getIndex());
+            }
+            String defaultValue = null;
+            if (parts.length >= 2) {
+                defaultValue = parts[1];
+            }
+            String key = parts[0];
+            return ExpressionBuilder.propertiesComponentExpression(key, defaultValue);
+        }
+
         // ref: prefix
         remainder = ifStartsWithReturnRemainder("ref:", function);
         if (remainder != null) {
diff --git a/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFunctionsTest.java b/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFunctionsTest.java
index b6d3acc..6335b3a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFunctionsTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFunctionsTest.java
@@ -79,7 +79,7 @@ public class XPathFunctionsTest extends ContextTestSupport {
                     // here we use the simple language to evaluate the
                     // expression
                     // which at runtime will be evaluated to 'Donkey Kong'
-                    .when().xpath("//name = function:simple('Donkey ${properties:bar}')").to("mock:donkey").otherwise().to("mock:other").end();
+                    .when().xpath("//name = function:simple('Donkey {{bar}}')").to("mock:donkey").otherwise().to("mock:other").end();
                 // END SNIPPET: ex
             }
         };
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentConcatenatePropertiesTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentConcatenatePropertiesTest.java
index 85adbe3..02f6b09 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentConcatenatePropertiesTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentConcatenatePropertiesTest.java
@@ -50,7 +50,7 @@ public class PropertiesComponentConcatenatePropertiesTest extends ContextTestSup
         context.addRoutes(new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("direct:start").setBody(simple("${properties:concat.property}")).to("mock:result");
+                from("direct:start").setBody(simple("{{concat.property}}")).to("mock:result");
             }
         });
         context.start();
@@ -67,7 +67,7 @@ public class PropertiesComponentConcatenatePropertiesTest extends ContextTestSup
         context.addRoutes(new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("direct:start").setBody(simple("${properties:property.complete}")).to("mock:result");
+                from("direct:start").setBody(simple("{{property.complete}}")).to("mock:result");
             }
         });
         context.start();
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEIPChoiceSimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEIPChoiceSimpleTest.java
index f1b0294..f16f3d8 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEIPChoiceSimpleTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEIPChoiceSimpleTest.java
@@ -40,7 +40,7 @@ public class PropertiesComponentEIPChoiceSimpleTest extends ContextTestSupport {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("direct:start").choice().when(simple("${body} contains '${properties:cool.name}'")).to("mock:camel").otherwise().to("mock:other");
+                from("direct:start").choice().when(simple("${body} contains '{{cool.name}}'")).to("mock:camel").otherwise().to("mock:other");
             }
         };
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEndpointMandatoryTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEndpointMandatoryTest.java
deleted file mode 100644
index aa77624..0000000
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentEndpointMandatoryTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.ContextTestSupport;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.builder.RouteBuilder;
-import org.junit.Test;
-
-public class PropertiesComponentEndpointMandatoryTest extends ContextTestSupport {
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    @Test
-    public void testPropertiesComponentMandatory() throws Exception {
-        context.removeComponent("properties");
-        try {
-            context.addRoutes(new RouteBuilder() {
-                @Override
-                public void configure() throws Exception {
-                    from("{{cool.start}}").to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}").to("mock:{{cool.result}}");
-                }
-            });
-            context.start();
-            fail("Should throw exception");
-        } catch (RuntimeCamelException e) {
-            IllegalArgumentException cause = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
-            String msg = "PropertiesComponent with name properties must be defined in CamelContext to support property placeholders.";
-            assertTrue(cause.getMessage().startsWith(msg));
-        }
-    }
-
-}
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentNestPropertiesTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentNestPropertiesTest.java
deleted file mode 100644
index 298e59f..0000000
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentNestPropertiesTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class PropertiesComponentNestPropertiesTest extends ContextTestSupport {
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext context = super.createCamelContext();
-        context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/adapter.properties");
-        return context;
-    }
-
-    @Override
-    @Before
-    public void setUp() throws Exception {
-        System.setProperty("environment", "junit");
-        super.setUp();
-    }
-
-    @Override
-    @After
-    public void tearDown() throws Exception {
-        System.clearProperty("environment");
-        super.tearDown();
-    }
-
-    @Test
-    public void testPropertiesComponentDefault() throws Exception {
-        context.addRoutes(new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").setBody(simple("${properties:someproperty}${body}")).to("mock:result");
-
-                from("direct:start2").setBody(simple("{json:{value:${properties:someproperty}}}")).to("mock:result2");
-            }
-        });
-        context.start();
-
-        getMockEndpoint("mock:result").expectedBodiesReceived("junitTest");
-        getMockEndpoint("mock:result2").expectedBodiesReceived("{json:{value:junit}}");
-
-        template.sendBody("direct:start", "Test");
-        template.sendBody("direct:start2", "Test");
-
-        assertMockEndpointsSatisfied();
-    }
-
-}
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentSimpleLanguageTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentSimpleLanguageTest.java
deleted file mode 100644
index d12d7ad..0000000
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentSimpleLanguageTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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;
-import org.junit.Test;
-
-public class PropertiesComponentSimpleLanguageTest extends ContextTestSupport {
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    @Test
-    public void testPropertiesComponentSimpleLanguage() throws Exception {
-        context.addRoutes(new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").transform().simple("Hi ${body} do you think ${properties:cheese.quote}?");
-            }
-        });
-        context.start();
-
-        String reply = template.requestBody("direct:start", "Claus", String.class);
-        assertEquals("Hi Claus do you think Camel rocks?", reply);
-    }
-
-    @Test
-    public void testPropertiesComponentDualSimpleLanguage() throws Exception {
-        context.addRoutes(new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").transform().simple("Hi ${body} do you think ${properties:cheese.quote}? And do you like ${properties:cheese.type} cheese?");
-            }
-        });
-        context.start();
-
-        String reply = template.requestBody("direct:start", "Claus", String.class);
-        assertEquals("Hi Claus do you think Camel rocks? And do you like Gouda cheese?", reply);
-    }
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext context = super.createCamelContext();
-        context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/cheese.properties");
-        return context;
-    }
-
-}
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
index 851cdf8..7e503d3 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java
@@ -52,7 +52,7 @@ public class MultipleLifecycleStrategyTest extends TestSupport {
         List<String> expectedEvents = Arrays.asList("onContextStart",
             "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd",
             "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd",
-            "onServiceAdd", "onServiceAdd", "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop");
+            "onServiceAdd", "onServiceAdd", "onServiceAdd", "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop");
         
         assertEquals(expectedEvents, dummy1.getEvents());
         assertEquals(expectedEvents, dummy2.getEvents());
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
index 6efc2e9..48bdd26 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
@@ -1310,6 +1310,30 @@ public class ExpressionBuilder {
         return constantExpression(str);
     }
 
+    public static Expression propertiesComponentExpression(final String key, final String defaultValue) {
+        return new ExpressionAdapter() {
+            public Object evaluate(Exchange exchange) {
+                String text = simpleExpression(key).evaluate(exchange, String.class);
+                try {
+                    PropertiesComponent pc = exchange.getContext().getPropertiesComponent();
+                    // enclose key with {{ }} to force parsing as key can be a nested expression too
+                    return pc.parseUri(PropertiesComponent.PREFIX_TOKEN + text + PropertiesComponent.SUFFIX_TOKEN);
+                } catch (Exception e) {
+                    // property with key not found, use default value if provided
+                    if (defaultValue != null) {
+                        return defaultValue;
+                    }
+                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "properties(" + key + ")";
+            }
+        };
+    }
+
     /**
      * Returns an {@link TokenPairExpressionIterator} expression
      */