Repository: tomee Updated Branches: refs/heads/master 9beea6937 -> 3ea255664
CXF 3.1.2 Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/3ea25566 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/3ea25566 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/3ea25566 Branch: refs/heads/master Commit: 3ea25566488eac63873b9ce6380991fb391cef8e Parents: 9beea69 Author: Romain Manni-Bucau <[email protected]> Authored: Mon Aug 3 19:11:35 2015 +0200 Committer: Romain Manni-Bucau <[email protected]> Committed: Mon Aug 3 19:11:35 2015 +0200 ---------------------------------------------------------------------- pom.xml | 2 +- .../apache/openejb/server/cxf/rs/CxfHacks.java | 1 + .../openejb/server/cxf/rs/CxfRSService.java | 60 +---- .../server/cxf/rs/CxfRsHttpListener.java | 246 ++++++++++++------- .../server/cxf/rs/CustomProviderTest.java | 32 ++- .../cxf/rs/CustomProviderWithConfigTest.java | 14 +- .../cxf/rs/DiscoverCustomProviderTest.java | 17 +- .../cxf/rs/ProviderWithConstructorTest.java | 4 +- .../openejb/server/cxf/rs/SortProviderTest.java | 54 ++-- 9 files changed, 254 insertions(+), 176 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index b8a1e8c..c83caa9 100644 --- a/pom.xml +++ b/pom.xml @@ -128,7 +128,7 @@ <tomcat.version>8.0.24</tomcat.version> - <cxf.version>3.1.0</cxf.version> + <cxf.version>3.1.2</cxf.version> <ehcache.version>2.8.5</ehcache.version> <!-- used by cxf for security (replay attack) --> <jetty.version>7.5.3.v20111011</jetty.version> http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfHacks.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfHacks.java b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfHacks.java index f83997b..0780e84 100644 --- a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfHacks.java +++ b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfHacks.java @@ -18,6 +18,7 @@ package org.apache.openejb.server.cxf.rs; import org.apache.cxf.common.util.ClassHelper; import org.apache.openejb.loader.SystemInstance; +import org.apache.openejb.server.cxf.transport.util.CxfUtil; import org.apache.openejb.util.reflection.Reflections; public final class CxfHacks { http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRSService.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRSService.java b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRSService.java index 581508a..61f016c 100644 --- a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRSService.java +++ b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRSService.java @@ -19,15 +19,6 @@ package org.apache.openejb.server.cxf.rs; import org.apache.cxf.Bus; import org.apache.cxf.binding.BindingFactoryManager; import org.apache.cxf.jaxrs.JAXRSBindingFactory; -import org.apache.cxf.jaxrs.client.ClientProviderFactory; -import org.apache.cxf.jaxrs.provider.BinaryDataProvider; -import org.apache.cxf.jaxrs.provider.DataSourceProvider; -import org.apache.cxf.jaxrs.provider.FormEncodingProvider; -import org.apache.cxf.jaxrs.provider.JAXBElementProvider; -import org.apache.cxf.jaxrs.provider.MultipartProvider; -import org.apache.cxf.jaxrs.provider.PrimitiveTextProvider; -import org.apache.cxf.jaxrs.provider.ProviderFactory; -import org.apache.cxf.jaxrs.provider.SourceProvider; import org.apache.cxf.transport.DestinationFactory; import org.apache.cxf.transport.http.HTTPTransportFactory; import org.apache.johnzon.jaxrs.JohnzonProvider; @@ -52,7 +43,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -60,9 +50,9 @@ import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.net.Socket; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import javax.enterprise.context.ApplicationScoped; @@ -190,7 +180,7 @@ public class CxfRSService extends RESTService { } } hacksOn(); - initCxfClientBuilderProviders(bus); + initCxfProviders(bus); } finally { if (oldLoader != null) { CxfUtil.clearBusLoader(oldLoader); @@ -198,33 +188,20 @@ public class CxfRSService extends RESTService { } } - private void initCxfClientBuilderProviders(final Bus bus) { - if (bus.getProperty("jaxrs.shared.client.factory") == null) { - try { - final Constructor<ClientProviderFactory> constructor = ClientProviderFactory.class.getDeclaredConstructor(ProviderFactory.class, Bus.class); - constructor.setAccessible(true); - final ClientProviderFactory factory = constructor.newInstance(null, bus); - - final Method set = ClientProviderFactory.class.getDeclaredMethod("setProviders", Object[].class); - set.setAccessible(true); + private void initCxfProviders(final Bus bus) { + if (bus.getProperty("org.apache.cxf.jaxrs.bus.providers") == null) { + bus.setProperty("skip.default.json.provider.registration", "true"); // client jaxrs, we want johnzon not jettison + try { + final List<Object> all; final String userProviders = SystemInstance.get().getProperty("openejb.jaxrs.client.providers"); - final Object[][] providers; // vararg -> array, reflection -> array if (userProviders == null) { - providers = new Object[][] {{ - new BinaryDataProvider<>(), - new SourceProvider<>(), - new DataSourceProvider<>(), - new FormEncodingProvider<>(), - new PrimitiveTextProvider<>(), + (all = new ArrayList<>(2)).addAll(asList( new JohnzonProvider<>(), - new JAXBElementProvider<>(), - new JsrProvider(), - new MultipartProvider() - }}; + new JsrProvider() + )); } else { - final Collection<Object> all = new ArrayList<>(16); - + all = new ArrayList<>(4 /* blind guess */); for (String p : userProviders.split(" *, *")) { p= p.trim(); if (p.isEmpty()) { @@ -235,21 +212,10 @@ public class CxfRSService extends RESTService { } all.addAll(asList( // added after to be after in the list once sorted - new BinaryDataProvider<>(), - new SourceProvider<>(), - new DataSourceProvider<>(), - new FormEncodingProvider<>(), - new PrimitiveTextProvider<>(), new JohnzonProvider<>(), - new JAXBElementProvider<>(), - new JsrProvider(), - new MultipartProvider())); - - providers = new Object[][] { all.toArray(new Object[all.size()]) }; + new JsrProvider())); } - set.invoke(factory, providers); - - bus.setProperty("jaxrs.shared.client.factory", factory); + bus.setProperty("org.apache.cxf.jaxrs.bus.providers", all); } catch (final Exception e) { throw new IllegalStateException(e); } http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java index fe5e613..e3eaae4 100644 --- a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java +++ b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java @@ -27,25 +27,20 @@ import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.JAXRSServiceImpl; import org.apache.cxf.jaxrs.ext.ResourceComparator; -import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper; import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.jaxrs.model.MethodDispatcher; import org.apache.cxf.jaxrs.model.OperationResourceInfo; -import org.apache.cxf.jaxrs.provider.BinaryDataProvider; -import org.apache.cxf.jaxrs.provider.DataSourceProvider; -import org.apache.cxf.jaxrs.provider.FormEncodingProvider; -import org.apache.cxf.jaxrs.provider.JAXBElementProvider; -import org.apache.cxf.jaxrs.provider.MultipartProvider; -import org.apache.cxf.jaxrs.provider.PrimitiveTextProvider; -import org.apache.cxf.jaxrs.provider.SourceProvider; +import org.apache.cxf.jaxrs.model.ProviderInfo; +import org.apache.cxf.jaxrs.provider.ProviderFactory; +import org.apache.cxf.jaxrs.provider.ServerProviderFactory; +import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.jaxrs.validation.ValidationExceptionMapper; +import org.apache.cxf.message.Message; import org.apache.cxf.service.invoker.Invoker; import org.apache.cxf.transport.DestinationFactory; import org.apache.cxf.transport.servlet.BaseUrlHelper; -import org.apache.johnzon.jaxrs.JohnzonProvider; -import org.apache.johnzon.jaxrs.JsrProvider; import org.apache.johnzon.jaxrs.WadlDocumentMessageBodyWriter; import org.apache.openejb.AppContext; import org.apache.openejb.BeanContext; @@ -81,28 +76,18 @@ import org.apache.openejb.util.AppFinder; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.openejb.util.proxy.ProxyEJB; +import org.apache.openejb.util.reflection.Reflections; import org.apache.webbeans.config.WebBeansContext; import org.apache.webbeans.container.BeanManagerImpl; import org.apache.webbeans.context.creational.CreationalContextImpl; -import javax.enterprise.context.spi.CreationalContext; -import javax.enterprise.inject.spi.Bean; -import javax.management.ObjectName; -import javax.management.openmbean.TabularData; -import javax.naming.Context; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.ConstrainedTo; -import javax.ws.rs.RuntimeType; -import javax.ws.rs.core.Application; -import javax.xml.bind.Marshaller; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; @@ -119,6 +104,22 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; import java.util.regex.Pattern; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.management.ObjectName; +import javax.management.openmbean.TabularData; +import javax.naming.Context; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.ConstrainedTo; +import javax.ws.rs.RuntimeType; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Configuration; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; import static org.apache.openejb.loader.JarLocation.jarLocation; @@ -230,7 +231,7 @@ public class CxfRsHttpListener implements RsHttpListener { } String path = request.getRequestURI().substring(request.getContextPath().length()); - if (path == null || path.isEmpty()) { + if (path.isEmpty()) { path = "/"; } for (final Pattern pattern : staticResourcesList) { @@ -461,20 +462,9 @@ public class CxfRsHttpListener implements RsHttpListener { } private static void addMandatoryProviders(final Collection<Object> instances) { - instances.add(new JsrProvider()); instances.add(new WadlDocumentMessageBodyWriter()); instances.add(EJBAccessExceptionMapper.INSTANCE); instances.add(new ValidationExceptionMapper()); - - if ("true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.jaxrs.cxf.add-cxf-providers", "false"))) { - instances.add(new WebApplicationExceptionMapper()); - instances.add(new BinaryDataProvider<>()); - instances.add(new SourceProvider<>()); - instances.add(new DataSourceProvider<>()); - instances.add(new FormEncodingProvider<>()); - instances.add(new PrimitiveTextProvider<>()); - instances.add(new MultipartProvider()); - } } private Object newProvider(final Class<?> clazz) throws IllegalAccessException, InstantiationException { @@ -590,6 +580,20 @@ public class CxfRsHttpListener implements RsHttpListener { try { server = factory.create(); fireServerCreated(oldLoader); + + final ServerProviderFactory spf = ServerProviderFactory.class.cast(server.getEndpoint().get(ServerProviderFactory.class.getName())); + LOGGER.info("Using readers:"); + for (final Object provider : List.class.cast(Reflections.get(spf, "messageReaders"))) { + LOGGER.info(" " + ProviderInfo.class.cast(provider).getProvider()); + } + LOGGER.info("Using writers:"); + for (final Object provider : List.class.cast(Reflections.get(spf, "messageWriters"))) { + LOGGER.info(" " + ProviderInfo.class.cast(provider).getProvider()); + } + LOGGER.info("Using exception mappers:"); + for (final Object provider : List.class.cast(Reflections.get(spf, "exceptionMappers"))) { + LOGGER.info(" " + ProviderInfo.class.cast(provider).getProvider()); + } } finally { try { SERVER_IMPL_LOGGER.setLevel(level); @@ -778,6 +782,12 @@ public class CxfRsHttpListener implements RsHttpListener { final ServiceConfiguration serviceConfiguration, final JAXRSServerFactoryBean factory, final WebBeansContext ctx) { + if (!"true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.cxf.rs.skip-provider-sorting", "false"))) { + final Comparator<?> providerComparator = findProviderComparator(serviceConfiguration, ctx); + if (providerComparator != null) { + factory.setProviderComparator(providerComparator); + } + } CxfUtil.configureEndpoint(factory, serviceConfiguration, CXF_JAXRS_PREFIX); final Collection<ServiceInfo> services = serviceConfiguration.getAvailableServices(); @@ -845,15 +855,13 @@ public class CxfRsHttpListener implements RsHttpListener { if (providersConfig != null) { providers = ServiceInfos.resolve(services, providersConfig.toArray(new String[providersConfig.size()]), OpenEJBProviderFactory.INSTANCE); if (providers != null && additionalProviders != null && !additionalProviders.isEmpty()) { - providers.addAll(sortProviders(serviceConfiguration, ctx, additionalProviders)); + providers.addAll(providers(serviceConfiguration.getAvailableServices(), additionalProviders, ctx)); } } if (providers == null) { providers = new ArrayList<>(4); if (additionalProviders != null && !additionalProviders.isEmpty()) { - providers.addAll(sortProviders(serviceConfiguration, ctx, additionalProviders)); - } else { - providers.addAll(defaultProviders()); + providers.addAll(providers(serviceConfiguration.getAvailableServices(), additionalProviders, ctx)); } } @@ -864,28 +872,19 @@ public class CxfRsHttpListener implements RsHttpListener { SystemInstance.get().fireEvent(new ExtensionProviderRegistration( AppFinder.findAppContextOrWeb(Thread.currentThread().getContextClassLoader(), AppFinder.AppContextTransformer.INSTANCE), providers)); - LOGGER.info("Using providers:"); - for (final Object provider : providers) { - LOGGER.info(" " + provider); + if (!providers.isEmpty()) { + factory.setProviders(providers); } - factory.setProviders(providers); } - private List<Object> sortProviders(final ServiceConfiguration serviceConfiguration, final WebBeansContext ctx, - final Collection<Object> additionalProviders) { - final Collection<ServiceInfo> services = serviceConfiguration.getAvailableServices(); - final List<Object> loadedProviders = providers(services, additionalProviders, ctx); - if ("true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.cxf.rs.skip-provider-sorting", "false"))) { - return loadedProviders; - } - + private Comparator<?> findProviderComparator(final ServiceConfiguration serviceConfiguration, final WebBeansContext ctx) { final String comparatorKey = CXF_JAXRS_PREFIX + "provider-comparator"; final String comparatorClass = serviceConfiguration.getProperties() .getProperty(comparatorKey, SystemInstance.get().getProperty(comparatorKey)); Comparator<Object> comparator = null; if (comparatorClass == null) { - comparator = DefaultProviderComparator.INSTANCE; + return null; // try to rely on CXF behavior otherwise just reactivate DefaultProviderComparator.INSTANCE if it is an issue } else { final BeanManagerImpl bm = ctx == null ? null : ctx.getBeanManagerImpl(); if (bm != null && bm.isInUse()) { @@ -904,7 +903,7 @@ public class CxfRsHttpListener implements RsHttpListener { } if (comparator == null) { - comparator = Comparator.class.cast(ServiceInfos.resolve(services, comparatorClass)); + comparator = Comparator.class.cast(ServiceInfos.resolve(serviceConfiguration.getAvailableServices(), comparatorClass)); } if (comparator == null) { try { @@ -913,30 +912,38 @@ public class CxfRsHttpListener implements RsHttpListener { throw new IllegalArgumentException(e); } } - } - Collections.sort(loadedProviders, comparator); - return loadedProviders; - } - private static List<Object> defaultProviders() { - final JAXBElementProvider jaxb = new JAXBElementProvider(); - final Map<String, Object> jaxbProperties = new HashMap<>(); - jaxbProperties.put(Marshaller.JAXB_FRAGMENT, true); - jaxb.setMarshallerProperties(jaxbProperties); + for (final Type itf : comparator.getClass().getGenericInterfaces()) { + if (!ParameterizedType.class.isInstance(itf)) { + continue; + } - final List<Object> providers = new ArrayList<>(2); - providers.add(new JohnzonProvider<>()); - providers.add(jaxb); - return providers; + final ParameterizedType pt = ParameterizedType.class.cast(itf); + if (Comparator.class == pt.getRawType() && pt.getActualTypeArguments().length > 0) { + final Type t = pt.getActualTypeArguments()[0]; + if (Class.class.isInstance(t) && ProviderInfo.class == t) { + return comparator; + } + if (ParameterizedType.class.isInstance(t) && ProviderInfo.class == ParameterizedType.class.cast(t).getRawType()) { + return comparator; + } + } + } + + return new ProviderComparatorWrapper(comparator); + } } - // we use Object cause an app with a custom comparator can desire to compare instances - private static final class DefaultProviderComparator implements Comparator<Object> { - private static final DefaultProviderComparator INSTANCE = new DefaultProviderComparator(); + // public to ensure it can be configured since not setup by default anymore + public static final class DefaultProviderComparator extends ProviderFactory implements Comparator<ProviderInfo<?>> { private static final ClassLoader SYSTEM_LOADER = ClassLoader.getSystemClassLoader(); + public DefaultProviderComparator() { + super(null); + } + @Override - public int compare(final Object o1, final Object o2) { + public int compare(final ProviderInfo<?> o1, final ProviderInfo<?> o2) { if (o1 == o2 || (o1 != null && o1.equals(o2))) { return 0; } @@ -947,8 +954,17 @@ public class CxfRsHttpListener implements RsHttpListener { return 1; } - final Class<?> c1 = o1.getClass(); - final Class<?> c2 = o2.getClass(); + final Class<?> c1 = o1.getProvider().getClass(); + final Class<?> c2 = o2.getProvider().getClass(); + if (c1.getName().startsWith("org.apache.cxf.")) { + if (!c2.getName().startsWith("org.apache.cxf.")) { + return 1; + } + return -1; + } + if (c2.getName().startsWith("org.apache.cxf.")) { + return -1; + } final ClassLoader classLoader1 = c1.getClassLoader(); final ClassLoader classLoader2 = c2.getClassLoader(); @@ -965,22 +981,64 @@ public class CxfRsHttpListener implements RsHttpListener { return -1; } } else { - final File l1 = jarLocation(c1); - final File l2 = jarLocation(c2); - if (l1 == null) { - return 1; + int result = compareClasses(o1.getProvider(), o2.getProvider()); + if (result != 0) { + return result; } - if (l2 == null) { - return -1; + + if (MessageBodyWriter.class.isInstance(o1.getProvider())) { + final List<MediaType> types1 = + JAXRSUtils.sortMediaTypes(JAXRSUtils.getProviderProduceTypes(MessageBodyWriter.class.cast(o1.getProvider())), JAXRSUtils.MEDIA_TYPE_QS_PARAM); + final List<MediaType> types2 = + JAXRSUtils.sortMediaTypes(JAXRSUtils.getProviderProduceTypes(MessageBodyWriter.class.cast(o2.getProvider())), JAXRSUtils.MEDIA_TYPE_QS_PARAM); + + if (types1.contains(MediaType.WILDCARD_TYPE) && !types2.contains(MediaType.WILDCARD_TYPE)) { + return 1; + } + if (types2.contains(MediaType.WILDCARD_TYPE) && !types1.contains(MediaType.WILDCARD_TYPE)) { + return -1; + } + + result = JAXRSUtils.compareSortedMediaTypes(types1, types2, JAXRSUtils.MEDIA_TYPE_QS_PARAM); + if (result != 0) { + return result; + } + } + if (MessageBodyReader.class.isInstance(o1.getProvider())) { + final List<MediaType> types1 = + JAXRSUtils.sortMediaTypes(JAXRSUtils.getProviderConsumeTypes(MessageBodyReader.class.cast(o1.getProvider())), null); + final List<MediaType> types2 = + JAXRSUtils.sortMediaTypes(JAXRSUtils.getProviderConsumeTypes(MessageBodyReader.class.cast(o2.getProvider())), null); + + result = JAXRSUtils.compareSortedMediaTypes(types1, types2, JAXRSUtils.MEDIA_TYPE_QS_PARAM); + if (result != 0) { + return result; + } } - try { // WEB-INF/classes will be before WEB-INF/lib automatically - return l1.getCanonicalPath().compareTo(l2.getCanonicalPath()); - } catch (final IOException e) { + final Boolean custom1 = o1.isCustom(); + final Boolean custom2 = o2.isCustom(); + final int customComp = custom1.compareTo(custom2) * -1; + if (customComp != 0) { + return customComp; + } + + try { // WEB-INF/classes will be before WEB-INF/lib + final File file1 = jarLocation(c1); + final File file2 = jarLocation(c2); + if ("classes".equals(file1.getName())) { + if ("classes".equals(file2.getName())) { + return c1.getName().compareTo(c2.getName()); + } + return -1; + } + if ("classes".equals(file2.getName())) { + return 1; + } + } catch (final Exception e) { // no-op: sort by class name } } - return c1.getName().compareTo(c2.getName()); } @@ -994,6 +1052,30 @@ public class CxfRsHttpListener implements RsHttpListener { } return false; } + + @Override + public Configuration getConfiguration(final Message message) { + throw new UnsupportedOperationException("not a real inheritance"); + } + + @Override + protected void setProviders(final boolean custom, final Object... providers) { + throw new UnsupportedOperationException("not a real inheritance"); + } + } + + // we use Object cause an app with a custom comparator can desire to compare instances + private static final class ProviderComparatorWrapper implements Comparator<ProviderInfo<?>> { + private final Comparator<Object> delegate; + + private ProviderComparatorWrapper(final Comparator<Object> delegate) { + this.delegate = delegate; + } + + @Override + public int compare(final ProviderInfo<?> o1, final ProviderInfo<?> o2) { + return delegate.compare(o1.getProvider(), o2.getProvider()); + } } private static class OpenEJBProviderFactory implements ServiceInfos.Factory { http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderTest.java index 1b082ef..57deee1 100644 --- a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderTest.java +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderTest.java @@ -26,6 +26,11 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Properties; import javax.ejb.Singleton; import javax.ejb.embeddable.EJBContainer; import javax.ws.rs.GET; @@ -35,11 +40,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Properties; import static org.junit.Assert.assertEquals; @@ -86,8 +86,8 @@ public class CustomProviderTest { @GET @Path("/reverse") @Produces("openejb/reverse") - public String go() { - return "redivorp"; + public Message go() { + return new Message("redivorp"); } } @@ -97,8 +97,8 @@ public class CustomProviderTest { @GET @Path("/constant") @Produces("openejb/constant") - public String go() { - return "will be overriden"; + public Message go() { + return new Message("will be overriden"); } } @@ -124,12 +124,12 @@ public class CustomProviderTest { @Override public boolean isWriteable(Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; + return Message.class == rawType; } @Override public void writeTo(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { - entityStream.write(reverse((String) t).getBytes()); + entityStream.write(reverse(Message.class.cast(t).text).getBytes()); } } @@ -143,7 +143,7 @@ public class CustomProviderTest { @Override public boolean isWriteable(Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; + return Message.class == rawType; } @Override @@ -151,4 +151,12 @@ public class CustomProviderTest { entityStream.write("it works!".getBytes()); } } + + public static class Message { + private final String text; + + public Message(final String text) { + this.text = text; + } + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderWithConfigTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderWithConfigTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderWithConfigTest.java index e1806f6..c7799de 100644 --- a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderWithConfigTest.java +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CustomProviderWithConfigTest.java @@ -25,6 +25,11 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Properties; import javax.ejb.Singleton; import javax.ejb.embeddable.EJBContainer; import javax.ws.rs.GET; @@ -34,11 +39,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Properties; import static org.junit.Assert.assertEquals; @@ -77,8 +77,8 @@ public class CustomProviderWithConfigTest { public static class CustomizedService { @GET @Produces("openejb/conf") - public String go() { - return ""; + public CustomizedService go() { + return new CustomizedService(); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/DiscoverCustomProviderTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/DiscoverCustomProviderTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/DiscoverCustomProviderTest.java index a2a7697..b0b29a5 100644 --- a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/DiscoverCustomProviderTest.java +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/DiscoverCustomProviderTest.java @@ -26,6 +26,12 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; import javax.ejb.Singleton; import javax.ejb.embeddable.EJBContainer; import javax.ws.rs.GET; @@ -35,11 +41,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Properties; import static org.junit.Assert.assertEquals; @@ -80,8 +81,8 @@ public class DiscoverCustomProviderTest { @GET @Path("service") @Produces("discover/reverse") - public String go() { - return "skcor ti"; + public AtomicReference<String> go() { + return new AtomicReference<>("skcor ti"); } } @@ -107,7 +108,7 @@ public class DiscoverCustomProviderTest { @Override public void writeTo(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { - entityStream.write(reverse((String) t).getBytes()); + entityStream.write(reverse(AtomicReference.class.cast(t).get().toString()).getBytes()); } } } http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java index 1b1ce04..988e8da 100644 --- a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java @@ -87,8 +87,8 @@ public class ProviderWithConstructorTest { public static class AnEndpointToCheckAProvider { @GET @Produces("openejb/constructor") - public String bar() { - return "bar"; // whatever the value is the provider will return the context path + public AnEndpointToCheckAProvider bar() { + return new AnEndpointToCheckAProvider(); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/3ea25566/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/SortProviderTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/SortProviderTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/SortProviderTest.java index 74e5f38..0b10dae 100644 --- a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/SortProviderTest.java +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/SortProviderTest.java @@ -25,9 +25,18 @@ import org.apache.openejb.testing.Configuration; import org.apache.openejb.testing.Module; import org.apache.openejb.testng.PropertiesBuilder; import org.apache.openejb.util.NetworkUtil; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.net.URL; +import java.util.Comparator; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -37,17 +46,11 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import javax.ws.rs.ext.Providers; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.net.URL; -import java.util.Comparator; -import java.util.Properties; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +@Ignore("no more supported by CXF - chaining providers") public class SortProviderTest { @Rule public final ApplicationComposerRule container = new ApplicationComposerRule(this); @@ -81,7 +84,24 @@ public class SortProviderTest { @Override public int compare(final Object o1, final Object o2) { saw = true; - return o1.getClass().getName().compareTo(o2.getClass().getName()); + + final Class<?> c1 = o1.getClass(); + if (c1 == ATestProvider11.class) { + return -1; + } + + final Class<?> c2 = o2.getClass(); + if (c2 == ATestProvider11.class) { + return 1; + } + if (c1 == ATestProviderA.class) { + return -1; + } + if (c2 == ATestProviderA.class) { + return 1; + } + + return c1.getName().compareTo(c2.getName()); } } @@ -92,14 +112,14 @@ public class SortProviderTest { @GET @Produces("test/test") - public String asserts() { - return "fail"; + public AtomicReference<String> asserts() { + return new AtomicReference<>("fail"); } } @Provider @Produces("test/test") - public static class TestProviderA<T> implements MessageBodyWriter<T> { + public static class ATestProviderA implements MessageBodyWriter<AtomicReference<String>> { private String reverse(String str) { if (str == null) { return ""; @@ -113,7 +133,7 @@ public class SortProviderTest { } @Override - public long getSize(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { + public long getSize(AtomicReference<String> t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @@ -123,16 +143,16 @@ public class SortProviderTest { } @Override - public void writeTo(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { - entityStream.write(reverse((String) t).getBytes()); + public void writeTo(AtomicReference<String> t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { + entityStream.write(reverse(t.get()).getBytes()); } } @Provider @Produces("test/test") - public static class TestProvider11<T> implements MessageBodyWriter<T> { + public static class ATestProvider11 implements MessageBodyWriter<AtomicReference<?>> { @Override - public long getSize(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { + public long getSize(AtomicReference<?> t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @@ -142,7 +162,7 @@ public class SortProviderTest { } @Override - public void writeTo(T t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { + public void writeTo(AtomicReference<?> t, Class<?> rawType, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { entityStream.write("it works!".getBytes()); } }
