/*******************************************************************************
* 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.contexts;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.wink.common.RuntimeContext;
import org.apache.wink.common.internal.MultivaluedMapImpl;
import org.apache.wink.common.internal.WinkConfiguration;
import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.server.internal.DeploymentConfiguration;
import org.jmock.Expectations;
import org.jmock.integration.junit3.MockObjectTestCase;
import org.junit.Test;
public class ServerMediaTypeCharsetAdjusterTest extends MockObjectTestCase {
RuntimeContext context = null;
DeploymentConfiguration myConfig = new DeploymentConfiguration();
MultivaluedMap<String, Object> responseHttpHeaders = null;
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
myConfig.init();
// default is false in the real config
myConfig.setDefaultResponseCharset(true);
// default is false in the real config
myConfig.setUseAcceptCharset(false);
// common expectations
context = mock(RuntimeContext.class);
responseHttpHeaders = mock(MultivaluedMap.class);
checking(new Expectations() {{
allowing(context).getAttribute(WinkConfiguration.class); will(returnValue(myConfig));
}});
RuntimeContextTLS.setRuntimeContext(context);
}
@Override
public void tearDown() {
RuntimeContextTLS.setRuntimeContext(null);
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithDefaultConfig() {
final String expected = "application/xml";
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// null httpHeaders param
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(null, MediaType.APPLICATION_XML_TYPE);
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueNullParam() {
final String expected = "application/xml";
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
myConfig.setDefaultResponseCharset(true);
// null httpHeaders param
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(null, MediaType.APPLICATION_XML_TYPE);
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndNullHeadersAndFalseConfig() {
final String expected = "application/xml";
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// switch off the default
myConfig.setDefaultResponseCharset(false);
// empty map
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(new MultivaluedMapImpl<String, Object>(), MediaType.APPLICATION_XML_TYPE);
// no charset attribute due to setDefaultResponseCharset(false)
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndNullHeaders() {
final String expected = "application/xml;charset=UTF-8";
checking(new Expectations() {{
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(true));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
}});
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// empty map
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndNullAcceptCharsetHeader() {
final String expected = "application/xml;charset=UTF-8";
final HttpHeaders httpHeaders = mock(HttpHeaders.class);
checking(new Expectations() {{
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(true));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
oneOf(context).getHttpHeaders(); will(returnValue(httpHeaders));
oneOf(httpHeaders).getRequestHeader(HttpHeaders.ACCEPT_CHARSET); will(returnValue(null));
}});
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// exercise code path that reads the Accept-Charset header
myConfig.setUseAcceptCharset(true);
// empty map
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndAcceptCharsetHeader() {
final String expected = "application/xml;charset=ISO-8859-1";
final List<String> acceptHeaders = new ArrayList<String>();
acceptHeaders.add("UTF-16");
final HttpHeaders httpHeaders = mock(HttpHeaders.class);
checking(new Expectations() {{
oneOf(responseHttpHeaders).add("nonesense", null);
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(false));
oneOf(responseHttpHeaders).get(HttpHeaders.CONTENT_TYPE); will(returnValue(null));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
oneOf(context).getHttpHeaders(); will(returnValue(httpHeaders));
oneOf(httpHeaders).getRequestHeader(HttpHeaders.ACCEPT_CHARSET); will(returnValue(acceptHeaders));
}});
// non-empty map, just to make sure production code path is as expected
responseHttpHeaders.add("nonesense", null);
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// exercise code path that reads the Accept-Charset header
myConfig.setUseAcceptCharset(true);
// empty map
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
// still defaults back to ISO-8859-1 because it is silently added as top q-valued charset on the client-originated Accept-Header. See HTTP spec.
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndAcceptCharsetButFalse() {
final String expected = "application/xml;charset=UTF-8";
final List<String> acceptHeaders = new ArrayList<String>();
acceptHeaders.add("UTF-16;q=1.0");
acceptHeaders.add("ISO-8859-1;q=0.5"); // re-prioritize silently added charset to lower q-value than UTF-16
checking(new Expectations() {{
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(true));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
}});
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// leave useAcceptHeader to the default of false
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
// UTF-16 has highest q-value, but Accept-Charset is being ignored due to config, so...
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigTrueAndAcceptCharset() {
final String expected = "application/xml;charset=UTF-16";
final List<String> acceptHeaders = new ArrayList<String>();
acceptHeaders.add("UTF-16;q=1.0");
acceptHeaders.add("ISO-8859-1;q=0.5"); // re-prioritize silently added charset to lower q-value than UTF-16
final HttpHeaders httpHeaders = mock(HttpHeaders.class);
checking(new Expectations() {{
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(true));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
oneOf(context).getHttpHeaders(); will(returnValue(httpHeaders));
oneOf(httpHeaders).getRequestHeader(HttpHeaders.ACCEPT_CHARSET); will(returnValue(acceptHeaders));
}});
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// exercise code path that reads the Accept-Charset header
myConfig.setUseAcceptCharset(true);
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
// UTF-16 has highest q-value
assertEquals(expected, mediaType.toString());
}
@Test
public void testSetDefaultCharsetOnMediaTypeHeaderWithConfigFalseAndAcceptCharset() {
final String expected = "application/xml;charset=UTF-16";
final List<String> acceptHeaders = new ArrayList<String>();
acceptHeaders.add("UTF-16;q=1.0");
acceptHeaders.add("ISO-8859-1;q=0.5"); // re-prioritize silently added charset to lower q-value than UTF-16
final HttpHeaders httpHeaders = mock(HttpHeaders.class);
checking(new Expectations() {{
oneOf(responseHttpHeaders).isEmpty(); will(returnValue(true));
oneOf(responseHttpHeaders).putSingle(HttpHeaders.CONTENT_TYPE, expected);
oneOf(context).getHttpHeaders(); will(returnValue(httpHeaders));
oneOf(httpHeaders).getRequestHeader(HttpHeaders.ACCEPT_CHARSET); will(returnValue(acceptHeaders));
}});
ServerMediaTypeCharsetAdjuster serverMediaTypeCharsetAdjuster = ServerMediaTypeCharsetAdjuster.getInstance();
// make sure when user expects to be using Accept-Header, they really do use it
// default is true in the real config. Resetting to false here to confirm code path is correct
myConfig.setUseAcceptCharset(false);
// exercise code path that reads the Accept-Charset header
myConfig.setUseAcceptCharset(true);
MediaType mediaType = serverMediaTypeCharsetAdjuster.setDefaultCharsetOnMediaTypeHeader(responseHttpHeaders, MediaType.APPLICATION_XML_TYPE);
// UTF-16 has highest q-value
assertEquals(expected, mediaType.toString());
}
}