You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/09/19 13:54:56 UTC
(camel) branch prop-capture created (now 0e2d7e9100c)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a change to branch prop-capture
in repository https://gitbox.apache.org/repos/asf/camel.git
at 0e2d7e9100c CAMEL-21241: properties component - Should capture details about resolved placeholders
This branch includes the following new commits:
new 0e2d7e9100c CAMEL-21241: properties component - Should capture details about resolved placeholders
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 01/01: CAMEL-21241: properties component - Should capture details about resolved placeholders
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch prop-capture
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 0e2d7e9100cb498e3563c397b9ba3506fe7de0c0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 19 15:54:35 2024 +0200
CAMEL-21241: properties component - Should capture details about resolved placeholders
---
.../org/apache/camel/spi/PropertiesComponent.java | 8 ++
.../apache/camel/spi/PropertiesResolvedValue.java | 24 ++++++
.../properties/DefaultPropertiesLookup.java | 9 ++-
.../DefaultPropertiesLookupListener.java | 62 +++++++++++++++
.../properties/DefaultPropertiesParser.java | 35 +++++---
.../component/properties/PropertiesComponent.java | 22 +++--
.../camel/impl/console/PropertiesDevConsole.java | 20 ++++-
.../PropertiesComponentResolvedValueTest.java | 93 ++++++++++++++++++++++
.../camel/main/MainConfigurationDevConsole.java | 18 +++++
.../core/commands/process/ListProperties.java | 26 +++++-
10 files changed, 299 insertions(+), 18 deletions(-)
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 ef725a8ec01..e078809d11e 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
@@ -84,6 +84,14 @@ public interface PropertiesComponent extends StaticService {
*/
Optional<String> resolveProperty(String key);
+ /**
+ * Returns metadata about a property which has successfully been resolved.
+ *
+ * @param key the name of the property
+ * @return the property value and metadata if present
+ */
+ Optional<PropertiesResolvedValue> getResolvedValue(String key);
+
/**
* Loads the properties from the default locations and sources.
*
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesResolvedValue.java b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesResolvedValue.java
new file mode 100644
index 00000000000..2863b5065f7
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesResolvedValue.java
@@ -0,0 +1,24 @@
+/*
+ * 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.spi;
+
+/**
+ * Data about a {@link PropertiesComponent} property placeholder that has been resolved to a value by Camel.
+ */
+public record PropertiesResolvedValue(String name, String originalValue, String value, String defaultValue, String source) {
+
+}
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 3f8ad715e0a..695edcee640 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
@@ -24,6 +24,8 @@ import org.apache.camel.RuntimeCamelException;
import org.apache.camel.spi.LoadablePropertiesSource;
import org.apache.camel.spi.PropertiesSource;
import org.apache.camel.util.OrderedLocationProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Default {@link PropertiesLookup} which lookup properties from a {@link java.util.Properties} with all existing
@@ -31,6 +33,8 @@ import org.apache.camel.util.OrderedLocationProperties;
*/
public class DefaultPropertiesLookup implements PropertiesLookup {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultPropertiesLookup.class);
+
private final PropertiesComponent component;
public DefaultPropertiesLookup(PropertiesComponent component) {
@@ -40,7 +44,9 @@ public class DefaultPropertiesLookup implements PropertiesLookup {
@Override
public String lookup(String name, String defaultValue) {
try {
- return doLookup(name, defaultValue);
+ String answer = doLookup(name, defaultValue);
+ LOG.trace("lookup(name: {} default: {}) -> {}", name, defaultValue, answer);
+ return answer;
} catch (NoTypeConversionAvailableException e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
@@ -119,6 +125,7 @@ public class DefaultPropertiesLookup implements PropertiesLookup {
}
private void onLookup(String name, String value, String defaultValue, String source) {
+ LOG.trace("Property (name: {} default: {}) resolved from source: {} -> {}", name, defaultValue, source, value);
for (PropertiesLookupListener listener : component.getPropertiesLookupListeners()) {
try {
listener.onLookup(name, value, defaultValue, source);
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookupListener.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookupListener.java
new file mode 100644
index 00000000000..d9af8fad85f
--- /dev/null
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookupListener.java
@@ -0,0 +1,62 @@
+/*
+ * 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.Map;
+
+import org.apache.camel.PropertiesLookupListener;
+import org.apache.camel.spi.PropertiesResolvedValue;
+import org.apache.camel.support.LRUCacheFactory;
+import org.apache.camel.support.service.ServiceSupport;
+
+/**
+ * A {@link PropertiesLookupListener} listener that captures the resolved properties for dev consoles, management and
+ * troubleshooting purposes.
+ */
+public class DefaultPropertiesLookupListener extends ServiceSupport implements PropertiesLookupListener {
+
+ private Map<String, PropertiesResolvedValue> properties;
+
+ @Override
+ public void onLookup(String name, String value, String defaultValue, String source) {
+ properties.put(name, new PropertiesResolvedValue(name, value, value, defaultValue, source));
+ }
+
+ void updateValue(String name, String newValue, String newSource) {
+ var p = properties.get(name);
+ if (p != null) {
+ String source = newSource != null ? newSource : p.source();
+ properties.put(name, new PropertiesResolvedValue(p.name(), p.originalValue(), newValue, p.defaultValue(), source));
+ }
+ }
+
+ public PropertiesResolvedValue getProperty(String key) {
+ return properties.get(key);
+ }
+
+ @Override
+ protected void doBuild() throws Exception {
+ // use a cache with max limit to avoid capturing endless property values
+ // if there are a lot of dynamic values
+ properties = LRUCacheFactory.newLRUCache(1000);
+ }
+
+ @Override
+ protected void doShutdown() throws Exception {
+ properties.clear();
+ }
+}
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
index efcdac9b64e..43edd497bb1 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
@@ -118,7 +118,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
input = input.replace("?nested=false", "");
}
if (nested) {
- return doParseNested(input, new HashSet<>());
+ return doParseNested(null, input, new HashSet<>());
} else {
return doParse(input);
}
@@ -137,7 +137,8 @@ public class DefaultPropertiesParser implements PropertiesParser {
StringBuilder answer = new StringBuilder(input.length());
Property property;
- while ((property = readProperty(input)) != null) {
+ String prevKey = null;
+ while ((property = readProperty(prevKey, input)) != null) {
String before = input.substring(0, property.getBeginIndex());
String after = input.substring(property.getEndIndex());
String parsed = property.getValue();
@@ -149,6 +150,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
return null;
}
input = after;
+ prevKey = property.getKey();
}
if (!input.isEmpty()) {
answer.append(input);
@@ -163,13 +165,13 @@ public class DefaultPropertiesParser implements PropertiesParser {
* @param replacedPropertyKeys Already replaced property keys used for tracking circular references
* @return Evaluated string
*/
- private String doParseNested(String input, Set<String> replacedPropertyKeys) {
+ private String doParseNested(String prevKey, String input, Set<String> replacedPropertyKeys) {
if (input == null) {
return null;
}
String answer = input;
Property property;
- while ((property = readProperty(answer)) != null) {
+ while ((property = readProperty(prevKey, answer)) != null) {
if (replacedPropertyKeys.contains(property.getKey())) {
// Check for circular references (skip optional)
boolean optional = property.getKey().startsWith(OPTIONAL_TOKEN);
@@ -181,6 +183,12 @@ public class DefaultPropertiesParser implements PropertiesParser {
}
}
+ if (propertiesComponent != null) {
+ // nested placeholder so update resolved property with new value
+ String k = prevKey != null ? prevKey : property.getKey();
+ propertiesComponent.updateResolvedValue(k, property.getValue(), null);
+ }
+
Set<String> newReplaced = new HashSet<>(replacedPropertyKeys);
newReplaced.add(property.getKey());
@@ -191,7 +199,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
}
String before = answer.substring(0, beginIndex);
String after = answer.substring(property.getEndIndex());
- String parsed = doParseNested(property.getValue(), newReplaced);
+ String parsed = doParseNested(property.getKey(), property.getValue(), newReplaced);
if (parsed != null) {
answer = before + parsed + after;
} else {
@@ -213,7 +221,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
* @param input Input string
* @return A property in the given string or {@code null} if not found
*/
- private Property readProperty(String input) {
+ private Property readProperty(String prevKey, String input) {
// Find the index of the first valid suffix token
int suffix = getSuffixIndex(input);
@@ -232,7 +240,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
}
String key = input.substring(prefix + PREFIX_TOKEN.length(), suffix);
- String value = getPropertyValue(key, input);
+ String value = getPropertyValue(prevKey, key, input);
return new Property(prefix, suffix + SUFFIX_TOKEN.length(), key, value);
}
@@ -308,7 +316,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
* @param input Input string (used for exception message if value not found)
* @return Value of the property with the given key
*/
- private String getPropertyValue(String key, String input) {
+ private String getPropertyValue(String prevKey, String key, String input) {
if (key == null) {
return null;
}
@@ -326,7 +334,7 @@ public class DefaultPropertiesParser implements PropertiesParser {
String remainder = StringHelper.after(key, ":");
boolean remainderOptional = remainder.startsWith(OPTIONAL_TOKEN);
if (function.lookupFirst(remainder)) {
- String value = getPropertyValue(remainder, input);
+ String value = getPropertyValue(prevKey, remainder, input);
if (value == null && (remainderOptional || function.optional(remainder))) {
return null;
}
@@ -366,6 +374,8 @@ public class DefaultPropertiesParser implements PropertiesParser {
log.debug("Property with key [{}] applied by function [{}] -> {}", key, function.getName(),
value);
}
+ String k = prevKey != null ? prevKey : key;
+ propertiesComponent.updateResolvedValue(k, value, function.getName());
return value;
}
}
@@ -382,6 +392,13 @@ public class DefaultPropertiesParser implements PropertiesParser {
if (value == null && defaultValue != null) {
log.debug("Property with key [{}] not found, using default value: {}", key, defaultValue);
value = defaultValue;
+ for (PropertiesLookupListener listener : propertiesComponent.getPropertiesLookupListeners()) {
+ try {
+ listener.onLookup(key, value, defaultValue, null);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
}
if (value == null) {
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 0cfa3746e72..698103884de 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
@@ -36,6 +36,7 @@ import org.apache.camel.spi.Configurer;
import org.apache.camel.spi.FactoryFinder;
import org.apache.camel.spi.LoadablePropertiesSource;
import org.apache.camel.spi.PropertiesFunction;
+import org.apache.camel.spi.PropertiesResolvedValue;
import org.apache.camel.spi.PropertiesSource;
import org.apache.camel.spi.PropertiesSourceFactory;
import org.apache.camel.spi.annotations.JdkService;
@@ -111,6 +112,7 @@ public class PropertiesComponent extends ServiceSupport
private final PropertiesLookup propertiesLookup = new DefaultPropertiesLookup(this);
private final List<PropertiesLookupListener> propertiesLookupListeners = new ArrayList<>();
private final PropertiesSourceFactory propertiesSourceFactory = new DefaultPropertiesSourceFactory(this);
+ private final DefaultPropertiesLookupListener defaultPropertiesLookupListener = new DefaultPropertiesLookupListener();
private final List<PropertiesSource> sources = new ArrayList<>();
private List<PropertiesLocation> locations = new ArrayList<>();
private String location;
@@ -128,6 +130,7 @@ public class PropertiesComponent extends ServiceSupport
private boolean autoDiscoverPropertiesSources = true;
public PropertiesComponent() {
+ addPropertiesLookupListener(defaultPropertiesLookupListener);
// include out of the box functions
addPropertiesFunction(new EnvPropertiesFunction());
addPropertiesFunction(new SysPropertiesFunction());
@@ -187,6 +190,15 @@ public class PropertiesComponent extends ServiceSupport
}
}
+ @Override
+ public Optional<PropertiesResolvedValue> getResolvedValue(String key) {
+ return Optional.ofNullable(defaultPropertiesLookupListener.getProperty(key));
+ }
+
+ public void updateResolvedValue(String key, String newValue, String newSource) {
+ defaultPropertiesLookupListener.updateValue(key, newValue, newSource);
+ }
+
@Override
public Properties loadProperties() {
// this method may be replaced by loadProperties(k -> true) but the underlying sources
@@ -784,27 +796,27 @@ public class PropertiesComponent extends ServiceSupport
}
sources.sort(OrderedComparator.get());
- ServiceHelper.initService(sources, propertiesFunctionResolver);
+ ServiceHelper.initService(sources, propertiesFunctionResolver, defaultPropertiesLookupListener);
}
@Override
protected void doBuild() throws Exception {
- ServiceHelper.buildService(sources, propertiesFunctionResolver);
+ ServiceHelper.buildService(sources, propertiesFunctionResolver, defaultPropertiesLookupListener);
}
@Override
protected void doStart() throws Exception {
- ServiceHelper.startService(sources, propertiesFunctionResolver);
+ ServiceHelper.startService(sources, propertiesFunctionResolver, defaultPropertiesLookupListener);
}
@Override
protected void doStop() throws Exception {
- ServiceHelper.stopService(sources, propertiesFunctionResolver);
+ ServiceHelper.stopService(sources, propertiesFunctionResolver, defaultPropertiesLookupListener);
}
@Override
protected void doShutdown() throws Exception {
- ServiceHelper.stopAndShutdownServices(sources, propertiesFunctionResolver);
+ ServiceHelper.stopAndShutdownServices(sources, propertiesFunctionResolver, defaultPropertiesLookupListener);
}
private void addPropertiesLocationsAsPropertiesSource(PropertiesLocation location, int order) {
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
index 9b0884b3e67..2ebe943ee55 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
@@ -82,10 +82,28 @@ public class PropertiesDevConsole extends AbstractDevConsole {
String k = entry.getKey().toString();
Object v = entry.getValue();
String loc = olp != null ? olp.getLocation(k) : null;
-
+ String originalValue = null;
+ String defaultValue = null;
+ String source = null;
+ var m = pc.getResolvedValue(k);
+ if (m.isPresent()) {
+ originalValue = m.get().originalValue();
+ defaultValue = m.get().defaultValue();
+ source = m.get().source();
+ v = m.get().value();
+ }
JsonObject jo = new JsonObject();
jo.put("key", k);
jo.put("value", v);
+ if (originalValue != null) {
+ jo.put("originalValue", originalValue);
+ }
+ if (defaultValue != null) {
+ jo.put("defaultValue", defaultValue);
+ }
+ if (source != null) {
+ jo.put("source", source);
+ }
if (loc != null) {
jo.put("location", loc);
jo.put("internal", isInternal(loc));
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentResolvedValueTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentResolvedValueTest.java
new file mode 100644
index 00000000000..c7768d33412
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentResolvedValueTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class PropertiesComponentResolvedValueTest extends ContextTestSupport {
+
+ @Test
+ public void testResolved() {
+ org.apache.camel.spi.PropertiesComponent pc = context.getPropertiesComponent();
+
+ Assertions.assertTrue(pc.getResolvedValue("unknown").isEmpty());
+ Assertions.assertTrue(pc.getResolvedValue("greeting").isPresent());
+ Assertions.assertTrue(pc.getResolvedValue("cool.end").isPresent());
+ Assertions.assertTrue(pc.getResolvedValue("place").isPresent());
+ Assertions.assertTrue(pc.getResolvedValue("myserver").isPresent());
+
+ // added initial via code
+ var p = pc.getResolvedValue("greeting").get();
+ Assertions.assertEquals("greeting", p.name());
+ Assertions.assertEquals("Hello World", p.originalValue());
+ Assertions.assertEquals("Hello World", p.value());
+ Assertions.assertEquals("Hi", p.defaultValue());
+ Assertions.assertEquals("InitialProperties", p.source());
+
+ // from properties file
+ p = pc.getResolvedValue("cool.end").get();
+ Assertions.assertEquals("cool.end", p.name());
+ Assertions.assertEquals("mock:result", p.originalValue());
+ Assertions.assertEquals("mock:result", p.value());
+ Assertions.assertNull(p.defaultValue());
+ Assertions.assertEquals("classpath:org/apache/camel/component/properties/myproperties.properties", p.source());
+
+ // no source but using default value
+ p = pc.getResolvedValue("place").get();
+ Assertions.assertEquals("place", p.name());
+ Assertions.assertEquals("Paris", p.originalValue());
+ Assertions.assertEquals("Paris", p.value());
+ Assertions.assertEquals("Paris", p.defaultValue());
+ Assertions.assertNull(p.source());
+
+ // nested
+ p = pc.getResolvedValue("myserver").get();
+ Assertions.assertEquals("myserver", p.name());
+ Assertions.assertEquals("127.0.0.1", p.value());
+ Assertions.assertEquals("{{env:MY_SERVER:127.0.0.1}}", p.originalValue());
+ Assertions.assertNull(p.defaultValue());
+ Assertions.assertEquals("env", p.source());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .setBody(constant("{{greeting:Hi}}"))
+ .setHeader("bar", constant("{{?place:Paris}}"))
+ .setHeader("server", constant("{{myserver}}"))
+ .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().addInitialProperty("myserver", "{{env:MY_SERVER:127.0.0.1}}");
+ return context;
+ }
+
+}
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationDevConsole.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationDevConsole.java
index e1a7dce07d7..aa88d984716 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationDevConsole.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationDevConsole.java
@@ -18,6 +18,7 @@ package org.apache.camel.main;
import java.util.Map;
+import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.spi.annotations.DevConsole;
import org.apache.camel.support.console.AbstractDevConsole;
import org.apache.camel.util.OrderedLocationProperties;
@@ -68,6 +69,8 @@ public class MainConfigurationDevConsole extends AbstractDevConsole {
@Override
protected Map<String, Object> doCallJson(Map<String, Object> options) {
+ PropertiesComponent pc = getCamelContext().getPropertiesComponent();
+
JsonObject root = new JsonObject();
if (!startupConfiguration.isEmpty()) {
JsonArray arr = new JsonArray();
@@ -75,10 +78,25 @@ public class MainConfigurationDevConsole extends AbstractDevConsole {
String k = entry.getKey().toString();
Object v = entry.getValue();
String loc = startupConfiguration.getLocation(k);
+ Object defaultValue = startupConfiguration.getDefaultValue(k);
JsonObject jo = new JsonObject();
jo.put("key", k);
jo.put("value", v);
+ if (defaultValue != null) {
+ jo.put("defaultValue", defaultValue);
+ }
+ // enrich if present
+ pc.getResolvedValue(k).ifPresent(r -> {
+ String ov = r.originalValue();
+ if (ov != null) {
+ jo.put("originalValue", ov);
+ }
+ String src = r.source();
+ if (src != null) {
+ jo.put("source", src);
+ }
+ });
if (loc != null) {
jo.put("location", loc);
jo.put("internal", isInternal(loc));
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProperties.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProperties.java
index 3da48a218bf..02bb13ceb90 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProperties.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProperties.java
@@ -28,6 +28,7 @@ import com.github.freva.asciitable.OverflowBehaviour;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.ProcessHelper;
import org.apache.camel.util.SensitiveUtils;
+import org.apache.camel.util.StringHelper;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
@@ -58,6 +59,9 @@ public class ListProperties extends ProcessWatchCommand {
@CommandLine.Option(names = { "--startup" }, description = "List only startup configuration")
boolean startup;
+ @CommandLine.Option(names = { "--verbose" }, description = "Whether to include more details")
+ boolean verbose;
+
@CommandLine.Option(names = { "--internal" }, description = "Whether to include internal configuration")
boolean internal;
@@ -109,7 +113,13 @@ public class ListProperties extends ProcessWatchCommand {
value = "xxxxxx";
}
row.value = value;
+ value = jo.getString("originalValue");
+ if (mask && SensitiveUtils.containsSensitive(row.key)) {
+ value = "xxxxxx";
+ }
+ row.originalValue = value;
row.internalLoc = jo.getBooleanOrDefault("internal", false);
+ row.source = jo.getString("source");
row.loc = sanitizeLocation(jo.getString("location"));
boolean accept = internal || !row.internalLoc;
if (accept) {
@@ -132,12 +142,22 @@ public class ListProperties extends ProcessWatchCommand {
new Column().header("KEY").dataAlign(HorizontalAlign.LEFT).maxWidth(50, OverflowBehaviour.ELLIPSIS_RIGHT)
.with(r -> r.key),
new Column().header("VALUE").dataAlign(HorizontalAlign.LEFT).maxWidth(80, OverflowBehaviour.NEWLINE)
- .with(r -> "" + r.value))));
+ .with(r -> "" + r.value),
+ new Column().header("FUNCTION").visible(verbose).dataAlign(HorizontalAlign.LEFT)
+ .maxWidth(50, OverflowBehaviour.ELLIPSIS_RIGHT)
+ .with(this::getFunction),
+ new Column().header("ORIGINAL VALUE").visible(verbose).dataAlign(HorizontalAlign.LEFT)
+ .maxWidth(80, OverflowBehaviour.NEWLINE)
+ .with(r -> "" + r.originalValue))));
}
return 0;
}
+ protected String getFunction(Row r) {
+ return StringHelper.before(r.source, ":", r.source);
+ }
+
protected int sortRow(Row o1, Row o2) {
String s = sort;
int negate = 1;
@@ -162,6 +182,8 @@ public class ListProperties extends ProcessWatchCommand {
String name;
String key;
Object value;
+ Object originalValue;
+ String source;
String loc;
boolean internalLoc;
@@ -182,7 +204,7 @@ public class ListProperties extends ProcessWatchCommand {
loc = "camel-main";
} else if ("SYS".equals(loc)) {
loc = "JVM System Property";
- } else if ("ENV".equals(loc)) {
+ } else if ("ENV".equals(loc) || "env".equals(loc)) {
loc = "OS Environment Variable";
} else if ("arguments".equals(loc) || "CLI".equals(loc)) {
loc = "Command Line";