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


The following commit(s) were added to refs/heads/main by this push:
     new 3447b838aa6 CAMEL-20897: Allow to use {xxx} inside RAW(xxx) for more 
power (#14615)
3447b838aa6 is described below

commit 3447b838aa6bca1ad70eb4914609b46bda5ddf96
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Jun 21 11:36:59 2024 +0200

    CAMEL-20897: Allow to use {xxx} inside RAW(xxx) for more power (#14615)
---
 .../impl/engine/PrototypeExchangeFactory.java      |  7 ---
 .../support/component/RawParameterHelperTest.java  | 56 ++++++++++++++++++++++
 .../org/apache/camel/support/DefaultComponent.java |  3 +-
 .../support/component/RawParameterHelper.java      | 51 ++++++++++++++++++++
 .../support/component/SendDynamicAwareSupport.java |  5 +-
 .../java/org/apache/camel/util/URISupport.java     | 23 +++++++++
 .../faq/pages/how-do-i-configure-endpoints.adoc    | 13 +++++
 7 files changed, 147 insertions(+), 11 deletions(-)

diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PrototypeExchangeFactory.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PrototypeExchangeFactory.java
index be8a697c10a..dbb808092e7 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PrototypeExchangeFactory.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PrototypeExchangeFactory.java
@@ -50,13 +50,6 @@ public class PrototypeExchangeFactory extends 
PooledObjectFactorySupport<Exchang
     protected void doBuild() throws Exception {
         super.doBuild();
         this.exchangeFactoryManager = 
camelContext.getCamelContextExtension().getExchangeFactoryManager();
-        // force creating and load the class during build time so the JVM does 
not
-        // load the class on first exchange to be created
-        DefaultExchange dummy = new DefaultExchange(camelContext);
-        // force message init to load classes
-        dummy.getIn();
-        dummy.getIn().getHeaders();
-        LOG.trace("Warming up PrototypeExchangeFactory loaded class: {}", 
dummy.getClass().getName());
     }
 
     @Override
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/support/component/RawParameterHelperTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/support/component/RawParameterHelperTest.java
new file mode 100644
index 00000000000..6d8cc4c968f
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/support/component/RawParameterHelperTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.support.component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class RawParameterHelperTest extends ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testResolveRawParameterValues() throws Exception {
+        Map<String, Object> map = new HashMap<>();
+        map.put("username", "abc");
+        map.put("password", "RAW(sec*ret)");
+
+        RawParameterHelper.resolveRawParameterValues(context, map);
+        Assertions.assertEquals("abc", map.get("username"));
+        Assertions.assertEquals("sec*ret", map.get("password"));
+
+        map.put("password", "RAW($simple{camelId})");
+        RawParameterHelper.resolveRawParameterValues(context, map);
+        Assertions.assertEquals("abc", map.get("username"));
+        Assertions.assertEquals(context.getName(), map.get("password"));
+
+        String usr = System.getenv("USER");
+        if (usr != null) {
+            map.put("password", "RAW($simple{env:USER})");
+            RawParameterHelper.resolveRawParameterValues(context, map);
+            Assertions.assertEquals("abc", map.get("username"));
+            Assertions.assertEquals(usr, map.get("password"));
+        }
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
index dd9ad5e8d19..577b92bfe3d 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
@@ -37,6 +37,7 @@ import 
org.apache.camel.component.extension.ComponentExtension;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.PropertyConfigurer;
 import org.apache.camel.spi.PropertyConfigurerAware;
+import org.apache.camel.support.component.RawParameterHelper;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.PropertiesHelper;
@@ -132,7 +133,7 @@ public abstract class DefaultComponent extends 
ServiceSupport implements Compone
             // parameters using raw syntax: RAW(value)
             // should have the token removed, so its only the value we have in 
parameters, as we are about to create
             // an endpoint and want to have the parameter values without the 
RAW tokens
-            URISupport.resolveRawParameterValues(parameters);
+            RawParameterHelper.resolveRawParameterValues(camelContext, 
parameters);
         }
 
         // use encoded or raw uri?
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/component/RawParameterHelper.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/component/RawParameterHelper.java
new file mode 100644
index 00000000000..1f5278c5ebb
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/component/RawParameterHelper.java
@@ -0,0 +1,51 @@
+/*
+ * 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.support.component;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.util.URISupport;
+
+public final class RawParameterHelper {
+
+    private RawParameterHelper() {
+    }
+
+    /**
+     * Traverses the given parameters, and resolve any parameter values which 
uses the RAW token syntax:
+     * <tt>key=RAW(value)</tt>. This method will then remove the RAW tokens, 
and replace the content of the value, with
+     * just the value.
+     *
+     * The value can refer to a simple expression using $simple{xxx} syntax 
which allows to refer to passwords defined
+     * as ENV variables etc.
+     *
+     * @param camelContext the camel context
+     * @param parameters   the uri parameters
+     */
+    public static void resolveRawParameterValues(CamelContext camelContext, 
Map<String, Object> parameters) {
+        URISupport.resolveRawParameterValues(parameters, s -> {
+            if (s != null && s.contains("$simple{")) {
+                Exchange dummy = new DefaultExchange(camelContext);
+                s = 
camelContext.resolveLanguage("simple").createExpression(s).evaluate(dummy, 
String.class);
+            }
+            return s;
+        });
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java
index 0d09f8f776e..3655d799693 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java
@@ -85,7 +85,7 @@ public abstract class SendDynamicAwareSupport extends 
ServiceSupport implements
                 // parameters using raw syntax: RAW(value)
                 // should have the token removed, so its only the value we 
have in parameters, as we are about to create
                 // an endpoint and want to have the parameter values without 
the RAW tokens
-                URISupport.resolveRawParameterValues(map);
+                
RawParameterHelper.resolveRawParameterValues(exchange.getContext(), map);
             }
             // okay so only add the known properties as they are the non 
lenient properties
             properties = new LinkedHashMap<>();
@@ -116,7 +116,7 @@ public abstract class SendDynamicAwareSupport extends 
ServiceSupport implements
                 // parameters using raw syntax: RAW(value)
                 // should have the token removed, so its only the value we 
have in parameters, as we are about to create
                 // an endpoint and want to have the parameter values without 
the RAW tokens
-                URISupport.resolveRawParameterValues(map);
+                
RawParameterHelper.resolveRawParameterValues(exchange.getContext(), map);
             }
             properties = new LinkedHashMap<>();
             map.forEach((k, v) -> {
@@ -138,7 +138,6 @@ public abstract class SendDynamicAwareSupport extends 
ServiceSupport implements
 
     public String asEndpointUri(Exchange exchange, String uri, Map<String, 
Object> properties) throws Exception {
         String query = URISupport.createQueryString(properties, false);
-
         return StringHelper.before(uri, "?", uri) + "?" + query;
     }
 
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java 
b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
index c8afdcb6f12..cfb09f010a0 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
@@ -30,6 +30,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.regex.Pattern;
 
 import static org.apache.camel.util.CamelURIParser.URI_ALREADY_NORMALIZED;
@@ -316,6 +317,22 @@ public final class URISupport {
      * @see              #RAW_TOKEN_END
      */
     public static void resolveRawParameterValues(Map<String, Object> 
parameters) {
+        resolveRawParameterValues(parameters, null);
+    }
+
+    /**
+     * Traverses the given parameters, and resolve any parameter values which 
uses the RAW token syntax:
+     * <tt>key=RAW(value)</tt>. This method will then remove the RAW tokens, 
and replace the content of the value, with
+     * just the value.
+     *
+     * @param parameters the uri parameters
+     * @param onReplace  optional function executed when replace the raw value
+     * @see              #parseQuery(String)
+     * @see              #RAW_TOKEN_PREFIX
+     * @see              #RAW_TOKEN_START
+     * @see              #RAW_TOKEN_END
+     */
+    public static void resolveRawParameterValues(Map<String, Object> 
parameters, Function<String, String> onReplace) {
         for (Map.Entry<String, Object> entry : parameters.entrySet()) {
             if (entry.getValue() == null) {
                 continue;
@@ -336,6 +353,9 @@ public final class URISupport {
                         // do not encode RAW parameters unless it has %
                         // need to reverse: replace % with %25 to avoid losing 
"%" when decoding
                         String s = raw.replace("%25", "%");
+                        if (onReplace != null) {
+                            s = onReplace.apply(s);
+                        }
                         list.set(i, s);
                     }
                 }
@@ -346,6 +366,9 @@ public final class URISupport {
                     // do not encode RAW parameters unless it has %
                     // need to reverse: replace % with %25 to avoid losing "%" 
when decoding
                     String s = raw.replace("%25", "%");
+                    if (onReplace != null) {
+                        s = onReplace.apply(s);
+                    }
                     entry.setValue(s);
                 }
             }
diff --git 
a/docs/user-manual/modules/faq/pages/how-do-i-configure-endpoints.adoc 
b/docs/user-manual/modules/faq/pages/how-do-i-configure-endpoints.adoc
index da44e99e9bb..79ec4d547a0 100644
--- a/docs/user-manual/modules/faq/pages/how-do-i-configure-endpoints.adoc
+++ b/docs/user-manual/modules/faq/pages/how-do-i-configure-endpoints.adoc
@@ -136,6 +136,19 @@ actual password would be as typed, eg `se+re?t&23`.
 
 NOTE: you may find a corner case when you use both `)` and `&` character as 
part of your password (ie, `se+re)t&23`). The parser will interpret the `)` as 
closing the `RAW` function and having a parameter started by `&`. In such case, 
you can instead use the `RAW{}` notation to let you include the `)` character 
and have it decoded as part of the password (ie, `RAW{se+re)t&23}`). As a safe 
alternative you can also use `password=#property:myPass` and then have `myPass` 
a xref:ROOT:property [...]
 
+==== Using ENV variables with raw values
+
+*Since Camel 4.7*
+
+If you need to use environment variables, for example as username or passwords 
then this is now possible by inlining
+the xref:components:languages:simple-language.adoc[Simple] language
+using `+++$simple{xxx}+++` syntax in `RAW(...)` as shown below:
+
+[source,java]
+----
+.to("ftp:[email protected]?password=RAW($simple{env:MY_FTP_PASSWORD})&binary=true")
+----
+
 [[HowdoIconfigureendpoints-Usingpropertyplaceholders]]
 === Using property placeholders
 

Reply via email to