Repository: camel
Updated Branches:
  refs/heads/master 19f27fd26 -> 88b8e447b


CAMEL-9089: rest-dsl when multiple candidates then use the most specific one.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b1c9132c
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b1c9132c
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b1c9132c

Branch: refs/heads/master
Commit: b1c9132cf22de1c066a9869b2f54235c6ab535dd
Parents: 57f48e8
Author: Claus Ibsen <davscl...@apache.org>
Authored: Fri Aug 21 10:24:41 2015 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Aug 21 10:53:02 2015 +0200

----------------------------------------------------------------------
 .../HttpServerMultiplexChannelHandler.java      | 61 ++++++++++++++-
 .../rest/RestNettyHttpGetWildcardsTest.java     | 79 ++++++++++++++++++++
 .../HttpServerMultiplexChannelHandler.java      |  2 +-
 3 files changed, 138 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java
index 2bcac76..747b242 100644
--- 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java
+++ 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java
@@ -203,18 +203,46 @@ public class HttpServerMultiplexChannelHandler extends 
SimpleChannelUpstreamHand
             }
         }
 
-        // then match by non wildcard path
+        // then match by wildcard path
         if (answer == null) {
             Iterator<Map.Entry<ContextPathMatcher, HttpServerChannelHandler>> 
it = candidates.iterator();
             while (it.hasNext()) {
                 Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry 
= it.next();
+                // filter non matching paths
                 if (!entry.getKey().matchesRest(path, true)) {
                     it.remove();
                 }
             }
 
-            // there should only be one
-            if (candidates.size() == 1) {
+            // if there is multiple candidates with wildcards then pick anyone 
with the least number of wildcards
+            int bestWildcard = Integer.MAX_VALUE;
+            Map.Entry<ContextPathMatcher, HttpServerChannelHandler> best = 
null;
+            if (candidates.size() > 1) {
+                it = candidates.iterator();
+                while (it.hasNext()) {
+                    Map.Entry<ContextPathMatcher, HttpServerChannelHandler> 
entry = it.next();
+                    String consumerPath = 
entry.getValue().getConsumer().getConfiguration().getPath();
+                    int wildcards = countWildcards(consumerPath);
+                    if (wildcards > 0) {
+                        if (best == null) {
+                            best = entry;
+                        } else {
+                            if (wildcards < bestWildcard) {
+                                bestWildcard = wildcards;
+                                best = entry;
+                            }
+                        }
+                    }
+                }
+
+                if (best != null) {
+                    // pick the best among the wildcards
+                    answer = best.getValue();
+                }
+            }
+
+            // if there is one left then its our answer
+            if (answer == null && candidates.size() == 1) {
                 answer = candidates.get(0).getValue();
             }
         }
@@ -232,6 +260,33 @@ public class HttpServerMultiplexChannelHandler extends 
SimpleChannelUpstreamHand
         return answer;
     }
 
+    /**
+     * Counts the number of wildcards in the path
+     *
+     * @param consumerPath  the consumer path which may use { } tokens
+     * @return number of wildcards, or <tt>0</tt> if no wildcards
+     */
+    private static int countWildcards(String consumerPath) {
+        int wildcards = 0;
+
+        // remove starting/ending slashes
+        if (consumerPath.startsWith("/")) {
+            consumerPath = consumerPath.substring(1);
+        }
+        if (consumerPath.endsWith("/")) {
+            consumerPath = consumerPath.substring(0, consumerPath.length() - 
1);
+        }
+
+        String[] consumerPaths = consumerPath.split("/");
+        for (String p2 : consumerPaths) {
+            if (p2.startsWith("{") && p2.endsWith("}")) {
+                wildcards++;
+            }
+        }
+
+        return wildcards;
+    }
+
     private static String pathAsKey(String path) {
         // cater for default path
         if (path == null || path.equals("/")) {

http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java
new file mode 100644
index 0000000..403bc8f
--- /dev/null
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java
@@ -0,0 +1,79 @@
+/**
+ * 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.netty.http.rest;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.netty.http.BaseNettyTest;
+import org.apache.camel.component.netty.http.RestNettyHttpBinding;
+import org.apache.camel.impl.JndiRegistry;
+import org.junit.Test;
+
+public class RestNettyHttpGetWildcardsTest extends BaseNettyTest {
+    
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("mybinding", new RestNettyHttpBinding());
+        return jndi;
+    }
+
+    @Test
+    public void testProducerGet() throws Exception {
+        String out = 
template.requestBody("netty-http:http://localhost:{{port}}/users/123/basic";, 
null, String.class);
+        assertEquals("123;Donald Duck", out);
+    }
+
+    @Test
+    public void testServletProducerGetWildcards() throws Exception {
+        String out = 
template.requestBody("netty-http:http://localhost:{{port}}/users/456/name=g*";, 
null, String.class);
+        assertEquals("456;Goofy", out);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // configure to use netty4-http on localhost with the given 
port
+                
restConfiguration().component("netty-http").host("localhost").port(getPort()).endpointProperty("nettyHttpBinding",
 "#mybinding");
+
+                // use the rest DSL to define the rest services
+                rest("/users/")
+                        .get("{id}/{query}")
+                        .route()
+                        .to("log:query")
+                        .process(new Processor() {
+                            public void process(Exchange exchange) throws 
Exception {
+                                String id = exchange.getIn().getHeader("id", 
String.class);
+                                exchange.getOut().setBody(id + ";Goofy");
+                            }
+                        }).endRest()
+                        .get("{id}/basic")
+                        .route()
+                        .to("log:input")
+                        .process(new Processor() {
+                            public void process(Exchange exchange) throws 
Exception {
+                                String id = exchange.getIn().getHeader("id", 
String.class);
+                                exchange.getOut().setBody(id + ";Donald Duck");
+                            }
+                        }).endRest();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
index 32fd20c..68bb656 100644
--- 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
@@ -263,7 +263,7 @@ public class HttpServerMultiplexChannelHandler extends 
SimpleChannelInboundHandl
      * @param consumerPath  the consumer path which may use { } tokens
      * @return number of wildcards, or <tt>0</tt> if no wildcards
      */
-    private int countWildcards(String consumerPath) {
+    private static int countWildcards(String consumerPath) {
         int wildcards = 0;
 
         // remove starting/ending slashes

Reply via email to