/******************************************************************************* * 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.registry; import java.io.UnsupportedEncodingException; import java.util.LinkedList; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.ext.RuntimeDelegate; 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 FindResourceMethod3Test extends MockServletInvocationTest { static List<Class<?>> resourceClasses = new LinkedList<Class<?>>(); static { List<Class<?>> allResources = new LinkedList<Class<?>>(); for (Class<?> cls : FindResourceMethod3Test.class.getClasses()) { if (cls.getSimpleName().startsWith("Resource")) { allResources.add(cls); } } resourceClasses = new LinkedList<Class<?>>(allResources); } @Override protected Class<?>[] getClasses() { return resourceClasses.toArray(new Class<?>[resourceClasses.size()]); } // /// -- Resources -- @Path("/simpleGetProduces") public static class ResourceSimpleGetProduces { @GET @Produces( {"application/xml"}) public String getXml() { return "ResourceSimpleGetProduces.getXml"; } @GET @Produces( {"application/atom+xml"}) public String getAtom() { return "ResourceSimpleGetProduces.getAtom"; } @GET @Produces( {"text/plain", "text/html"}) public String getText() { return "ResourceSimpleGetProduces.getText"; } @GET @Produces( {"image/jpeg"}) public String getImageJpeg() { return "ResourceSimpleGetProduces.getImageJpeg"; } @GET @Produces( {"image/*", "image/jpeg"}) public String getImageAny() { return "ResourceSimpleGetProduces.getImageAny"; } @GET @Produces( {"*/*"}) public Response get(@Context HttpHeaders headers) { List<MediaType> mediaTypes = headers.getAcceptableMediaTypes(); for (int i = 0; i < mediaTypes.size(); i++) { MediaType mediaType = mediaTypes.get(i); String qualityString = mediaType.getParameters().get("q"); if (qualityString != null) { Double d = Double.parseDouble(qualityString); if (d.equals(Double.valueOf(0))) { // intentionally returning the accept media type with // q=0 to ensure outbound flow rejects it ResponseBuilder responseBuilder = RuntimeDelegate.getInstance().createResponseBuilder(); // send back a media type that has q=0 -- this should be // detected somewhere responseBuilder.type(new MediaType("image", "jpeg")); return responseBuilder.status(Response.Status.OK).entity("unknown string") .build(); } } } return RuntimeDelegate.getInstance().createResponseBuilder().status(Response.Status.OK) .entity("ResourceSimpleGetProduces.getAny").build(); } } @Path("/hello") public static class ResourceHello { @GET @Produces("*/*") public String get() { return "ResourceHello.get"; } } /** * test the q=0 param on accept-header media types. See http spec section 14 * for q=0 behavior: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */ public void testFindResourceSimple() throws Exception { MockHttpServletRequest request = null; MockHttpServletResponse response = null; request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "application/xml"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getXml"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "application/atom+xml"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getAtom"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "text/plain"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getText"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "text/html"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getText"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "image/jpeg"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageJpeg"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "image/gif"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageAny"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "image/gif;q=0.6,image/jpeg;q=0.5"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageAny"); // q=0 means do not return that media type request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "image/gif;q=0,image/jpeg;q=0.5"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageJpeg"); // q=0 means do not return that media type request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "image/gif;q=0.5,image/jpeg;q=0"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageAny"); // q=0 means do not return that media type request = MockRequestConstructor .constructMockRequest("GET", "/simpleGetProduces", "*/*,image/gif;q=0,image/jpeg;q=0,application/atom+xml;q=0"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getXml"); // q=0 means do not return that media type request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "*/*,image/*;q=0,application/*;q=0"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getText"); // q=0 means do not return that media type request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "text/plain,text/html;q=0"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getText"); // q=0 means do not return that media type request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "text/plain;q=0,text/html"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getText"); // q=0 means do not return that media type request = MockRequestConstructor .constructMockRequest("GET", "/simpleGetProduces", "*/*,text/plain;q=0,text/html;q=0,application/atom+xml;q=0"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getXml"); // q=0 means do not return that media type. In this test, we accept // nothing. request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "*/*;q=0"); response = invoke(request); assertMethodNotFound(response); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "text/plain;q=0.4,image/jpeg;q=0.5"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getImageJpeg"); request = MockRequestConstructor.constructMockRequest("GET", "/simpleGetProduces", "mytype/mysubtype"); response = invoke(request); assertMethodFound(response, ResourceSimpleGetProduces.class, "getAny"); // https://issues.apache.org/jira/browse/WINK-106 (positive result) request = MockRequestConstructor.constructMockRequest("GET", "/hello", "text/xml"); response = invoke(request); assertMethodFound(response, ResourceHello.class, "get"); // https://issues.apache.org/jira/browse/WINK-106 (negative result) request = MockRequestConstructor.constructMockRequest("GET", "/hello", "text/xml;q=0"); response = invoke(request); assertMethodNotFound(response); } // // TODO: review and implement test // public void testPopulateResponseMediaType() throws Exception { // MockHttpServletRequest request = null; // MockHttpServletResponse response = null; // // // q=0 means do not return that media type // // since our method that supports * / * will try to return one of the // excluded media types, // // PopulateResponseMediaTypeHandler should detect this and return a 406. // request = MockRequestConstructor.constructMockRequest("GET", // "/simpleGetProduces", "*/*,image/*;q=0,application/*;q=0,text/*;q=0"); // response = invoke(request); // assertMethodNotFound(response); // // } static void assertMethodFound(MockHttpServletResponse response, Class<?> expectedResource, String expectedMethod) throws UnsupportedEncodingException { assertEquals(200, response.getStatus()); /* * avoid a bug in the MockServletResponse#setContentType where it tries * to parse the charset there could be a * "text/plain;charset=UTF-8;otherParam=otherValue" but * MockServletResponse will treat charset as * "UTF-8;otherParam=otherValue" instead of just "UTF-8" */ String charset = MediaType.valueOf(response.getContentType()).getParameters().get("charset"); response.setCharacterEncoding(charset); String expected = expectedResource.getSimpleName() + "." + expectedMethod; assertEquals(expected, response.getContentAsString()); } static void assertMethodNotFound(MockHttpServletResponse response) throws UnsupportedEncodingException { assertEquals(406, response.getStatus()); } }