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 <claus.ib...@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")); } }