Repository: camel
Updated Branches:
  refs/heads/master cba6e2e8f -> 61a1a2ab0


CAMEL-7354: Rest DSL. Integrate with camel-jetty.


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

Branch: refs/heads/master
Commit: c5098c1df62e54ca7e7b5482f2f609ff7181e81f
Parents: cba6e2e
Author: Claus Ibsen <davscl...@apache.org>
Authored: Mon Jul 28 13:49:07 2014 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Mon Jul 28 13:49:07 2014 +0200

----------------------------------------------------------------------
 .../component/jetty/JettyRestHttpBinding.java   | 36 +++++----
 ...JettyRestServletResolveConsumerStrategy.java | 78 ++++++++++----------
 .../jetty/rest/RestPathMatchingTest.java        | 55 ++++++++++++++
 3 files changed, 117 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java
----------------------------------------------------------------------
diff --git 
a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java
 
b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java
index b92cf3f..178d5a1 100644
--- 
a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java
+++ 
b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java
@@ -23,8 +23,6 @@ import org.apache.camel.component.http.HttpMessage;
 
 public class JettyRestHttpBinding extends DefaultHttpBinding {
 
-    // TODO: a better and faster rest pattern matcher, without the .split as 
they may be slower
-
     @Override
     protected void populateRequestParameters(HttpServletRequest request, 
HttpMessage message) throws Exception {
         super.populateRequestParameters(request, message);
@@ -40,21 +38,31 @@ public class JettyRestHttpBinding extends 
DefaultHttpBinding {
         JettyHttpEndpoint endpoint = (JettyHttpEndpoint) 
message.getExchange().getFromEndpoint();
         String consumerPath = endpoint.getPath();
 
-        String[] paths = path.split("/");
-        String[] consumerPaths = consumerPath.split("/");
+        if (useRestMatching(consumerPath)) {
 
-        for (int i = 0; i < consumerPaths.length; i++) {
-            if (paths.length < i) {
-                break;
-            }
-            String p1 = consumerPaths[i];
-            if (p1.startsWith("{") && p1.endsWith("}")) {
-                String key = p1.substring(1, p1.length() - 1);
-                String value = paths[i];
-                if (value != null) {
-                    message.setHeader(key, value);
+            // split using single char / is optimized in the jdk
+            String[] paths = path.split("/");
+            String[] consumerPaths = consumerPath.split("/");
+
+            for (int i = 0; i < consumerPaths.length; i++) {
+                if (paths.length < i) {
+                    break;
+                }
+                String p1 = consumerPaths[i];
+                if (p1.startsWith("{") && p1.endsWith("}")) {
+                    String key = p1.substring(1, p1.length() - 1);
+                    String value = paths[i];
+                    if (value != null) {
+                        message.setHeader(key, value);
+                    }
                 }
             }
         }
     }
+
+    private boolean useRestMatching(String path) {
+        // only need to do rest matching if using { } placeholders
+        return path.indexOf('{') > -1;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java
----------------------------------------------------------------------
diff --git 
a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java
 
b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java
index 4832f84..34f8ce2 100644
--- 
a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java
+++ 
b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java
@@ -28,37 +28,56 @@ import org.apache.camel.util.ObjectHelper;
  */
 public class JettyRestServletResolveConsumerStrategy extends 
HttpServletResolveConsumerStrategy {
 
-    // TODO: a better and faster rest pattern matcher, without the .split as 
they may be slower
-
     @Override
     public HttpConsumer resolve(HttpServletRequest request, Map<String, 
HttpConsumer> consumers) {
-        HttpConsumer answer = super.resolve(request, consumers);
-
-        if (answer == null) {
-
-            String path = request.getPathInfo();
-            if (path == null) {
-                return null;
-            }
+        String path = request.getPathInfo();
+        if (path == null) {
+            return null;
+        }
 
-            for (String key : consumers.keySet()) {
-                String consumerPath = normalizePath(key);
-                String requestPath = normalizePath(path);
-                if (matchPaths(requestPath, consumerPath)) {
-                    answer = consumers.get(key);
-                    break;
-                }
+        for (String key : consumers.keySet()) {
+            if (useRestMatching(key) && matchRestPath(path, key)) {
+                return consumers.get(key);
             }
         }
 
-        return answer;
+        // fallback to default
+        return super.resolve(request, consumers);
     }
 
-    private boolean matchPaths(String requestPath, String consumerPath) {
+    private boolean useRestMatching(String path) {
+        // only need to do rest matching if using { } placeholders
+        return path.indexOf('{') > -1;
+    }
+
+    /**
+     * Matches the given request path with the configured consumer path
+     *
+     * @param requestPath   the request path
+     * @param consumerPath  the consumer path which may use { } tokens
+     * @return <tt>true</tt> if matched, <tt>false</tt> otherwise
+     */
+    public boolean matchRestPath(String requestPath, String consumerPath) {
+        // remove starting/ending slashes
+        if (requestPath.startsWith("/")) {
+            requestPath = requestPath.substring(1);
+        }
+        if (requestPath.endsWith("/")) {
+            requestPath = requestPath.substring(0, requestPath.length() - 1);
+        }
+        // remove starting/ending slashes
+        if (consumerPath.startsWith("/")) {
+            consumerPath = consumerPath.substring(1);
+        }
+        if (consumerPath.endsWith("/")) {
+            consumerPath = consumerPath.substring(0, consumerPath.length() - 
1);
+        }
+
+        // split using single char / is optimized in the jdk
         String[] requestPaths = requestPath.split("/");
         String[] consumerPaths = consumerPath.split("/");
 
-        // must be same length
+        // must be same number of path's
         if (requestPaths.length != consumerPaths.length) {
             return false;
         }
@@ -67,7 +86,7 @@ public class JettyRestServletResolveConsumerStrategy extends 
HttpServletResolveC
             String p1 = requestPaths[i];
             String p2 = consumerPaths[i];
 
-            if (p2.equals("*")) {
+            if (p2.startsWith("{") && p2.endsWith("}")) {
                 // always matches
                 continue;
             }
@@ -81,21 +100,4 @@ public class JettyRestServletResolveConsumerStrategy 
extends HttpServletResolveC
         return true;
     }
 
-    protected String normalizePath(String path) {
-        StringBuilder sb = new StringBuilder();
-        String[] paths = path.split("/");
-        for (String s : paths) {
-            if (ObjectHelper.isEmpty(s)) {
-                continue;
-            }
-            sb.append("/");
-            if (s.startsWith("{") && s.endsWith("}")) {
-                sb.append("*");
-            } else {
-                sb.append(s);
-            }
-        }
-        return sb.toString();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java
 
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java
new file mode 100644
index 0000000..df66449
--- /dev/null
+++ 
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.jetty.rest;
+
+import junit.framework.TestCase;
+import 
org.apache.camel.component.jetty.JettyRestServletResolveConsumerStrategy;
+
+public class RestPathMatchingTest extends TestCase {
+
+    private JettyRestServletResolveConsumerStrategy matcher = new 
JettyRestServletResolveConsumerStrategy();
+
+    public void testRestPathMatcher() throws Exception {
+        assertTrue(matcher.matchRestPath("/foo/", "/foo/"));
+        assertTrue(matcher.matchRestPath("/foo/", "foo/"));
+        assertTrue(matcher.matchRestPath("/foo/", "foo"));
+        assertTrue(matcher.matchRestPath("foo/", "foo"));
+        assertTrue(matcher.matchRestPath("foo", "foo"));
+        assertTrue(matcher.matchRestPath("foo/", "foo"));
+        assertTrue(matcher.matchRestPath("/foo/", "foo"));
+
+        assertTrue(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/1234/list/2014"));
+        assertTrue(matcher.matchRestPath("/foo/1234/list/2014/", 
"/foo/1234/list/2014"));
+        assertTrue(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/1234/list/2014/"));
+        assertTrue(matcher.matchRestPath("/foo/1234/list/2014/", 
"/foo/1234/list/2014/"));
+        assertTrue(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/{user}/list/{year}"));
+
+        assertFalse(matcher.matchRestPath("/foo/", "/bar/"));
+        assertFalse(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/1234/list/2015"));
+        assertFalse(matcher.matchRestPath("/foo/1234/list/2014/", 
"/foo/1234/list/2015"));
+        assertFalse(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/1234/list/2015/"));
+        assertFalse(matcher.matchRestPath("/foo/1234/list/2014/", 
"/foo/1234/list/2015/"));
+        assertFalse(matcher.matchRestPath("/foo/1234/list/2014", 
"/foo/{user}/list/"));
+
+        assertTrue(matcher.matchRestPath("/foo/1/list/2", 
"/foo/{user}/list/{year}"));
+        assertTrue(matcher.matchRestPath("/foo/1234567890/list/2", 
"/foo/{user}/list/{year}"));
+        assertTrue(matcher.matchRestPath("/foo/1234567890/list/1234567890", 
"/foo/{user}/list/{year}"));
+
+        assertTrue(matcher.matchRestPath("/123/list/2014", 
"/{user}/list/{year}"));
+        assertTrue(matcher.matchRestPath("/1234567890/list/2014", 
"/{user}/list/{year}"));
+    }
+}

Reply via email to