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 11abba064cb CAMEL-22480: fix using endpoint URIs with property 
placeholders in co… (#19389)
11abba064cb is described below

commit 11abba064cb0695c41d74404bb98c2b1e732bbf2
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Oct 1 12:55:05 2025 +0200

    CAMEL-22480: fix using endpoint URIs with property placeholders in co… 
(#19389)
    
    * CAMEL-22480: fix using endpoint URIs with property placeholders in 
context path with ? sign can cause double ?
---
 .../java/org/apache/camel/reifier/PollReifier.java |  9 ++++
 .../PropertyPlaceholderWithQuestionSignTest.java   | 61 ++++++++++++++++++++++
 .../org/apache/camel/support/EndpointHelper.java   | 34 ++++++++++--
 3 files changed, 99 insertions(+), 5 deletions(-)

diff --git 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollReifier.java
 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollReifier.java
index de0e35fb00d..9f919d7c43f 100644
--- 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollReifier.java
+++ 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollReifier.java
@@ -21,6 +21,8 @@ import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.model.PollDefinition;
 import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
+import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.PollProcessor;
 import org.apache.camel.spi.Language;
 import org.apache.camel.support.EndpointHelper;
@@ -44,6 +46,13 @@ public class PollReifier extends 
ProcessorReifier<PollDefinition> {
             uri = StringHelper.notEmpty(definition.getUri(), "uri", this);
             exp = createExpression(uri);
         }
+
+        // route templates should pre parse uri as they have dynamic values as 
part of their template parameters
+        RouteDefinition rd = ProcessorDefinitionHelper.getRoute(definition);
+        if (rd != null && rd.isTemplate() != null && rd.isTemplate()) {
+            uri = 
EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, uri);
+        }
+
         long timeout = parseDuration(definition.getTimeout(), 20000);
         PollProcessor answer = new PollProcessor(exp, uri, timeout);
         answer.setDisabled(isDisabled(camelContext, definition));
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyPlaceholderWithQuestionSignTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyPlaceholderWithQuestionSignTest.java
new file mode 100644
index 00000000000..8237be7b6bd
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyPlaceholderWithQuestionSignTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PropertyPlaceholderWithQuestionSignTest extends 
ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testQuestionSign() throws Exception {
+        Properties prop = new Properties();
+        prop.put("whereTo", "result?retainLast=2");
+        context.getPropertiesComponent().setInitialProperties(prop);
+
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start")
+                        .to("mock:{{whereTo}}?retainFirst=1");
+            }
+        });
+        context.start();
+
+        log.debug("{}", context.getEndpoints());
+        
assertNotNull(context.hasEndpoint("mock://result?retainLast=2&retainFirst=1"));
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        
context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/myproperties.properties");
+        return context;
+    }
+
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java 
b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
index f728f31068d..65e60755b66 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
@@ -63,15 +63,39 @@ public final class EndpointHelper {
      * @return              returns endpoint uri with property placeholders 
resolved
      */
     public static String resolveEndpointUriPropertyPlaceholders(CamelContext 
camelContext, String uri) {
-        // the uri may have optional property placeholders which is not 
possible to resolve
-        // so we keep the unresolved in the uri, which we then afterwards will 
remove
-        // which is a little complex depending on the placeholder is from 
context-path or query parameters
-        // in the uri string
+        if (uri == null || uri.isEmpty()) {
+            return uri;
+        }
+
         try {
-            uri = 
camelContext.getCamelContextExtension().resolvePropertyPlaceholders(uri, true);
+            // special for resolving uris with query parameters,
+            // as there can also be ? signs in context-path that are being 
resolved
+            // (only trigger this code if there are property placeholders in 
the context-path otherwise resolve using
+            // the complete uri in the else block)
+            int pos = uri.indexOf(PropertiesComponent.PREFIX_TOKEN);
+            int pos1 = uri.indexOf('?');
+            int pos2 = uri.indexOf(PropertiesComponent.PREFIX_OPTIONAL_TOKEN);
+            // split only if there are query parameters (and that any optional 
tokens are positioned later)
+            if (pos != -1 && pos1 != uri.length() - 1 && pos1 != -1 && (pos2 
== -1 || pos2 + 2 > pos1)) {
+                String u1 = uri.substring(0, pos1);
+                String u2 = uri.substring(pos1 + 1);
+                u1 = 
camelContext.getCamelContextExtension().resolvePropertyPlaceholders(u1, true);
+                u2 = 
camelContext.getCamelContextExtension().resolvePropertyPlaceholders(u2, true);
+                if (u1.indexOf('?') != -1) {
+                    uri = u1 + "&" + u2;
+                } else {
+                    uri = u1 + "?" + u2;
+                }
+            } else {
+                uri = 
camelContext.getCamelContextExtension().resolvePropertyPlaceholders(uri, true);
+            }
             if (uri == null || uri.isEmpty()) {
                 return uri;
             }
+            // the uri may have optional property placeholders which is not 
possible to resolve
+            // so we keep the unresolved in the uri, which we then afterwards 
will remove
+            // which is a little complex depending on the placeholder is from 
context-path or query parameters
+            // in the uri string
             String prefix = PropertiesComponent.PREFIX_OPTIONAL_TOKEN;
             if (uri.contains(prefix)) {
                 String unresolved = uri;

Reply via email to