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/08/14 07:53:00 UTC

[camel] 06/21: CAMEL-13850: Optimize model classes to provide changeable properties that support property placeholders to avoid reflection. Work in progress.

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

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

commit c947278c884a64119de17c0e4885766c9d7f12db
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 13 06:03:50 2019 +0200

    CAMEL-13850: Optimize model classes to provide changeable properties that support property placeholders to avoid reflection. Work in progress.
---
 .../DefinitionPropertyPlaceholderConfigurable.java |  2 +
 .../camel/model/ProcessorDefinitionHelper.java     | 62 ++++++++++++++++++++++
 .../OptionalPropertiesDslInvalidSyntaxTest.java    |  7 ++-
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java b/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
index 8d5758c..16520e3 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
@@ -16,12 +16,14 @@
  */
 package org.apache.camel.model;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.model.placeholder.DefinitionPropertiesPlaceholderProviderHelper;
+import org.apache.camel.spi.PropertiesComponent;
 
 /**
  * To be used for configuring property placeholder options on the EIP models.
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java b/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 169dc3d..439ffbe 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -29,10 +29,16 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
+import javax.xml.namespace.QName;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.NamedNode;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.ExecutorServiceManager;
+import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.RouteContext;
+import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -670,6 +676,7 @@ public final class ProcessorDefinitionHelper {
      * @see org.apache.camel.CamelContext#resolvePropertyPlaceholders(String)
      * @see org.apache.camel.component.properties.PropertiesComponent
      */
+    @SuppressWarnings("unchecked")
     public static void resolvePropertyPlaceholders(CamelContext camelContext, Object definition) throws Exception {
         LOG.trace("Resolving property placeholders for: {}", definition);
 
@@ -685,6 +692,61 @@ public final class ProcessorDefinitionHelper {
         Map<String, Supplier<String>> readProperties = ppa.getReadPropertyPlaceholderOptions(camelContext);
         Map<String, Consumer<String>> writeProperties = ppa.getWritePropertyPlaceholderOptions(camelContext);
 
+        // processor's may have additional placeholder properties (can typically be used by the XML DSL to
+        // allow to configure using placeholders for properties that are not xs:string types)
+        if (definition instanceof ProcessorDefinition) {
+            ProcessorDefinition pd = (ProcessorDefinition) definition;
+
+            if (pd.getOtherAttributes() != null && !pd.getOtherAttributes().isEmpty()) {
+                Map<String, Supplier<String>> extraRead = new HashMap<>();
+                if (readProperties != null && !readProperties.isEmpty()) {
+                    extraRead.putAll(readProperties);
+                }
+                Map<String, Consumer<String>> extraWrite = new HashMap<>();
+                if (writeProperties != null && !writeProperties.isEmpty()) {
+                    extraWrite.putAll(writeProperties);
+                }
+
+                Map<QName, Object> other = pd.getOtherAttributes();
+                other.forEach((k, v) -> {
+                    if (Constants.PLACEHOLDER_QNAME.equals(k.getNamespaceURI())) {
+                        if (v instanceof String) {
+                            // enforce a properties component to be created if none existed
+                            camelContext.getPropertiesComponent(true);
+
+                            // value must be enclosed with placeholder tokens
+                            String s = (String) v;
+                            String prefixToken = PropertiesComponent.PREFIX_TOKEN;
+                            String suffixToken = PropertiesComponent.SUFFIX_TOKEN;
+
+                            if (!s.startsWith(prefixToken)) {
+                                s = prefixToken + s;
+                            }
+                            if (!s.endsWith(suffixToken)) {
+                                s = s + suffixToken;
+                            }
+                            final String value = s;
+                            extraRead.put(k.getLocalPart(), () -> value);
+                            extraWrite.put(k.getLocalPart(), text -> {
+                                try {
+                                    PropertyBindingSupport.build()
+                                            .withCamelContext(camelContext)
+                                            .withTarget(definition)
+                                            .withMandatory(true)
+                                            .withProperty(k.getLocalPart(), text)
+                                            .bind();
+                                } catch (Exception e) {
+                                    throw RuntimeCamelException.wrapRuntimeException(e);
+                                }
+                            });
+                        }
+                    }
+                });
+                readProperties = extraRead;
+                writeProperties = extraWrite;
+            }
+        }
+
         if (readProperties != null && !readProperties.isEmpty()) {
             if (LOG.isTraceEnabled()) {
                 LOG.trace("There are {} properties on: {}", readProperties.size(), definition);
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
index e22b671..301e668 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertiesDslInvalidSyntaxTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.properties;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.PropertyBindingException;
 import org.apache.camel.builder.RouteBuilder;
 import org.junit.Test;
 
@@ -59,8 +60,10 @@ public class OptionalPropertiesDslInvalidSyntaxTest extends ContextTestSupport {
             context.start();
             fail("Should have thrown exception");
         } catch (Exception 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());
+            PropertyBindingException cause = assertIsInstanceOf(PropertyBindingException.class, e.getCause());
+            assertEquals("xxx", cause.getPropertyName());
+            assertEquals("true", cause.getValue());
+            assertTrue(cause.getMessage().startsWith("Error binding property (xxx=true) with name: xxx on bean: Multicast"));
         }
     }