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

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

commit e9fdf399d52745f93ad1ce3ef1414454f3bebc05
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Apr 14 13:53:20 2022 +0200

    CAMEL-17969: properties component - Add lookup listener so we can cature 
from where a property placeholder was from.
---
 .../org/apache/camel/PropertiesLookupListener.java | 34 ++++++++
 .../org/apache/camel/spi/PropertiesComponent.java  |  6 ++
 .../properties/DefaultPropertiesLookup.java        | 35 ++++++++-
 .../component/properties/PropertiesComponent.java  | 20 +++++
 .../PropertiesComponentLookupListenerTest.java     | 90 ++++++++++++++++++++++
 5 files changed, 181 insertions(+), 4 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/PropertiesLookupListener.java 
b/core/camel-api/src/main/java/org/apache/camel/PropertiesLookupListener.java
new file mode 100644
index 00000000000..05c85629899
--- /dev/null
+++ 
b/core/camel-api/src/main/java/org/apache/camel/PropertiesLookupListener.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Listener to trigger when the properties component is looking up and found a 
property.
+ */
+@FunctionalInterface
+public interface PropertiesLookupListener {
+
+    /**
+     * Triggers when the given property was found.
+     *
+     * @param name   property name
+     * @param value  the resolved value
+     * @param source optional source containing the properties
+     */
+    void onLookup(String name, String value, String source);
+
+}
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
index 391b6dd42a6..8b12fe48243 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
@@ -23,6 +23,7 @@ import java.util.Properties;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
+import org.apache.camel.PropertiesLookupListener;
 import org.apache.camel.StaticService;
 
 /**
@@ -252,4 +253,9 @@ public interface PropertiesComponent extends StaticService {
      */
     boolean reloadProperties(String pattern);
 
+    /**
+     * Adds the {@link PropertiesLookupListener}.
+     */
+    void addPropertiesLookupListener(PropertiesLookupListener 
propertiesLookupListener);
+
 }
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
index 31e1289aefd..e5573f83d6f 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
@@ -16,10 +16,10 @@
  */
 package org.apache.camel.component.properties;
 
-import java.util.Iterator;
 import java.util.Properties;
 
 import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.PropertiesLookupListener;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.PropertiesSource;
 
@@ -54,6 +54,7 @@ public class DefaultPropertiesLookup implements 
PropertiesLookup {
             Object value = local.get(name);
             if (value != null) {
                 answer = 
component.getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, 
value);
+                onLookup(name, answer, "LocalProperties");
             }
         }
 
@@ -63,13 +64,27 @@ public class DefaultPropertiesLookup implements 
PropertiesLookup {
             Object value = component.getOverrideProperties().get(name);
             if (value != null) {
                 answer = 
component.getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, 
value);
+                onLookup(name, answer, "OverrideProperties");
             }
         }
         if (answer == null) {
             // try till first found source
-            Iterator<PropertiesSource> it2 = component.getSources().iterator();
-            while (answer == null && it2.hasNext()) {
-                answer = it2.next().getProperty(name);
+            for (PropertiesSource ps : component.getSources()) {
+                answer = ps.getProperty(name);
+                if (answer != null) {
+                    String source = ps.getName();
+                    if (ps instanceof ClasspathPropertiesSource) {
+                        source = "classpath:" + ((LocationPropertiesSource) 
ps).getLocation().getPath();
+                    } else if (ps instanceof FilePropertiesSource) {
+                        source = "file:" + ((LocationPropertiesSource) 
ps).getLocation().getPath();
+                    } else if (ps instanceof RefPropertiesSource) {
+                        source = "ref:" + ((LocationPropertiesSource) 
ps).getLocation().getPath();
+                    } else if (ps instanceof LocationPropertiesSource) {
+                        source = ((LocationPropertiesSource) 
ps).getLocation().getPath();
+                    }
+                    onLookup(name, answer, source);
+                    break;
+                }
             }
         }
         // initial properties are last
@@ -78,9 +93,21 @@ public class DefaultPropertiesLookup implements 
PropertiesLookup {
             Object value = component.getInitialProperties().get(name);
             if (value != null) {
                 answer = 
component.getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, 
value);
+                onLookup(name, answer, "InitialProperties");
             }
         }
 
         return answer;
     }
+
+    private void onLookup(String name, String value, String source) {
+        for (PropertiesLookupListener listener : 
component.getPropertiesLookupListeners()) {
+            try {
+                listener.onLookup(name, value, source);
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
 }
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 807476cd392..0dc27aa33a9 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -30,6 +30,7 @@ import java.util.stream.Collectors;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.PropertiesLookupListener;
 import org.apache.camel.StaticService;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedOperation;
@@ -107,6 +108,7 @@ public class PropertiesComponent extends ServiceSupport
     private final PropertiesFunctionResolver functionResolver = new 
PropertiesFunctionResolver();
     private PropertiesParser propertiesParser = new 
DefaultPropertiesParser(this);
     private final PropertiesLookup propertiesLookup = new 
DefaultPropertiesLookup(this);
+    private List<PropertiesLookupListener> propertiesLookupListeners = new 
ArrayList<>();
     private final List<PropertiesSource> sources = new ArrayList<>();
     private List<PropertiesLocation> locations = new ArrayList<>();
     private String location;
@@ -657,6 +659,24 @@ public class PropertiesComponent extends ServiceSupport
         return sources;
     }
 
+    public void addPropertiesLookupListener(PropertiesLookupListener 
propertiesLookupListener) {
+        propertiesLookupListeners.add(propertiesLookupListener);
+    }
+
+    /**
+     * Remove {@link PropertiesLookupListener}
+     */
+    public void removePropertiesLookupListener(PropertiesLookupListener 
propertiesLookupListener) {
+        propertiesLookupListeners.remove(propertiesLookupListener);
+    }
+
+    /**
+     * Gets the {@link PropertiesLookupListener}
+     */
+    public List<PropertiesLookupListener> getPropertiesLookupListeners() {
+        return propertiesLookupListeners;
+    }
+
     @ManagedOperation(description = "Reload properties from the given location 
patterns")
     @Override
     public boolean reloadProperties(String pattern) {
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentLookupListenerTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentLookupListenerTest.java
new file mode 100644
index 00000000000..5d09a4750c4
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentLookupListenerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.PropertiesLookupListener;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PropertiesComponentLookupListenerTest extends ContextTestSupport {
+
+    private final MyListener myListener = new MyListener();
+
+    @Test
+    public void testListener() throws Exception {
+        assertTrue(myListener.hasName("greeting"));
+        assertEquals("Hello World", myListener.getValue("greeting"));
+        assertEquals("InitialProperties", myListener.getSource("greeting"));
+
+        assertTrue(myListener.hasName("cool.end"));
+        assertEquals("mock:result", myListener.getValue("cool.end"));
+        
assertEquals("classpath:org/apache/camel/component/properties/myproperties.properties",
+                myListener.getSource("cool.end"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setBody(constant("{{greeting}}"))
+                        .to("{{cool.end}}");
+            }
+        };
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        
context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/myproperties.properties");
+        context.getPropertiesComponent().addInitialProperty("greeting", "Hello 
World");
+        
context.getPropertiesComponent().addPropertiesLookupListener(myListener);
+        return context;
+    }
+
+    private class MyListener implements PropertiesLookupListener {
+
+        private Map<String, String[]> map = new HashMap<>();
+
+        @Override
+        public void onLookup(String name, String value, String source) {
+            map.put(name, new String[] { value, source });
+        }
+
+        public boolean hasName(String name) {
+            return map.containsKey(name);
+        }
+
+        public String getValue(String name) {
+            return map.get(name)[0];
+        }
+
+        public String getSource(String name) {
+            return map.get(name)[1];
+        }
+    }
+
+}

Reply via email to