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
The following commit(s) were added to refs/heads/master by this push: new 2a68f61 CAMEL-15224: camel-api-component - Avoid reflection when configured nested configuration classes. 2a68f61 is described below commit 2a68f6152304a82325910256869b87823f6cdf0a Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Tue Jun 23 07:32:43 2020 +0200 CAMEL-15224: camel-api-component - Avoid reflection when configured nested configuration classes. --- .../camel-olingo2/camel-olingo2-component/pom.xml | 19 ++++++ .../camel/component/olingo2/Olingo2Component.java | 3 + .../camel/component/olingo2/Olingo2Endpoint.java | 73 +++++++++++++++++----- .../olingo2/AbstractOlingo2TestSupport.java | 8 +-- .../olingo2/Olingo2ComponentConsumerTest.java | 19 ++++++ 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/components/camel-olingo2/camel-olingo2-component/pom.xml b/components/camel-olingo2/camel-olingo2-component/pom.xml index 359a740..ae776d7 100644 --- a/components/camel-olingo2/camel-olingo2-component/pom.xml +++ b/components/camel-olingo2/camel-olingo2-component/pom.xml @@ -193,6 +193,25 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <!-- add the olingo odata2 sample service source. See profile get-olingo2-sample below --> + <execution> + <id>add-test-source</id> + <phase>generate-test-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>${basedir}/target/olingo2-my-car-service/src/main/java</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> </plugins> <pluginManagement> diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java index a7f8995..47e9fac 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java @@ -84,7 +84,10 @@ public class Olingo2Component extends AbstractApiComponent<Olingo2ApiName, Oling final Olingo2Configuration endpointConfiguration = createEndpointConfiguration(Olingo2ApiName.DEFAULT); final Endpoint endpoint = createEndpoint(uri, methodName, Olingo2ApiName.DEFAULT, endpointConfiguration); + + // configure endpoint properties and initialize state setProperties(endpoint, parameters); + return endpoint; } diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Endpoint.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Endpoint.java index 7e2dfdd..f34fc06 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Endpoint.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Endpoint.java @@ -19,19 +19,24 @@ package org.apache.camel.component.olingo2; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.apache.camel.Category; import org.apache.camel.Consumer; +import org.apache.camel.ExtendedCamelContext; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.olingo2.internal.Olingo2ApiCollection; import org.apache.camel.component.olingo2.internal.Olingo2ApiName; import org.apache.camel.component.olingo2.internal.Olingo2Constants; import org.apache.camel.component.olingo2.internal.Olingo2PropertiesHelper; +import org.apache.camel.spi.PropertyConfigurer; +import org.apache.camel.spi.PropertyConfigurerGetter; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; +import org.apache.camel.support.PropertyBindingSupport; import org.apache.camel.support.component.AbstractApiEndpoint; import org.apache.camel.support.component.ApiMethod; import org.apache.camel.support.component.ApiMethodPropertiesHelper; @@ -59,7 +64,7 @@ public class Olingo2Endpoint extends AbstractApiEndpoint<Olingo2ApiName, Olingo2 // unparsed variants private static final String UREAD_METHOD = "uread"; - private final Set<String> endpointPropertyNames; + private Set<String> olingo2endpointPropertyNames; @UriParam private Olingo2Configuration configuration; @@ -68,16 +73,7 @@ public class Olingo2Endpoint extends AbstractApiEndpoint<Olingo2ApiName, Olingo2 public Olingo2Endpoint(String uri, Olingo2Component component, Olingo2ApiName apiName, String methodName, Olingo2Configuration endpointConfiguration) { super(uri, component, apiName, methodName, Olingo2ApiCollection.getCollection().getHelper(apiName), endpointConfiguration); - this.configuration = endpointConfiguration; - - // get all endpoint property names - endpointPropertyNames = new HashSet<>(getPropertiesHelper().getValidEndpointProperties(component.getCamelContext(), configuration)); - // avoid adding edm as queryParam - endpointPropertyNames.add(EDM_PROPERTY); - endpointPropertyNames.add(ENDPOINT_HTTP_HEADERS_PROPERTY); - endpointPropertyNames.add(SERVICE_URI_PROPERTY); - endpointPropertyNames.add(FILTER_ALREADY_SEEN); } @Override @@ -113,13 +109,62 @@ public class Olingo2Endpoint extends AbstractApiEndpoint<Olingo2ApiName, Olingo2 @Override public void configureProperties(Map<String, Object> options) { - super.configureProperties(options); - // handle individual query params - parseQueryParams(options); + // filter out options that are with $ as they are for query + Map<String, Object> query = new LinkedHashMap<>(); + Map<String, Object> known = new LinkedHashMap<>(); + options.forEach((k, v) -> { + if (k.startsWith("$")) { + query.put(k, v); + } else { + known.put(k, v); + } + }); + options.keySet().removeIf(known::containsKey); + + // configure endpoint first (from the known options) and then specialized configuration class afterwards + PropertyConfigurer configurer = getComponent().getEndpointPropertyConfigurer(); + if (configurer instanceof PropertyConfigurerGetter) { + PropertyConfigurerGetter getter = (PropertyConfigurerGetter) configurer; + for (String name : getter.getAllOptions(this).keySet()) { + if (known.containsKey(name)) { + Object value = known.remove(name); + configurer.configure(getCamelContext(), this, name, value, true); + } + }; + } + // configure on configuration first to be reflection free + configurer = getCamelContext().adapt(ExtendedCamelContext.class).getConfigurerResolver().resolvePropertyConfigurer(configuration.getClass().getSimpleName(), getCamelContext()); + if (configurer != null) { + PropertyBindingSupport.build() + .withConfigurer(configurer) + .withIgnoreCase(true) + .withTarget(configuration) + .withCamelContext(getCamelContext()) + .withProperties(known) + .withRemoveParameters(true) + .bind(); + } + super.configureProperties(known); + if (!known.isEmpty()) { + // handle individual query params + query.putAll(known); + } + // and remove from original options as it was used by query + options.keySet().removeIf(query::containsKey); + // this will parse query and expand these $ keys into the actual query keys + parseQueryParams(query); + // and restore back to options + options.putAll(query); } @Override protected void afterConfigureProperties() { + olingo2endpointPropertyNames = new HashSet<>(getEndpointPropertyNames()); + olingo2endpointPropertyNames.add(EDM_PROPERTY); + olingo2endpointPropertyNames.add(ENDPOINT_HTTP_HEADERS_PROPERTY); + olingo2endpointPropertyNames.add(SERVICE_URI_PROPERTY); + olingo2endpointPropertyNames.add(FILTER_ALREADY_SEEN); + // set default inBody if (!(READ_METHOD.equals(methodName) || DELETE_METHOD.equals(methodName) || UREAD_METHOD.equals(methodName)) && inBody == null) { inBody = DATA_PROPERTY; @@ -210,7 +255,7 @@ public class Olingo2Endpoint extends AbstractApiEndpoint<Olingo2ApiName, Olingo2 continue; } - if (!endpointPropertyNames.contains(paramName)) { + if (!olingo2endpointPropertyNames.contains(paramName)) { // add to query params final Object value = entry.getValue(); diff --git a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/AbstractOlingo2TestSupport.java b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/AbstractOlingo2TestSupport.java index 2bfa3fe..090685f 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/AbstractOlingo2TestSupport.java +++ b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/AbstractOlingo2TestSupport.java @@ -53,13 +53,9 @@ public class AbstractOlingo2TestSupport extends CamelTestSupport { throw new IOException(String.format("%s could not be loaded: %s", TEST_OPTIONS_PROPERTIES, e.getMessage()), e); } - Map<String, Object> options = new HashMap<>(); - for (Map.Entry<Object, Object> entry : properties.entrySet()) { - options.put(entry.getKey().toString(), entry.getValue()); - } - final Olingo2Configuration configuration = new Olingo2Configuration(); - PropertyBindingSupport.bindProperties(context, configuration, options); + configuration.setServiceUri(properties.getProperty("serviceUri")); + configuration.setContentType(properties.getProperty("contentType")); // add OlingoComponent to Camel context final Olingo2Component component = new Olingo2Component(context); diff --git a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java index e24df0d..32ded7f 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java +++ b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java @@ -18,6 +18,9 @@ package org.apache.camel.component.olingo2; import java.util.Map; +import org.apache.camel.CamelContext; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.LoggingLevel; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.AvailablePortFinder; @@ -53,6 +56,14 @@ public class Olingo2ComponentConsumerTest extends AbstractOlingo2TestSupport { setDefaultTestProperty("serviceUri", "http://localhost:" + PORT + "/MyFormula.svc"); } + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + context.adapt(ExtendedCamelContext.class).getBeanIntrospection().setLoggingLevel(LoggingLevel.INFO); + context.adapt(ExtendedCamelContext.class).getBeanIntrospection().setExtendedStatistics(true); + return context; + } + @BeforeAll public static void beforeClass() throws Exception { startServers(PORT); @@ -122,6 +133,10 @@ public class Olingo2ComponentConsumerTest extends AbstractOlingo2TestSupport { assertNull(body); } } + + // should be reflection free + long counter = context.adapt(ExtendedCamelContext.class).getBeanIntrospection().getInvokedCounter(); + assertEquals(0, counter); } /** @@ -258,6 +273,10 @@ public class Olingo2ComponentConsumerTest extends AbstractOlingo2TestSupport { Object nameValue = entry.getProperties().get("Name"); assertNotNull(nameValue); assertEquals("Star Powered Racing", nameValue.toString()); + + // should be reflection free + long counter = context.adapt(ExtendedCamelContext.class).getBeanIntrospection().getInvokedCounter(); + assertEquals(0, counter); } /**