You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/05/01 23:26:07 UTC

svn commit: r1478196 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ systests/jaxrs/src/test/java/org/apac...

Author: sergeyb
Date: Wed May  1 21:26:07 2013
New Revision: 1478196

URL: http://svn.apache.org/r1478196
Log:
[CXF-4988] Support for instantiating providers with non default constructors, more updates

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java?rev=1478196&r1=1478195&r2=1478196&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java Wed May  1 21:26:07 2013
@@ -171,7 +171,6 @@ public class JAXRSServerFactoryBean exte
             
             ServerProviderFactory factory = setupFactory(ep);
             ep.put(Application.class.getName(), appProvider);
-            factory.setApplicationProvider(appProvider);
             factory.setRequestPreprocessor(
                 new RequestPreprocessor(languageMappings, extensionMappings));
             ep.put(Bus.class.getName(), getBus());
@@ -216,6 +215,7 @@ public class JAXRSServerFactoryBean exte
     protected ServerProviderFactory setupFactory(Endpoint ep) { 
         ServerProviderFactory factory = ServerProviderFactory.createInstance(getBus()); 
         setBeanInfo(factory);
+        factory.setApplicationProvider(appProvider);
         super.setupFactory(factory, ep);
         return factory;
     }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=1478196&r1=1478195&r2=1478196&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java Wed May  1 21:26:07 2013
@@ -20,6 +20,7 @@
 package org.apache.cxf.jaxrs.provider;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
@@ -28,9 +29,11 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.logging.Logger;
 
@@ -56,11 +59,13 @@ import org.apache.cxf.jaxrs.ext.ContextP
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
 import org.apache.cxf.jaxrs.impl.ReaderInterceptorMBR;
 import org.apache.cxf.jaxrs.impl.WriterInterceptorMBW;
+import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.ProviderInfo;
 import org.apache.cxf.jaxrs.utils.AnnotationUtils;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 
@@ -457,42 +462,56 @@ public abstract class ProviderFactory {
     }
     
     //CHECKSTYLE:OFF       
+    @SuppressWarnings("unchecked")
     protected void setProviders(Object... providers) {
         
         for (Object o : providers) {
             if (o == null) {
                 continue;
             }
-            Class<?> oClass = ClassHelper.getRealClass(o);
             
-            if (MessageBodyReader.class.isAssignableFrom(oClass)) {
-                messageReaders.add(new ProviderInfo<MessageBodyReader<?>>((MessageBodyReader<?>)o, bus)); 
+            ProviderInfo<? extends Object> provider = null;
+            Class<?> providerCls = null;
+            Object realObject = null;            
+            if (o instanceof ProviderInfo) {
+                provider = (ProviderInfo<? extends Object>)o;
+                providerCls = provider.getProvider().getClass();
+                realObject = provider;
+            } else {
+                providerCls = ClassHelper.getRealClass(o);
+                provider = new ProviderInfo<Object>(o, getBus());
+                realObject = o;
+            }
+            
+            
+            if (MessageBodyReader.class.isAssignableFrom(providerCls)) {
+                messageReaders.add((ProviderInfo<MessageBodyReader<?>>)provider); 
             }
             
-            if (MessageBodyWriter.class.isAssignableFrom(oClass)) {
-                messageWriters.add(new ProviderInfo<MessageBodyWriter<?>>((MessageBodyWriter<?>)o, bus)); 
+            if (MessageBodyWriter.class.isAssignableFrom(providerCls)) {
+                messageWriters.add((ProviderInfo<MessageBodyWriter<?>>)provider); 
             }
             
-            if (ContextResolver.class.isAssignableFrom(oClass)) {
-                contextResolvers.add(new ProviderInfo<ContextResolver<?>>((ContextResolver<?>)o, bus)); 
+            if (ContextResolver.class.isAssignableFrom(providerCls)) {
+                contextResolvers.add((ProviderInfo<ContextResolver<?>>)provider); 
             }
             
-            if (ContextProvider.class.isAssignableFrom(oClass)) {
-                contextProviders.add(new ProviderInfo<ContextProvider<?>>((ContextProvider<?>)o, bus)); 
+            if (ContextProvider.class.isAssignableFrom(providerCls)) {
+                contextProviders.add((ProviderInfo<ContextProvider<?>>)provider); 
             }
             
-            if (ReaderInterceptor.class.isAssignableFrom(oClass)) {
-                readerInterceptors.add(
-                   new ProviderInfo<ReaderInterceptor>((ReaderInterceptor)o, bus));
+            if (ReaderInterceptor.class.isAssignableFrom(providerCls)) {
+                readerInterceptors.add((ProviderInfo<ReaderInterceptor>)provider);
             }
             
-            if (WriterInterceptor.class.isAssignableFrom(oClass)) {
-                writerInterceptors.add(
-                   new ProviderInfo<WriterInterceptor>((WriterInterceptor)o, bus));
+            if (WriterInterceptor.class.isAssignableFrom(providerCls)) {
+                writerInterceptors.add((ProviderInfo<WriterInterceptor>)provider);
             }
             
-            if (ParamConverterProvider.class.isAssignableFrom(oClass)) {
-                newParamConverter = (ParamConverterProvider)o;
+            if (ParamConverterProvider.class.isAssignableFrom(providerCls)) {
+                //TODO: review the possibility of ParamConverterProvider needing to have Contexts injected
+                Object converter = realObject == provider ? provider.getProvider() : realObject;
+                newParamConverter = (ParamConverterProvider)converter;
             }
         }
         sortReaders();
@@ -948,5 +967,26 @@ public abstract class ProviderFactory {
         }
     }
     
-    
+    protected ProviderInfo<Object> createProviderFromConstructor(Constructor<?> c, 
+                                                                 Map<Class<?>, Object> values) {
+        Object[] cArgs = ResourceUtils.createConstructorArguments(c, null, false, values);
+        Object instance = null;
+        try {
+            instance = c.newInstance(cArgs);
+        } catch (Throwable ex) {
+            throw new RuntimeException("Resource or provider class " + c.getDeclaringClass().getName()
+                                       + " can not be instantiated"); 
+        }
+        Map<Class<?>, ThreadLocalProxy<?>> proxies = 
+            new HashMap<Class<?>, ThreadLocalProxy<?>>();
+        Class<?>[] paramTypes = c.getParameterTypes();
+        for (int i = 0; i < paramTypes.length; i++) {
+            if (cArgs[i] instanceof ThreadLocalProxy) {
+                @SuppressWarnings("unchecked")
+                ThreadLocalProxy<Object> proxy = (ThreadLocalProxy<Object>)cArgs[i];
+                proxies.put(paramTypes[i], proxy);
+            }
+        }
+        return new ProviderInfo<Object>(instance, proxies, getBus()); 
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java?rev=1478196&r1=1478195&r2=1478196&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java Wed May  1 21:26:07 2013
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.jaxrs.provider;
 
+import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,6 +50,7 @@ import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.common.util.ClassHelper;
 import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.RequestPreprocessor;
 import org.apache.cxf.jaxrs.impl.ResourceInfoImpl;
@@ -219,9 +221,9 @@ public final class ServerProviderFactory
     }
     
   //CHECKSTYLE:OFF 
+    @SuppressWarnings("unchecked")
     @Override
     protected void setProviders(Object... providers) {
-        super.setProviders(providers);
         List<ProviderInfo<ContainerRequestFilter>> postMatchRequestFilters = 
             new LinkedList<ProviderInfo<ContainerRequestFilter>>();
         List<ProviderInfo<ContainerResponseFilter>> postMatchResponseFilters = 
@@ -231,25 +233,40 @@ public final class ServerProviderFactory
             if (o == null) {
                 continue;
             }
-            Class<?> oClass = ClassHelper.getRealClass(o);
+            ProviderInfo<? extends Object> provider = null;
+            Class<?> providerCls = null;
+            Object realObject = null;
+            if (o instanceof Constructor) {
+                Map<Class<?>, Object> values = CastUtils.cast((application == null ? null 
+                    : Collections.singletonMap(Application.class, application.getProvider())));
+                provider = createProviderFromConstructor((Constructor<?>)o, values);
+                providerCls = provider.getProvider().getClass();
+                realObject = provider;
+            } else {
+                providerCls = ClassHelper.getRealClass(o);
+                provider = new ProviderInfo<Object>(o, getBus());
+                realObject = o;
+            }
+            super.setProviders(realObject);
                         
-            if (ContainerRequestFilter.class.isAssignableFrom(oClass)) {
-                addContainerRequestFilter(postMatchRequestFilters,
-                    new ProviderInfo<ContainerRequestFilter>((ContainerRequestFilter)o, getBus()));
+            if (ContainerRequestFilter.class.isAssignableFrom(providerCls)) {
+                addContainerRequestFilter(postMatchRequestFilters, 
+                                          (ProviderInfo<ContainerRequestFilter>)provider);
             }
             
-            if (ContainerResponseFilter.class.isAssignableFrom(oClass)) {
-                postMatchResponseFilters.add(
-                   new ProviderInfo<ContainerResponseFilter>((ContainerResponseFilter)o, getBus())); 
+            if (ContainerResponseFilter.class.isAssignableFrom(providerCls)) {
+                postMatchResponseFilters.add((ProviderInfo<ContainerResponseFilter>)provider); 
             }
             
-            if (DynamicFeature.class.isAssignableFrom(oClass)) {
-                dynamicFeatures.add((DynamicFeature)o);
+            if (DynamicFeature.class.isAssignableFrom(providerCls)) {
+                //TODO: review the possibility of DynamicFeatures needing to have Contexts injected
+                Object feature = realObject == provider ? provider.getProvider() : realObject;
+                dynamicFeatures.add((DynamicFeature)feature);
             }
             
             
-            if (ExceptionMapper.class.isAssignableFrom(oClass)) {
-                exceptionMappers.add(new ProviderInfo<ExceptionMapper<?>>((ExceptionMapper<?>)o, getBus())); 
+            if (ExceptionMapper.class.isAssignableFrom(providerCls)) {
+                exceptionMappers.add((ProviderInfo<ExceptionMapper<?>>)provider); 
             }
             
         }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java?rev=1478196&r1=1478195&r2=1478196&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java Wed May  1 21:26:07 2013
@@ -614,7 +614,16 @@ public final class ResourceUtils {
         return op;
     }
     
-    public static Object[] createConstructorArguments(Constructor<?> c, Message m, boolean perRequest) {
+    public static Object[] createConstructorArguments(Constructor<?> c, 
+                                                      Message m, 
+                                                      boolean perRequest) {
+        return createConstructorArguments(c, m, perRequest, null);
+    }
+    
+    public static Object[] createConstructorArguments(Constructor<?> c, 
+                                                      Message m, 
+                                                      boolean perRequest,
+                                                      Map<Class<?>, Object> contextValues) {
         Class<?>[] params = c.getParameterTypes();
         Annotation[][] anns = c.getParameterAnnotations();
         Type[] genericTypes = c.getGenericParameterTypes();
@@ -624,10 +633,15 @@ public final class ResourceUtils {
         Object[] values = new Object[params.length];
         for (int i = 0; i < params.length; i++) {
             if (AnnotationUtils.getAnnotation(anns[i], Context.class) != null) {
-                if (perRequest) {
-                    values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]);
+                Object contextValue = contextValues != null ? contextValues.get(params[i]) : null;
+                if (contextValue == null) {
+                    if (perRequest) {
+                        values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]);
+                    } else {
+                        values[i] = InjectionUtils.createThreadLocalProxy(params[i]);
+                    }
                 } else {
-                    values[i] = InjectionUtils.createThreadLocalProxy(params[i]);
+                    values[i] = contextValue;
                 }
             } else {
                 // this branch won't execute for singletons given that the found constructor

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java?rev=1478196&r1=1478195&r2=1478196&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java Wed May  1 21:26:07 2013
@@ -85,13 +85,18 @@ public class BookApplication extends App
     
     public static class BookRequestFilter implements ContainerRequestFilter {
         private UriInfo ui;
+        private Application ap;
         
-        public BookRequestFilter(@Context UriInfo ui) {
+        public BookRequestFilter(@Context UriInfo ui, @Context Application ap) {
             this.ui = ui;
+            this.ap = ap;
         }
         
         @Override
         public void filter(ContainerRequestContext context) throws IOException {
+            if (ap == null) {
+                throw new RuntimeException();
+            }
             if (ui.getRequestUri().toString().endsWith("/application11/thebooks/bookstore2/bookheaders")) {
                 context.getHeaders().put("BOOK", Arrays.asList("1", "2", "3"));    
             }