cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r1466096 - 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/
Date Tue, 09 Apr 2013 16:12:08 GMT
Author: sergeyb
Date: Tue Apr  9 16:12:07 2013
New Revision: 1466096

URL: http://svn.apache.org/r1466096
Log:
[CXF-4950] Some updates to the way Consumes annotated methods are selected

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java
    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/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java?rev=1466096&r1=1466095&r2=1466096&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java
(original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java
Tue Apr  9 16:12:07 2013
@@ -182,14 +182,14 @@ public class OperationResourceInfo {
     private void checkMediaTypes(String consumeMediaTypes,
                                  String produceMediaTypes) {
         if (consumeMediaTypes != null) {
-            consumeMimes = JAXRSUtils.sortMediaTypes(consumeMediaTypes);
+            consumeMimes = JAXRSUtils.sortMediaTypes(consumeMediaTypes, null);
         } else {
             Consumes cm = 
                 AnnotationUtils.getMethodAnnotation(annotatedMethod, Consumes.class);
             if (cm != null) {
-                consumeMimes = JAXRSUtils.sortMediaTypes(JAXRSUtils.getMediaTypes(cm.value()));
+                consumeMimes = JAXRSUtils.sortMediaTypes(JAXRSUtils.getMediaTypes(cm.value()),
null);
             } else if (classResourceInfo != null) {
-                consumeMimes = JAXRSUtils.sortMediaTypes(classResourceInfo.getConsumeMime());
+                consumeMimes = JAXRSUtils.sortMediaTypes(classResourceInfo.getConsumeMime(),
null);
             }
         }
         if (produceMediaTypes != null) {

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=1466096&r1=1466095&r2=1466096&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
Tue Apr  9 16:12:07 2013
@@ -20,6 +20,9 @@
 package org.apache.cxf.jaxrs.model;
 
 import java.util.Comparator;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
 
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.jaxrs.ext.ResourceComparator;
@@ -31,9 +34,14 @@ public class OperationResourceInfoCompar
     private static final String HEAD_METHOD = "HEAD";
     private boolean headMethod;
     private Message message;
-    private ResourceComparator rc;    
+    private ResourceComparator rc;  
+    private MediaType contentType;
+    private List<MediaType> acceptTypes;
 
-    public OperationResourceInfoComparator(Message m, String method) {
+    public OperationResourceInfoComparator(Message m, 
+                                           String method, 
+                                           MediaType contentType,
+                                           List<MediaType> acceptTypes) {
         this.message = m;
         if (message != null) {
             Object o = m.getExchange().get(Endpoint.class).get("org.apache.cxf.jaxrs.comparator");
@@ -42,6 +50,8 @@ public class OperationResourceInfoCompar
             }
         }
         headMethod = HEAD_METHOD.equals(method);
+        this.contentType = contentType;
+        this.acceptTypes = acceptTypes;
     }
     
     public int compare(OperationResourceInfo e1, OperationResourceInfo e2) {
@@ -73,15 +83,17 @@ public class OperationResourceInfoCompar
         
         if (result == 0) {
         
-            result = JAXRSUtils.compareSortedMediaTypes(
+            result = JAXRSUtils.compareSortedConsumesMediaTypes(
                           e1.getConsumeTypes(), 
-                          e2.getConsumeTypes());
+                          e2.getConsumeTypes(),
+                          contentType);
         }
         
         if (result == 0) {
             //use the media type of output data as the secondary key.
-            result = JAXRSUtils.compareSortedMediaTypes(e1.getProduceTypes(), 
-                                                        e2.getProduceTypes());
+            result = JAXRSUtils.compareSortedAcceptMediaTypes(e1.getProduceTypes(), 
+                                                              e2.getProduceTypes(),
+                                                              acceptTypes);
         }
         
         return result;

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=1466096&r1=1466095&r2=1466096&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 Tue
Apr  9 16:12:07 2013
@@ -36,6 +36,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.ResourceBundle;
@@ -395,15 +396,14 @@ public final class JAXRSUtils {
                 
         MediaType requestType;
         try {
-            requestType = requestContentType == null
-                                ? ALL_TYPES : toMediaType(requestContentType);
+            requestType = toMediaType(requestContentType);
         } catch (IllegalArgumentException ex) {
             throw new NotSupportedException(ex);
         }
         
         SortedMap<OperationResourceInfo, MultivaluedMap<String, String>> candidateList
= 
             new TreeMap<OperationResourceInfo, MultivaluedMap<String, String>>(
-                new OperationResourceInfoComparator(message, httpMethod));
+                new OperationResourceInfoComparator(message, httpMethod, requestType, acceptContentTypes));
 
         int pathMatched = 0;
         int methodMatched = 0;
@@ -623,36 +623,72 @@ public final class JAXRSUtils {
                           : getMediaTypes(pm.value());
     }
     
+    public static int compareSortedConsumesMediaTypes(List<MediaType> mts1, List<MediaType>
mts2, MediaType ct) {
+        List<MediaType> actualMts1 = getCompatibleMediaTypes(mts1, ct);
+        List<MediaType> actualMts2 = getCompatibleMediaTypes(mts2, ct);
+        return compareSortedMediaTypes(actualMts1, actualMts2, null);
+    }
+    
+    public static int compareSortedAcceptMediaTypes(List<MediaType> mts1, List<MediaType>
mts2, 
+                                                    List<MediaType> acceptTypes) {
+        //TODO: discard incompatible accept types
+        return compareSortedMediaTypes(mts1, mts2);
+    }
+    
+    private static List<MediaType> getCompatibleMediaTypes(List<MediaType> mts,
MediaType ct) {
+        List<MediaType> actualMts;
+        if (mts.size() == 1) {
+            actualMts = mts;
+        } else {
+            actualMts = new LinkedList<MediaType>();
+            for (MediaType mt : mts) {
+                if (isMediaTypeCompatible(mt, ct)) {
+                    actualMts.add(mt);    
+                }
+            }
+        }
+        return actualMts;
+    }
+    
     public static int compareSortedMediaTypes(List<MediaType> mts1, List<MediaType>
mts2) {
+        return compareSortedMediaTypes(mts1, mts2, "q");
+    }
+    
+    public static int compareSortedMediaTypes(List<MediaType> mts1, List<MediaType>
mts2, String qs) {
         int size1 = mts1.size();
         int size2 = mts2.size();
         for (int i = 0; i < size1 && i < size2; i++) {
-            int result = compareMediaTypes(mts1.get(i), mts2.get(i));
+            int result = compareMediaTypes(mts1.get(i), mts2.get(i), qs);
             if (result != 0) {
                 return result;
             }
         }
         return size1 == size2 ? 0 : size1 < size2 ? -1 : 1;
     }
-    
     public static int compareMediaTypes(MediaType mt1, MediaType mt2) {
+        return compareMediaTypes(mt1, mt2, "q");
+    }
+    public static int compareMediaTypes(MediaType mt1, MediaType mt2, String qs) {
         
-        if (mt1.isWildcardType() && !mt2.isWildcardType()) {
+        boolean mt1TypeWildcard = mt1.isWildcardType();
+        boolean mt2TypeWildcard = mt2.isWildcardType();
+        if (mt1TypeWildcard && !mt2TypeWildcard) {
             return 1;
         }
-        if (!mt1.isWildcardType() && mt2.isWildcardType()) {
+        if (!mt1TypeWildcard && mt2TypeWildcard) {
             return -1;
         }
          
-        
-        if (mt1.isWildcardSubtype() && !mt2.isWildcardSubtype()) {
+        boolean mt1SubTypeWildcard = mt1.getSubtype().contains(MediaType.MEDIA_TYPE_WILDCARD);
+        boolean mt2SubTypeWildcard = mt2.getSubtype().contains(MediaType.MEDIA_TYPE_WILDCARD);
+        if (mt1SubTypeWildcard && !mt2SubTypeWildcard) {
             return 1;
         }
-        if (!mt1.isWildcardSubtype() && mt2.isWildcardSubtype()) {
+        if (!mt1SubTypeWildcard && mt2SubTypeWildcard) {
             return -1;
         }       
         
-        return compareMediaTypesQualityFactors(mt1, mt2);
+        return qs != null ? compareMediaTypesQualityFactors(mt1, mt2, qs) : 0;
     }
     
     public static int compareMediaTypesQualityFactors(MediaType mt1, MediaType mt2) {
@@ -661,6 +697,11 @@ public final class JAXRSUtils {
         return Float.compare(q1, q2) * -1;
     }
     
+    public static int compareMediaTypesQualityFactors(MediaType mt1, MediaType mt2, String
qs) {
+        float q1 = getMediaTypeQualityFactor(mt1.getParameters().get(qs));
+        float q2 = getMediaTypeQualityFactor(mt2.getParameters().get(qs));
+        return Float.compare(q1, q2) * -1;
+    }
 
     public static float getMediaTypeQualityFactor(String q) {
         if (q == null) {
@@ -1357,31 +1398,7 @@ public final class JAXRSUtils {
 
         for (MediaType requiredType : requiredMediaTypes) {
             for (MediaType userType : userMediaTypes) {
-                boolean isCompatible = 
-                    requiredType.isCompatible(userType) || userType.isCompatible(requiredType);
-                if (!isCompatible && requiredType.getType().equalsIgnoreCase(userType.getType()))
{
-                    // check if we have composite subtypes
-                    String subType1 = requiredType.getSubtype();
-                    String subType2 = userType.getSubtype();
-                    
-                    String subTypeAfterPlus1 = splitMediaSubType(subType1, true); 
-                    String subTypeAfterPlus2 = splitMediaSubType(subType2, true);
-                    
-                    if (subTypeAfterPlus1 != null && subTypeAfterPlus2 != null) {
-                    
-                        isCompatible = subTypeAfterPlus1.equalsIgnoreCase(subTypeAfterPlus2)
-                            && (subType1.charAt(0) == '*' || subType2.charAt(0) ==
'*');
-                        
-                        if (!isCompatible) {
-                            String subTypeBeforePlus1 = splitMediaSubType(subType1, false);
-                            String subTypeBeforePlus2 = splitMediaSubType(subType2, false);
-                            
-                            isCompatible = subTypeBeforePlus1.equalsIgnoreCase(subTypeBeforePlus2)
-                                && (subType1.charAt(subType1.length() - 1) == '*'

-                                    || subType2.charAt(subType2.length() - 1) == '*');
-                        }
-                    }
-                }
+                boolean isCompatible = isMediaTypeCompatible(requiredType, userType);
                 if (isCompatible) {
                     boolean parametersMatched = true;
                     for (Map.Entry<String, String> entry : userType.getParameters().entrySet())
{
@@ -1417,6 +1434,34 @@ public final class JAXRSUtils {
         
     }
     
+    private static boolean isMediaTypeCompatible(MediaType requiredType, MediaType userType)
{
+        boolean isCompatible = requiredType.isCompatible(userType);
+        if (!isCompatible && requiredType.getType().equalsIgnoreCase(userType.getType()))
{
+            // check if we have composite subtypes
+            String subType1 = requiredType.getSubtype();
+            String subType2 = userType.getSubtype();
+            
+            String subTypeAfterPlus1 = splitMediaSubType(subType1, true); 
+            String subTypeAfterPlus2 = splitMediaSubType(subType2, true);
+            
+            if (subTypeAfterPlus1 != null && subTypeAfterPlus2 != null) {
+            
+                isCompatible = subTypeAfterPlus1.equalsIgnoreCase(subTypeAfterPlus2)
+                    && (subType1.charAt(0) == '*' || subType2.charAt(0) == '*');
+                
+                if (!isCompatible) {
+                    String subTypeBeforePlus1 = splitMediaSubType(subType1, false);
+                    String subTypeBeforePlus2 = splitMediaSubType(subType2, false);
+                    
+                    isCompatible = subTypeBeforePlus1.equalsIgnoreCase(subTypeBeforePlus2)
+                        && (subType1.charAt(subType1.length() - 1) == '*' 
+                            || subType2.charAt(subType2.length() - 1) == '*');
+                }
+            }
+        }
+        return isCompatible;
+    }
+    
     private static String splitMediaSubType(String type, boolean after) {
         int index = type.indexOf('+');
         return index == -1 ? null : after ? type.substring(index + 1) : type.substring(0,
index);
@@ -1439,12 +1484,18 @@ public final class JAXRSUtils {
         return sortMediaTypes(JAXRSUtils.parseMediaTypes(mediaTypes));
     }
     
+    public static List<MediaType> sortMediaTypes(String mediaTypes, String qs) {
+        return sortMediaTypes(JAXRSUtils.parseMediaTypes(mediaTypes), qs);
+    }
     public static List<MediaType> sortMediaTypes(List<MediaType> types) {
+        return sortMediaTypes(types, "q");
+    }
+    public static List<MediaType> sortMediaTypes(List<MediaType> types, final
String qs) {
         if (types.size() > 1) {
             Collections.sort(types, new Comparator<MediaType>() {
 
                 public int compare(MediaType mt1, MediaType mt2) {
-                    return JAXRSUtils.compareMediaTypes(mt1, mt2);
+                    return JAXRSUtils.compareMediaTypes(mt1, mt2, qs);
                 }
                 
             });
@@ -1604,7 +1655,11 @@ public final class JAXRSUtils {
     }
     
     public static MediaType toMediaType(String value) {
-        return MediaTypeHeaderProvider.valueOf(value);
+        if (value == null) {
+            return ALL_TYPES;
+        } else {
+            return MediaTypeHeaderProvider.valueOf(value);
+        }
     }
     
     public static Response toResponse(int status) {

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java?rev=1466096&r1=1466095&r2=1466096&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
(original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
Tue Apr  9 16:12:07 2013
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -182,6 +183,66 @@ public class SelectMethodCandidatesTest 
     }
     
     @Test
+    public void testConsumesResource1() throws Exception {
+        doTestConsumesResource(ConsumesResource1.class, "text/xml", "m2");
+    }
+    @Test
+    public void testConsumesResource2() throws Exception {
+        doTestConsumesResource(ConsumesResource2.class, "m1");
+    }
+    @Test
+    public void testConsumesResource3() throws Exception {
+        doTestConsumesResource(ConsumesResource3.class, "m1");
+    }
+    @Test
+    public void testConsumesResource4() throws Exception {
+        doTestConsumesResource(ConsumesResource4.class, "application/xml+bar", "m2");
+    }
+    
+    private void doTestConsumesResource(Class<?> resourceClass, String expectedMethodName)
throws Exception {
+        doTestConsumesResource(resourceClass, null, expectedMethodName);
+    }
+    private void doTestConsumesResource(Class<?> resourceClass, String ct, 
+                                        String expectedMethodName) throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(resourceClass);
+        sf.create();
+        List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        String contentType = ct == null ? "application/xml" : ct;
+        String acceptContentTypes = "*/*";
+        
+        Message m = new MessageImpl();
+        m.put(Message.CONTENT_TYPE, contentType);
+        Exchange ex = new ExchangeImpl();
+        ex.setInMessage(m);
+        m.setExchange(ex);
+        Endpoint e = EasyMock.createMock(Endpoint.class);
+        e.isEmpty();
+        EasyMock.expectLastCall().andReturn(true).anyTimes();
+        e.size();
+        EasyMock.expectLastCall().andReturn(0).anyTimes();
+        e.getEndpointInfo();
+        EasyMock.expectLastCall().andReturn(null).anyTimes();
+        e.get(ServerProviderFactory.class.getName());
+        EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(2);
+        e.get("org.apache.cxf.jaxrs.comparator");
+        EasyMock.expectLastCall().andReturn(null);
+        EasyMock.replay(e);
+        ex.put(Endpoint.class, e);
+        
+        MetadataMap<String, String> values = new MetadataMap<String, String>();
+        OperationResourceInfo ori = findTargetResourceClass(resources, 
+                                                            m, 
+                                                            "/",
+                                                            "POST",
+                                                            values, 
+                                                            contentType, 
+                                                            JAXRSUtils.sortMediaTypes(acceptContentTypes));
+        assertNotNull(ori);
+        assertEquals(expectedMethodName,  ori.getMethodToInvoke().getName());
+    }
+    
+    @Test
     public void testRootResourcesWithSameName() throws Exception {
         doTestRootResourcesWithSameName("/a/books", "put", RootResource.class);
         doTestRootResourcesWithSameName("/a1/books", "put", RootResource.class);
@@ -559,4 +620,54 @@ public class SelectMethodCandidatesTest 
             
         }
     }
+    
+    public static class ConsumesResource1 {
+        @POST
+        @Consumes({"application/xml", "text/*" })
+        public void m1() {
+            
+        }
+        @POST
+        @Consumes({"application/xml", "text/xml" })
+        public void m2() {
+            
+        }
+    }
+    public static class ConsumesResource2 {
+        @POST
+        @Consumes({"application/*", "text/xml" })
+        public void m2() {
+            
+        }
+        @POST
+        @Consumes({"text/*", "application/xml" })
+        public void m1() {
+            
+        }
+    }
+    public static class ConsumesResource3 {
+        @POST
+        @Consumes({"application/*" })
+        public void m2() {
+            
+        }
+        @POST
+        @Consumes({"application/xml" })
+        public void m1() {
+            
+        }
+    }
+    public static class ConsumesResource4 {
+        @POST
+        @Consumes({"application/xml", "application/xml+*" })
+        public void m1() {
+            
+        }
+        @POST
+        @Consumes({"application/*", "application/xml+bar" })
+        public void m2() {
+            
+        }
+    }
+    
 }



Mime
View raw message