You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by bl...@apache.org on 2009/08/24 20:48:32 UTC
svn commit: r807336 - in /incubator/wink/trunk:
wink-common/src/main/java/org/apache/wink/common/internal/http/
wink-common/src/main/java/org/apache/wink/common/internal/providers/header/
wink-common/src/main/java/org/apache/wink/common/internal/runtim...
Author: bluk
Date: Mon Aug 24 18:48:31 2009
New Revision: 807336
URL: http://svn.apache.org/viewvc?rev=807336&view=rev
Log:
Request#selectVariant use Accept* request headers
See [WINK-107]
Added:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java (with props)
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java (with props)
incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java (with props)
Modified:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptLanguage.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptLanguageHeaderDelegate.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/runtime/RuntimeDelegateImpl.java
incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java
incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FlushResultHandler.java
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java?rev=807336&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java Mon Aug 24 18:48:31 2009
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.wink.common.internal.http;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.ws.rs.ext.RuntimeDelegate;
+import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+
+/**
+ * Represent HTTP Accept-Language header.
+ * <p>
+ * This version of the API does not support construction.
+ *
+ * @see <a href='http://tools.ietf.org/html/rfc2616#section-14.3'>RFC 2616
+ * 14.3</a>
+ */
+public class AcceptEncoding {
+
+ public static final class ValuedEncoding implements Comparable<ValuedEncoding> {
+ public final double qValue;
+ public final String encoding;
+
+ public ValuedEncoding(double qValue, String encoding) {
+ this.qValue = qValue;
+ this.encoding = encoding;
+ }
+
+ public int compareTo(ValuedEncoding other) {
+ return Double.compare(qValue, other.qValue);
+ }
+
+ public boolean isWildcard() {
+ return encoding == null;
+ }
+ }
+
+ private static final HeaderDelegate<AcceptEncoding> delegate =
+ RuntimeDelegate
+ .getInstance()
+ .createHeaderDelegate(AcceptEncoding.class);
+
+ private final String acceptEncodingHeader;
+ private final boolean anyAllowed;
+ private final List<String> acceptable;
+ private final List<String> banned;
+ private final List<AcceptEncoding.ValuedEncoding> valuedEncodings;
+
+ public AcceptEncoding(String acceptEncodingValue,
+ List<String> acceptableEncodings,
+ List<String> bannedEncodings,
+ boolean anyEncodingAllowed,
+ List<AcceptEncoding.ValuedEncoding> encodings) {
+ this.acceptEncodingHeader = acceptEncodingValue;
+ this.anyAllowed = anyEncodingAllowed;
+ this.acceptable = Collections.unmodifiableList(acceptableEncodings);
+ this.banned = Collections.unmodifiableList(bannedEncodings);
+ this.valuedEncodings = Collections.unmodifiableList(encodings);
+ }
+
+ public List<String> getAcceptableEncodings() {
+ return acceptable;
+ }
+
+ /**
+ * Is any encoding acceptable? Note that expresions are listed by
+ * {@link #getBannedLanguages()}. This means that the value contains
+ * wildcard (with non-zero priority) or the header is not present at all.
+ *
+ * @return <code>true</code> if any encoding is acceptable
+ */
+ public boolean isAnyEncodingAllowed() {
+ return anyAllowed;
+ }
+
+ public List<String> getBannedEncodings() {
+ return banned;
+ }
+
+ public static AcceptEncoding valueOf(String value) throws IllegalArgumentException {
+ return delegate.fromString(value);
+ }
+
+ public String getAcceptEncodingHeader() {
+ return acceptEncodingHeader;
+ }
+
+ public List<AcceptEncoding.ValuedEncoding> getValuedEncodings() {
+ return valuedEncodings;
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString(this);
+ }
+}
Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptEncoding.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptLanguage.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptLanguage.java?rev=807336&r1=807335&r2=807336&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptLanguage.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/http/AcceptLanguage.java Mon Aug 24 18:48:31 2009
@@ -37,6 +37,24 @@
*/
public class AcceptLanguage {
+ public static final class ValuedLocale implements Comparable<ValuedLocale> {
+ public final double qValue;
+ public final Locale locale;
+
+ public ValuedLocale(double qValue, Locale locale) {
+ this.qValue = qValue;
+ this.locale = locale;
+ }
+
+ public int compareTo(ValuedLocale other) {
+ return Double.compare(qValue, other.qValue);
+ }
+
+ public boolean isWildcard() {
+ return locale == null;
+ }
+ }
+
private static final HeaderDelegate<AcceptLanguage> delegate =
RuntimeDelegate
.getInstance()
@@ -46,15 +64,18 @@
private final boolean anyAllowed;
private final List<Locale> acceptable;
private final List<Locale> banned;
+ private final List<AcceptLanguage.ValuedLocale> valuedLocales;
public AcceptLanguage(String acceptLanguageValue,
List<Locale> acceptableLanguages,
List<Locale> bannedLanguages,
- boolean anyLanguageAllowed) {
+ boolean anyLanguageAllowed,
+ List<AcceptLanguage.ValuedLocale> valuedLocales) {
this.acceptLanguageHeader = acceptLanguageValue;
this.anyAllowed = anyLanguageAllowed;
this.acceptable = Collections.unmodifiableList(acceptableLanguages);
this.banned = Collections.unmodifiableList(bannedLanguages);
+ this.valuedLocales = Collections.unmodifiableList(valuedLocales);
}
// /**
@@ -203,6 +224,10 @@
return acceptLanguageHeader;
}
+ public List<AcceptLanguage.ValuedLocale> getValuedLocales() {
+ return valuedLocales;
+ }
+
@Override
public String toString() {
return delegate.toString(this);
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java?rev=807336&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java Mon Aug 24 18:48:31 2009
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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.wink.common.internal.providers.header;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+
+import org.apache.wink.common.internal.http.AcceptEncoding;
+
+public class AcceptEncodingHeaderDelegate implements HeaderDelegate<AcceptEncoding> {
+
+ public AcceptEncoding fromString(String value) throws IllegalArgumentException {
+ List<String> acceptable = new LinkedList<String>();
+ List<String> banned = new LinkedList<String>();
+ boolean anyAllowed = (value == null);
+
+ // parse the Accept-Encoding header
+ List<AcceptEncoding.ValuedEncoding> vEncodings = parseAcceptEncoding(value);
+
+ for (AcceptEncoding.ValuedEncoding qEncoding : vEncodings) {
+ if (anyAllowed) {
+ if (qEncoding.qValue == 0 && !qEncoding.isWildcard()) {
+ banned.add(qEncoding.encoding);
+ }
+ } else {
+ if (qEncoding.qValue == 0) {
+ break; // gone through all acceptable languages
+ }
+ if (qEncoding.isWildcard()) {
+ anyAllowed = true;
+ } else {
+ acceptable.add(qEncoding.encoding);
+ }
+ }
+ }
+ return new AcceptEncoding(value, acceptable, banned, anyAllowed, vEncodings);
+ }
+
+ private List<AcceptEncoding.ValuedEncoding> parseAcceptEncoding(String acceptableEncodingValue) {
+ List<AcceptEncoding.ValuedEncoding> qEncodings =
+ new LinkedList<AcceptEncoding.ValuedEncoding>();
+ if (acceptableEncodingValue == null) {
+ return qEncodings;
+ }
+
+ for (String encodingRange : acceptableEncodingValue.split(",")) {
+ int semicolonIndex = encodingRange.indexOf(';');
+ double qValue;
+ String encodingSpec;
+ if (semicolonIndex == -1) {
+ qValue = 1.0d;
+ encodingSpec = encodingRange;
+ } else {
+ encodingSpec = encodingRange.substring(0, semicolonIndex);
+ int equalsIndex = encodingRange.indexOf('=', semicolonIndex + 1);
+ String qString =
+ encodingRange.substring(equalsIndex != -1 ? equalsIndex + 1 : encodingRange
+ .length());
+ try {
+ qValue = Double.parseDouble(qString.trim());
+ } catch (NumberFormatException nfe) {
+ // silently ignore incorrect q-specification and assume 1
+ qValue = 1.0d;
+ }
+ }
+ encodingSpec = encodingSpec.trim();
+ if (encodingSpec.length() == 0) {
+ // ignore empty encoding specifications
+ continue;
+ } else if (encodingSpec.equals("*")) {
+ qEncodings.add(new AcceptEncoding.ValuedEncoding(qValue, null));
+ } else {
+ qEncodings.add(new AcceptEncoding.ValuedEncoding(qValue, encodingSpec));
+ }
+ }
+ Collections.sort(qEncodings, Collections.reverseOrder());
+ return qEncodings;
+ }
+
+ public String toString(AcceptEncoding value) {
+ return value.getAcceptEncodingHeader();
+ }
+}
Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptEncodingHeaderDelegate.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptLanguageHeaderDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptLanguageHeaderDelegate.java?rev=807336&r1=807335&r2=807336&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptLanguageHeaderDelegate.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptLanguageHeaderDelegate.java Mon Aug 24 18:48:31 2009
@@ -38,9 +38,9 @@
boolean anyAllowed = (value == null);
// parse the Accept-Language header
- List<ValuedLocale> qLocales = parseAcceptLanguage(value);
+ List<AcceptLanguage.ValuedLocale> qLocales = parseAcceptLanguage(value);
- for (ValuedLocale qLocale : qLocales) {
+ for (AcceptLanguage.ValuedLocale qLocale : qLocales) {
if (anyAllowed) {
if (qLocale.qValue == 0 && !qLocale.isWildcard()) {
banned.add(qLocale.locale);
@@ -56,11 +56,11 @@
}
}
}
- return new AcceptLanguage(value, acceptable, banned, anyAllowed);
+ return new AcceptLanguage(value, acceptable, banned, anyAllowed, qLocales);
}
- private List<ValuedLocale> parseAcceptLanguage(String acceptLanguageValue) {
- List<ValuedLocale> qLocales = new LinkedList<ValuedLocale>();
+ private List<AcceptLanguage.ValuedLocale> parseAcceptLanguage(String acceptLanguageValue) {
+ List<AcceptLanguage.ValuedLocale> qLocales = new LinkedList<AcceptLanguage.ValuedLocale>();
if (acceptLanguageValue == null) {
return qLocales;
}
@@ -90,34 +90,16 @@
// ignore empty language specifications
continue;
} else if (languageSpec.equals("*")) {
- qLocales.add(new ValuedLocale(qValue, null));
+ qLocales.add(new AcceptLanguage.ValuedLocale(qValue, null));
} else {
Locale newLocale = HeaderUtils.languageToLocale(languageSpec);
- qLocales.add(new ValuedLocale(qValue, newLocale));
+ qLocales.add(new AcceptLanguage.ValuedLocale(qValue, newLocale));
}
}
Collections.sort(qLocales, Collections.reverseOrder());
return qLocales;
}
- private static final class ValuedLocale implements Comparable<ValuedLocale> {
- final double qValue;
- final Locale locale;
-
- ValuedLocale(double qValue, Locale locale) {
- this.qValue = qValue;
- this.locale = locale;
- }
-
- public int compareTo(ValuedLocale other) {
- return Double.compare(qValue, other.qValue);
- }
-
- boolean isWildcard() {
- return locale == null;
- }
- }
-
public String toString(AcceptLanguage value) {
return value.getAcceptLanguageHeader();
}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/runtime/RuntimeDelegateImpl.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/runtime/RuntimeDelegateImpl.java?rev=807336&r1=807335&r2=807336&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/runtime/RuntimeDelegateImpl.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/runtime/RuntimeDelegateImpl.java Mon Aug 24 18:48:31 2009
@@ -38,9 +38,11 @@
import org.apache.wink.common.internal.UriBuilderImpl;
import org.apache.wink.common.internal.VariantListBuilderImpl;
import org.apache.wink.common.internal.http.Accept;
+import org.apache.wink.common.internal.http.AcceptEncoding;
import org.apache.wink.common.internal.http.AcceptLanguage;
import org.apache.wink.common.internal.http.ContentDispositionHeader;
import org.apache.wink.common.internal.http.EntityTagMatchHeader;
+import org.apache.wink.common.internal.providers.header.AcceptEncodingHeaderDelegate;
import org.apache.wink.common.internal.providers.header.AcceptHeaderDelegate;
import org.apache.wink.common.internal.providers.header.AcceptLanguageHeaderDelegate;
import org.apache.wink.common.internal.providers.header.CacheControlHeaderDelegate;
@@ -67,6 +69,7 @@
headerDelegates.put(EntityTagMatchHeader.class, new EntityTagMatchHeaderDelegate());
headerDelegates.put(Accept.class, new AcceptHeaderDelegate());
headerDelegates.put(AcceptLanguage.class, new AcceptLanguageHeaderDelegate());
+ headerDelegates.put(AcceptEncoding.class, new AcceptEncodingHeaderDelegate());
headerDelegates.put(ContentDispositionHeader.class, new ContentDispositionHeaderDelegate());
}
Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java?rev=807336&r1=807335&r2=807336&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java Mon Aug 24 18:48:31 2009
@@ -21,10 +21,11 @@
package org.apache.wink.server.internal.contexts;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.EntityTag;
@@ -37,6 +38,8 @@
import javax.ws.rs.ext.RuntimeDelegate;
import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+import org.apache.wink.common.internal.http.AcceptEncoding;
+import org.apache.wink.common.internal.http.AcceptLanguage;
import org.apache.wink.common.internal.http.EntityTagMatchHeader;
import org.apache.wink.server.handlers.MessageContext;
@@ -191,57 +194,225 @@
}
public Variant selectVariant(List<Variant> variants) throws IllegalArgumentException {
- MediaType inputMediaType = msgContext.getHttpHeaders().getMediaType();
- String inputEncoding =
- msgContext.getAttribute(HttpServletRequest.class).getCharacterEncoding();
- String inputLanguage = getHeaderValue("Content-Language");
- for (Variant variant : variants) {
- String variantEncoding = variant.getEncoding();
- Locale variantLanguage = variant.getLanguage();
- javax.ws.rs.core.MediaType variantMediaType = variant.getMediaType();
- if (isEncodingEqual(inputEncoding, variantEncoding) && isLanguageEqual(inputLanguage,
- variantLanguage)
- && isMediaTypeEqual(inputMediaType, variantMediaType)) {
- return variant;
- }
+ if (variants == null) {
+ throw new IllegalArgumentException();
}
- return null;
- }
- private boolean isEncodingEqual(String inputEncoding, String variantEncoding) {
- if (inputEncoding == null && variantEncoding == null) {
- return true;
+ if (variants.size() == 0) {
+ return null;
}
- if ((inputEncoding == null && variantEncoding != null) || (inputEncoding != null && variantEncoding == null)) {
- return false;
+ // algorithm is based on Apache Content Negotiation algorithm with
+ // slight modifications
+ // http://httpd.apache.org/docs/2.0/content-negotiation.html
+
+ // eliminate all Accept* variants that are not acceptable
+ List<MediaType> acceptableMediaTypes =
+ msgContext.getHttpHeaders().getAcceptableMediaTypes();
+
+ List<String> acceptableLanguages =
+ msgContext.getHttpHeaders().getRequestHeader(HttpHeaders.ACCEPT_LANGUAGE);
+ AcceptLanguage languages = null;
+ if (acceptableLanguages != null) {
+ StringBuilder acceptLanguageTemp = new StringBuilder();
+ acceptLanguageTemp.append(acceptableLanguages.get(0));
+ for (int c = 1; c < acceptableLanguages.size(); ++c) {
+ acceptLanguageTemp.append(",");
+ acceptLanguageTemp.append(acceptableLanguages.get(c));
+ }
+ String acceptLanguage = acceptLanguageTemp.toString();
+ languages = AcceptLanguage.valueOf(acceptLanguage);
}
- return variantEncoding.equals(inputEncoding.toString());
- }
+ List<String> acceptableEncodings =
+ msgContext.getHttpHeaders().getRequestHeader(HttpHeaders.ACCEPT_ENCODING);
+ AcceptEncoding encodings = null;
+ if (acceptableEncodings != null) {
+ StringBuilder acceptEncodingsTemp = new StringBuilder();
+ acceptEncodingsTemp.append(acceptableEncodings.get(0));
+ for (int c = 1; c < acceptableEncodings.size(); ++c) {
+ acceptEncodingsTemp.append(",");
+ acceptEncodingsTemp.append(acceptableEncodings.get(c));
+ }
+ String acceptEncodings = acceptEncodingsTemp.toString();
+ encodings = AcceptEncoding.valueOf(acceptEncodings);
+ }
+
+ VariantQChecked bestVariant = null;
+ boolean isIdentityEncodingChecked = false;
+
+ for (Iterator<Variant> iter = variants.iterator(); iter.hasNext();) {
+ double acceptQFactor = -1.0d;
+ Variant v = iter.next();
+ MediaType vMediaType = v.getMediaType();
+ if (vMediaType != null && acceptableMediaTypes != null) {
+ boolean isCompatible = false;
+ boolean isAcceptable = true; // explicitly denied by the client
+ for (MediaType mt : acceptableMediaTypes) {
+ if (mt.isCompatible(vMediaType)) {
+ Map<String, String> params = mt.getParameters();
+ String q = params.get("q");
+ if (q != null) {
+ try {
+ Double qAsDouble = Double.valueOf(q);
+ if (qAsDouble.equals(0.0)) {
+ isAcceptable = false;
+ break;
+ }
+ acceptQFactor = qAsDouble;
+ } catch (NumberFormatException e) {
+ // silently ignore
+ e.printStackTrace();
+ }
+ } else {
+ acceptQFactor = 1.0d;
+ }
+ isCompatible = true;
+ break;
+ }
+ }
+ if (!isCompatible || !isAcceptable) {
+ continue;
+ }
+ }
+
+ if (bestVariant != null) {
+ if (acceptQFactor < bestVariant.acceptMediaTypeQFactor) {
+ continue;
+ }
+ }
+
+ double acceptLanguageQFactor = -1.0d;
+ Locale vLocale = v.getLanguage();
+ if (vLocale != null && languages != null) {
+ boolean isCompatible = false;
+ if (languages.getBannedLanguages().contains(vLocale)) {
+ continue;
+ }
+ for (AcceptLanguage.ValuedLocale locale : languages.getValuedLocales()) {
+ if (locale.isWildcard() || vLocale.equals(locale.locale)) {
+ isCompatible = true;
+ acceptLanguageQFactor = locale.qValue;
+ break;
+ }
+ }
+ if (!isCompatible) {
+ continue;
+ }
+ }
+
+ if (bestVariant != null) {
+ if (acceptLanguageQFactor < bestVariant.acceptLanguageQFactor) {
+ continue;
+ }
+ }
- private boolean isLanguageEqual(String inputLanguage, Locale variantLanguage) {
- if (inputLanguage == null && variantLanguage == null) {
- return true;
+ double acceptEncodingQFactor = -1.0d;
+ String vEncoding = v.getEncoding();
+ if (vEncoding != null) {
+ if (encodings == null || encodings.isAnyEncodingAllowed()) {
+ if (!v.getEncoding().equalsIgnoreCase("identity")) {
+ // if there is no Accept Encoding, only identity is
+ // acceptable
+ isIdentityEncodingChecked = true;
+ continue;
+ }
+ } else {
+ boolean isAcceptable = true;
+ for (String encoding : encodings.getBannedEncodings()) {
+ if (encoding.equalsIgnoreCase(vEncoding)) {
+ isAcceptable = false;
+ break;
+ }
+ }
+ if (!isAcceptable) {
+ continue;
+ }
+
+ boolean isCompatible = false;
+ for (AcceptEncoding.ValuedEncoding encoding : encodings.getValuedEncodings()) {
+ if (encoding.isWildcard() || encoding.encoding.equalsIgnoreCase(vEncoding)) {
+ isCompatible = true;
+ acceptEncodingQFactor = encoding.qValue;
+ break;
+ }
+ }
+ if (!isCompatible) {
+ continue;
+ }
+ }
+ }
+
+ if (bestVariant != null) {
+ if (acceptEncodingQFactor < bestVariant.acceptEncodingQFactor) {
+ continue;
+ }
+ }
+
+ bestVariant =
+ new VariantQChecked(v, acceptQFactor, acceptLanguageQFactor, acceptEncodingQFactor);
}
- if ((inputLanguage == null && variantLanguage != null) || (inputLanguage != null && variantLanguage == null)) {
- return false;
+ if (bestVariant == null) {
+ return null;
}
- return variantLanguage.getLanguage().equalsIgnoreCase(inputLanguage.toString());
- }
+ StringBuilder varyHeaderValue = new StringBuilder();
+ boolean isValueWritten = false;
+ if (bestVariant.acceptMediaTypeQFactor > 0) {
+ varyHeaderValue.append(HttpHeaders.ACCEPT);
+ isValueWritten = true;
+ }
+ if (bestVariant.acceptLanguageQFactor > 0) {
+ if (isValueWritten) {
+ varyHeaderValue.append(", ");
+ }
+ varyHeaderValue.append(HttpHeaders.ACCEPT_LANGUAGE);
+ isValueWritten = true;
+ }
+ if (isIdentityEncodingChecked || bestVariant.acceptEncodingQFactor > 0) {
+ if (isValueWritten) {
+ varyHeaderValue.append(", ");
+ }
+ varyHeaderValue.append(HttpHeaders.ACCEPT_ENCODING);
+ isValueWritten = true;
+ }
- private boolean isMediaTypeEqual(MediaType inputMediaType, MediaType variantMediaType) {
- if (inputMediaType == null && variantMediaType == null) {
- return true;
+ msgContext.setAttribute(RequestImpl.VaryHeader.class, new VaryHeader(varyHeaderValue
+ .toString().trim()));
+ return bestVariant.variant;
+ }
+
+ private static class VariantQChecked {
+ final Variant variant;
+ final double acceptMediaTypeQFactor;
+ final double acceptLanguageQFactor;
+ final double acceptEncodingQFactor;
+
+ public VariantQChecked(Variant v,
+ double acceptMediaType,
+ double acceptLanguage,
+ double acceptEncoding) {
+ this.variant = v;
+ this.acceptMediaTypeQFactor = acceptMediaType;
+ this.acceptLanguageQFactor = acceptLanguage;
+ this.acceptEncodingQFactor = acceptEncoding;
}
+ }
+
+ /**
+ * Stores the Vary header value created from the
+ * {@link RequestImpl#selectVariant(List)} method call.
+ */
+ public static class VaryHeader {
+ final private String varyHeaderValue;
- if ((inputMediaType == null && variantMediaType != null) || (inputMediaType != null && variantMediaType == null)) {
- return false;
+ private VaryHeader(String varyHeaderValue) {
+ this.varyHeaderValue = varyHeaderValue;
}
- return variantMediaType.toString().equals(inputMediaType.toString());
+ public String getVaryHeaderValue() {
+ return varyHeaderValue;
+ }
}
-
}
Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FlushResultHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FlushResultHandler.java?rev=807336&r1=807335&r2=807336&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FlushResultHandler.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FlushResultHandler.java Mon Aug 24 18:48:31 2009
@@ -46,8 +46,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.wink.common.internal.MultivaluedMapImpl;
+import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.server.handlers.AbstractHandler;
import org.apache.wink.server.handlers.MessageContext;
+import org.apache.wink.server.internal.contexts.RequestImpl;
public class FlushResultHandler extends AbstractHandler {
@@ -200,6 +202,14 @@
@SuppressWarnings("unchecked")
private static void flushHeaders(final HttpServletResponse httpResponse,
final MultivaluedMap<String, Object> headers) {
+ if (headers.get(HttpHeaders.VARY) == null) {
+ RequestImpl.VaryHeader varyHeader =
+ RuntimeContextTLS.getRuntimeContext().getAttribute(RequestImpl.VaryHeader.class);
+ if (varyHeader != null) {
+ headers.putSingle(HttpHeaders.VARY, varyHeader.getVaryHeaderValue());
+ }
+ }
+
for (Entry<String, List<Object>> entry : headers.entrySet()) {
String key = entry.getKey();
List<Object> values = entry.getValue();
Added: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java?rev=807336&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java (added)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java Mon Aug 24 18:48:31 2009
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * 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.wink.server.internal;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.apache.wink.server.internal.servlet.MockServletInvocationTest;
+import org.apache.wink.test.mock.MockRequestConstructor;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+public class RequestsTest extends MockServletInvocationTest {
+
+ @Override
+ protected Class<?>[] getClasses() {
+ return new Class[] {RequestRootResource.class};
+ }
+
+ @Path("/root")
+ public static class RequestRootResource {
+
+ @GET
+ public Response getOnlyMediaType(@Context Request request) {
+ List<Variant> responseVariants =
+ Variant.mediaTypes(MediaType.TEXT_PLAIN_TYPE,
+ MediaType.APPLICATION_XML_TYPE,
+ MediaType.APPLICATION_JSON_TYPE).add().build();
+ Variant bestResponseVariant = request.selectVariant(responseVariants);
+ if (bestResponseVariant != null) {
+ return Response.ok("Hello world!").variant(request.selectVariant(responseVariants))
+ .build();
+ }
+ return Response.notAcceptable(responseVariants).build();
+ }
+
+ @GET
+ @Path("language")
+ public Response getOnlyLanguage(@Context Request request) {
+ List<Variant> responseVariants =
+ Variant.languages(Locale.ENGLISH, Locale.FRENCH, Locale.KOREAN).add().build();
+ Variant bestResponseVariant = request.selectVariant(responseVariants);
+ if (bestResponseVariant != null) {
+ return Response.ok("Hello world!").variant(bestResponseVariant).build();
+ }
+ return Response.notAcceptable(responseVariants).build();
+ }
+
+ @GET
+ @Path("encoding")
+ public Response getOnlyEncoding(@Context Request request) {
+ List<Variant> responseVariants =
+ Collections.unmodifiableList(Variant.encodings("gzip", "identity", "deflate").add()
+ .build());
+ Variant bestResponseVariant = request.selectVariant(responseVariants);
+ if (bestResponseVariant != null) {
+ return Response.ok("Hello world!").variant(bestResponseVariant).build();
+ }
+ return Response.notAcceptable(responseVariants).build();
+ }
+
+ @GET
+ @Path("noidentityencoding")
+ public Response getNoIdentityEncoding(@Context Request request) {
+ List<Variant> responseVariants =
+ Collections.unmodifiableList(Variant.encodings("gzip", "deflate").add().build());
+ Variant bestResponseVariant = request.selectVariant(responseVariants);
+ if (bestResponseVariant != null) {
+ return Response.ok("Hello world!").variant(bestResponseVariant).build();
+ }
+ return Response.notAcceptable(responseVariants).build();
+ }
+
+ @GET
+ @Path("multipleheaders")
+ public Response getMultipleAcceptHeaders(@Context Request request) {
+ List<Variant> responseVariants =
+ Collections.unmodifiableList(Variant.mediaTypes(MediaType.APPLICATION_XML_TYPE,
+ MediaType.APPLICATION_JSON_TYPE,
+ MediaType.TEXT_PLAIN_TYPE)
+ .encodings("gzip", "identity", "deflate").languages(Locale.ENGLISH,
+ Locale.FRENCH,
+ Locale.US).add().build());
+ Variant bestResponseVariant = request.selectVariant(responseVariants);
+ if (bestResponseVariant != null) {
+ return Response.ok("Hello world!").variant(bestResponseVariant).build();
+ }
+ return Response.notAcceptable(responseVariants).build();
+ }
+ }
+
+ public void testSimpleMediaTypeSelect() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET", "/root", MediaType.TEXT_PLAIN);
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+
+ request = MockRequestConstructor.constructMockRequest("GET", "/root", "text/*");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET", "/root", MediaType.APPLICATION_XML);
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_XML, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET", "/root", MediaType.APPLICATION_JSON);
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.APPLICATION_ATOM_XML);
+ response = invoke(request);
+ assertEquals(406, response.getStatus());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ }
+
+ public void testMultipleMediaTypeSelect() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.TEXT_PLAIN + ";q=1.0,"
+ + MediaType.APPLICATION_XML
+ + ";q=0.9");
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(response.getContentType(), MediaType.TEXT_PLAIN);
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.APPLICATION_XML + ";q=0.9,"
+ + "text/*"
+ + ";q=1.0");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.TEXT_PLAIN + ";q=0.9,"
+ + MediaType.APPLICATION_XML
+ + ";q=1.0");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_XML, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET", "/root", MediaType.WILDCARD + ","
+ + MediaType.TEXT_PLAIN
+ + ";q=0.0,"
+ + MediaType.APPLICATION_XML
+ + ";q=0.0");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.APPLICATION_ATOM_XML);
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.APPLICATION_ATOM_XML + ";q=1.0,"
+ + MediaType.TEXT_PLAIN
+ + ";q=0.0,"
+ + MediaType.APPLICATION_XML
+ + ";q=0.0");
+ response = invoke(request);
+ assertEquals(406, response.getStatus());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root",
+ MediaType.WILDCARD + ";q=0.1 ,"
+ + MediaType.APPLICATION_ATOM_XML
+ + ";q=1.0,"
+ + MediaType.TEXT_PLAIN
+ + ";q=0.0,"
+ + MediaType.APPLICATION_XML
+ + ";q=0.0");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON, response.getContentType());
+ assertEquals(HttpHeaders.ACCEPT, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ }
+
+ public void testSimpleLanguagesSelect() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/language",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "en");
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("en", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT_LANGUAGE, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/language",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "fr");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("fr", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT_LANGUAGE, response.getHeader(HttpHeaders.VARY));
+ assertNull(response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ }
+
+ public void testMultipleLanguagesSelect() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/language",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "en;q=0.6,fr;q=0.5");
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("en", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT_LANGUAGE, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/language",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "en;q=0.6,fr;q=0.7");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("fr", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT_LANGUAGE, response.getHeader(HttpHeaders.VARY));
+ }
+
+ public void testSimpleEncoding() throws Exception {
+ // test that a null Accept-Encoding means the only thing that can come
+ // back is identity
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/encoding",
+ MediaType.TEXT_PLAIN);
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("identity", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/encoding",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("gzip", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/noidentityencoding",
+ MediaType.TEXT_PLAIN);
+ response = invoke(request);
+ assertEquals(406, response.getStatus());
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/noidentityencoding",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("gzip", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+ }
+
+ public void testMultipleEncoding() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/encoding",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip;q=0.8,deflate;q=0.7");
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("gzip", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/encoding",
+ MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "deflate;q=0.8,gzip;q=0.7");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("deflate", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals(HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+ }
+
+ public void testSimpleMultipleAcceptHeaders() throws Exception {
+ MockHttpServletRequest request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/multipleheaders",
+ MediaType.TEXT_PLAIN + ";q=1.0,"
+ + MediaType.APPLICATION_XML
+ + ";q=0.8");
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip;q=0.8,deflate;q=0.7");
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "en-us");
+ MockHttpServletResponse response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN, response.getContentType());
+ assertEquals("gzip", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals("en_US", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT + ", "
+ + HttpHeaders.ACCEPT_LANGUAGE
+ + ", "
+ + HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/multipleheaders",
+ MediaType.TEXT_PLAIN + ";q=0.9,"
+ + MediaType.APPLICATION_XML
+ + ";q=1.0");
+ request.addHeader(HttpHeaders.ACCEPT_ENCODING, "deflate;q=0.8,gzip;q=0.7");
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "en-us;q=0.9,fr;q=1.0");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_XML, response.getContentType());
+ assertEquals("deflate", response.getHeader(HttpHeaders.CONTENT_ENCODING));
+ assertEquals("fr", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT + ", "
+ + HttpHeaders.ACCEPT_LANGUAGE
+ + ", "
+ + HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+
+ request =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/root/multipleheaders",
+ "text/*" + ";q=0.9,"
+ + MediaType.APPLICATION_XML
+ + ";q=1.0");
+ request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "fr;q=1.0, en-us;q=0.9");
+ response = invoke(request);
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_XML, response.getContentType());
+ assertEquals("fr", response.getHeader(HttpHeaders.CONTENT_LANGUAGE));
+ assertEquals(HttpHeaders.ACCEPT + ", "
+ + HttpHeaders.ACCEPT_LANGUAGE
+ + ", "
+ + HttpHeaders.ACCEPT_ENCODING, response.getHeader(HttpHeaders.VARY));
+ }
+}
Propchange: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/RequestsTest.java
------------------------------------------------------------------------------
svn:eol-style = native