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 2013/04/10 18:46:11 UTC

svn commit: r1466559 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ rt/frontend/jaxrs/src/main/ja...

Author: sergeyb
Date: Wed Apr 10 16:46:10 2013
New Revision: 1466559

URL: http://svn.apache.org/r1466559
Log:
[CXF-4950] Updates to the way Accept and Produces values affect the selection of methods and response types, cleanup to follow

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
    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/utils/HttpUtils.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
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProviderTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth/src/main/java/org/apache/cxf/rs/security/oauth/services/AuthorizationRequestService.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProvider.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProvider.java Wed Apr 10 16:46:10 2013
@@ -22,6 +22,7 @@ package org.apache.cxf.jaxrs.impl;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.logging.Logger;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.PhaseInterceptorChain;
@@ -102,8 +104,12 @@ public class MediaTypeHeaderProvider imp
     public String toString(MediaType type) {
         return typeToString(type);
     }
-    
     public static String typeToString(MediaType type) {
+        return typeToString(type, null);
+    }
+    // Max number of parameters that may be ignored is 3, at least as known 
+    // to the implementation
+    public static String typeToString(MediaType type, List<String> ignoreParams) {
         StringBuilder sb = new StringBuilder();
         sb.append(type.getType()).append('/').append(type.getSubtype());
         
@@ -112,6 +118,9 @@ public class MediaTypeHeaderProvider imp
             for (Iterator<Map.Entry<String, String>> iter = params.entrySet().iterator();
                 iter.hasNext();) {
                 Map.Entry<String, String> entry = iter.next();
+                if (ignoreParams != null && ignoreParams.contains(entry.getKey())) {
+                    continue;
+                }
                 sb.append(';').append(entry.getKey()).append('=').append(entry.getValue());
             }
         }
@@ -121,9 +130,22 @@ public class MediaTypeHeaderProvider imp
 
     private static MediaType handleMediaTypeWithoutSubtype(String mType) {
         if (mType.startsWith(MediaType.MEDIA_TYPE_WILDCARD)) {
-            char next = mType.length() == 1 ? ' ' : mType.charAt(1);
-            if (next == ' ' || next == ';') {
-                return MediaType.WILDCARD_TYPE;
+            String mTypeNext = mType.length() == 1 ? "" : mType.substring(1).trim();
+            boolean mTypeNextEmpty = StringUtils.isEmpty(mTypeNext);
+            if (mTypeNextEmpty || mTypeNext.startsWith(";")) {
+                if (!mTypeNextEmpty) {
+                    Map<String, String> parameters = new LinkedHashMap<String, String>();
+                    StringTokenizer st = new StringTokenizer(mType.substring(2).trim(), ";");
+                    while (st.hasMoreTokens()) {
+                        addParameter(parameters, st.nextToken());
+                    }
+                    return new MediaType(MediaType.MEDIA_TYPE_WILDCARD,
+                                         MediaType.MEDIA_TYPE_WILDCARD,
+                                         parameters);
+                } else { 
+                    return MediaType.WILDCARD_TYPE;
+                }
+                
             }
         }
         Message message = PhaseInterceptorChain.getCurrentMessage();

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java Wed Apr 10 16:46:10 2013
@@ -388,8 +388,6 @@ public class JAXRSOutInterceptor extends
     private MediaType checkFinalContentType(MediaType mt) {
         if (mt.isWildcardType() || mt.isWildcardSubtype() && mt.getType().equals("application")) {
             return MediaType.APPLICATION_OCTET_STREAM_TYPE;
-        } else if (mt.getParameters().containsKey("q")) {
-            return JAXRSUtils.toMediaType(JAXRSUtils.removeMediaTypeParameter(mt, "q"));
         } else {
             return mt;
         }

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=1466559&r1=1466558&r2=1466559&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 Wed Apr 10 16:46:10 2013
@@ -193,14 +193,16 @@ public class OperationResourceInfo {
             }
         }
         if (produceMediaTypes != null) {
-            produceMimes = JAXRSUtils.sortMediaTypes(produceMediaTypes);
+            produceMimes = JAXRSUtils.sortMediaTypes(produceMediaTypes, JAXRSUtils.MEDIA_TYPE_QS_PARAM);
         } else {
             Produces pm = 
                 AnnotationUtils.getMethodAnnotation(annotatedMethod, Produces.class);
             if (pm != null) {
-                produceMimes = JAXRSUtils.sortMediaTypes(JAXRSUtils.getMediaTypes(pm.value()));
+                produceMimes = JAXRSUtils.sortMediaTypes(JAXRSUtils.getMediaTypes(pm.value()),
+                                                         JAXRSUtils.MEDIA_TYPE_QS_PARAM);
             } else if (classResourceInfo != null) {
-                produceMimes = JAXRSUtils.sortMediaTypes(classResourceInfo.getProduceMime());
+                produceMimes = JAXRSUtils.sortMediaTypes(classResourceInfo.getProduceMime(),
+                                                         JAXRSUtils.MEDIA_TYPE_QS_PARAM);
             }
         }
     }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java Wed Apr 10 16:46:10 2013
@@ -450,7 +450,7 @@ public final class HttpUtils {
                                  BUNDLE, enc, defaultEncoding).toString();
             LOG.warning(message);
             headers.putSingle(HttpHeaders.CONTENT_TYPE, 
-                JAXRSUtils.removeMediaTypeParameter(mt, CHARSET_PARAMETER) 
+                JAXRSUtils.mediaTypeToString(mt, CHARSET_PARAMETER) 
                 + ';' + CHARSET_PARAMETER + "=" 
                 + (defaultEncoding == null ? "UTF-8" : defaultEncoding));
         }

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=1466559&r1=1466558&r2=1466559&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 Apr 10 16:46:10 2013
@@ -160,6 +160,9 @@ public final class JAXRSUtils {
     public static final String ROOT_PROVIDER = "service.root.provider";
     public static final String DOC_LOCATION = "wadl.location";
     public static final String DEFAULT_PROVIDERS_FOR_SIMPLE_TYPES = "defaultProviders.for.simpleTypes";
+    public static final String MEDIA_TYPE_Q_PARAM = "q";
+    public static final String MEDIA_TYPE_QS_PARAM = "qs";
+    private static final String MEDIA_TYPE_DISTANCE_PARAM = "d";
     
     private static final Logger LOG = LogUtils.getL7dLogger(JAXRSUtils.class);
     private static final ResourceBundle BUNDLE = BundleUtils.getBundle(JAXRSUtils.class);
@@ -423,55 +426,61 @@ public final class JAXRSUtils {
                 
             }
             
-            boolean subresourcesOnly = true;
-            for (MediaType acceptType : acceptContentTypes) {
-                for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
-                    boolean added = false;
-                    
-                    URITemplate uriTemplate = ori.getURITemplate();
-                    MultivaluedMap<String, String> map = new MetadataMap<String, String>(values);
-                    if (uriTemplate != null && uriTemplate.match(path, map)) {
-                        if (ori.isSubResourceLocator()) {
-                            candidateList.put(ori, map);
-                            added = true;
-                        } else {
-                            String finalGroup = map.getFirst(URITemplate.FINAL_MATCH_GROUP);
-                            //CHECKSTYLE:OFF
-                            if (StringUtils.isEmpty(finalGroup) || PATH_SEGMENT_SEP.equals(finalGroup)) {
-                                pathMatched++;
-                                if (matchHttpMethod(ori.getHttpMethod(), httpMethod)) {
-                                    methodMatched++;
-                                    if (matchConsumeTypes(requestType, ori)) {
-                                        consumeMatched++;
+            for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
+                boolean added = false;
+                
+                URITemplate uriTemplate = ori.getURITemplate();
+                MultivaluedMap<String, String> map = new MetadataMap<String, String>(values);
+                if (uriTemplate != null && uriTemplate.match(path, map)) {
+                    if (ori.isSubResourceLocator()) {
+                        candidateList.put(ori, map);
+                        added = true;
+                    } else {
+                        String finalGroup = map.getFirst(URITemplate.FINAL_MATCH_GROUP);
+                        if (StringUtils.isEmpty(finalGroup) || PATH_SEGMENT_SEP.equals(finalGroup)) {
+                            pathMatched++;
+                            if (matchHttpMethod(ori.getHttpMethod(), httpMethod)) {
+                                methodMatched++;
+                                //CHECKSTYLE:OFF
+                                if (matchConsumeTypes(requestType, ori)) {
+                                    consumeMatched++;
+                                    for (MediaType acceptType : acceptContentTypes) {
                                         MediaType pMediaType = matchProduceTypes(acceptType, ori);
                                         if (pMediaType != null) {
-                                            map.putSingle(Message.CONTENT_TYPE, mediaTypeToString(pMediaType));
+                                            if (acceptContentTypes.size() > 1 
+                                                || ori.getProduceTypes().size() > 1) {
+                                                pMediaType = intersectSortMediaTypes(acceptContentTypes,
+                                                                                     ori.getProduceTypes(),
+                                                                                     false).get(0);
+                                            }
+                                            map.putSingle(Message.CONTENT_TYPE, 
+                                                          mediaTypeToString(pMediaType, 
+                                                                            MEDIA_TYPE_Q_PARAM, 
+                                                                            MEDIA_TYPE_QS_PARAM));
                                             
-                                            subresourcesOnly = false;
                                             candidateList.put(ori, map);
                                             added = true;
+                                            break;
                                         }
                                     }
                                 }
+                                //CHECKSTYLE:ON
                             }
-                            //CHECKSTYLE:ON
-                        }
-                    } 
-                    if (isFineLevelLoggable) {
-                        if (added) {
-                            LOG.fine(new org.apache.cxf.common.i18n.Message("OPER_SELECTED_POSSIBLY", 
-                                      BUNDLE, 
-                                      ori.getMethodToInvoke().getName()).toString());
-                        } else {
-                            logNoMatchMessage(ori, path, httpMethod, requestType, acceptContentTypes);
                         }
                     }
-                }
-                if (!candidateList.isEmpty() && !subresourcesOnly) {
-                    break;
+                } 
+                if (isFineLevelLoggable) {
+                    if (added) {
+                        LOG.fine(new org.apache.cxf.common.i18n.Message("OPER_SELECTED_POSSIBLY", 
+                                  BUNDLE, 
+                                  ori.getMethodToInvoke().getName()).toString());
+                    } else {
+                        logNoMatchMessage(ori, path, httpMethod, requestType, acceptContentTypes);
+                    }
                 }
             }
         }
+        
         if (!candidateList.isEmpty()) {
             Map.Entry<OperationResourceInfo, MultivaluedMap<String, String>> firstEntry = 
                 candidateList.entrySet().iterator().next();
@@ -535,6 +544,35 @@ public final class JAXRSUtils {
         
     }    
 
+    private static List<MediaType> intersectSortMediaTypes(List<MediaType> acceptTypes,
+                                                           List<MediaType> producesTypes,
+                                                           final boolean checkDistance) {
+        List<MediaType> all = intersectMimeTypes(acceptTypes, producesTypes, true, checkDistance);
+        if (all.size() > 1) {
+            Collections.sort(all, new Comparator<MediaType>() {
+
+                public int compare(MediaType mt1, MediaType mt2) {
+                    return compareQualityAndDistance(mt1, mt2, checkDistance);
+                }
+                
+            });    
+        }
+        return all;
+    }
+    
+    private static int compareQualityAndDistance(MediaType mt1, MediaType mt2, boolean checkDistance) {
+        int result = compareMediaTypesQualityFactors(mt1, mt2, MEDIA_TYPE_Q_PARAM);
+        if (result == 0) {
+            result = compareMediaTypesQualityFactors(mt1, mt2, MEDIA_TYPE_QS_PARAM);
+        }
+        if (result == 0 && checkDistance) {
+            Integer dist1 = Integer.valueOf(mt1.getParameters().get(MEDIA_TYPE_DISTANCE_PARAM));
+            Integer dist2 = Integer.valueOf(mt2.getParameters().get(MEDIA_TYPE_DISTANCE_PARAM));
+            result = dist1.compareTo(dist2);
+        }
+        return result;
+    }
+    
     private static String getCurrentPath(MultivaluedMap<String, String> values) {
         String path = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         return path == null ?  "/" : path;
@@ -631,8 +669,17 @@ public final class JAXRSUtils {
     
     public static int compareSortedAcceptMediaTypes(List<MediaType> mts1, List<MediaType> mts2, 
                                                     List<MediaType> acceptTypes) {
-        //TODO: discard incompatible accept types
-        return compareSortedMediaTypes(mts1, mts2);
+        List<MediaType> actualMts1 = intersectSortMediaTypes(mts1, acceptTypes, true);
+        List<MediaType> actualMts2 = intersectSortMediaTypes(mts2, acceptTypes, true);
+        int size1 = mts1.size();
+        int size2 = mts2.size();
+        for (int i = 0; i < size1 && i < size2; i++) {
+            int result = compareQualityAndDistance(actualMts1.get(i), actualMts2.get(i), true);
+            if (result != 0) {
+                return result;
+            }
+        }
+        return size1 == size2 ? 0 : size1 < size2 ? -1 : 1;
     }
     
     private static List<MediaType> getCompatibleMediaTypes(List<MediaType> mts, MediaType ct) {
@@ -651,7 +698,7 @@ public final class JAXRSUtils {
     }
     
     public static int compareSortedMediaTypes(List<MediaType> mts1, List<MediaType> mts2) {
-        return compareSortedMediaTypes(mts1, mts2, "q");
+        return compareSortedMediaTypes(mts1, mts2, MEDIA_TYPE_Q_PARAM);
     }
     
     public static int compareSortedMediaTypes(List<MediaType> mts1, List<MediaType> mts2, String qs) {
@@ -666,7 +713,7 @@ public final class JAXRSUtils {
         return size1 == size2 ? 0 : size1 < size2 ? -1 : 1;
     }
     public static int compareMediaTypes(MediaType mt1, MediaType mt2) {
-        return compareMediaTypes(mt1, mt2, "q");
+        return compareMediaTypes(mt1, mt2, MEDIA_TYPE_Q_PARAM);
     }
     public static int compareMediaTypes(MediaType mt1, MediaType mt2, String qs) {
         
@@ -692,8 +739,8 @@ public final class JAXRSUtils {
     }
     
     public static int compareMediaTypesQualityFactors(MediaType mt1, MediaType mt2) {
-        float q1 = getMediaTypeQualityFactor(mt1.getParameters().get("q"));
-        float q2 = getMediaTypeQualityFactor(mt2.getParameters().get("q"));
+        float q1 = getMediaTypeQualityFactor(mt1.getParameters().get(MEDIA_TYPE_Q_PARAM));
+        float q2 = getMediaTypeQualityFactor(mt2.getParameters().get(MEDIA_TYPE_Q_PARAM));
         return Float.compare(q1, q2) * -1;
     }
     
@@ -1394,6 +1441,12 @@ public final class JAXRSUtils {
     public static List<MediaType> intersectMimeTypes(List<MediaType> requiredMediaTypes, 
                                                      List<MediaType> userMediaTypes,
                                                      boolean addRequiredParamsIfPossible) {
+        return intersectMimeTypes(requiredMediaTypes, userMediaTypes, addRequiredParamsIfPossible, false);
+    }
+    public static List<MediaType> intersectMimeTypes(List<MediaType> requiredMediaTypes, 
+                                                     List<MediaType> userMediaTypes,
+                                                     boolean addRequiredParamsIfPossible,
+                                                     boolean addDistanceParameter) {
         Set<MediaType> supportedMimeTypeList = new LinkedHashSet<MediaType>();
 
         for (MediaType requiredType : requiredMediaTypes) {
@@ -1411,11 +1464,12 @@ public final class JAXRSUtils {
                     if (!parametersMatched) {
                         continue;
                     }
-                   
-                    String type = requiredType.getType().equals(MediaType.MEDIA_TYPE_WILDCARD) 
-                                      ? userType.getType() : requiredType.getType();
-                    String subtype = requiredType.getSubtype().startsWith(MediaType.MEDIA_TYPE_WILDCARD) 
-                                      ? userType.getSubtype() : requiredType.getSubtype();
+                    boolean requiredTypeWildcard = requiredType.getType().equals(MediaType.MEDIA_TYPE_WILDCARD);
+                    boolean requiredSubTypeWildcard = requiredType.getSubtype().contains(MediaType.MEDIA_TYPE_WILDCARD);
+                    
+                    String type = requiredTypeWildcard ? userType.getType() : requiredType.getType();
+                    String subtype = requiredSubTypeWildcard ? userType.getSubtype() : requiredType.getSubtype();
+                    
                     Map<String, String> parameters = userType.getParameters();
                     if (addRequiredParamsIfPossible) {
                         parameters = new LinkedHashMap<String, String>(parameters);
@@ -1425,6 +1479,16 @@ public final class JAXRSUtils {
                             }
                         }
                     }
+                    if (addDistanceParameter) {
+                        int distance = 0;
+                        if (requiredTypeWildcard) {
+                            distance++;
+                        }
+                        if (requiredSubTypeWildcard) {
+                            distance++;
+                        }
+                        parameters.put(MEDIA_TYPE_DISTANCE_PARAM, Integer.toString(distance));
+                    }
                     supportedMimeTypeList.add(new MediaType(type, subtype, parameters));
                 }
             }
@@ -1488,7 +1552,7 @@ public final class JAXRSUtils {
         return sortMediaTypes(JAXRSUtils.parseMediaTypes(mediaTypes), qs);
     }
     public static List<MediaType> sortMediaTypes(List<MediaType> types) {
-        return sortMediaTypes(types, "q");
+        return sortMediaTypes(types, MEDIA_TYPE_Q_PARAM);
     }
     public static List<MediaType> sortMediaTypes(List<MediaType> types, final String qs) {
         if (types.size() > 1) {
@@ -1563,19 +1627,6 @@ public final class JAXRSUtils {
         
     }
     
-    public static String removeMediaTypeParameter(MediaType mt, String paramName) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(mt.getType()).append('/').append(mt.getSubtype());
-        if (mt.getParameters().size() > 1) {
-            for (String key : mt.getParameters().keySet()) {
-                if (!paramName.equals(key)) {
-                    sb.append(';').append(key).append('=').append(mt.getParameters().get(key));
-                }
-            }
-        }    
-        return sb.toString();
-    }
-        
     public static boolean propogateException(Message m) {
         
         Object value = m.getContextualProperty(PROPAGATE_EXCEPTION);
@@ -1650,8 +1701,11 @@ public final class JAXRSUtils {
         }
     }
     
-    public static String mediaTypeToString(MediaType mt) {
-        return MediaTypeHeaderProvider.typeToString(mt);
+    public static String mediaTypeToString(MediaType mt, String... ignoreParams) {
+        List<String> list = ignoreParams == null || ignoreParams.length == 0 ? null 
+            : Arrays.asList(ignoreParams);
+            
+        return MediaTypeHeaderProvider.typeToString(mt, list);
     }
     
     public static MediaType toMediaType(String value) {

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=1466559&r1=1466558&r2=1466559&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 Wed Apr 10 16:46:10 2013
@@ -26,12 +26,14 @@ import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.jaxrs.fortest.BookEntity;
@@ -243,6 +245,129 @@ public class SelectMethodCandidatesTest 
     }
     
     @Test
+    public void testResponseType1() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m1", 
+                               "application/xml", "application/xml", "m1");
+    }
+    
+    @Test
+    public void testResponseType2() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m1", 
+                               "application/*,application/json", 
+                               "application/json", "m1");
+    }
+    @Test
+    public void testResponseType3() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m1", 
+                               "text/xml, application/xml;q=0.8,application/json;q=0.4", 
+                               "application/xml", "m1");
+    }
+    
+    @Test
+    public void testResponseType4() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m1", 
+                               "text/xml, application/xml;q=0.8,application/json;q=0.4", 
+                               "application/xml", "m1");
+    }
+    
+    @Test
+    public void testResponseType5() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m2", 
+                               "text/xml, application/xml;q=0.3,application/json;q=0.4", 
+                               "application/json", "m2");
+    }
+    
+    @Test
+    public void testResponseType6() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m3", 
+                               "text/*,application/json;q=0.4", 
+                               "text/xml", "m3");
+    }
+    
+    @Test
+    public void testResponseType7() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m3", 
+                               "text/*,application/json", 
+                               "application/json", "m3");
+    }
+    
+    @Test
+    public void testResponseType8() throws Exception {
+        doTestProducesResource(ResponseMediaTypeResource.class, "/m4", 
+                               "application/*", "application/xml", "m4");
+    }
+    
+    @Test
+    public void testProducesResource1() throws Exception {
+        doTestProducesResource(ProducesResource1.class, "/", 
+                               "text/plain, application/xml", 
+                               "application/xml", "m2");
+    }
+    
+    @Test
+    public void testProducesResource2() throws Exception {
+        doTestProducesResource(ProducesResource1.class, "/", 
+                               "text/plain, application/xml;q=0.8", 
+                               "text/plain", "m1");
+    }
+    
+    @Test
+    public void testProducesResource3() throws Exception {
+        doTestProducesResource(ProducesResource2.class, "/", 
+                               "application/*", 
+                               "application/json", "m1");
+    }
+    
+    @Test
+    public void testProducesResource4() throws Exception {
+        doTestProducesResource(ProducesResource2.class, "/", 
+                               "application/xml,application/json;q=0.9", 
+                               "application/xml", "m2");
+    }
+    
+    private void doTestProducesResource(Class<?> resourceClass, 
+                                        String path,
+                                        String acceptContentTypes,
+                                        String expectedResponseType,
+                                        String expectedMethodName) throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(resourceClass);
+        sf.create();
+        List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        String contentType = "*/*";
+        
+        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>();
+        Map<ClassResourceInfo, MultivaluedMap<String, String>> mResources 
+            = JAXRSUtils.selectResourceClass(resources, path, m);
+     
+        OperationResourceInfo ori = JAXRSUtils.findTargetMethod(mResources, m, "GET", 
+                                                values, contentType, 
+                                                JAXRSUtils.sortMediaTypes(acceptContentTypes));
+        assertNotNull(ori);
+        assertEquals(expectedMethodName,  ori.getMethodToInvoke().getName());
+        assertEquals(expectedResponseType, m.getExchange().get(Message.CONTENT_TYPE));
+    }
+    
+    @Test
     public void testRootResourcesWithSameName() throws Exception {
         doTestRootResourcesWithSameName("/a/books", "put", RootResource.class);
         doTestRootResourcesWithSameName("/a1/books", "put", RootResource.class);
@@ -498,7 +623,7 @@ public class SelectMethodCandidatesTest 
         List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
         
         String contentTypes = "*/*";
-        String acceptContentTypes = "application/bar,application/foo";
+        String acceptContentTypes = "application/bar,application/foo;q=0.8";
         
         MetadataMap<String, String> values = new MetadataMap<String, String>();
         OperationResourceInfo ori = findTargetResourceClass(resources, null, 
@@ -509,7 +634,7 @@ public class SelectMethodCandidatesTest 
         
         assertNotNull(ori);
         assertEquals("readBar", ori.getMethodToInvoke().getName());
-        acceptContentTypes = "application/foo,application/bar";
+        acceptContentTypes = "application/foo,application/bar;q=0.8";
         ori = findTargetResourceClass(resources, null, 
                                       "/1/2/3/d/custom",
                                       "GET",
@@ -670,4 +795,55 @@ public class SelectMethodCandidatesTest 
         }
     }
     
+    public static class ResponseMediaTypeResource {
+        @GET
+        @Path("m1")
+        @Produces({"application/json", "application/xml" })
+        public Response m1() {
+            return null;
+        }
+        @GET
+        @Path("m2")
+        @Produces({"application/*" })
+        public Response m2() {
+            return null;
+        }
+        @GET
+        @Path("m3")
+        @Produces({"application/json", "text/xml", "application/xml" })
+        public Response m3() {
+            return null;
+        }
+        @GET
+        @Path("m4")
+        @Produces({"application/json;qs=0.9", "application/xml" })
+        public Response m4() {
+            return null;
+        }
+    }
+    
+    public static class ProducesResource1 {
+        @GET
+        @Produces({"text/*" })
+        public Response m1() {
+            return null;
+        }
+        @GET
+        @Produces({"application/xml" })
+        public Response m2() {
+            return null;
+        }
+    }
+    public static class ProducesResource2 {
+        @GET
+        @Produces({"application/json" })
+        public Response m1() {
+            return null;
+        }
+        @GET
+        @Produces({"application/xml;qs=0.9" })
+        public Response m2() {
+            return null;
+        }
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProviderTest.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProviderTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MediaTypeHeaderProviderTest.java Wed Apr 10 16:46:10 2013
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.jaxrs.impl;
 
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -54,21 +55,21 @@ public class MediaTypeHeaderProviderTest
     public void testShortWildcardWithParameters() {
         MediaType m = MediaType.valueOf("*;q=0.2");
         assertEquals("Media type was not parsed correctly", 
-                     m, new MediaType("*", "*"));
+                     m, new MediaType("*", "*", Collections.singletonMap("q", "0.2")));
     }
     
     @Test
     public void testShortWildcardWithParameters2() {
         MediaType m = MediaType.valueOf("* ;q=0.2");
         assertEquals("Media type was not parsed correctly", 
-                     m, new MediaType("*", "*"));
+                     m, new MediaType("*", "*", Collections.singletonMap("q", "0.2")));
     }
     
     @Test
     public void testShortWildcardWithParameters3() {
         MediaType m = MediaType.valueOf("*; q=.2");
         assertEquals("Media type was not parsed correctly", 
-                     m, new MediaType("*", "*"));
+                     m, new MediaType("*", "*", Collections.singletonMap("q", ".2")));
     }
     
     @Test

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=1466559&r1=1466558&r2=1466559&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 Apr 10 16:46:10 2013
@@ -318,7 +318,7 @@ public class JAXRSUtilsTest extends Asse
         //method is declared with a most specific ProduceMime type is selected.
         OperationResourceInfo ori = findTargetResourceClass(resources, createMessage2(), 
              "/bookstore/1/books/123/", "GET", new MetadataMap<String, String>(), contentTypes, 
-             getTypes("application/json,application/xml"));       
+             getTypes("application/json,application/xml;q=0.9"));       
         assertNotNull(ori);
         assertEquals("getBookJSON", ori.getMethodToInvoke().getName());
         
@@ -1491,12 +1491,12 @@ public class JAXRSUtilsTest extends Asse
         
         ori = JAXRSUtils.findTargetMethod(getMap(cri), createMessage2(), "GET", new MetadataMap<String, String>(), 
                                           "*/*", 
-                                          JAXRSUtils.sortMediaTypes(getTypes("*,text/plain,text/xml")));
+                                          JAXRSUtils.sortMediaTypes(getTypes("*/*;q=0.1,text/plain,text/xml;q=0.8")));
                      
         assertSame(ori, ori2);
         ori = JAXRSUtils.findTargetMethod(getMap(cri), createMessage2(), "GET", new MetadataMap<String, String>(), 
                                           "*/*", 
-                                          JAXRSUtils.sortMediaTypes(getTypes("*,text/plain, text/xml,x/y")));
+                                          JAXRSUtils.sortMediaTypes(getTypes("*;q=0.1,text/plain,text/xml;q=0.9,x/y")));
                      
         assertSame(ori, ori2);
     }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth/src/main/java/org/apache/cxf/rs/security/oauth/services/AuthorizationRequestService.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth/src/main/java/org/apache/cxf/rs/security/oauth/services/AuthorizationRequestService.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth/src/main/java/org/apache/cxf/rs/security/oauth/services/AuthorizationRequestService.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth/src/main/java/org/apache/cxf/rs/security/oauth/services/AuthorizationRequestService.java Wed Apr 10 16:46:10 2013
@@ -61,8 +61,8 @@ public class AuthorizationRequestService
     @Path("/decision")
     @Produces({"application/xhtml+xml", 
                "text/html", 
-               "application/xml;q=0.9", 
-               "application/json;q=0.9",
+               "application/xml;qs=0.9", 
+               "application/json;qs=0.9",
                "application/x-www-form-urlencoded" })
     public Response authorizeDecision() {
         return authorize();
@@ -73,8 +73,8 @@ public class AuthorizationRequestService
     @Consumes("application/x-www-form-urlencoded")
     @Produces({"application/xhtml+xml", 
                "text/html", 
-               "application/xml;q=0.9", 
-               "application/json;q=0.9",
+               "application/xml;qs=0.9", 
+               "application/json;qs=0.9",
                "application/x-www-form-urlencoded" })
     public Response authorizeDecisionForm() {
         return authorizeDecision();

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=1466559&r1=1466558&r2=1466559&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Wed Apr 10 16:46:10 2013
@@ -1357,7 +1357,7 @@ public class JAXRSClientServerBookTest e
         
         getAndCompareAsStrings("http://localhost:" + PORT + "/bookstore/books/123",
                                "resources/expected_get_book123json.txt",
-                               "application/json, application/xml", 
+                               "application/json, application/xml;q=0.9", 
                                "application/json", 200);
         
         getAndCompareAsStrings("http://localhost:" + PORT + "/bookstore/books/123",