/** * 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.cxf.jaxrs; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.jaxrs.fortest.BookEntity; import org.apache.cxf.jaxrs.fortest.BookEntity2; import org.apache.cxf.jaxrs.fortest.ConcreteRestController; import org.apache.cxf.jaxrs.fortest.ConcreteRestResource; import org.apache.cxf.jaxrs.fortest.GenericEntityImpl; import org.apache.cxf.jaxrs.fortest.GenericEntityImpl2; import org.apache.cxf.jaxrs.fortest.GenericEntityImpl3; import org.apache.cxf.jaxrs.fortest.GenericEntityImpl4; import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.jaxrs.model.OperationResourceInfo; import org.apache.cxf.jaxrs.provider.ProviderFactory; import org.apache.cxf.jaxrs.provider.ServerProviderFactory; import org.apache.cxf.jaxrs.resources.Book; import org.apache.cxf.jaxrs.resources.Chapter; import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.ExchangeImpl; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.easymock.EasyMock; import org.junit.Assert; import org.junit.Test; public class SelectMethodCandidatesTest extends Assert { @Test public void testFindFromAbstractGenericClass() throws Exception { doTestGenericSuperType(BookEntity.class, "POST"); } @Test public void testFindFromAbstractGenericClass2() throws Exception { doTestGenericSuperType(BookEntity2.class, "POST"); } @Test public void testFindFromAbstractGenericInterface() throws Exception { doTestGenericSuperType(GenericEntityImpl.class, "POST"); } @Test public void testFindFromAbstractGenericInterface2() throws Exception { doTestGenericSuperType(GenericEntityImpl2.class, "POST"); } @Test public void testFindFromAbstractGenericImpl3() throws Exception { doTestGenericSuperType(GenericEntityImpl3.class, "POST"); } private static List<MediaType> sortMediaTypes(String mediaTypes) { return JAXRSUtils.sortMediaTypes(mediaTypes, JAXRSUtils.MEDIA_TYPE_Q_PARAM); } @Test public void testFindFromAbstractGenericImpl4() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(GenericEntityImpl4.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "text/xml"; String acceptContentTypes = "text/xml"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, "text/xml"); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(2); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/books", "POST", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "postEntity", ori.getMethodToInvoke().getName()); String value = "<Books><Book><name>The Book</name><id>2</id></Book></Books>"; m.setContent(InputStream.class, new ByteArrayInputStream(value.getBytes())); List<Object> params = JAXRSUtils.processParameters(ori, values, m); assertEquals(1, params.size()); List<?> books = (List<?>)params.get(0); assertEquals(1, books.size()); Book book = (Book)books.get(0); assertNotNull(book); assertEquals(2L, book.getId()); assertEquals("The Book", book.getName()); } @Test public void testFindFromAbstractGenericImpl5() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(ConcreteRestController.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); Message m = createMessage(); m.put(Message.CONTENT_TYPE, "text/xml"); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/", "POST", values, "text/xml", sortMediaTypes("*/*")); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "add", ori.getMethodToInvoke().getName()); String value = "<concreteRestResource><name>The Book</name></concreteRestResource>"; m.setContent(InputStream.class, new ByteArrayInputStream(value.getBytes())); List<Object> params = JAXRSUtils.processParameters(ori, values, m); assertEquals(1, params.size()); ConcreteRestResource book = (ConcreteRestResource)params.get(0); assertNotNull(book); assertEquals("The Book", book.getName()); } @Test public void testFindFromAbstractGenericClass3() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(BookEntity.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "text/xml"; String acceptContentTypes = "text/xml"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, "text/xml"); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(3); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/books", "PUT", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "putEntity", ori.getMethodToInvoke().getName()); String value = "<Chapter><title>The Book</title><id>2</id></Chapter>"; m.setContent(InputStream.class, new ByteArrayInputStream(value.getBytes())); List<Object> params = JAXRSUtils.processParameters(ori, values, m); assertEquals(1, params.size()); Chapter c = (Chapter)params.get(0); assertNotNull(c); assertEquals(2L, c.getId()); assertEquals("The Book", c.getTitle()); } @Test public void testDefaultMethod() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(DefaultMethodResource.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentType = "text/xml"; String acceptContentTypes = "text/xml"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, contentType); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(3); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/service/all", "PUT", values, contentType, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "all", ori.getMethodToInvoke().getName()); values.clear(); ori = findTargetResourceClass(resources, m, "/service/all", "GET", values, contentType, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "getAll", ori.getMethodToInvoke().getName()); ori = findTargetResourceClass(resources, m, "/service", "GET", values, contentType, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", "get", ori.getMethodToInvoke().getName()); } @Test public void testConsumesResource1() throws Exception { doTestConsumesResource(ConsumesResource1.class, "text/xml", "m2"); } @Test public void testConsumesResource2() throws Exception { doTestConsumesResource(ConsumesResource2.class, "m1"); } @Test public void testConsumesResource3() throws Exception { doTestConsumesResource(ConsumesResource3.class, "m1"); } @Test public void testConsumesResource4() throws Exception { doTestConsumesResource(ConsumesResource4.class, "application/xml+bar", "m2"); } @Test public void testConsumesResource5() throws Exception { doTestConsumesResource(ConsumesResource5.class, "text/xml", "m2"); } private void doTestConsumesResource(Class<?> resourceClass, String expectedMethodName) throws Exception { doTestConsumesResource(resourceClass, null, expectedMethodName); } private void doTestConsumesResource(Class<?> resourceClass, String ct, String expectedMethodName) throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(resourceClass); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentType = ct == null ? "application/xml" : ct; String acceptContentTypes = "*/*"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, contentType); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(2); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/", "POST", values, contentType, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals(expectedMethodName, ori.getMethodToInvoke().getName()); } @Test public void testResponseType1() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m1", "application/xml", "application/xml", "m1"); } @Test public void testResponseType2() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m1", "application/*,application/json", "application/json", "m1"); } @Test public void testResponseType3() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m1", "text/xml, application/xml;q=0.8,application/json;q=0.4", "application/xml", "m1"); } @Test public void testResponseType4() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m1", "text/xml, application/xml;q=0.8,application/json;q=0.4", "application/xml", "m1"); } @Test public void testResponseType5() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m2", "text/xml, application/xml;q=0.3,application/json;q=0.4", "application/json", "m2"); } @Test public void testResponseType6() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m3", "text/*,application/json;q=0.4", "text/xml", "m3"); } @Test public void testResponseType7() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m3", "text/*,application/json", "application/json", "m3"); } @Test public void testResponseType8() throws Exception { doTestProducesResource(ResponseMediaTypeResource.class, "/m4", "application/*", "application/xml", "m4"); } @Test public void testProducesResource1() throws Exception { doTestProducesResource(ProducesResource1.class, "/", "text/plain, application/xml", "application/xml", "m2"); } @Test public void testProducesResource2() throws Exception { doTestProducesResource(ProducesResource1.class, "/", "text/plain, application/xml;q=0.8", "text/plain", "m1"); } @Test public void testProducesResource3() throws Exception { doTestProducesResource(ProducesResource2.class, "/", "application/*", "application/json", "m1"); } @Test public void testProducesResource4() throws Exception { doTestProducesResource(ProducesResource2.class, "/", "application/xml,application/json;q=0.9", "application/xml", "m2"); } @Test public void testProducesResource5() throws Exception { doTestProducesResource(ProducesResource2.class, "/", "application/xml;q=0.3,application/json;q=0.5", "application/json", "m1"); } @Test public void testProducesResource6() throws Exception { doTestProducesResource(ProducesResource3.class, "/", "application/xml,application/json", "application/xml", "m2"); } @Test public void testProducesResource7() throws Exception { doTestProducesResource(ProducesResource4.class, "/", "application/xml,", "application/xml", "m1"); } @Test public void testProducesResource8() throws Exception { doTestProducesResource(ProducesResource5.class, "/", "application/*,text/html", "text/html", "m1"); } @Test public void testProducesResource9() throws Exception { doTestProducesResource(ProducesResource5.class, "/", "application/*,text/html;q=0.3", "text/html", "m1"); } @Test public void testProducesResource10() throws Exception { doTestProducesResource(ProducesResource6.class, "/", "application/*,text/html", "text/html", "m1"); } private void doTestProducesResource(Class<?> resourceClass, String path, String acceptContentTypes, String expectedResponseType, String expectedMethodName) throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(resourceClass); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentType = "*/*"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, contentType); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(2); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); Map<ClassResourceInfo, MultivaluedMap<String, String>> mResources = JAXRSUtils.selectResourceClass(resources, path, m); OperationResourceInfo ori = JAXRSUtils.findTargetMethod(mResources, m, "GET", values, contentType, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals(expectedMethodName, ori.getMethodToInvoke().getName()); assertEquals(expectedResponseType, m.getExchange().get(Message.CONTENT_TYPE)); } @Test public void testRootResourcesWithSameName() throws Exception { doTestRootResourcesWithSameName("/a/books", "put", RootResource.class); doTestRootResourcesWithSameName("/a1/books", "put", RootResource.class); } @Test public void testRootResourcesWithSameName2() throws Exception { doTestRootResourcesWithSameName("/a/books/1", "put", RootResource2.class); doTestRootResourcesWithSameName("/c/thebooks", "put2", RootResource2.class); doTestRootResourcesWithSameName("/b/books", "put", RootResource3.class); } private void doTestRootResourcesWithSameName(String path, String methodName, Class<?> expectedRoot) throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(RootResource.class, RootResource2.class, RootResource3.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); assertEquals(3, resources.size()); String contentTypes = "text/xml"; String acceptContentTypes = "text/xml"; Message m = prepareMessage(); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, path, "PUT", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", methodName, ori.getMethodToInvoke().getName()); assertSame(expectedRoot, ori.getClassResourceInfo().getServiceClass()); } private Message prepareMessage() { Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, "text/xml"); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(3); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); return m; } private void doTestGenericSuperType(Class<?> serviceClass, String methodName) throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(serviceClass); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "text/xml"; String acceptContentTypes = "text/xml"; Message m = new MessageImpl(); m.put(Message.CONTENT_TYPE, "text/xml"); Exchange ex = new ExchangeImpl(); ex.setInMessage(m); m.setExchange(ex); Endpoint e = EasyMock.createMock(Endpoint.class); e.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); e.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); e.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); e.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(ServerProviderFactory.getInstance()).times(3); e.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); EasyMock.replay(e); ex.put(Endpoint.class, e); MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, m, "/books", methodName, values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", methodName.toLowerCase() + "Entity", ori.getMethodToInvoke().getName()); String value = "<Book><name>The Book</name><id>2</id></Book>"; m.setContent(InputStream.class, new ByteArrayInputStream(value.getBytes())); List<Object> params = JAXRSUtils.processParameters(ori, values, m); assertEquals(1, params.size()); Book book = (Book)params.get(0); assertNotNull(book); assertEquals(2L, book.getId()); assertEquals("The Book", book.getName()); } @Test public void testFindTargetSubResource() throws Exception { doTestFindTargetSubResource("/1/2/3/d/resource", "resourceMethod"); } @Test public void testFindTargetSubResource2() throws Exception { doTestFindTargetSubResource("/1/2/3/d/resource/sub", "subresource"); } @Test public void testFindTargetSubResource3() throws Exception { doTestFindTargetSubResource("/1/2/3/d/resource2/2/2", "resourceMethod2"); } @Test public void testFindTargetSubResource4() throws Exception { doTestFindTargetSubResource("/1/2/3/d/resource2/1/2", "subresource2", true); } @Test public void testFindTargetSubResource5() throws Exception { doTestFindTargetSubResource("/1/2/3/d/resource2/1/2", "resourceMethod2"); } public void doTestFindTargetSubResource(String path, String method) throws Exception { doTestFindTargetSubResource(path, method, false); } public void doTestFindTargetSubResource(String path, String method, boolean setKeepSubProp) throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(org.apache.cxf.jaxrs.resources.TestResource.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "*/*"; String acceptContentTypes = "text/xml,*/*"; MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, createMessage(), path, "GET", values, contentTypes, sortMediaTypes(acceptContentTypes), setKeepSubProp); assertNotNull(ori); assertEquals("resourceMethod needs to be selected", method, ori.getMethodToInvoke().getName()); } @Test public void testSelectUsingQualityFactors() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(org.apache.cxf.jaxrs.resources.TestResource.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "*/*"; String acceptContentTypes = "application/xml;q=0.5,application/json"; MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, createMessage(), "/1/2/3/d/resource1", "GET", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("jsonResource needs to be selected", "jsonResource", ori.getMethodToInvoke().getName()); } @Test public void testFindTargetResourceClassWithTemplates() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(org.apache.cxf.jaxrs.resources.TestResource.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "*/*"; String acceptContentTypes = "application/xml"; //If acceptContentTypes does not specify a specific Mime type, the //method is declared with a most specific ProduceMime type is selected. MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, createMessage(), "/1/2/3/d", "GET", values, contentTypes, Collections.singletonList(MediaType.valueOf(acceptContentTypes))); assertNotNull(ori); assertEquals("listMethod needs to be selected", "listMethod", ori.getMethodToInvoke().getName()); acceptContentTypes = "application/xml,application/json;q=0.8"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/1", "GET", values, contentTypes, JAXRSUtils.parseMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("readMethod needs to be selected", "readMethod", ori.getMethodToInvoke().getName()); contentTypes = "application/xml"; acceptContentTypes = "application/xml"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/1", "GET", values, contentTypes, Collections.singletonList(MediaType.valueOf(acceptContentTypes))); assertNotNull(ori); assertEquals("readMethod needs to be selected", "readMethod", ori.getMethodToInvoke().getName()); contentTypes = "application/json"; acceptContentTypes = "application/json"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/1/bar/baz/baz", "GET", values, contentTypes, Collections.singletonList(MediaType.valueOf(acceptContentTypes))); assertNotNull(ori); assertEquals("readMethod2 needs to be selected", "readMethod2", ori.getMethodToInvoke().getName()); contentTypes = "application/json"; acceptContentTypes = "application/json"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/1", "GET", values, contentTypes, Collections.singletonList(MediaType.valueOf(acceptContentTypes))); assertNotNull(ori); assertEquals("unlimitedPath needs to be selected", "unlimitedPath", ori.getMethodToInvoke().getName()); ori = findTargetResourceClass(resources, null, "/1/2/3/d/1/2", "GET", values, contentTypes, Collections.singletonList(MediaType.valueOf(acceptContentTypes))); assertNotNull(ori); assertEquals("limitedPath needs to be selected", "limitedPath", ori.getMethodToInvoke().getName()); } @Test public void testSelectBar() throws Exception { JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean(); sf.setResourceClasses(org.apache.cxf.jaxrs.resources.TestResource.class); sf.create(); List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos(); String contentTypes = "*/*"; String acceptContentTypes = "application/bar,application/foo;q=0.8"; MetadataMap<String, String> values = new MetadataMap<String, String>(); OperationResourceInfo ori = findTargetResourceClass(resources, null, "/1/2/3/d/custom", "GET", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("readBar", ori.getMethodToInvoke().getName()); acceptContentTypes = "application/foo,application/bar;q=0.8"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/custom", "GET", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("readFoo", ori.getMethodToInvoke().getName()); acceptContentTypes = "application/foo;q=0.5,application/bar"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/custom", "GET", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("readBar", ori.getMethodToInvoke().getName()); acceptContentTypes = "application/foo,application/bar;q=0.5"; ori = findTargetResourceClass(resources, null, "/1/2/3/d/custom", "GET", values, contentTypes, sortMediaTypes(acceptContentTypes)); assertNotNull(ori); assertEquals("readFoo", ori.getMethodToInvoke().getName()); } private Message createMessage() { return createMessage(false); } private Message createMessage(boolean setKeepSubProp) { ProviderFactory factory = ServerProviderFactory.getInstance(); Message m = new MessageImpl(); m.put("org.apache.cxf.http.case_insensitive_queries", false); if (setKeepSubProp) { m.put("keep.subresource.candidates", true); } Exchange e = new ExchangeImpl(); m.setExchange(e); e.setInMessage(m); Endpoint endpoint = EasyMock.createMock(Endpoint.class); endpoint.getEndpointInfo(); EasyMock.expectLastCall().andReturn(null).anyTimes(); endpoint.get("org.apache.cxf.jaxrs.comparator"); EasyMock.expectLastCall().andReturn(null); endpoint.size(); EasyMock.expectLastCall().andReturn(0).anyTimes(); endpoint.isEmpty(); EasyMock.expectLastCall().andReturn(true).anyTimes(); endpoint.get(ServerProviderFactory.class.getName()); EasyMock.expectLastCall().andReturn(factory).anyTimes(); EasyMock.replay(endpoint); e.put(Endpoint.class, endpoint); return m; } private OperationResourceInfo findTargetResourceClass(List<ClassResourceInfo> resources, Message message, String path, String httpMethod, MultivaluedMap<String, String> values, String requestContentType, List<MediaType> acceptContentTypes) { return findTargetResourceClass(resources, message, path, httpMethod, values, requestContentType, acceptContentTypes, false); } //CHECKSTYLE:OFF private OperationResourceInfo findTargetResourceClass(List<ClassResourceInfo> resources, Message message, String path, String httpMethod, MultivaluedMap<String, String> values, String requestContentType, List<MediaType> acceptContentTypes, boolean setKeepSubProp) { //CHECKSTYLE:ON message = message == null ? new MessageImpl() : message; Map<ClassResourceInfo, MultivaluedMap<String, String>> mResources = JAXRSUtils.selectResourceClass(resources, path, message); if (mResources != null) { OperationResourceInfo ori = JAXRSUtils.findTargetMethod(mResources, createMessage(setKeepSubProp), httpMethod, values, requestContentType, acceptContentTypes); if (ori != null) { return ori; } } return null; } @Path("{a}") @Produces("text/xml") @Consumes("text/xml") public static class RootResource { @PUT @Path("books") public void put() { } } @Path("{b}") @Produces("text/xml") @Consumes("text/xml") public static class RootResource2 { @PUT @Path("books/1") public void put() { } @PUT @Path("thebooks") public void put2() { } } @Path("b") @Produces("text/xml") @Consumes("text/xml") public static class RootResource3 { @PUT @Path("books") public void put() { } } public static class ConsumesResource1 { @POST @Consumes({"application/xml", "text/*" }) public void m1() { } @POST @Consumes({"application/xml", "text/xml" }) public void m2() { } } public static class ConsumesResource2 { @POST @Consumes({"application/*", "text/xml" }) public void m2() { } @POST @Consumes({"text/*", "application/xml" }) public void m1() { } } public static class ConsumesResource3 { @POST @Consumes({"application/*" }) public void m2() { } @POST @Consumes({"application/xml" }) public void m1() { } } public static class ConsumesResource4 { @POST @Consumes({"application/xml", "application/xml+*" }) public void m1() { } @POST @Consumes({"application/*", "application/xml+bar" }) public void m2() { } } public static class ConsumesResource5 { @POST @Consumes("text/*") public void m1() { } @POST @Consumes("text/xml;qs=0.7") public void m2() { } } public static class ResponseMediaTypeResource { @GET @Path("m1") @Produces({"application/json", "application/xml" }) public Response m1() { return null; } @GET @Path("m2") @Produces({"application/*" }) public Response m2() { return null; } @GET @Path("m3") @Produces({"application/json", "text/xml", "application/xml" }) public Response m3() { return null; } @GET @Path("m4") @Produces({"application/json;qs=0.9", "application/xml" }) public Response m4() { return null; } } public static class ProducesResource1 { @GET @Produces({"text/*" }) public Response m1() { return null; } @GET @Produces({"application/xml" }) public Response m2() { return null; } } public static class ProducesResource2 { @GET @Produces({"application/json" }) public Response m1() { return null; } @GET @Produces({"application/xml;qs=0.9" }) public Response m2() { return null; } } public static class ProducesResource3 { @GET @Produces({"application/json;qs=0.2" }) public Response m1() { return null; } @GET @Produces({"application/xml;qs=0.9" }) public Response m2() { return null; } } public static class ProducesResource4 { @GET @Produces({"application/*" }) public Response m1() { return null; } @GET @Produces({"application/xml;qs=0.9" }) public Response m2() { return null; } } public static class ProducesResource5 { @GET @Produces({"text/*" }) public Response m1() { return null; } @GET @Produces({"application/*" }) public Response m2() { return null; } } public static class ProducesResource6 { @GET @Produces({"text/*;qs=0.9" }) public Response m1() { return null; } @GET @Produces({"application/*" }) public Response m2() { return null; } } }