/**
* 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.provider;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.validation.Schema;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.jaxrs.Customer;
import org.apache.cxf.jaxrs.CustomerParameterHandler;
import org.apache.cxf.jaxrs.JAXBContextProvider;
import org.apache.cxf.jaxrs.JAXBContextProvider2;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper;
import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
import org.apache.cxf.jaxrs.model.ProviderInfo;
import org.apache.cxf.jaxrs.resources.Book;
import org.apache.cxf.jaxrs.resources.SuperBook;
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.Before;
import org.junit.Test;
public class ProviderFactoryTest extends Assert {
@Before
public void setUp() {
ServerProviderFactory.getInstance().clearProviders();
AbstractResourceInfo.clearAllMaps();
}
@Test
public void testMultipleFactories() {
assertNotSame(ServerProviderFactory.getInstance(), ServerProviderFactory.getInstance());
}
@Test
public void testOrderOfProvidersWithSameProperties() {
ProviderFactory pf = ServerProviderFactory.getInstance();
WildcardReader reader1 = new WildcardReader();
pf.registerUserProvider(reader1);
WildcardReader2 reader2 = new WildcardReader2();
pf.registerUserProvider(reader2);
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(11, readers.size());
assertSame(reader1, readers.get(7).getProvider());
assertSame(reader2, readers.get(8).getProvider());
}
@Test
public void testCustomProviderSorting() {
ProviderFactory pf = ServerProviderFactory.getInstance();
Comparator<?> comp = new Comparator<ProviderInfo<?>>() {
@Override
public int compare(ProviderInfo<?> o1, ProviderInfo<?> o2) {
Object provider1 = o1.getProvider();
Object provider2 = o2.getProvider();
if (provider1 instanceof StringTextProvider) {
return 1;
} else if (provider2 instanceof StringTextProvider) {
return -1;
} else {
return 0;
}
}
};
pf.setProviderComparator(comp);
// writers
List<ProviderInfo<MessageBodyWriter<?>>> writers = pf.getMessageWriters();
assertEquals(10, writers.size());
Object lastWriter = writers.get(9).getProvider();
assertTrue(lastWriter instanceof StringTextProvider);
//readers
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(9, readers.size());
Object lastReader = readers.get(8).getProvider();
assertTrue(lastReader instanceof StringTextProvider);
}
@Test
public void testCustomProviderSorting2() {
ProviderFactory pf = ServerProviderFactory.getInstance();
Comparator<Object> comp = new Comparator<Object>() {
@Override
public int compare(Object provider1, Object provider2) {
if (provider1 instanceof StringTextProvider) {
return 1;
} else if (provider2 instanceof StringTextProvider) {
return -1;
} else {
return 0;
}
}
};
pf.setProviderComparator(comp);
// writers
List<ProviderInfo<MessageBodyWriter<?>>> writers = pf.getMessageWriters();
assertEquals(10, writers.size());
Object lastWriter = writers.get(9).getProvider();
assertTrue(lastWriter instanceof StringTextProvider);
//readers
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(9, readers.size());
Object lastReader = readers.get(8).getProvider();
assertTrue(lastReader instanceof StringTextProvider);
}
@SuppressWarnings("rawtypes")
@Test
public void testCustomProviderSortingMBROnly() {
ProviderFactory pf = ServerProviderFactory.getInstance();
Comparator<ProviderInfo<MessageBodyReader>> comp =
new Comparator<ProviderInfo<MessageBodyReader>>() {
@Override
public int compare(ProviderInfo<MessageBodyReader> o1, ProviderInfo<MessageBodyReader> o2) {
MessageBodyReader<?> provider1 = o1.getProvider();
MessageBodyReader<?> provider2 = o2.getProvider();
if (provider1 instanceof StringTextProvider) {
return 1;
} else if (provider2 instanceof StringTextProvider) {
return -1;
} else {
return 0;
}
}
};
pf.setProviderComparator(comp);
// writers
List<ProviderInfo<MessageBodyWriter<?>>> writers = pf.getMessageWriters();
assertEquals(10, writers.size());
Object lastWriter = writers.get(8).getProvider();
assertFalse(lastWriter instanceof StringTextProvider);
//readers
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(9, readers.size());
Object lastReader = readers.get(8).getProvider();
assertTrue(lastReader instanceof StringTextProvider);
}
@Test
public void testCustomProviderSortingMBWOnly() {
ProviderFactory pf = ServerProviderFactory.getInstance();
Comparator<ProviderInfo<MessageBodyWriter<?>>> comp =
new Comparator<ProviderInfo<MessageBodyWriter<?>>>() {
@Override
public int compare(ProviderInfo<MessageBodyWriter<?>> o1, ProviderInfo<MessageBodyWriter<?>> o2) {
MessageBodyWriter<?> provider1 = o1.getProvider();
MessageBodyWriter<?> provider2 = o2.getProvider();
if (provider1 instanceof StringTextProvider) {
return 1;
} else if (provider2 instanceof StringTextProvider) {
return -1;
} else {
return 0;
}
}
};
pf.setProviderComparator(comp);
// writers
List<ProviderInfo<MessageBodyWriter<?>>> writers = pf.getMessageWriters();
assertEquals(10, writers.size());
Object lastWriter = writers.get(9).getProvider();
assertTrue(lastWriter instanceof StringTextProvider);
//readers
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(9, readers.size());
Object lastReader = readers.get(8).getProvider();
assertFalse(lastReader instanceof StringTextProvider);
}
@Test
public void testCustomProviderSortingWithBus() {
WildcardReader wc1 = new WildcardReader();
WildcardReader2 wc2 = new WildcardReader2();
Bus bus = BusFactory.newInstance().createBus();
bus.setProperty(MessageBodyReader.class.getName(), wc1);
ProviderFactory pf = ServerProviderFactory.createInstance(bus);
pf.registerUserProvider(wc2);
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(11, readers.size());
assertSame(wc2, readers.get(7).getProvider());
assertSame(wc1, readers.get(8).getProvider());
}
@Test
public void testCustomProviderSortingWithBus2() {
WildcardReader wc1 = new WildcardReader();
WildcardReader2 wc2 = new WildcardReader2();
Bus bus = BusFactory.newInstance().createBus();
bus.setProperty(MessageBodyReader.class.getName(), wc2);
ProviderFactory pf = ServerProviderFactory.createInstance(bus);
pf.registerUserProvider(wc1);
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertEquals(11, readers.size());
assertSame(wc1, readers.get(7).getProvider());
assertSame(wc2, readers.get(8).getProvider());
}
@Test
public void testCustomJaxbProvider() {
ProviderFactory pf = ServerProviderFactory.getInstance();
JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
pf.registerUserProvider(provider);
MessageBodyReader<Book> customJaxbReader = pf.createMessageBodyReader(Book.class, null, null,
MediaType.TEXT_XML_TYPE, new MessageImpl());
assertSame(customJaxbReader, provider);
MessageBodyWriter<Book> customJaxbWriter = pf.createMessageBodyWriter(Book.class, null, null,
MediaType.TEXT_XML_TYPE, new MessageImpl());
assertSame(customJaxbWriter, provider);
}
@Test
public void testDataSourceReader() {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new DataSourceProvider<Object>());
MessageBodyReader<DataSource> reader = pf.createMessageBodyReader(
DataSource.class, null, null,
MediaType.valueOf("image/png"), new MessageImpl());
assertTrue(reader instanceof DataSourceProvider);
MessageBodyReader<DataHandler> reader2 = pf.createMessageBodyReader(
DataHandler.class, null, null,
MediaType.valueOf("image/png"), new MessageImpl());
assertSame(reader, reader2);
}
@Test
public void testDataSourceWriter() {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new DataSourceProvider<Object>());
MessageBodyWriter<DataSource> writer = pf.createMessageBodyWriter(
DataSource.class, null, null,
MediaType.valueOf("image/png"), new MessageImpl());
assertTrue(writer instanceof DataSourceProvider);
MessageBodyWriter<DataHandler> writer2 = pf.createMessageBodyWriter(
DataHandler.class, null, null,
MediaType.valueOf("image/png"), new MessageImpl());
assertSame(writer, writer2);
}
@Test
public void testSchemaLocations() {
ProviderFactory pf = ServerProviderFactory.getInstance();
MessageBodyReader<Book> jaxbReader = pf.createMessageBodyReader(Book.class, null, null,
MediaType.TEXT_XML_TYPE, new MessageImpl());
assertTrue(jaxbReader instanceof JAXBElementProvider);
pf.setSchemaLocations(Collections.singletonList("classpath:/test.xsd"));
MessageBodyReader<Book> customJaxbReader = pf.createMessageBodyReader(
Book.class, null, null, MediaType.TEXT_XML_TYPE, new MessageImpl());
assertTrue(jaxbReader instanceof JAXBElementProvider);
assertSame(jaxbReader, customJaxbReader);
assertNotNull(((JAXBElementProvider<Book>)customJaxbReader).getSchema());
}
@Test
public void testGetFactoryInboundMessage() {
ProviderFactory factory = ServerProviderFactory.getInstance();
Message m = new MessageImpl();
Exchange e = new ExchangeImpl();
m.setExchange(e);
Endpoint endpoint = EasyMock.createMock(Endpoint.class);
endpoint.get(ServerProviderFactory.class.getName());
EasyMock.expectLastCall().andReturn(factory);
EasyMock.replay(endpoint);
e.put(Endpoint.class, endpoint);
assertSame(ProviderFactory.getInstance(m), factory);
}
@Test
public void testDefaultUserExceptionMappers() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
ExceptionMapper<?> mapper =
pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
assertNotNull(mapper);
WebApplicationExceptionMapper wm = new WebApplicationExceptionMapper();
pf.registerUserProvider(wm);
ExceptionMapper<?> mapper2 =
pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
assertNotSame(mapper, mapper2);
assertSame(wm, mapper2);
}
@Test
public void testExceptionMappersHierarchy1() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
WebApplicationExceptionMapper wm = new WebApplicationExceptionMapper();
pf.registerUserProvider(wm);
assertSame(wm, pf.createExceptionMapper(WebApplicationException.class, new MessageImpl()));
assertNull(pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
TestRuntimeExceptionMapper rm = new TestRuntimeExceptionMapper();
pf.registerUserProvider(rm);
assertSame(wm, pf.createExceptionMapper(WebApplicationException.class, new MessageImpl()));
assertSame(rm, pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
}
@Test
public void testExceptionMappersHierarchy2() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
TestRuntimeExceptionMapper rm = new TestRuntimeExceptionMapper();
pf.registerUserProvider(rm);
ExceptionMapper<WebApplicationException> em =
pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
assertTrue(em instanceof WebApplicationExceptionMapper);
assertSame(rm, pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
WebApplicationExceptionMapper wm = new WebApplicationExceptionMapper();
pf.registerUserProvider(wm);
assertSame(wm, pf.createExceptionMapper(WebApplicationException.class, new MessageImpl()));
assertSame(rm, pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
}
@Test
public void testExceptionMappersHierarchy3() throws Exception {
Message m = new MessageImpl();
m.put("default.wae.mapper.least.specific", true);
ServerProviderFactory pf = ServerProviderFactory.getInstance();
TestRuntimeExceptionMapper rm = new TestRuntimeExceptionMapper();
pf.registerUserProvider(rm);
ExceptionMapper<WebApplicationException> em =
pf.createExceptionMapper(WebApplicationException.class, m);
assertSame(rm, em);
assertSame(rm, pf.createExceptionMapper(RuntimeException.class, m));
WebApplicationExceptionMapper wm = new WebApplicationExceptionMapper();
pf.registerUserProvider(wm);
assertSame(wm, pf.createExceptionMapper(WebApplicationException.class, m));
assertSame(rm, pf.createExceptionMapper(RuntimeException.class, m));
}
@Test
public void testExceptionMappersHierarchy4() throws Exception {
Message m = new MessageImpl();
m.put("default.wae.mapper.least.specific", true);
ServerProviderFactory pf = ServerProviderFactory.getInstance();
ExceptionMapper<WebApplicationException> em =
pf.createExceptionMapper(WebApplicationException.class, m);
assertTrue(em instanceof WebApplicationExceptionMapper);
}
@Test
public void testExceptionMappersHierarchy5() throws Exception {
Message m = new MessageImpl();
ServerProviderFactory pf = ServerProviderFactory.getInstance();
ExceptionMapper<WebApplicationException> em =
pf.createExceptionMapper(WebApplicationException.class, m);
assertTrue(em instanceof WebApplicationExceptionMapper);
}
@Test
public void testExceptionMappersHierarchyWithGenerics() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
RuntimeExceptionMapper1 exMapper1 = new RuntimeExceptionMapper1();
pf.registerUserProvider(exMapper1);
RuntimeExceptionMapper2 exMapper2 = new RuntimeExceptionMapper2();
pf.registerUserProvider(exMapper2);
assertSame(exMapper1, pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
Object webExMapper = pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
assertSame(exMapper2, webExMapper);
}
@Test
public void testMessageBodyReaderString() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
MessageBodyReader<String> mbr = pf.createMessageBodyReader(String.class, String.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl());
assertTrue(mbr instanceof StringTextProvider);
}
@Test
public void testMessageBodyReaderBoolean() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new CustomBooleanReader());
MessageBodyReader<Boolean> mbr = pf.createMessageBodyReader(Boolean.class, Boolean.class, new Annotation[]{},
MediaType.TEXT_PLAIN_TYPE, new MessageImpl());
assertTrue(mbr instanceof PrimitiveTextProvider);
}
@Test
public void testMessageBodyReaderBoolean2() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new CustomBooleanReader2());
MessageBodyReader<Boolean> mbr = pf.createMessageBodyReader(Boolean.class, Boolean.class, new Annotation[]{},
MediaType.TEXT_PLAIN_TYPE, new MessageImpl());
assertTrue(mbr instanceof CustomBooleanReader2);
}
@Test
public void testMessageBodyWriterString() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
MessageBodyWriter<String> mbr = pf.createMessageBodyWriter(String.class, String.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl());
assertTrue(mbr instanceof StringTextProvider);
}
@Test
public void testMessageBodyHandlerHierarchy() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
List<Object> providers = new ArrayList<>();
BookReaderWriter bookHandler = new BookReaderWriter();
providers.add(bookHandler);
SuperBookReaderWriter superBookHandler = new SuperBookReaderWriter();
providers.add(superBookHandler);
pf.setUserProviders(providers);
assertSame(bookHandler,
pf.createMessageBodyReader(Book.class, Book.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
assertSame(superBookHandler,
pf.createMessageBodyReader(SuperBook.class, SuperBook.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
assertSame(bookHandler,
pf.createMessageBodyWriter(Book.class, Book.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
assertSame(superBookHandler,
pf.createMessageBodyWriter(SuperBook.class, SuperBook.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
}
@Test
public void testMessageBodyWriterNoTypes() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
List<Object> providers = new ArrayList<>();
SuperBookReaderWriter2<SuperBook> superBookHandler = new SuperBookReaderWriter2<SuperBook>();
providers.add(superBookHandler);
pf.setUserProviders(providers);
assertSame(superBookHandler,
pf.createMessageBodyReader(SuperBook.class, SuperBook.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
assertSame(superBookHandler,
pf.createMessageBodyWriter(SuperBook.class, SuperBook.class, new Annotation[]{},
MediaType.APPLICATION_XML_TYPE, new MessageImpl()));
}
@Test
public void testSortEntityProviders() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new TestStringProvider());
pf.registerUserProvider(new PrimitiveTextProvider<Object>());
List<ProviderInfo<MessageBodyReader<?>>> readers = pf.getMessageReaders();
assertTrue(indexOf(readers, TestStringProvider.class)
< indexOf(readers, PrimitiveTextProvider.class));
List<ProviderInfo<MessageBodyWriter<?>>> writers = pf.getMessageWriters();
assertTrue(indexOf(writers, TestStringProvider.class)
< indexOf(writers, PrimitiveTextProvider.class));
}
@Test
public void testParameterHandlerProvider() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
ParamConverterProvider h = new CustomerParameterHandler();
pf.registerUserProvider(h);
ParamConverter<Customer> h2 = pf.createParameterHandler(Customer.class, Customer.class, null,
new MessageImpl());
assertSame(h2, h);
}
@Test
public void testGetStringProvider() throws Exception {
verifyProvider(String.class, StringTextProvider.class, "text/plain");
}
@Test
public void testGetBinaryProvider() throws Exception {
verifyProvider(byte[].class, BinaryDataProvider.class, "*/*");
verifyProvider(InputStream.class, BinaryDataProvider.class, "image/png");
MessageBodyWriter<File> writer = ServerProviderFactory.getInstance()
.createMessageBodyWriter(File.class, null, null, MediaType.APPLICATION_OCTET_STREAM_TYPE,
new MessageImpl());
assertTrue(BinaryDataProvider.class == writer.getClass());
}
@Test
public void testGetComplexProvider() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new ComplexMessageBodyReader());
Message m = new MessageImpl();
Exchange ex = new ExchangeImpl();
m.setExchange(ex);
m.put(ServerProviderFactory.IGNORE_TYPE_VARIABLES, true);
MessageBodyReader<Book> reader =
pf.createMessageBodyReader(Book.class, Book.class, null, MediaType.APPLICATION_JSON_TYPE,
m);
assertTrue(ComplexMessageBodyReader.class == reader.getClass());
}
@Test
public void testGetComplexProvider2() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new ComplexMessageBodyReader());
MessageBodyReader<Book> reader =
pf.createMessageBodyReader(Book.class, Book.class, null, MediaType.APPLICATION_JSON_TYPE,
new MessageImpl());
assertTrue(ComplexMessageBodyReader.class == reader.getClass());
}
private void verifyProvider(ProviderFactory pf, Class<?> type, Class<?> provider, String mediaType)
throws Exception {
if (pf == null) {
pf = ServerProviderFactory.getInstance();
}
MediaType mType = MediaType.valueOf(mediaType);
MessageBodyReader<?> reader = pf.createMessageBodyReader(type, type, null, mType, new MessageImpl());
assertSame("Unexpected provider found", provider, reader.getClass());
MessageBodyWriter<?> writer = pf.createMessageBodyWriter(type, type, null, mType, new MessageImpl());
assertTrue("Unexpected provider found", provider == writer.getClass());
}
private void verifyProvider(Class<?> type, Class<?> provider, String mediaType)
throws Exception {
verifyProvider(null, type, provider, mediaType);
}
@Test
public void testGetStringProviderWildCard() throws Exception {
verifyProvider(String.class, StringTextProvider.class, "text/*");
}
@Test
public void testGetStringProviderUsingProviderDeclaration() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new TestStringProvider());
verifyProvider(pf, String.class, TestStringProvider.class, "text/html");
}
@Test
public void testRegisterCustomJSONEntityProvider() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new CustomJSONProvider());
verifyProvider(pf, Book.class, CustomJSONProvider.class,
"application/json");
}
@Test
public void testComplexExceptionMapper() {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new SecurityExceptionMapper());
ExceptionMapper<SecurityException> mapper =
pf.createExceptionMapper(SecurityException.class, new MessageImpl());
assertTrue(mapper instanceof SecurityExceptionMapper);
ExceptionMapper<Throwable> mapper2 =
pf.createExceptionMapper(Throwable.class, new MessageImpl());
assertNull(mapper2);
}
@Test
public void testRegisterCustomResolver() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new JAXBContextProvider());
Message message = prepareMessage("*/*", null);
ContextResolver<JAXBContext> cr = pf.createContextResolver(JAXBContext.class, message);
assertFalse(cr instanceof ProviderFactory.ContextResolverProxy);
assertTrue("JAXBContext ContextProvider can not be found",
cr instanceof JAXBContextProvider);
}
@Test
public void testRegisterCustomResolver2() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new JAXBContextProvider());
pf.registerUserProvider(new JAXBContextProvider2());
Message message = prepareMessage("text/xml+b", null);
ContextResolver<JAXBContext> cr = pf.createContextResolver(JAXBContext.class, message);
assertFalse(cr instanceof ProviderFactory.ContextResolverProxy);
assertTrue("JAXBContext ContextProvider can not be found",
cr instanceof JAXBContextProvider2);
}
@Test
public void testNoCustomResolver() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new JAXBContextProvider());
pf.registerUserProvider(new JAXBContextProvider2());
Message message = prepareMessage("text/xml+c", null);
ContextResolver<JAXBContext> cr = pf.createContextResolver(JAXBContext.class, message);
assertNull(cr);
}
@Test
public void testCustomResolverProxy() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new JAXBContextProvider());
pf.registerUserProvider(new JAXBContextProvider2());
Message message = prepareMessage("text/xml+*", null);
ContextResolver<JAXBContext> cr = pf.createContextResolver(JAXBContext.class, message);
assertTrue(cr instanceof ProviderFactory.ContextResolverProxy);
assertTrue(((ProviderFactory.ContextResolverProxy<?>)cr).getResolvers().get(0)
instanceof JAXBContextProvider);
assertTrue(((ProviderFactory.ContextResolverProxy<?>)cr).getResolvers().get(1)
instanceof JAXBContextProvider2);
}
private Message prepareMessage(String contentType, String acceptType) {
Message message = new MessageImpl();
Map<String, List<String>> headers = new MetadataMap<String, String>();
message.put(Message.PROTOCOL_HEADERS, headers);
Exchange exchange = new ExchangeImpl();
exchange.setInMessage(message);
if (acceptType != null) {
headers.put("Accept", Collections.singletonList(acceptType));
exchange.setOutMessage(new MessageImpl());
} else {
headers.put("Content-Type", Collections.singletonList(contentType));
}
message.put("Content-Type", contentType);
message.setExchange(exchange);
return message;
}
@Test
public void testRegisterCustomEntityProvider() throws Exception {
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(new CustomWidgetProvider());
verifyProvider(pf, org.apache.cxf.jaxrs.resources.Book.class, CustomWidgetProvider.class,
"application/widget");
}
private int indexOf(List<? extends Object> providerInfos, Class<?> providerType) {
int index = 0;
for (Object pi : providerInfos) {
Object p = ((ProviderInfo<?>)pi).getProvider();
if (p.getClass().isAssignableFrom(providerType)) {
break;
}
index++;
}
return index;
}
@Consumes("text/html")
@Produces("text/html")
private final class TestStringProvider
implements MessageBodyReader<String>, MessageBodyWriter<String> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type == String.class;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type == String.class;
}
public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return s.length();
}
public String readFrom(Class<String> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, String> headers, InputStream is) {
try {
return IOUtils.toString(is);
} catch (IOException e) {
// TODO: better exception handling
}
return null;
}
public void writeTo(String obj, Class<?> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
try {
os.write(obj.getBytes());
} catch (IOException e) {
// TODO: better exception handling
}
}
}
@Consumes("application/json")
@Produces("application/json")
private final class CustomJSONProvider
implements MessageBodyReader<Book>, MessageBodyWriter<Book> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type.getAnnotation(XmlRootElement.class) != null;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type.getAnnotation(XmlRootElement.class) != null;
}
public long getSize(Book b, Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return -1;
}
public Book readFrom(Class<Book> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, String> headers, InputStream is) {
//Dummy
return null;
}
public void writeTo(Book obj, Class<?> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
//Dummy
}
}
@Consumes("application/widget")
@Produces("application/widget")
private final class CustomWidgetProvider
implements MessageBodyReader<Book>, MessageBodyWriter<Book> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type.getAnnotation(XmlRootElement.class) != null;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return type.getAnnotation(XmlRootElement.class) != null;
}
public long getSize(Book s, Class<?> type, Type genericType, Annotation[] annotations,
MediaType m) {
return -1;
}
public Book readFrom(Class<Book> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, String> headers, InputStream is) {
//Dummy
return null;
}
public void writeTo(Book obj, Class<?> clazz, Type genericType, Annotation[] annotations,
MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
//Dummy
}
}
@Test
public void testSetSchemasFromClasspath() {
JAXBElementProvider<?> provider = new JAXBElementProvider<Object>();
ProviderFactory pf = ServerProviderFactory.getInstance();
pf.registerUserProvider(provider);
List<String> locations = new ArrayList<>();
locations.add("classpath:/test.xsd");
pf.setSchemaLocations(locations);
Schema s = provider.getSchema();
assertNotNull("schema can not be read from classpath", s);
}
private static class TestRuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
public Response toResponse(RuntimeException exception) {
// TODO Auto-generated method stub
return null;
}
}
@Produces("application/xml")
@Consumes("application/xml")
private static class BookReaderWriter
implements MessageBodyReader<Book>, MessageBodyWriter<Book> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public Book readFrom(Class<Book> arg0, Type arg1, Annotation[] arg2,
MediaType arg3, MultivaluedMap<String, String> arg4, InputStream arg5)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
return null;
}
public long getSize(Book t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
// TODO Auto-generated method stub
return 0;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public void writeTo(Book arg0, Class<?> arg1, Type arg2, Annotation[] arg3,
MediaType arg4, MultivaluedMap<String, Object> arg5, OutputStream arg6)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
}
}
@Produces("application/xml")
@Consumes("application/xml")
private static class SuperBookReaderWriter
implements MessageBodyReader<SuperBook>, MessageBodyWriter<SuperBook> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public SuperBook readFrom(Class<SuperBook> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
return null;
}
public long getSize(SuperBook t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// TODO Auto-generated method stub
return 0;
}
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public void writeTo(SuperBook arg0, Class<?> arg1, Type arg2,
Annotation[] arg3, MediaType arg4, MultivaluedMap<String, Object> arg5,
OutputStream arg6) throws IOException, WebApplicationException {
// TODO Auto-generated method stub
}
}
@Produces("application/xml")
@Consumes("application/xml")
private static class SuperBookReaderWriter2<T>
implements MessageBodyReader<T>, MessageBodyWriter<T> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public T readFrom(Class<T> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
return null;
}
public long getSize(T t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// TODO Auto-generated method stub
return 0;
}
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
}
}
@Produces("*/*")
@Consumes("*/*")
private static class WildcardReader implements MessageBodyReader<Object> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public Object readFrom(Class<Object> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
return null;
}
}
@Produces("*/*")
@Consumes("*/*")
private static class WildcardReader2 implements MessageBodyReader<Object> {
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return true;
}
public Object readFrom(Class<Object> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5)
throws IOException, WebApplicationException {
// TODO Auto-generated method stub
return null;
}
}
private static class RuntimeExceptionMapper1
extends AbstractTestExceptionMapper<RuntimeException> {
}
private static class RuntimeExceptionMapper2
extends AbstractTestExceptionMapper<WebApplicationException> {
}
private static class AbstractTestExceptionMapper<T extends RuntimeException>
implements ExceptionMapper<T> {
public Response toResponse(T arg0) {
// TODO Auto-generated method stub
return null;
}
}
private static class ComplexMessageBodyReader extends ProviderBase<AClass> {
}
private abstract static class ProviderBase<A> implements
MessageBodyReader<Object>, MessageBodyWriter<Object> {
@Override
public boolean isReadable(Class<?> cls, Type arg1, Annotation[] arg2, MediaType arg3) {
return true;
}
@Override
public Object readFrom(Class<Object> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5) throws IOException,
WebApplicationException {
// TODO Auto-generated method stub
return null;
}
@Override
public long getSize(Object arg0, Class<?> arg1, Type arg2, Annotation[] arg3, MediaType arg4) {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2, MediaType arg3) {
// TODO Auto-generated method stub
return false;
}
@Override
public void writeTo(Object arg0, Class<?> arg1, Type arg2, Annotation[] arg3, MediaType arg4,
MultivaluedMap<String, Object> arg5, OutputStream arg6) throws IOException,
WebApplicationException {
// TODO Auto-generated method stub
}
}
public static class AClass {
}
private static class SecurityExceptionMapper
extends AbstractBadRequestExceptionMapper<SecurityException> {
}
private static class CustomWebApplicationExceptionMapper
extends AbstractBadRequestExceptionMapper<WebApplicationException> {
}
private abstract static class AbstractBadRequestExceptionMapper<T extends Throwable>
implements ExceptionMapper<T> {
@Override
public Response toResponse(T exception) {
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
@Test
public void testWebApplicationMapperWithGenerics() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
CustomWebApplicationExceptionMapper mapper = new CustomWebApplicationExceptionMapper();
pf.registerUserProvider(mapper);
Object mapperResponse = pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
assertSame(mapperResponse, mapper);
}
@Test
public void testBadCustomExceptionMappersHierarchyWithGenerics() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
BadExceptionMapperA badExceptionMapperA = new BadExceptionMapperA();
pf.registerUserProvider(badExceptionMapperA);
BadExceptionMapperB badExceptionMapperB = new BadExceptionMapperB();
pf.registerUserProvider(badExceptionMapperB);
Object mapperResponse1 = pf.createExceptionMapper(RuntimeExceptionA.class, new MessageImpl());
assertSame(badExceptionMapperA, mapperResponse1);
Object mapperResponse2 = pf.createExceptionMapper(RuntimeExceptionB.class, new MessageImpl());
assertSame(badExceptionMapperB, mapperResponse2);
Object mapperResponse3 = pf.createExceptionMapper(RuntimeExceptionAA.class, new MessageImpl());
assertSame(badExceptionMapperA, mapperResponse3);
Object mapperResponse4 = pf.createExceptionMapper(RuntimeExceptionBB.class, new MessageImpl());
assertSame(badExceptionMapperB, mapperResponse4);
}
@Test
public void testGoodExceptionMappersHierarchyWithGenerics() throws Exception {
ServerProviderFactory pf = ServerProviderFactory.getInstance();
GoodRuntimeExceptionAMapper runtimeExceptionAMapper = new GoodRuntimeExceptionAMapper();
pf.registerUserProvider(runtimeExceptionAMapper);
GoodRuntimeExceptionBMapper runtimeExceptionBMapper = new GoodRuntimeExceptionBMapper();
pf.registerUserProvider(runtimeExceptionBMapper);
Object mapperResponse1 = pf.createExceptionMapper(RuntimeExceptionA.class, new MessageImpl());
assertSame(runtimeExceptionAMapper, mapperResponse1);
Object mapperResponse2 = pf.createExceptionMapper(RuntimeExceptionB.class, new MessageImpl());
assertSame(runtimeExceptionBMapper, mapperResponse2);
Object mapperResponse3 = pf.createExceptionMapper(RuntimeExceptionAA.class, new MessageImpl());
assertSame(runtimeExceptionAMapper, mapperResponse3);
Object mapperResponse4 = pf.createExceptionMapper(RuntimeExceptionBB.class, new MessageImpl());
assertSame(runtimeExceptionBMapper, mapperResponse4);
}
private static class RuntimeExceptionA extends RuntimeException {
private static final long serialVersionUID = 1L;
}
private static class RuntimeExceptionAA extends RuntimeExceptionA {
private static final long serialVersionUID = 1L;
}
private static class RuntimeExceptionB extends RuntimeException {
private static final long serialVersionUID = 1L;
}
private static class RuntimeExceptionBB extends RuntimeExceptionB {
private static final long serialVersionUID = 1L;
}
private static class GoodRuntimeExceptionAMapper implements ExceptionMapper<RuntimeExceptionA> {
@Override
public Response toResponse(RuntimeExceptionA exception) {
return null;
}
}
private static class GoodRuntimeExceptionBMapper implements ExceptionMapper<RuntimeExceptionB> {
@Override
public Response toResponse(RuntimeExceptionB exception) {
return null;
}
}
public abstract static class BadParentExceptionMapper<T extends Throwable> implements ExceptionMapper<T> {
}
public static class BadExceptionMapperA extends BadParentExceptionMapper<RuntimeExceptionA> {
@Override
public Response toResponse(RuntimeExceptionA exception) {
return null;
}
}
public static class BadExceptionMapperB extends BadParentExceptionMapper<RuntimeExceptionB> {
@Override
public Response toResponse(RuntimeExceptionB exception) {
return null;
}
}
@Consumes("text/plain")
public static class CustomBooleanReader2 extends CustomBooleanReader {
}
public static class CustomBooleanReader implements MessageBodyReader<Boolean> {
@Override
public boolean isReadable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
return type == Boolean.class;
}
@Override
public Boolean readFrom(Class<Boolean> type,
Type type1,
Annotation[] antns,
MediaType mt, MultivaluedMap<String, String> mm,
InputStream in) throws IOException, WebApplicationException {
return Boolean.TRUE;
}
}
}