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 6380fe68d874b894d0eaf2e8b99cbc0382f5f85e
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon Jul 1 11:13:20 2019 +0200

    CAMEL-13705: Properties component should work with Eclipse MicroProfile 
Config
---
 components/camel-microprofile-config/pom.xml       | 87 ++++++++++++++++++++++
 .../src/main/docs/microprofile-config.adoc         | 19 +++++
 .../config/CamelMicroProfilePropertiesSource.java  | 85 +++++++++++++++++++++
 .../org/apache/camel/properties-source-factory     | 18 +++++
 .../CamelMicroProfilePropertiesSourceTest.java     | 74 ++++++++++++++++++
 .../src/test/resources/log4j2.properties           | 28 +++++++
 .../component/properties/PropertiesComponent.java  | 61 +++++++++++++++
 .../component/properties/PropertiesSource.java     | 38 ++++++++++
 .../camel/impl/engine/AbstractCamelContext.java    |  2 +
 9 files changed, 412 insertions(+)

diff --git a/components/camel-microprofile-config/pom.xml 
b/components/camel-microprofile-config/pom.xml
new file mode 100644
index 0000000..0f64b79
--- /dev/null
+++ b/components/camel-microprofile-config/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns="http://maven.apache.org/POM/4.0.0";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-microprofile-config</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: MicroProfile Config</name>
+    <description>Camel Eclipse MicroProfile Config</description>
+
+    <dependencies>
+
+        <!-- extends the properties component -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-properties</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.microprofile.config</groupId>
+            <artifactId>microprofile-config-api</artifactId>
+            <version>1.3</version>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.smallrye</groupId>
+            <artifactId>smallrye-config-1.3</artifactId>
+            <version>1.0.0</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+</project>
diff --git 
a/components/camel-microprofile-config/src/main/docs/microprofile-config.adoc 
b/components/camel-microprofile-config/src/main/docs/microprofile-config.adoc
new file mode 100644
index 0000000..ae43410
--- /dev/null
+++ 
b/components/camel-microprofile-config/src/main/docs/microprofile-config.adoc
@@ -0,0 +1,19 @@
+[[MicroProfileConfig-MicroProfileConfigComponent]]
+=== MicroProfile Config Component
+
+*Available as of Camel 3.0*
+
+The microprofile-config component is used for bridging the Eclipse 
MicroProfile Config with Camels
+properties component. This allows to use configuration management from Eclipse 
MicroProfile with Camel.
+
+To enable this just add this component to the classpath and Camel should 
auto-detect this when starting up.
+
+=== Register manually
+
+You can also register the microprofile-config component manually with Apache 
Camel properties component as shown below:
+
+[source,java]
+----
+    PropertiesComponent pc = (PropertiesComponent) 
camelContext.getPropertiesComponent();
+    pc.addPropertiesSource(new CamelMicroProfilePropertiesSource());
+----
diff --git 
a/components/camel-microprofile-config/src/main/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSource.java
 
b/components/camel-microprofile-config/src/main/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSource.java
new file mode 100644
index 0000000..31aed16
--- /dev/null
+++ 
b/components/camel-microprofile-config/src/main/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSource.java
@@ -0,0 +1,85 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.microprofile.config;
+
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.component.properties.PropertiesSource;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.OrderedProperties;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * To use Camel's {@link PropertiesComponent} as an Eclipse {@link 
ConfigSource}.
+ */
+public class CamelMicroProfilePropertiesSource extends ServiceSupport 
implements CamelContextAware, PropertiesSource {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(CamelMicroProfilePropertiesSource.class);
+
+    private CamelContext camelContext;
+    private final Properties properties = new OrderedProperties();
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public String getName() {
+        return "CamelMicroProfilePropertiesSource";
+    }
+
+    @Override
+    public Properties loadProperties() {
+        return properties;
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        Config config = ConfigProvider.getConfig();
+
+        for (String name : config.getPropertyNames()) {
+            Optional<String> value = config.getOptionalValue(name, 
String.class);
+            value.ifPresent(s -> properties.put(name, s));
+        }
+
+        LOG.info("Initialized CamelMicroProfilePropertiesSource with {} 
properties loaded", properties.size());
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        // noop
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        // noop
+    }
+}
diff --git 
a/components/camel-microprofile-config/src/main/resources/META-INF/services/org/apache/camel/properties-source-factory
 
b/components/camel-microprofile-config/src/main/resources/META-INF/services/org/apache/camel/properties-source-factory
new file mode 100644
index 0000000..74bd136
--- /dev/null
+++ 
b/components/camel-microprofile-config/src/main/resources/META-INF/services/org/apache/camel/properties-source-factory
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.component.microprofile.config.CamelMicroProfileConfigSource
diff --git 
a/components/camel-microprofile-config/src/test/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSourceTest.java
 
b/components/camel-microprofile-config/src/test/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSourceTest.java
new file mode 100644
index 0000000..3bb0c61
--- /dev/null
+++ 
b/components/camel-microprofile-config/src/test/java/org/apache/camel/component/microprofile/config/CamelMicroProfilePropertiesSourceTest.java
@@ -0,0 +1,74 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.microprofile.config;
+
+import java.util.Properties;
+
+import io.smallrye.config.PropertiesConfigSource;
+import io.smallrye.config.SmallRyeConfigBuilder;
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.junit.Test;
+
+public class CamelMicroProfilePropertiesSourceTest extends CamelTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        // setup MPC
+        Properties prop = new Properties();
+        prop.put("start", "direct:start");
+        prop.put("hi", "World");
+        prop.put("my-mock", "result");
+
+        // create PMC config source and register it so we can use it for 
testing
+        PropertiesConfigSource pcs = new PropertiesConfigSource(prop, 
"my-smallrye-config");
+        final Config config = new 
SmallRyeConfigBuilder().withSources(pcs).build();
+        ConfigProviderResolver.instance().registerConfig(config, 
CamelMicroProfilePropertiesSourceTest.class.getClassLoader());
+
+        // should auto-detect this JAR on the classpath and use it (but this 
can only be tested outside this component)
+        CamelContext context = super.createCamelContext();
+        // ... so we add the source manually
+        PropertiesComponent pc = (PropertiesComponent) 
context.getPropertiesComponent();
+        pc.addPropertiesSource(new CamelMicroProfilePropertiesSource());
+        return context;
+    }
+
+    @Test
+    public void testMicroProfileConfig() throws Exception {
+          getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
+          template.sendBody("direct:start", 
context.resolvePropertyPlaceholders("Hello {{hi}}"));
+
+          assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("{{start}}")
+                        .to("mock:{{my-mock}}");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-microprofile-config/src/test/resources/log4j2.properties 
b/components/camel-microprofile-config/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..27dc528
--- /dev/null
+++ b/components/camel-microprofile-config/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-microprofile-config-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git 
a/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
 
b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 4ddea23..120fcb6 100644
--- 
a/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++ 
b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -27,17 +27,25 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.stream.Collectors;
 
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.Endpoint;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.NoFactoryAvailableException;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedOperation;
 import org.apache.camel.api.management.ManagedResource;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.spi.HeadersMapFactory;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.DefaultComponent;
 import org.apache.camel.support.LRUCacheFactory;
+import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.FilePathResolver;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.OrderedProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The <a href="http://camel.apache.org/properties";>Properties Component</a> 
allows you to use property placeholders when defining Endpoint URIs
@@ -46,6 +54,8 @@ import org.apache.camel.util.OrderedProperties;
 @ManagedResource(description = "Managed PropertiesComponent")
 public class PropertiesComponent extends DefaultComponent implements 
org.apache.camel.spi.PropertiesComponent {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(PropertiesComponent.class);
+
     /**
      *  Never check system properties.
      */
@@ -96,6 +106,7 @@ public class PropertiesComponent extends DefaultComponent 
implements org.apache.
     private PropertiesResolver propertiesResolver = new 
DefaultPropertiesResolver(this);
     private PropertiesParser propertiesParser = new 
DefaultPropertiesParser(this);
     private List<PropertiesLocation> locations = Collections.emptyList();
+    private List<PropertiesSource> sources = new ArrayList<>();
 
     private transient String propertyPrefixResolved;
 
@@ -204,6 +215,14 @@ public class PropertiesComponent extends DefaultComponent 
implements org.apache.
             prop.putAll(initialProperties);
         }
 
+        // add 3rd party sources
+        if (!sources.isEmpty()) {
+            for (PropertiesSource ps : sources) {
+                Properties p = ps.loadProperties();
+                prop.putAll(p);
+            }
+        }
+
         // use locations
         if (paths != null) {
             // location may contain JVM system property or OS environment 
variables
@@ -577,9 +596,50 @@ public class PropertiesComponent extends DefaultComponent 
implements org.apache.
         this.cacheMap.clear();
     }
 
+    /**
+     * Adds a custom {@link PropertiesSource}
+     */
+    public void addPropertiesSource(PropertiesSource propertiesSource) {
+        sources.add(propertiesSource);
+        // prepare properties sources which we must do eager
+        for (PropertiesSource ps : sources) {
+            if (ps instanceof CamelContextAware) {
+                ((CamelContextAware) ps).setCamelContext(getCamelContext());
+            }
+        }
+        ServiceHelper.initService(propertiesSource);
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+
+        // discover any 3rd party properties sources
+        try {
+            FactoryFinder factoryFinder = 
getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder("META-INF/services/org/apache/camel");
+            Class<?> type = 
factoryFinder.findClass("properties-source-factory");
+            if (type != null) {
+                Object ps = getCamelContext().getInjector().newInstance(type, 
false);
+                if (ps != null) {
+                    if (ps instanceof PropertiesSource) {
+                        LOG.info("PropertiesComponent added custom 
PropertiesSource: {}", ps);
+                        addPropertiesSource((PropertiesSource) ps);
+                    } else {
+                        LOG.warn("PropertiesComponent cannot add custom 
PropertiesSource as the type is not a 
org.apache.camel.component.properties.PropertiesSource but: " + type.getName());
+                    }
+                }
+            }
+        } catch (NoFactoryAvailableException e) {
+            // ignore
+        } catch (Exception e) {
+            LOG.debug("Error discovering and using custom PropertiesSource due 
to " + e.getMessage() + ". This exception is ignored", e);
+        }
+    }
+
     @Override
     protected void doStart() throws Exception {
         super.doStart();
+        ServiceHelper.startService(sources);
 
         if (systemPropertiesMode != SYSTEM_PROPERTIES_MODE_NEVER
                 && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_FALLBACK
@@ -602,6 +662,7 @@ public class PropertiesComponent extends DefaultComponent 
implements org.apache.
     protected void doStop() throws Exception {
         cacheMap.clear();
         super.doStop();
+        ServiceHelper.stopAndShutdownService(sources);
     }
 
     private List<PropertiesLocation> parseLocations(List<PropertiesLocation> 
locations) {
diff --git 
a/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesSource.java
 
b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesSource.java
new file mode 100644
index 0000000..0f8f43a
--- /dev/null
+++ 
b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesSource.java
@@ -0,0 +1,38 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 java.util.Properties;
+
+/**
+ * A source for 3rd party properties, such as Eclipse MicroProfile Config, a 
custom implementation
+ * that loads properties from a database table, or HashiCorp Vault etc.
+ */
+public interface PropertiesSource {
+
+    /**
+     * Name of properties source
+     */
+    String getName();
+
+    /**
+     * Loads the properties from the source
+     *
+     * @return the loaded properties
+     */
+    Properties loadProperties();
+}
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 6d5b5c7..4da8795 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -441,6 +441,8 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
         // keep reference to properties component up to date
         if (component instanceof PropertiesComponent && 
"properties".equals(componentName)) {
             propertiesComponent = (PropertiesComponent)component;
+            // ensure properties component is initialize early
+            ServiceHelper.initService(propertiesComponent);
         }
     }
 

Reply via email to