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

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

commit 2b695defc151dff11cac5d6e4f0302ff94beece6
Author: luke.me <[email protected]>
AuthorDate: Thu Jun 15 16:04:58 2023 +0900

    [CAMEL-19456] The invocation of the removeRoute() method is too slow when 
using RAW().
---
 .../camel/impl/engine/AbstractCamelContext.java    | 44 +++++++++--------
 .../camel/impl/engine/DefaultCamelContextTest.java | 34 +++++++++++++
 .../java/org/apache/camel/impl/engine/MyBean.java  |  8 ++++
 .../camel/util/UnsafeUriCharactersDecoder.java     | 55 ++++++++++++++++++++++
 4 files changed, 122 insertions(+), 19 deletions(-)

diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index c67cadb0387..5982d6001d6 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -175,12 +175,7 @@ import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.support.service.BaseService;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.startup.DefaultStartupStepRecorder;
-import org.apache.camel.util.IOHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StopWatch;
-import org.apache.camel.util.StringHelper;
-import org.apache.camel.util.TimeUtils;
-import org.apache.camel.util.URISupport;
+import org.apache.camel.util.*;
 import org.apache.camel.vault.VaultConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -702,6 +697,10 @@ public abstract class AbstractCamelContext extends 
BaseService
         removeEndpoints(endpoint.getEndpointUri());
     }
 
+    public String unsafeUriCharactersDecodeWithOutPercent(String uri){
+        return UnsafeUriCharactersDecoder.decode(uri);
+    }
+
     @Override
     public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
         Collection<Endpoint> answer = new ArrayList<>();
@@ -710,21 +709,28 @@ public abstract class AbstractCamelContext extends 
BaseService
             answer.add(oldEndpoint);
             stopServices(oldEndpoint);
         } else {
-            List<NormalizedUri> toRemove = new ArrayList<>();
-            for (Map.Entry<NormalizedUri, Endpoint> entry : 
endpoints.entrySet()) {
-                oldEndpoint = entry.getValue();
-                if (EndpointHelper.matchEndpoint(this, 
oldEndpoint.getEndpointUri(), uri)) {
-                    try {
-                        stopServices(oldEndpoint);
-                    } catch (Exception e) {
-                        LOG.warn("Error stopping endpoint {}. This exception 
will be ignored.", oldEndpoint, e);
+            String decodeUri = unsafeUriCharactersDecodeWithOutPercent(uri);
+            oldEndpoint = endpoints.remove(getEndpointKey(decodeUri));
+            if(oldEndpoint != null){
+                answer.add(oldEndpoint);
+                stopServices(oldEndpoint);
+            } else {
+                List<NormalizedUri> toRemove = new ArrayList<>();
+                for (Map.Entry<NormalizedUri, Endpoint> entry : 
endpoints.entrySet()) {
+                    oldEndpoint = entry.getValue();
+                    if (EndpointHelper.matchEndpoint(this, 
oldEndpoint.getEndpointUri(), uri)) {
+                        try {
+                            stopServices(oldEndpoint);
+                        } catch (Exception e) {
+                            LOG.warn("Error stopping endpoint " + oldEndpoint 
+ ". This exception will be ignored.", e);
+                        }
+                        answer.add(oldEndpoint);
+                        toRemove.add(entry.getKey());
                     }
-                    answer.add(oldEndpoint);
-                    toRemove.add(entry.getKey());
                 }
-            }
-            for (NormalizedUri key : toRemove) {
-                endpoints.remove(key);
+                for (NormalizedUri key : toRemove) {
+                    endpoints.remove(key);
+                }
             }
         }
 
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
index 5e236feec55..6322df0088c 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.impl.engine;
 
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
@@ -37,6 +38,7 @@ import org.apache.camel.spi.EndpointRegistry;
 import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.DefaultUuidGenerator;
+import org.apache.camel.support.NormalizedUri;
 import org.apache.camel.support.service.ServiceSupport;
 import org.junit.jupiter.api.Test;
 
@@ -413,6 +415,38 @@ public class DefaultCamelContextTest extends TestSupport {
         assertNull(ctx.hasService(MyService.class));
     }
 
+    @Test
+    public void testRemoveRoute() throws Exception {
+        DefaultCamelContext ctx = new DefaultCamelContext(false);
+
+        ctx.disableJMX();
+        ctx.getRegistry().bind("MyBean", MyBean.class);
+
+        ctx.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").routeId("rawRoute").to("bean:MyBean?method=RAW(addString('aa
 a',${body}))");
+            }
+        });
+        ctx.start();
+
+
+        EndpointRegistry<NormalizedUri> endpoints = ctx.getEndpointRegistry();
+        Map<String, RouteService> routeServices = ctx.getRouteServices();
+        Set<Endpoint> routeEndpoints =  
routeServices.get("rawRoute").gatherEndpoints();
+        for(Endpoint endpoint : routeEndpoints) {
+            Endpoint oldEndpoint = 
endpoints.remove(ctx.getEndpointKey(endpoint.getEndpointUri()));
+            if(oldEndpoint == null){
+                oldEndpoint = 
endpoints.remove(ctx.getEndpointKey(ctx.unsafeUriCharactersDecodeWithOutPercent(endpoint.getEndpointUri())));
+            }else {
+                assertNotNull(oldEndpoint);
+            }
+            assertNotNull(oldEndpoint);
+        }
+
+    }
+
+
     private static class MyService extends ServiceSupport implements 
CamelContextAware {
 
         private CamelContext camelContext;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/MyBean.java 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/MyBean.java
new file mode 100644
index 00000000000..d6e9faf43e2
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/engine/MyBean.java
@@ -0,0 +1,8 @@
+package org.apache.camel.impl.engine;
+
[email protected](value = "MyBean")
+public class MyBean {
+    public String addString(String source, String dst) throws Exception {
+        return source + dst;
+    }
+}
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/UnsafeUriCharactersDecoder.java
 
b/core/camel-util/src/main/java/org/apache/camel/util/UnsafeUriCharactersDecoder.java
new file mode 100644
index 00000000000..6fa7af5a49b
--- /dev/null
+++ 
b/core/camel-util/src/main/java/org/apache/camel/util/UnsafeUriCharactersDecoder.java
@@ -0,0 +1,55 @@
+package org.apache.camel.util;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class UnsafeUriCharactersDecoder {
+    private static final Map<String,String> unsafeStringsRfc1738;
+
+    static {
+        unsafeStringsRfc1738 = new HashMap<>();
+        unsafeStringsRfc1738.put("%22","\"");
+        unsafeStringsRfc1738.put("%3C","<");
+        unsafeStringsRfc1738.put("%3E",">");
+        unsafeStringsRfc1738.put("%7B","{");
+        unsafeStringsRfc1738.put("%7D","}");
+        unsafeStringsRfc1738.put("%7C","|");
+        unsafeStringsRfc1738.put("%5C","\\\\");
+        unsafeStringsRfc1738.put("%5E","^");
+        unsafeStringsRfc1738.put("%7E","~");
+        unsafeStringsRfc1738.put("%5B","[");
+        unsafeStringsRfc1738.put("%5D","]");
+        unsafeStringsRfc1738.put("%60","`");
+        unsafeStringsRfc1738.put("%20"," ");
+        unsafeStringsRfc1738.put("%23","#");
+    }
+
+    public static String decode(String uri){
+        int len = uri.length();
+        StringBuilder sb = new StringBuilder(len > 500 ? len / 2 : len);
+        for (int i = 0; i < len; i++) {
+            char ch = uri.charAt(i);
+            if (ch == '%') {
+                char next = i + 1 < len ? uri.charAt(i + 1) : ' ';
+                char next2 = i + 2 < len ? uri.charAt(i + 2) : ' ';
+                String encodedString = String.valueOf(ch) + next + next2;
+                if (isHexDigit(next) && isHexDigit(next2) && 
unsafeStringsRfc1738.containsKey(encodedString.toUpperCase())) {
+                    i = i + 2;
+                    sb.append(unsafeStringsRfc1738.get(encodedString));
+                } else {
+                    sb.append(ch);
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static boolean isHexDigit(char ch) {
+        // 0..9 A..F a..f
+        return ch >= 48 && ch <= 57 || ch >= 65 && ch <= 70 || ch >= 97 && ch 
<= 102;
+    }
+
+}
\ No newline at end of file

Reply via email to