Author: rmannibucau
Date: Fri Aug 23 07:11:37 2013
New Revision: 1516714

URL: http://svn.apache.org/r1516714
Log:
TOMEE-1020 creating @Provider (jaxrs) from contructor if parameters uses 
@Context

Added:
    
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java
      - copied, changed from r1516706, 
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiInterceptorContextTest.java
Modified:
    
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/util/ServiceInfos.java
    
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/rest/ThreadLocalContextManager.java
    
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java

Modified: 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/util/ServiceInfos.java
URL: 
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/util/ServiceInfos.java?rev=1516714&r1=1516713&r2=1516714&view=diff
==============================================================================
--- 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/util/ServiceInfos.java
 (original)
+++ 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/util/ServiceInfos.java
 Fri Aug 23 07:11:37 2013
@@ -72,6 +72,10 @@ public final class ServiceInfos {
     }
 
     public static List<Object> resolve(final Collection<ServiceInfo> 
serviceInfos, final String[] ids) {
+        return resolve(serviceInfos, ids, null);
+    }
+
+    public static List<Object> resolve(final Collection<ServiceInfo> 
serviceInfos, final String[] ids, final Factory factory) {
         if (ids == null || ids.length == 0) {
             return null;
         }
@@ -81,8 +85,13 @@ public final class ServiceInfos {
             Object instance = resolve(serviceInfos, id);
             if (instance == null) {  // maybe id == classname
                 try {
-                    instance = 
Thread.currentThread().getContextClassLoader().loadClass(id).newInstance();
-                } catch (Exception e) {
+                    final Class<?> aClass = 
Thread.currentThread().getContextClassLoader().loadClass(id);
+                    if (factory == null) {
+                        instance = aClass.newInstance();
+                    } else {
+                        instance = factory.newInstance(aClass);
+                    }
+                } catch (final Exception e) {
                     // ignore
                 }
             }
@@ -147,4 +156,8 @@ public final class ServiceInfos {
 
         return service;
     }
+
+    public static interface Factory {
+        Object newInstance(final Class<?> clazz) throws Exception;
+    }
 }

Modified: 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/rest/ThreadLocalContextManager.java
URL: 
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/rest/ThreadLocalContextManager.java?rev=1516714&r1=1516713&r2=1516714&view=diff
==============================================================================
--- 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/rest/ThreadLocalContextManager.java
 (original)
+++ 
tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/rest/ThreadLocalContextManager.java
 Fri Aug 23 07:11:37 2013
@@ -17,7 +17,17 @@
 
 package org.apache.openejb.rest;
 
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Providers;
 import java.util.Map;
 
 public class ThreadLocalContextManager {
@@ -53,4 +63,29 @@ public class ThreadLocalContextManager {
         }
         OTHERS.remove();
     }
+
+    public static Object findThreadLocal(final Class<?> type) {
+        if (Request.class.equals(type)) {
+            return ThreadLocalContextManager.REQUEST;
+        } else if (UriInfo.class.equals(type)) {
+            return ThreadLocalContextManager.URI_INFO;
+        } else if (HttpHeaders.class.equals(type)) {
+            return ThreadLocalContextManager.HTTP_HEADERS;
+        } else if (SecurityContext.class.equals(type)) {
+            return ThreadLocalContextManager.SECURITY_CONTEXT;
+        } else if (ContextResolver.class.equals(type)) {
+            return ThreadLocalContextManager.CONTEXT_RESOLVER;
+        } else if (Providers.class.equals(type)) {
+            return ThreadLocalContextManager.PROVIDERS;
+        } else if (ServletRequest.class.equals(type)) {
+            return ThreadLocalContextManager.SERVLET_REQUEST;
+        } else if (HttpServletRequest.class.equals(type)) {
+            return ThreadLocalContextManager.HTTP_SERVLET_REQUEST;
+        } else if (HttpServletResponse.class.equals(type)) {
+            return ThreadLocalContextManager.HTTP_SERVLET_RESPONSE;
+        } else if (ServletConfig.class.equals(type)) {
+            return ThreadLocalContextManager.SERVLET_CONFIG;
+        }
+        return null;
+    }
 }

Modified: 
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java
URL: 
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java?rev=1516714&r1=1516713&r2=1516714&view=diff
==============================================================================
--- 
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java
 (original)
+++ 
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java
 Fri Aug 23 07:11:37 2013
@@ -28,6 +28,7 @@ import org.apache.cxf.jaxrs.model.Method
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
 import org.apache.cxf.jaxrs.provider.json.JSONProvider;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.service.invoker.Invoker;
 import org.apache.cxf.transport.http.AbstractHTTPDestination;
 import org.apache.cxf.transport.http.HTTPTransportFactory;
@@ -38,6 +39,7 @@ import org.apache.openejb.assembler.clas
 import org.apache.openejb.assembler.classic.util.ServiceConfiguration;
 import org.apache.openejb.assembler.classic.util.ServiceInfos;
 import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.rest.ThreadLocalContextManager;
 import org.apache.openejb.server.cxf.transport.util.CxfUtil;
 import org.apache.openejb.server.httpd.HttpRequest;
 import org.apache.openejb.server.httpd.HttpRequestImpl;
@@ -59,6 +61,8 @@ import javax.ws.rs.core.Application;
 import javax.xml.bind.Marshaller;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -107,7 +111,6 @@ public class CxfRsHttpListener implement
     public CxfRsHttpListener(final HTTPTransportFactory httpTransportFactory, 
final String star) {
         transportFactory = httpTransportFactory;
         wildcard = star;
-
     }
 
     @Override
@@ -269,13 +272,13 @@ public class CxfRsHttpListener implement
         for (Object o : additionalProviders) {
             if (o instanceof Class<?>) {
                 final Class<?> clazz = (Class<?>) o;
-                final Object instance = ServiceInfos.resolve(services, 
clazz.getName());
-                if (instance != null) {
-                    instances.add(instance);
+                final Collection<Object> instance = 
ServiceInfos.resolve(services, new String[] { clazz.getName() }, 
ProviderFactory.INSTANCE);
+                if (instance != null && !instance.isEmpty()) {
+                    instances.add(instance.iterator().next());
                 } else {
                     try {
-                        instances.add(clazz.newInstance());
-                    } catch (Exception e) {
+                        instances.add(newProvider(clazz));
+                    } catch (final Exception e) {
                         LOGGER.error("can't instantiate " + clazz.getName(), 
e);
                     }
                 }
@@ -286,6 +289,10 @@ public class CxfRsHttpListener implement
         return instances;
     }
 
+    private Object newProvider(final Class<?> clazz) throws 
IllegalAccessException, InstantiationException {
+        return clazz.newInstance();
+    }
+
     public void undeploy() {
         final ClassLoader oldLoader = 
Thread.currentThread().getContextClassLoader();
         Thread.currentThread().setContextClassLoader(CxfUtil.initBusLoader());
@@ -514,7 +521,7 @@ public class CxfRsHttpListener implement
 
         List<Object> providers = null;
         if (providersConfig != null) {
-            providers = ServiceInfos.resolve(services, 
providersConfig.toArray(new String[providersConfig.size()]));
+            providers = ServiceInfos.resolve(services, 
providersConfig.toArray(new String[providersConfig.size()]), 
ProviderFactory.INSTANCE);
             if (providers != null && additionalProviders != null && 
!additionalProviders.isEmpty()) {
                 providers.addAll(providers(services, additionalProviders));
             }
@@ -545,4 +552,43 @@ public class CxfRsHttpListener implement
 
         return Arrays.asList((Object) jaxb, json);
     }
+
+    private static class ProviderFactory implements ServiceInfos.Factory {
+        private static final ServiceInfos.Factory INSTANCE = new 
ProviderFactory();
+
+        @Override
+        public Object newInstance(final Class<?> clazz) throws Exception {
+            boolean found = false;
+            Object instance = null;
+            for (final Constructor<?> c : clazz.getConstructors()) {
+                int contextAnnotations = 0;
+                for (final Annotation[] annotations : 
c.getParameterAnnotations()) {
+                    for (final Annotation a : annotations) {
+                        if 
(javax.ws.rs.core.Context.class.equals(a.annotationType())) {
+                            contextAnnotations++;
+                            break;
+                        }
+                    }
+                }
+                if (contextAnnotations == c.getParameterTypes().length) {
+                    if (found) {
+                        LOGGER.warning("Found multiple matching constructor 
for " + clazz.getName());
+                        return instance;
+                    }
+
+                    final Object[] params = new 
Object[c.getParameterTypes().length];
+                    for (int i = 0; i < params.length; i++) {
+                        params[i] = 
ThreadLocalContextManager.findThreadLocal(c.getParameterTypes()[i]);
+                        // params[i] can be null if not a known type
+                    }
+                    instance = c.newInstance(params);
+                    found = true;
+                }
+            }
+            if (instance != null) {
+                return instance;
+            }
+            return clazz.newInstance();
+        }
+    }
 }

Copied: 
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java
 (from r1516706, 
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiInterceptorContextTest.java)
URL: 
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java?p2=tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java&p1=tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiInterceptorContextTest.java&r1=1516706&r2=1516714&rev=1516714&view=diff
==============================================================================
--- 
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiInterceptorContextTest.java
 (original)
+++ 
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ProviderWithConstructorTest.java
 Fri Aug 23 07:11:37 2013
@@ -25,77 +25,86 @@ import org.apache.openejb.testing.Module
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.Interceptor;
-import javax.interceptor.InterceptorBinding;
-import javax.interceptor.InvocationContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Context;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+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.HashSet;
 import java.util.Set;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static org.junit.Assert.assertEquals;
 
 @EnableServices("jax-rs")
 @RunWith(ApplicationComposer.class)
-public class CdiInterceptorContextTest {
+public class ProviderWithConstructorTest {
     @Module
-    @Classes(value = { Endpoint.class, AnswerPerfect.class }, cdiInterceptors 
= AnswerPerfect.class)
+    @Classes(value = { AnEndpointToCheckAProvider.class })
     public WebApp war() {
         return new WebApp()
                 .contextRoot("app")
                 .addServlet("REST Application", Application.class.getName())
-                .addInitParam("REST Application", "javax.ws.rs.Application", 
PerfectApplication.class.getName());
+                .addInitParam("REST Application", "javax.ws.rs.Application", 
ApplicationWithProvider.class.getName());
     }
 
     @Test
     public void checkServiceWasDeployed() {
-        assertEquals("perfect", 
WebClient.create("http://localhost:4204/app";).path("/foo").get(String.class));
+        assertEquals("/app", 
WebClient.create("http://localhost:4204/app";).path("/foo").accept("openejb/constructor").get(String.class));
     }
 
     @Path("/foo")
-    @Perfect
-    public static class Endpoint {
-        @GET
+    public static class AnEndpointToCheckAProvider {
+        @GET @Produces("openejb/constructor")
         public String bar() {
-            return "bar";
+            return "bar"; // whatever the value is the provider will return 
the context path
         }
     }
 
-    @InterceptorBinding
-    @Target(TYPE)
-    @Retention(RUNTIME)
-    public static @interface Perfect {
-
+    public static class ApplicationWithProvider extends Application {
+        @Override
+        public Set<Class<?>> getClasses() {
+            final Set<Class<?>> classes = new HashSet<Class<?>>();
+            classes.add(AnEndpointToCheckAProvider.class);
+            classes.add(ConstructorProvider.class);
+            return classes;
+        }
     }
 
-    @Interceptor @Perfect
-    public static class AnswerPerfect {
-        @Context
-        private HttpServletRequest request;
-
-        @AroundInvoke
-        public Object invoke(final InvocationContext ic) throws Exception {
-            if (ic.getMethod().getName().equals("bar") && 
"foo".equals(request.getRequestURI())) {
-                return "perfect";
+    @Provider
+    @Produces("openejb/constructor")
+    public static class ConstructorProvider<T> implements MessageBodyWriter<T> 
{
+        private final HttpServletRequest request;
+
+        public ConstructorProvider(final @Context HttpServletRequest request) {
+            if (request == null) {
+                throw new IllegalArgumentException();
             }
-            return ic.proceed();
+            this.request = request;
         }
-    }
 
-    public static class PerfectApplication extends Application {
         @Override
-        public Set<Class<?>> getClasses() {
-            final Set<Class<?>> classes = new HashSet<Class<?>>();
-            classes.add(Endpoint.class);
-            return classes;
+        public long getSize(T t, Class<?> rawType, Type genericType, 
Annotation[] annotations, MediaType mediaType) {
+            return -1;
+        }
+
+        @Override
+        public boolean isWriteable(Class<?> rawType, Type genericType, 
Annotation[] annotations, MediaType mediaType) {
+            return true;
+        }
+
+        @Override
+        public void writeTo(T t, Class<?> rawType, Type genericType, 
Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> 
httpHeaders, OutputStream entityStream) throws IOException {
+            entityStream.write(request.getContextPath().getBytes());
         }
     }
+
 }


Reply via email to