You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by am...@apache.org on 2017/11/14 17:49:14 UTC

[cxf] branch master updated: [CXF-7553] Consider the req headers' quality factors in selectVariant

This is an automated email from the ASF dual-hosted git repository.

amccright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new aa7cbcd  [CXF-7553] Consider the req headers' quality factors in selectVariant
aa7cbcd is described below

commit aa7cbcdbe33f36ea398835350088994071172ade
Author: Andy McCright <j....@gmail.com>
AuthorDate: Wed Nov 8 11:05:03 2017 -0600

    [CXF-7553] Consider the req headers' quality factors in selectVariant
    
    The Request.selectVariant method should return one of the passed-in
    Variants that is closest to the variant (combination of Accept,
    Accept-Language and Accept-Encoding headers with quality factors
    included).
    
    # Conflicts:
    #	rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java
    #	rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestImplTest.java
---
 .../org/apache/cxf/jaxrs/impl/RequestImpl.java     | 99 +++++++++++-----------
 .../org/apache/cxf/jaxrs/impl/RequestImplTest.java | 28 ++++++
 2 files changed, 79 insertions(+), 48 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java
index bb99409..9190eb0 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java
@@ -68,45 +68,59 @@ public class RequestImpl implements Request {
         List<Locale> acceptLangs = headers.getAcceptableLanguages();
         List<String> acceptEncs = parseAcceptEnc(
             headers.getRequestHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING));
-
+        List<Variant> requestVariants = sortAllCombinations(acceptMediaTypes, acceptLangs, acceptEncs);
         List<Object> varyValues = new LinkedList<Object>();
+        for (Variant requestVar : requestVariants) {
+            for (Variant var : vars) {
+                MediaType mt = var.getMediaType();
+                Locale lang = var.getLanguage();
+                String enc = var.getEncoding();
+
+                boolean mtMatched = mt == null || requestVar.getMediaType().isCompatible(mt);
+                if (mtMatched) {
+                    handleVaryValues(varyValues, HttpHeaders.ACCEPT);
+                }
 
-        List<Variant> matchingVars = new LinkedList<Variant>();
-        for (Variant var : vars) {
-            MediaType mt = var.getMediaType();
-            Locale lang = var.getLanguage();
-            String enc = var.getEncoding();
-
-            boolean mtMatched = mt == null || acceptMediaTypes.isEmpty()
-                || JAXRSUtils.intersectMimeTypes(acceptMediaTypes, mt).size() != 0;
-            if (mtMatched) {
-                handleVaryValues(varyValues, HttpHeaders.ACCEPT);
-            }
+                boolean langMatched = lang == null || isLanguageMatched(requestVar.getLanguage(), lang);
+                if (langMatched) {
+                    handleVaryValues(varyValues, HttpHeaders.ACCEPT_LANGUAGE);
+                }
 
-            boolean langMatched = lang == null || acceptLangs.isEmpty()
-                || isLanguageMatched(acceptLangs, lang);
-            if (langMatched) {
-                handleVaryValues(varyValues, HttpHeaders.ACCEPT_LANGUAGE);
-            }
+                boolean encMatched = acceptEncs.isEmpty() || enc == null 
+                    || isEncMatached(requestVar.getEncoding(), enc);
+                if (encMatched) {
+                    handleVaryValues(varyValues, HttpHeaders.ACCEPT_ENCODING);
+                }
 
-            boolean encMatched = acceptEncs.isEmpty() || enc == null
-                || isEncMatached(acceptEncs, enc);
-            if (encMatched) {
-                handleVaryValues(varyValues, HttpHeaders.ACCEPT_ENCODING);
+                if (mtMatched && encMatched && langMatched) {
+                    addVaryHeader(varyValues);
+                    return var;
+                }
             }
+        }
+        return null;
+    }
 
-            if (mtMatched && encMatched && langMatched) {
-                matchingVars.add(var);
+    private static List<Variant> sortAllCombinations(List<MediaType> mediaTypes,
+                                                     List<Locale> langs,
+                                                     List<String> encs) {
+        List<Variant> requestVars = new LinkedList<>();
+        for (MediaType mt : mediaTypes) {
+            for (Locale lang : langs) {
+                if (encs.size() < 1) {
+                    requestVars.add(new Variant(mt, lang, null));
+                } else {
+                    for (String enc : encs) {
+                        requestVars.add(new Variant(mt, lang, enc));
+                    }
+                }
             }
         }
-        if (!matchingVars.isEmpty()) {
-            addVaryHeader(varyValues);
-            Collections.sort(matchingVars, new VariantComparator());
-            return matchingVars.get(0);
-        }
-        return null;
+        Collections.sort(requestVars, VariantComparator.INSTANCE);
+        return requestVars;
     }
 
+
     private static void handleVaryValues(List<Object> varyValues, String ...values) {
         for (String v : values) {
             if (v != null && !varyValues.contains(v)) {
@@ -136,28 +150,15 @@ public class RequestImpl implements Request {
         }
     }
 
-    private static boolean isLanguageMatched(List<Locale> locales, Locale l) {
+    private static boolean isLanguageMatched(Locale locale, Locale l) {
 
-        for (Locale locale : locales) {
-            String language = locale.getLanguage();
-            if ("*".equals(language)
-                || language.equalsIgnoreCase(l.getLanguage())) {
-                return true;
-            }
-        }
-        return false;
+        String language = locale.getLanguage();
+        return "*".equals(language) 
+            || language.equalsIgnoreCase(l.getLanguage());
     }
 
-    private static boolean isEncMatached(List<String> accepts, String enc) {
-        if (accepts.contains(enc)) {
-            return true;
-        }
-        for (String accept : accepts) {
-            if ("*".equals(accept)) {
-                return true;
-            }
-        }
-        return false;
+    private static boolean isEncMatached(String accepts, String enc) {
+        return accepts == null || "*".equals(accepts) || accepts.contains(enc);
     }
 
     private static List<String> parseAcceptEnc(String acceptEnc) {
@@ -339,6 +340,8 @@ public class RequestImpl implements Request {
 
     private static class VariantComparator implements Comparator<Variant> {
 
+        static final VariantComparator INSTANCE = new VariantComparator();
+
         public int compare(Variant v1, Variant v2) {
             int result = compareMediaTypes(v1.getMediaType(), v2.getMediaType());
 
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestImplTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestImplTest.java
index 2a435a0..ae21c97 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestImplTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestImplTest.java
@@ -145,6 +145,34 @@ public class RequestImplTest extends Assert {
         assertSame(var3, new RequestImpl(m).selectVariant(list));
     }
 
+    @Test
+    public void testMultipleVariantsBestMatchMediaTypeQualityFactors() {
+        metadata.putSingle(HttpHeaders.ACCEPT, "a/b;q=0.6, c/d;q=0.5, e/f+json");
+        metadata.putSingle(HttpHeaders.ACCEPT_LANGUAGE, "en-us");
+        metadata.putSingle(HttpHeaders.ACCEPT_ENCODING, "gzip;q=1.0, compress");
+
+        List<Variant> list = new ArrayList<Variant>();
+        Variant var1 = new Variant(MediaType.valueOf("a/b"), new Locale("en"), "gzip");
+        Variant var2 = new Variant(MediaType.valueOf("x/z"), new Locale("en"), "gzip");
+        Variant var3 = new Variant(MediaType.valueOf("e/f+json"), new Locale("en"), "gzip");
+        Variant var4 = new Variant(MediaType.valueOf("c/d"), new Locale("en"), "gzip");
+        list.add(var1);
+        list.add(var2);
+        list.add(var3);
+        list.add(var4);
+        assertSame(var3, new RequestImpl(m).selectVariant(list));
+
+        list.clear();
+        list.add(var1);
+        list.add(var4);
+        assertSame(var1, new RequestImpl(m).selectVariant(list));
+
+        list.clear();
+        list.add(var2);
+        list.add(var4);
+        assertSame(var4, new RequestImpl(m).selectVariant(list));
+    }
+
     private void assertSameVariant(MediaType mt, Locale lang, String enc) {
         Variant var = new Variant(mt, lang, enc);
         List<Variant> list = new ArrayList<>();

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <co...@cxf.apache.org>'].