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]; + } + } + +}
