[seam-commits] Seam SVN: r8453 - in trunk/src/resteasy: META-INF and 4 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Mon Jul 14 06:39:58 EDT 2008


Author: christian.bauer at jboss.com
Date: 2008-07-14 06:39:57 -0400 (Mon, 14 Jul 2008)
New Revision: 8453

Added:
   trunk/src/resteasy/META-INF/
   trunk/src/resteasy/META-INF/seam-deployment.properties
   trunk/src/resteasy/org/
   trunk/src/resteasy/org/jboss/
   trunk/src/resteasy/org/jboss/seam/
   trunk/src/resteasy/org/jboss/seam/resteasy/
   trunk/src/resteasy/org/jboss/seam/resteasy/RestApplicationConfig.java
   trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyBootstrap.java
   trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyDispatcher.java
   trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyResourceAdapter.java
   trunk/src/resteasy/org/jboss/seam/resteasy/reasteasy-2.1.xsd
   trunk/src/resteasy/seam.properties
Log:
First round of RESTEasy integration

Added: trunk/src/resteasy/META-INF/seam-deployment.properties
===================================================================
--- trunk/src/resteasy/META-INF/seam-deployment.properties	                        (rev 0)
+++ trunk/src/resteasy/META-INF/seam-deployment.properties	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1 @@
+org.jboss.seam.deployment.annotationTypes=javax.ws.rs.ext.Provider:javax.ws.rs.Path

Added: trunk/src/resteasy/org/jboss/seam/resteasy/RestApplicationConfig.java
===================================================================
--- trunk/src/resteasy/org/jboss/seam/resteasy/RestApplicationConfig.java	                        (rev 0)
+++ trunk/src/resteasy/org/jboss/seam/resteasy/RestApplicationConfig.java	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1,134 @@
+package org.jboss.seam.resteasy;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.Component;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Install;
+
+import javax.ws.rs.core.MediaType;
+import java.util.*;
+
+/**
+ * Resteasy and JAX-RS configuration, override in components.xml to
+ * customize Resteasy settings.
+ *
+ * @author Christian Bauer
+ */
+ at Name("org.jboss.seam.resteasy.restApplicationConfig")
+ at Scope(ScopeType.APPLICATION)
+ at Install(precedence= Install.BUILT_IN)
+ at AutoCreate
+public class RestApplicationConfig extends javax.ws.rs.core.ApplicationConfig {
+
+    private Map<Class<?>, Component> providerClasses = new HashMap<Class<?>, Component>();
+    private Map<Class<?>, Component> resourceClasses = new HashMap<Class<?>, Component>();
+
+    private List<String> providerClassNames = new ArrayList<String>();
+    private List<String> resourceClassNames = new ArrayList<String>();
+
+    private Map<String,String> mediaTypeMappings = new HashMap<String,String>();
+    private Map<String,String> languageMappings = new HashMap<String,String>();
+
+    private boolean scanForProviderClasses = true;
+    private boolean scanForResourceClasses = true;
+    private boolean useBuiltinProviders = true;
+
+    public RestApplicationConfig() {
+        super();
+    }
+
+    public Set<Class<?>> getProviderClasses() {
+        return providerClasses.keySet();
+    }
+
+    public Set<Class<?>> getResourceClasses() {
+        return resourceClasses.keySet();
+    }
+
+    public void addProviderClass(Class<?> clazz, Component component) {
+        providerClasses.put(clazz, component);
+    }
+
+    public void removeProviderClass(Class<?> clazz) {
+        providerClasses.remove(clazz);
+    }
+
+    public void addResourceClass(Class<?> clazz, Component component) {
+        resourceClasses.put(clazz, component);
+    }
+
+    public void removeResourceClass(Class<?> clazz) {
+        resourceClasses.remove(clazz);
+    }
+
+    public Component getProviderClassComponent(Class clazz) {
+        return providerClasses.get(clazz) != null ? providerClasses.get(clazz) : null;
+    }
+
+    public Component getResourceClassComponent(Class clazz) {
+        return resourceClasses.get(clazz) != null ? resourceClasses.get(clazz) : null;
+    }
+
+    public Map<String, MediaType> getMediaTypeMappings() {
+        Map<String, MediaType> extMap = new HashMap<String, MediaType>();
+        for (String ext : mediaTypeMappings.keySet()) {
+            String value = mediaTypeMappings.get(ext);
+            extMap.put(ext, MediaType.valueOf(value));
+        }
+        return extMap;
+    }
+
+    public void setMediaTypeMappings(Map<String, String> mediaTypeMappings) {
+        this.mediaTypeMappings = mediaTypeMappings;
+    }
+
+    public Map<String, String> getLanguageMappings() {
+        return languageMappings;
+    }
+
+    public void setLanguageMappings(Map<String, String> languageMappings) {
+        this.languageMappings = languageMappings;
+    }
+
+    public List<String> getProviderClassNames() {
+        return providerClassNames;
+    }
+
+    public void setProviderClassNames(List<String> providerClassNames) {
+        this.providerClassNames = providerClassNames;
+    }
+
+    public List<String> getResourceClassNames() {
+        return resourceClassNames;
+    }
+
+    public void setResourceClassNames(List<String> resourceClassNames) {
+        this.resourceClassNames = resourceClassNames;
+    }
+
+    public boolean isScanForProviderClasses() {
+        return scanForProviderClasses;
+    }
+
+    public void setScanForProviderClasses(boolean scanForProviderClasses) {
+        this.scanForProviderClasses = scanForProviderClasses;
+    }
+
+    public boolean isScanForResourceClasses() {
+        return scanForResourceClasses;
+    }
+
+    public void setScanForResourceClasses(boolean scanForResourceClasses) {
+        this.scanForResourceClasses = scanForResourceClasses;
+    }
+
+    public boolean isUseBuiltinProviders() {
+        return useBuiltinProviders;
+    }
+
+    public void setUseBuiltinProviders(boolean useBuiltinProviders) {
+        this.useBuiltinProviders = useBuiltinProviders;
+    }
+}

Added: trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyBootstrap.java
===================================================================
--- trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyBootstrap.java	                        (rev 0)
+++ trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyBootstrap.java	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1,138 @@
+package org.jboss.seam.resteasy;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.deployment.AnnotationDeploymentHandler;
+import org.jboss.seam.deployment.DeploymentStrategy;
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.log.Log;
+import org.jboss.seam.util.Reflections;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+
+
+/**
+ * @author Christian Bauer
+ */
+ at Name("org.jboss.seam.resteasy.bootstrap")
+ at Scope(ScopeType.APPLICATION)
+ at Startup
+ at AutoCreate
+ at Install(classDependencies = "org.resteasy.Dispatcher")
+public class ResteasyBootstrap {
+
+    @Logger
+    Log log;
+
+    @In
+    protected RestApplicationConfig restApplicationConfig;
+
+    @Create
+    public void onStartup() {
+        log.info("deploying Resteasy providers and resources");
+
+        Collection<Class<java.lang.Object>> annotatedProviderClasses = null;
+        Collection<Class<java.lang.Object>> annotatedResourceClasses = null;
+        if (restApplicationConfig.isScanForProviderClasses() || restApplicationConfig.isScanForResourceClasses()) {
+            log.debug("scanning all classes for JAX-RS annotations");
+
+            DeploymentStrategy deployment = (DeploymentStrategy) Component.getInstance("deploymentStrategy");
+            AnnotationDeploymentHandler handler =
+                    (AnnotationDeploymentHandler)deployment.getDeploymentHandlers().get(AnnotationDeploymentHandler.NAME);
+
+            annotatedProviderClasses = handler.getClasses().get(javax.ws.rs.ext.Provider.class.getName());
+            annotatedResourceClasses = handler.getClasses().get(javax.ws.rs.Path.class.getName());
+        }
+
+        log.debug("finding all Seam component classes");
+        Map<Class, Component> seamComponents = new HashMap<Class, Component>();
+        String[] applicationContextNames = Contexts.getApplicationContext().getNames();
+        for (String applicationContextName : applicationContextNames) {
+            if (applicationContextName.endsWith(".component")) {
+                Component seamComponent =
+                        (Component)Component.getInstance(applicationContextName, ScopeType.APPLICATION);
+                // TODO: This should consider EJB components/annotations on interfaces somehow?
+                seamComponents.put(seamComponent.getBeanClass(), seamComponent);
+            }
+        }
+
+        registerProviders(seamComponents, annotatedProviderClasses);
+        registerResources(seamComponents, annotatedResourceClasses);
+    }
+
+    // Load all provider classes, either scanned or through explicit configuration
+    protected void registerProviders(Map<Class, Component> seamComponents, Collection annotatedProviderClasses) {
+        Collection<Class> providerClasses = new HashSet<Class>();
+        try {
+            if (restApplicationConfig.isScanForProviderClasses() && annotatedProviderClasses != null)
+                providerClasses.addAll(annotatedProviderClasses);
+
+            for (String s : new HashSet<String>(restApplicationConfig.getProviderClassNames()))
+                providerClasses.add(Reflections.classForName(s));
+
+        } catch (ClassNotFoundException ex) {
+            log.error("error loading JAX-RS provider class: " + ex.getMessage());
+        }
+        for (Class providerClass : providerClasses) {
+            // Ignore built-in providers, we register them manually later
+            if (providerClass.getName().startsWith("org.resteasy.plugins.providers")) continue;
+
+            Component seamComponent = null;
+            // Check if this is also a Seam component bean class
+            if (seamComponents.containsKey(providerClass)) {
+                seamComponent = seamComponents.get(providerClass);
+                // Needs to be APPLICATION or STATELESS
+                if (!seamComponent.getScope().equals(ScopeType.APPLICATION) &&
+                    !seamComponent.getScope().equals(ScopeType.STATELESS)) {
+                    log.warn("not registering as  provider Seam component, must be APPLICATION or STATELESS scoped: "
+                             + seamComponent.getName());
+                    seamComponent = null;
+                }
+            }
+            if (seamComponent != null) {
+                log.debug("registering provider Seam component: " + seamComponent.getName());
+            } else {
+                log.debug("registering provider class: " + providerClass.getName());
+            }
+            restApplicationConfig.addProviderClass(providerClass, seamComponent);
+        }
+        if (restApplicationConfig.getProviderClasses().size() == 0 &&
+            !restApplicationConfig.isUseBuiltinProviders()) {
+            log.info("no RESTEasy provider classes registered");
+        }
+    }
+
+    // Load all resource classes, either scanned or through explicit configuration
+    protected void registerResources(Map<Class, Component> seamComponents, Collection annotatedResourceClasses) {
+        Collection<Class> resourceClasses = new HashSet<Class>();
+        try {
+            if (restApplicationConfig.isScanForResourceClasses() && annotatedResourceClasses != null)
+                resourceClasses.addAll(annotatedResourceClasses);
+
+            for (String s : new HashSet<String>(restApplicationConfig.getResourceClassNames()))
+                resourceClasses.add(Reflections.classForName(s));
+
+        } catch (ClassNotFoundException ex) {
+            log.error("error loading JAX-RS resource class: " + ex.getMessage());
+        }
+        for (Class<Object> resourceClass : resourceClasses) {
+
+            Component seamComponent = null;
+            // Check if this is also a Seam component bean class
+            if (seamComponents.containsKey(resourceClass)) {
+                seamComponent = seamComponents.get(resourceClass);
+                log.debug("registering resource Seam component: " + seamComponent.getName());
+            } else {
+                log.debug("registering resource class with JAX-RS default lifecycle: " + resourceClass.getName());
+            }
+            restApplicationConfig.addResourceClass(resourceClass, seamComponent);
+        }
+        if (restApplicationConfig.getResourceClasses().size() == 0)
+            log.info("no JAX-RS resource classes registered");
+    }
+
+}

Added: trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyDispatcher.java
===================================================================
--- trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyDispatcher.java	                        (rev 0)
+++ trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyDispatcher.java	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1,98 @@
+package org.jboss.seam.resteasy;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.log.Log;
+import org.resteasy.Dispatcher;
+import org.resteasy.plugins.providers.RegisterBuiltin;
+import org.resteasy.plugins.server.servlet.HttpServletDispatcher;
+import org.resteasy.plugins.server.resourcefactory.POJOResourceFactory;
+import org.resteasy.spi.*;
+
+/**
+ * @author Christian Bauer
+ */
+ at Name("org.jboss.seam.resteasy.dispatcher")
+ at Scope(ScopeType.APPLICATION)
+ at Startup(depends = "resteasyBootstrap")
+ at AutoCreate
+ at Install(classDependencies = "org.resteasy.Dispatcher")
+public class ResteasyDispatcher extends HttpServletDispatcher {
+
+    @In
+    RestApplicationConfig restApplicationConfig;
+
+    @Logger
+    Log log;
+
+    @Create
+    public void onStartup() {
+        log.info("registering RESTEasy resources and providers");
+
+        ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
+        ResteasyProviderFactory.setInstance(providerFactory); // This is really necessary
+        setDispatcher(new Dispatcher(providerFactory));
+
+        getDispatcher().setLanguageMappings(restApplicationConfig.getLanguageMappings());
+        getDispatcher().setMediaTypeMappings(restApplicationConfig.getMediaTypeMappings());
+
+        // Resource registration
+        Registry registry = getDispatcher().getRegistry();
+        for (final Class resourceClass : restApplicationConfig.getResourceClasses()) {
+            final Component seamComponent = restApplicationConfig.getResourceClassComponent(resourceClass);
+            if (seamComponent != null) {
+                // Seam component lookup when call is dispatched to resource
+                registry.addResourceFactory(
+                    new ResourceFactory() {
+
+                        private PropertyInjector propertyInjector;
+
+                        public Class<?> getScannableClass() {
+                            return resourceClass;
+                        }
+
+                        public void registered(InjectorFactory factory) {
+                            this.propertyInjector = factory.createPropertyInjector(getScannableClass());
+                        }
+
+                        public Object createResource(HttpRequest request, HttpResponse response, InjectorFactory factory) {
+                            Object target = Component.getInstance(seamComponent.getName());
+                            propertyInjector.inject(request, response, target);
+                            return target;
+                        }
+
+                        public void requestFinished(HttpRequest request, HttpResponse response, Object resource) {}
+                        public void unregistered() {}
+                    }
+                );
+            } else {
+                // JAX-RS default lifecycle
+                registry.addResourceFactory(new POJOResourceFactory(resourceClass));
+            }
+        }
+
+        // Provider registration
+        if (restApplicationConfig.isUseBuiltinProviders()) {
+            log.info("registering built-in RESTEasy providers");
+            RegisterBuiltin.register(providerFactory);
+        }
+        for (Class providerClass : restApplicationConfig.getProviderClasses()) {
+            Component seamComponent = restApplicationConfig.getProviderClassComponent(providerClass);
+            if (seamComponent != null) {
+                if (ScopeType.STATELESS.equals(seamComponent.getScope())) {
+                    throw new RuntimeException(
+                        "Registration of STATELESS Seam components as RESTEasy providers not implemented!"
+                    );
+                } else if (ScopeType.APPLICATION.equals(seamComponent.getScope())) {
+                    Object providerInstance = Component.getInstance(seamComponent.getName());
+                    providerFactory.registerProviderInstance(providerInstance);
+                }
+            } else {
+                // Just plain RESTEasy, no Seam component lookup or lifecycle
+                providerFactory.registerProvider(providerClass);
+            }
+        }
+
+    }
+}

Added: trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyResourceAdapter.java
===================================================================
--- trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyResourceAdapter.java	                        (rev 0)
+++ trunk/src/resteasy/org/jboss/seam/resteasy/ResteasyResourceAdapter.java	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1,65 @@
+package org.jboss.seam.resteasy;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.servlet.ContextualHttpServletRequest;
+import org.jboss.seam.web.AbstractResource;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Accepts incoming HTTP request under the Seam resource-servlet URL mapping and
+ * dispatches the call to RESTEasy. Wraps the call in Seam contexts.
+ * <p>
+ * Hardcoded URL path is <tt>/rest</tt>. Subclass and override the
+ * <tt>getResourcePath()</tt> method to customize this.
+ * </p>
+ *
+ * @author Christian Bauer
+ */
+ at Scope(ScopeType.APPLICATION)
+ at Name("org.jboss.seam.resteasy.resourceAdapter")
+ at BypassInterceptors
+public class ResteasyResourceAdapter extends AbstractResource {
+
+    public static final String RESTEASY_RESOURCE_BASEPATH = "/rest";
+
+    @Override
+    public String getResourcePath() {
+        return RESTEASY_RESOURCE_BASEPATH;
+    }
+
+    @Override
+    public void getResource(final HttpServletRequest request, final HttpServletResponse response)
+            throws ServletException, IOException {
+
+        // Wrap this in Seam contexts
+        new ContextualHttpServletRequest(request) {
+            @Override
+            public void process() throws ServletException, IOException {
+
+                ResteasyDispatcher dispatcher =
+                        (ResteasyDispatcher)Component.getInstance(ResteasyDispatcher.class);
+                if (dispatcher == null) {
+                    throw new IllegalStateException("RESTEasy is not installed, check your classpath");
+                }
+                dispatcher.invoke(
+                    new HttpServletRequestWrapper(request) {
+                        // TODO: Strip out the /seam/resource/rest stuff
+                        public String getPathInfo() {
+                            return super.getPathInfo();
+                        }
+                    },
+                    response
+                );
+            }
+        }.run();
+    }
+}

Added: trunk/src/resteasy/org/jboss/seam/resteasy/reasteasy-2.1.xsd
===================================================================
--- trunk/src/resteasy/org/jboss/seam/resteasy/reasteasy-2.1.xsd	                        (rev 0)
+++ trunk/src/resteasy/org/jboss/seam/resteasy/reasteasy-2.1.xsd	2008-07-14 10:39:57 UTC (rev 8453)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           elementFormDefault="qualified"
+           targetNamespace="http://jboss.com/products/seam/resteasy"
+           xmlns:pdf="http://jboss.com/products/seam/resteasy"
+           xmlns:components="http://jboss.com/products/seam/components"
+           attributeFormDefault="unqualified">
+    <xs:import namespace="http://jboss.com/products/seam/components" schemaLocation="components-2.1.xsd"/>
+
+   <!-- TODO -->
+
+</xs:schema>

Added: trunk/src/resteasy/seam.properties
===================================================================




More information about the seam-commits mailing list