[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