Author: markt Date: Fri Aug 15 07:34:43 2014 New Revision: 1618112 URL: http://svn.apache.org/r1618112 Log: Need to put all locales in order before adding them to the locales collection - not just those from the first header.
Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1618112&r1=1618111&r2=1618112&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Fri Aug 15 07:34:43 2014 @@ -3086,26 +3086,33 @@ public class Request localesParsed = true; + // Store the accumulated languages that have been requested in + // a local collection, sorted by the quality value (so we can + // add Locales in descending order). The values will be ArrayLists + // containing the corresponding Locales to be added + TreeMap<Double, ArrayList<Locale>> locales = new TreeMap<>(); + Enumeration<String> values = getHeaders("accept-language"); while (values.hasMoreElements()) { String value = values.nextElement(); - parseLocalesHeader(value); + parseLocalesHeader(value, locales); } + // Process the quality values in highest->lowest order (due to + // negating the Double value when creating the key) + for (ArrayList<Locale> list : locales.values()) { + for (Locale locale : list) { + addLocale(locale); + } + } } /** * Parse accept-language header value. */ - protected void parseLocalesHeader(String value) { - - // Store the accumulated languages that have been requested in - // a local collection, sorted by the quality value (so we can - // add Locales in descending order). The values will be ArrayLists - // containing the corresponding Locales to be added - TreeMap<Double, ArrayList<Locale>> locales = new TreeMap<>(); + protected void parseLocalesHeader(String value, TreeMap<Double, ArrayList<Locale>> locales) { // Preprocess the value to remove all whitespace int white = value.indexOf(' '); @@ -3200,17 +3207,7 @@ public class Request locales.put(key, values); } values.add(locale); - - } - - // Process the quality values in highest->lowest order (due to - // negating the Double value when creating the key) - for (ArrayList<Locale> list : locales.values()) { - for (Locale locale : list) { - addLocale(locale); - } } - } Modified: tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java?rev=1618112&r1=1618111&r2=1618112&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java (original) +++ tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java Fri Aug 15 07:34:43 2014 @@ -27,6 +27,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.Locale; import java.util.TreeMap; import javax.servlet.ServletException; @@ -39,8 +40,8 @@ import static org.junit.Assert.assertNot import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.junit.Assert; import org.junit.Test; - import org.apache.catalina.Context; import org.apache.catalina.authenticator.BasicAuthenticator; import org.apache.catalina.filters.FailedRequestFilter; @@ -795,4 +796,35 @@ public class TestRequest extends TomcatB resp.getWriter().print(req.getContextPath()); } } + + @Test + public void getLocaleMultipleHeaders01() throws Exception { + TesterRequest req = new TesterRequest(); + + req.addHeader("accept-language", "en;q=0.5"); + req.addHeader("accept-language", "en-gb"); + + Locale actual = req.getLocale(); + Locale expected = Locale.forLanguageTag("en-gb"); + + Assert.assertEquals(expected, actual); + } + + /* + * Reverse header order of getLocaleMultipleHeaders01() and make sure the + * result is the same. + */ + @Test + public void getLocaleMultipleHeaders02() throws Exception { + TesterRequest req = new TesterRequest(); + + req.addHeader("accept-language", "en-gb"); + req.addHeader("accept-language", "en;q=0.5"); + + Locale actual = req.getLocale(); + Locale expected = Locale.forLanguageTag("en-gb"); + + Assert.assertEquals(expected, actual); + } + } Modified: tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java?rev=1618112&r1=1618111&r2=1618112&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java (original) +++ tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java Fri Aug 15 07:34:43 2014 @@ -16,6 +16,13 @@ */ package org.apache.catalina.connector; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class TesterRequest extends Request { @Override public String getScheme() { @@ -45,4 +52,31 @@ public class TesterRequest extends Reque public String getMethod() { return method; } + + private final Map<String,List<String>> headers = new HashMap<>(); + protected void addHeader(String name, String value) { + List<String> values = headers.get(name); + if (values == null) { + values = new ArrayList<>(); + headers.put(name, values); + } + values.add(value); + } + @Override + public String getHeader(String name) { + List<String> values = headers.get(name); + if (values == null || values.size() == 0) { + return null; + } + return values.get(0); + } + @Override + public Enumeration<String> getHeaders(String name) { + return Collections.enumeration(headers.get(name)); + } + + @Override + public Enumeration<String> getHeaderNames() { + return Collections.enumeration(headers.keySet()); + } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1618112&r1=1618111&r2=1618112&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Fri Aug 15 07:34:43 2014 @@ -136,6 +136,11 @@ <bug>56840</bug>: Avoid NPE when the rewrite valve is mapped to a context. (remm) </fix> + <fix> + Correctly handle multiple <code>accept-language</code> headers rather + than just using the first header to determine the user's preferred + Locale. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org