You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2008/07/09 19:50:13 UTC

svn commit: r675267 - in /cxf/trunk/rt/frontend/jaxrs/src: main/java/org/apache/cxf/jaxrs/model/ main/java/org/apache/cxf/jaxrs/utils/ test/java/org/apache/cxf/jaxrs/impl/ test/java/org/apache/cxf/jaxrs/model/ test/java/org/apache/cxf/jaxrs/resources/ ...

Author: sergeyb
Date: Wed Jul  9 10:50:13 2008
New Revision: 675267

URL: http://svn.apache.org/viewvc?rev=675267&view=rev
Log:
JAX-RS : Fixing the resource class selection issue

Added:
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfoComparator.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookInterface.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfoComparator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfoComparator.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfoComparator.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfoComparator.java Wed Jul  9 10:50:13 2008
@@ -36,6 +36,13 @@
             return e1.getHttpMethod() != null ? -1 : 1;
         }
         
+        String l1 = e1.getURITemplate().getLiteralChars();
+        String l2 = e2.getURITemplate().getLiteralChars();
+        if (!l1.equals(l2)) {
+            // descending order 
+            return l1.length() < l2.length() ? 1 : -1; 
+        }
+                
         if (e1.getHttpMethod() == null && e2.getHttpMethod() == null) {
             // with two subresource locators, those with more capturing groups win
             int g1 = e1.getURITemplate().getNumberOfGroups();
@@ -58,14 +65,6 @@
                                                 mimeTypeP2.get(0));
         }
         
-        if (result == 0 && e1.getHttpMethod() != null && e2.getHttpMethod() != null) {
-            // we're comparing two resource methods with matching http methods and produce/consume types
-            int g1 = e1.getURITemplate().getNumberOfGroups();
-            int g2 = e2.getURITemplate().getNumberOfGroups();
-            // ascending order 
-            return g1 < g2 ? -1 : g1 > g2 ? 1 : 0;  
-        }
-
         return result;
     }
 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java Wed Jul  9 10:50:13 2008
@@ -40,28 +40,33 @@
     /**
      * The regular expression for matching URI templates and names.
      */
-    private static final Pattern TEMPLATE_NAMES_PATTERN = Pattern.compile("\\{([\\w-\\._~]+?)\\}");
+    private static final Pattern TEMPLATE_NAMES_PATTERN = Pattern.compile("\\{([a-zA-Z0-9][-\\w.]*)\\}");
 
     /**
      * A URI template is converted into a regular expression by substituting
      * (.*?) for each occurrence of {\([w- 14 \. ]+?\)} within the URL
      * template
      */
-    private static final String URITEMPLATE_VARIABLE_REGEX = "(.*?)";
+    private static final String PATH_VARIABLE_REGEX = "([^/]+?)";
+    private static final String PATH_UNLIMITED_VARIABLE_REGEX = "(.*?)";
 
     private final String template;
-    private final String regexSuffix;
+    private final boolean limited;
+    private final boolean encoded;
     private final List<String> templateVariables;
     private final Pattern templateRegexPattern;
+    private final String literals;
 
     public URITemplate(String theTemplate) {
-        this(theTemplate, null);
+        this(theTemplate, true, false);
     }
     
-    public URITemplate(String theTemplate, String theRegexSuffix) {
+    public URITemplate(String theTemplate, boolean limited, boolean encoded) {
         this.template = theTemplate;
-        this.regexSuffix = theRegexSuffix;
-
+        this.limited = limited;
+        this.encoded = encoded;
+        
+        StringBuilder literalChars = new StringBuilder();
         StringBuilder stringBuilder = new StringBuilder();
         List<String> names = new ArrayList<String>();
 
@@ -69,27 +74,45 @@
         Matcher matcher = TEMPLATE_NAMES_PATTERN.matcher(template);
         int i = 0;
         while (matcher.find()) {
+            literalChars.append(template.substring(i, matcher.start()));
             copyURITemplateCharacters(template, i, matcher.start(), stringBuilder);
-            stringBuilder.append(URITEMPLATE_VARIABLE_REGEX);
-            names.add(matcher.group(1));
             i = matcher.end();
+            if (!limited && i == template.length()) {
+                stringBuilder.append(PATH_UNLIMITED_VARIABLE_REGEX);
+            } else {
+                stringBuilder.append(PATH_VARIABLE_REGEX);
+            }
+            names.add(matcher.group(1));
         }
+        literalChars.append(template.substring(i, template.length()));
         copyURITemplateCharacters(template, i, template.length(), stringBuilder);
 
+        literals = literalChars.toString();
         templateVariables = Collections.unmodifiableList(names);
 
         int endPos = stringBuilder.length() - 1;
         boolean endsWithSlash = (endPos >= 0) ? stringBuilder.charAt(endPos) == '/' : false;
-        if (regexSuffix != null) {
-            if (endsWithSlash) {
-                stringBuilder.deleteCharAt(endPos);
-            }
-            stringBuilder.append(regexSuffix);
+        
+        if (endsWithSlash) {
+            stringBuilder.deleteCharAt(endPos);
         }
-
+        stringBuilder.append(limited ? LIMITED_REGEX_SUFFIX : UNLIMITED_REGEX_SUFFIX);
+        
         templateRegexPattern = Pattern.compile(stringBuilder.toString());
     }
 
+    public boolean isLimited() {
+        return limited;
+    }
+    
+    public boolean encode() {
+        return encoded;
+    }
+    
+    public String getLiteralChars() {
+        return literals;
+    }
+    
     public String getValue() {
         return template;
     }
@@ -132,10 +155,10 @@
         }
 
         // The right hand side value, might be used to further resolve sub-resources.
-        if (regexSuffix != null) {
-            String finalGroup = m.group(i);
-            templateVariableToValue.putSingle(FINAL_MATCH_GROUP, finalGroup == null ? "/" : finalGroup);
-        }
+        
+        String finalGroup = m.group(i);
+        templateVariableToValue.putSingle(FINAL_MATCH_GROUP, finalGroup == null ? "/" : finalGroup);
+        
 
         return true;
     }
@@ -144,7 +167,7 @@
                                              Path path) {
         
         if (path == null) {
-            return new URITemplate("/", URITemplate.LIMITED_REGEX_SUFFIX);
+            return new URITemplate("/");
         }
         
         String pathValue = path.value();
@@ -152,9 +175,6 @@
             pathValue = "/" + pathValue;
         }
         
-        String suffixPattern = (path.limited())
-            ? URITemplate.LIMITED_REGEX_SUFFIX : URITemplate.UNLIMITED_REGEX_SUFFIX;
-        
-        return new URITemplate(pathValue, suffixPattern);
+        return new URITemplate(pathValue, path.limited(), path.encode());
     }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Wed Jul  9 10:50:13 2008
@@ -179,6 +179,14 @@
                 new Comparator<ClassResourceInfo>() {
 
                     public int compare(ClassResourceInfo cr1, ClassResourceInfo cr2) {
+                        
+                        String l1 = cr1.getURITemplate().getLiteralChars();
+                        String l2 = cr2.getURITemplate().getLiteralChars();
+                        if (!l1.equals(l2)) {
+                            // descending order 
+                            return l1.length() < l2.length() ? 1 : -1; 
+                        }
+                        
                         int g1 = cr1.getURITemplate().getNumberOfGroups();
                         int g2 = cr2.getURITemplate().getNumberOfGroups();
                         // descending order 

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java Wed Jul  9 10:50:13 2008
@@ -122,7 +122,7 @@
         
         // with suffix
         values.clear();
-        new URITemplate("/bar", URITemplate.UNLIMITED_REGEX_SUFFIX).match("/bar", values);
+        new URITemplate("/bar", false, false).match("/bar", values);
         
         u = new UriInfoImpl(mockMessage("http://localhost:8080/baz", "/bar"),
                                         values);

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java Wed Jul  9 10:50:13 2008
@@ -36,7 +36,7 @@
     @Test
     public void testMatchBasic() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{id}",
-                                                  URITemplate.UNLIMITED_REGEX_SUFFIX);
+                                                  false, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/customers/123/", values);
@@ -48,7 +48,7 @@
     @Test
     public void testMatchBasicTwoParametersVariation1() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{name}/{department}",
-                                                  URITemplate.UNLIMITED_REGEX_SUFFIX);
+                                                  false, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/customers/john/CS", values);
@@ -62,7 +62,7 @@
     @Test
     public void testMatchBasicTwoParametersVariation2() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/name/{name}/dep/{department}",
-                                                  URITemplate.UNLIMITED_REGEX_SUFFIX);
+                                                  false, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/customers/name/john/dep/CS", values);
@@ -76,7 +76,7 @@
     @Test
     public void testURITemplateWithSubResource() throws Exception {
         //So "/customers" is the URITemplate for the root resource class
-        URITemplate uriTemplate = new URITemplate("/customers", URITemplate.LIMITED_REGEX_SUFFIX);
+        URITemplate uriTemplate = new URITemplate("/customers", true, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/customers/123", values);
@@ -88,7 +88,7 @@
     @Test
     public void testURITemplateWithSubResourceVariation2() throws Exception {
         //So "/customers" is the URITemplate for the root resource class
-        URITemplate uriTemplate = new URITemplate("/customers", URITemplate.LIMITED_REGEX_SUFFIX);
+        URITemplate uriTemplate = new URITemplate("/customers", true, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/customers/name/john/dep/CS", values);
@@ -103,7 +103,7 @@
      * public Book getBook(@UriParam("bookId") String id)
      */
     public void testURITemplateWithSubResourceVariation3() throws Exception {
-        URITemplate uriTemplate = new URITemplate("/books/{bookId}/", URITemplate.LIMITED_REGEX_SUFFIX);
+        URITemplate uriTemplate = new URITemplate("/books/{bookId}/", true, false);
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
         
         boolean match = uriTemplate.match("/books/123/chapter/1", values);

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookInterface.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookInterface.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookInterface.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookInterface.java Wed Jul  9 10:50:13 2008
@@ -33,6 +33,6 @@
     @ConsumeMime("text/foo2")
     String getAuthor();
     
-    @Path("/books/{bookId}/")
+    @Path("/books/{bookId}")
     Book getBook(@PathParam("bookId") String id);
 }

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java?rev=675267&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java Wed Jul  9 10:50:13 2008
@@ -0,0 +1,31 @@
+/**
+ * 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.cxf.jaxrs.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("{id}")
+public class TestResourceTemplate1 {
+    @GET
+    public String get() {
+        return null;
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate1.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java?rev=675267&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java Wed Jul  9 10:50:13 2008
@@ -0,0 +1,31 @@
+/**
+ * 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.cxf.jaxrs.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("{id}/foo")
+public class TestResourceTemplate2 {
+    @GET
+    public String get() {
+        return null;
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/TestResourceTemplate2.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java?rev=675267&r1=675266&r2=675267&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Wed Jul  9 10:50:13 2008
@@ -87,7 +87,7 @@
         
         bStore = JAXRSUtils.selectResourceClass(resources, "/bookstore/", map);
         assertEquals(bStore.getResourceClass(), 
-                     org.apache.cxf.jaxrs.resources.BookStoreNoSubResource.class);
+                     org.apache.cxf.jaxrs.resources.BookStore.class);
         
         bStore = JAXRSUtils.selectResourceClass(resources, "/bookstore/bar", map);
         assertEquals(bStore.getResourceClass(), 
@@ -95,6 +95,30 @@
     }
     
     @Test
+    public void testSelectBetweenMultipleResourceClasses2() throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(org.apache.cxf.jaxrs.resources.TestResourceTemplate1.class,
+                              org.apache.cxf.jaxrs.resources.TestResourceTemplate2.class);
+        sf.create();        
+        List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        MultivaluedMap<String, String> map = new MetadataMap<String, String>();
+        ClassResourceInfo bStore = JAXRSUtils.selectResourceClass(resources, "/1", map);
+        assertEquals(bStore.getResourceClass(), org.apache.cxf.jaxrs.resources.TestResourceTemplate1.class);
+        
+        bStore = JAXRSUtils.selectResourceClass(resources, "/1/", map);
+        assertEquals(bStore.getResourceClass(), 
+                     org.apache.cxf.jaxrs.resources.TestResourceTemplate1.class);
+        
+        bStore = JAXRSUtils.selectResourceClass(resources, "/1/foo", map);
+        assertEquals(bStore.getResourceClass(), 
+                     org.apache.cxf.jaxrs.resources.TestResourceTemplate2.class);
+        
+        bStore = JAXRSUtils.selectResourceClass(resources, "/1/foo/bar", map);
+        assertEquals(bStore.getResourceClass(), 
+                     org.apache.cxf.jaxrs.resources.TestResourceTemplate2.class);
+    }
+    
+    @Test
     public void testFindTargetResourceClass() throws Exception {
         JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
         sf.setResourceClasses(org.apache.cxf.jaxrs.resources.BookStoreNoSubResource.class);