[exo-jcr-commits] exo-jcr SVN: r3375 - in ws/trunk: exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl and 10 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Nov 2 04:56:58 EDT 2010


Author: aparfonov
Date: 2010-11-02 04:56:55 -0400 (Tue, 02 Nov 2010)
New Revision: 3375

Added:
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationProviders.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationRegistry.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProvidersRegistry.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/StartableApplication.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/ApplicationResource.java
Modified:
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/ApplicationContext.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationContextImpl.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProviderBinder.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestDispatcher.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestHandlerImpl.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ResourceBinder.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBContextResolver.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBElementEntityProvider.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBObjectEntityProvider.java
   ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/AbstractResourceDescriptorImpl.java
   ws/trunk/exo.ws.rest.core/src/main/resources/conf/portal/configuration.xml
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/BaseTest.java
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/VariantsHandlerTest.java
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/OtherEntityTest.java
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/SourceEntityProviderTest.java
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/resource/ApplicationTest.java
   ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/wadl/WadlProcessorTest.java
   ws/trunk/exo.ws.rest.core/src/test/resources/conf/standalone/test-configuration.xml
   ws/trunk/exo.ws.rest.ext/src/test/resources/conf/standalone/test-configuration.xml
Log:
EXOJCR-1024

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/ApplicationContext.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/ApplicationContext.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/ApplicationContext.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -31,9 +31,9 @@
 import javax.ws.rs.ext.Providers;
 
 /**
- * Provides access to ContainerRequest, ContainerResponse and request URI
- * information.
- * 
+ * Provides access to ContainerRequest, ContainerResponse and other context
+ * information information.
+ *
  * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
  * @version $Id: $
  */
@@ -41,19 +41,20 @@
 {
 
    /**
-    * Should be used to pass template values in context by using returned list in
-    * matching to @see
-    * {@link org.exoplatform.services.rest.uri.UriPattern#match(String, List)}
-    * . List will be cleared during matching.
-    * 
+    * Should be used to pass template values in context by using returned list
+    * in matching at
+    * {@link org.exoplatform.services.rest.uri.UriPattern#match(String, List)} .
+    * List will be cleared during matching.
+    *
     * @return the list for template values
     */
    List<String> getParameterValues();
 
    /**
-    * Pass in context list of path template parameters @see {@link UriPattern}.
-    * 
+    * Pass in context list of path template parameters .
+    *
     * @param parameterNames list of templates parameters
+    * @see UriPattern
     */
    void setParameterNames(List<String> parameterNames);
 
@@ -64,9 +65,9 @@
     * the root resource last.
     * </p>
     * So add each new resource at the begin of list.
-    * 
+    *
     * @param resource the resource e. g. resource class, sub-resource method or
-    *          sub-resource locator.
+    *        sub-resource locator
     */
    void addMatchedResource(Object resource);
 
@@ -77,9 +78,9 @@
     * resource URI last.
     * </p>
     * So add each new URI at the begin of list.
-    * 
-    * @param uri the partial part of that matched to resource class, sub-resource
-    *          method or sub-resource locator.
+    *
+    * @param uri the partial part of that matched to resource class,
+    *        sub-resource method or sub-resource locator
     */
    void addMatchedURI(String uri);
 
@@ -89,43 +90,49 @@
    Map<String, Object> getAttributes();
 
    /**
-    * @return See {@link Request}
+    * @return request
+    * @see Request
     */
    Request getRequest();
 
    /**
-    * @return See {@link HttpHeaders}
+    * @return request HTTP headers
+    * @see HttpHeaders
     */
    HttpHeaders getHttpHeaders();
-   
-   
+
    /**
-    * @return {@link InitialProperties}
+    * @return properties
+    * @see InitialProperties
     */
    InitialProperties getInitialProperties();
 
    /**
-    * @return See {@link SecurityContext}
+    * @return security context
+    * @see SecurityContext
     */
    SecurityContext getSecurityContext();
 
    /**
-    * @return See {@link GenericContainerRequest}
+    * @return JAX-RS request
+    * @see GenericContainerRequest
     */
    GenericContainerRequest getContainerRequest();
 
    /**
-    * @return See {@link UriInfo}
+    * @return URI info
+    * @see UriInfo
     */
    UriInfo getUriInfo();
 
    /**
-    * @return See {@link GenericContainerResponse}
+    * @return JAX-RS request
+    * @see GenericContainerResponse
     */
    GenericContainerResponse getContainerResponse();
 
    /**
-    * @return {@link ProviderBinder}
+    * @return set of providers
     * @see Providers
     */
    ProviderBinder getProviders();

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationContextImpl.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationContextImpl.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationContextImpl.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -51,21 +51,21 @@
    private static ThreadLocal<ApplicationContext> current = new ThreadLocal<ApplicationContext>();
 
    /**
-    * Set ApplicationContext for current thread.
-    * 
-    * @param context the ApplicationContext.
+    * @return current ApplicationContext.
     */
-   public static void setCurrent(ApplicationContext context)
+   public static ApplicationContext getCurrent()
    {
-      current.set(context);
+      return current.get();
    }
 
    /**
-    * @return current ApplicationContext.
+    * Set ApplicationContext for current thread.
+    *
+    * @param context the ApplicationContext.
     */
-   public static ApplicationContext getCurrent()
+   public static void setCurrent(ApplicationContext context)
    {
-      return current.get();
+      current.set(context);
    }
 
    /**
@@ -92,13 +92,18 @@
     * Mutable runtime attributes.
     */
    private Map<String, Object> attributes;
-   
+
    /**
     * Properties.
     */
    private Map<String, String> properties;
 
    /**
+    * Providers.
+    */
+   protected ProviderBinder providers;
+
+   /**
     * See {@link GenericContainerRequest}.
     */
    protected GenericContainerRequest request;
@@ -109,217 +114,156 @@
    protected GenericContainerResponse response;
 
    /**
-    * Providers.
+    * Absolute path, full requested URI without query string and fragment.
     */
-   protected ProviderBinder providers;
+   private URI absolutePath;
 
    /**
-    * Constructs new instance of ApplicationContext.
-    * 
-    * @param request See {@link GenricContainerRequest}
-    * @param response See {@link GenericContainerResponse}
-    * @param providers See {@link ProviderBinder}
+    * Decoded relative path.
     */
-   public ApplicationContextImpl(GenericContainerRequest request, GenericContainerResponse response,
-      ProviderBinder providers)
-   {
-      this.request = request;
-      this.response = response;
-      this.providers = providers;
-   }
+   private String path;
 
    /**
-    * {@inheritDoc}
+    * Not decoded relative path.
     */
-   public List<String> getParameterValues()
-   {
-      return parameterValues;
-   }
+   private String encodedPath;
 
    /**
-    * {@inheritDoc}
+    * Not decoded path template parameters.
     */
-   public void setParameterNames(List<String> parameterNames)
-   {
-      if (encodedPathParameters == null)
-         encodedPathParameters = new MultivaluedMapImpl();
+   private MultivaluedMap<String, String> encodedPathParameters;
 
-      for (int i = 0; i < parameterNames.size(); i++)
-         encodedPathParameters.add(parameterNames.get(i), parameterValues.get(i));
+   /**
+    * Decoded path template parameters.
+    */
+   private MultivaluedMap<String, String> pathParameters;
 
-   }
+   /**
+    * List of not decoded path segments.
+    */
+   private List<PathSegment> encodedPathSegments;
 
    /**
-    * {@inheritDoc}
+    * Decoded path segments.
     */
-   public void addMatchedResource(Object resource)
-   {
-      matchedResources.add(0, resource);
-   }
+   private List<PathSegment> pathSegments;
 
    /**
-    * {@inheritDoc}
+    * Not decoded query parameters.
     */
-   public void addMatchedURI(String uri)
-   {
-      encodedMatchedURIs.add(0, uri);
-      matchedURIs.add(0, UriComponent.decode(uri, UriComponent.PATH_SEGMENT));
-   }
+   private MultivaluedMap<String, String> encodedQueryParameters;
 
    /**
-    * {@inheritDoc}
+    * Decoded query parameters.
     */
-   public Map<String, Object> getAttributes()
-   {
-      return attributes == null ? attributes = new HashMap<String, Object>() : attributes;
-   }
+   private MultivaluedMap<String, String> queryParameters;
 
    /**
-    * {@inheritDoc}
+    * Constructs new instance of ApplicationContext.
+    *
+    * @param request See {@link GenricContainerRequest}
+    * @param response See {@link GenericContainerResponse}
+    * @param providerBinder
     */
-   public Request getRequest()
+   public ApplicationContextImpl(GenericContainerRequest request, GenericContainerResponse response,
+      ProviderBinder providers)
    {
-      return request;
+      this.request = request;
+      this.response = response;
+      this.providers = providers;
    }
 
    /**
     * {@inheritDoc}
     */
-   public HttpHeaders getHttpHeaders()
+   public void addMatchedResource(Object resource)
    {
-      return request;
+      matchedResources.add(0, resource);
    }
-   
+
    /**
     * {@inheritDoc}
     */
-   public InitialProperties getInitialProperties()
+   public void addMatchedURI(String uri)
    {
-      return this;
+      encodedMatchedURIs.add(0, uri);
+      matchedURIs.add(0, UriComponent.decode(uri, UriComponent.PATH_SEGMENT));
    }
 
    /**
     * {@inheritDoc}
     */
-   public SecurityContext getSecurityContext()
+   public URI getAbsolutePath()
    {
-      return request;
+      if (absolutePath != null)
+      {
+         return absolutePath;
+      }
+      return absolutePath = getRequestUriBuilder().replaceQuery(null).fragment(null).build();
    }
 
    /**
     * {@inheritDoc}
     */
-   public GenericContainerRequest getContainerRequest()
+   public UriBuilder getAbsolutePathBuilder()
    {
-      return request;
+      return UriBuilder.fromUri(getAbsolutePath());
    }
 
    /**
     * {@inheritDoc}
     */
-   public UriInfo getUriInfo()
+   public Map<String, Object> getAttributes()
    {
-      return this;
+      return attributes == null ? attributes = new HashMap<String, Object>() : attributes;
    }
 
    /**
     * {@inheritDoc}
     */
-   public GenericContainerResponse getContainerResponse()
+   public URI getBaseUri()
    {
-      return response;
+      return request.getBaseUri();
    }
-   
-   // InitialProperties
 
    /**
     * {@inheritDoc}
     */
-   public Map<String, String> getProperties()
+   public UriBuilder getBaseUriBuilder()
    {
-      return properties == null ? properties = new HashMap<String, String>() : properties;
+      return UriBuilder.fromUri(getBaseUri());
    }
 
    /**
     * {@inheritDoc}
     */
-   public String getProperty(String name)
+   public GenericContainerRequest getContainerRequest()
    {
-      return getProperties().get(name);
+      return request;
    }
 
    /**
     * {@inheritDoc}
     */
-   public void setProperty(String name, String value)
+   public GenericContainerResponse getContainerResponse()
    {
-      getProperties().put(name, value);
+      return response;
    }
 
-   // UriInfo
-
    /**
-    * Absolute path, full requested URI without query string and fragment.
-    */
-   private URI absolutePath;
-
-   /**
-    * Decoded relative path.
-    */
-   private String path;
-
-   /**
-    * Not decoded relative path.
-    */
-   private String encodedPath;
-
-   /**
-    * Not decoded path template parameters.
-    */
-   private MultivaluedMap<String, String> encodedPathParameters;
-
-   /**
-    * Decoded path template parameters.
-    */
-   private MultivaluedMap<String, String> pathParameters;
-
-   /**
-    * List of not decoded path segments.
-    */
-   private List<PathSegment> encodedPathSegments;
-
-   /**
-    * Decoded path segments.
-    */
-   private List<PathSegment> pathSegments;
-
-   /**
-    * Not decoded query parameters.
-    */
-   private MultivaluedMap<String, String> encodedQueryParameters;
-
-   /**
-    * Decoded query parameters.
-    */
-   private MultivaluedMap<String, String> queryParameters;
-
-   /**
     * {@inheritDoc}
     */
-   public URI getAbsolutePath()
+   public HttpHeaders getHttpHeaders()
    {
-      if (absolutePath != null)
-         return absolutePath;
-
-      return absolutePath = getRequestUriBuilder().replaceQuery(null).fragment(null).build();
+      return request;
    }
 
    /**
     * {@inheritDoc}
     */
-   public UriBuilder getAbsolutePathBuilder()
+   public InitialProperties getInitialProperties()
    {
-      return UriBuilder.fromUri(getAbsolutePath());
+      return this;
    }
 
    /**
@@ -349,22 +293,14 @@
    /**
     * {@inheritDoc}
     */
-   public URI getBaseUri()
+   public List<String> getParameterValues()
    {
-      return request.getBaseUri();
+      return parameterValues;
    }
 
    /**
     * {@inheritDoc}
     */
-   public UriBuilder getBaseUriBuilder()
-   {
-      return UriBuilder.fromUri(getBaseUri());
-   }
-
-   /**
-    * {@inheritDoc}
-    */
    public String getPath()
    {
       return getPath(true);
@@ -376,17 +312,17 @@
    public String getPath(boolean decode)
    {
       if (encodedPath == null)
+      {
          encodedPath = getAbsolutePath().getRawPath().substring(getBaseUri().getRawPath().length());
-
+      }
       if (decode)
       {
          if (path != null)
+         {
             return path;
-
+         }
          return path = UriComponent.decode(encodedPath, UriComponent.PATH);
-
       }
-
       return encodedPath;
    }
 
@@ -404,15 +340,15 @@
    public MultivaluedMap<String, String> getPathParameters(boolean decode)
    {
       if (encodedPathParameters == null)
+      {
          throw new IllegalStateException("Path template variables not initialized yet.");
-
+      }
       if (decode)
       {
          if (pathParameters == null)
          {
             pathParameters = new MultivaluedMapImpl();
          }
-
          if (pathParameters.size() != encodedPathParameters.size())
          {
             for (String key : encodedPathParameters.keySet())
@@ -426,7 +362,6 @@
          }
          return pathParameters;
       }
-
       return encodedPathParameters;
    }
 
@@ -454,6 +389,30 @@
    /**
     * {@inheritDoc}
     */
+   public Map<String, String> getProperties()
+   {
+      return properties == null ? properties = new HashMap<String, String>() : properties;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getProperty(String name)
+   {
+      return getProperties().get(name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ProviderBinder getProviders()
+   {
+      return providers;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public MultivaluedMap<String, String> getQueryParameters()
    {
       return getQueryParameters(true);
@@ -465,8 +424,10 @@
    public MultivaluedMap<String, String> getQueryParameters(boolean decode)
    {
       if (decode)
+      {
          return queryParameters != null ? queryParameters : (queryParameters =
             UriComponent.parseQueryString(getRequestUri().getRawQuery(), true));
+      }
       return encodedQueryParameters != null ? encodedQueryParameters : (encodedQueryParameters =
          UriComponent.parseQueryString(getRequestUri().getRawQuery(), false));
    }
@@ -474,6 +435,14 @@
    /**
     * {@inheritDoc}
     */
+   public Request getRequest()
+   {
+      return request;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public URI getRequestUri()
    {
       return request.getRequestUri();
@@ -490,9 +459,49 @@
    /**
     * {@inheritDoc}
     */
-   public ProviderBinder getProviders()
+   public SecurityContext getSecurityContext()
    {
-      return providers;
+      return request;
    }
 
+   /**
+    * {@inheritDoc}
+    */
+   public UriInfo getUriInfo()
+   {
+      return this;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void setParameterNames(List<String> parameterNames)
+   {
+      if (encodedPathParameters == null)
+      {
+         encodedPathParameters = new MultivaluedMapImpl();
+      }
+      for (int i = 0; i < parameterNames.size(); i++)
+      {
+         encodedPathParameters.add(parameterNames.get(i), parameterValues.get(i));
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void setProperty(String name, String value)
+   {
+      getProperties().put(name, value);
+   }
+
+   /**
+    * @param providers providers
+    * @see javax.ws.rs.ext.Providers
+    */
+   public void setProviders(ProviderBinder providers)
+   {
+      this.providers = providers;
+   }
+
 }

Added: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationProviders.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationProviders.java	                        (rev 0)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationProviders.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.rest.impl;
+
+/**
+ * Application specific set of providers. Providers which were delivered via
+ * subclass of javax.ws.rs.core.Application will have an advantage over default
+ * providers. Default (embedded in this framework) providers will be in use only
+ * if JAX-RS application does not provide own providers with same purposes.
+ * 
+ * @author <a href="andrew00x at gmail.com">Andrey Parfonov</a>
+ * @version $Id$
+ */
+public class ApplicationProviders extends ProviderBinder
+{
+
+   private final String applicationId;
+
+   public ApplicationProviders(String applicationId)
+   {
+      this.applicationId = applicationId;
+   }
+
+   /**
+    * @return identifier (suppose to use FQN) of application-supplied subclass
+    *         of {@link javax.ws.rs.core.Application} via this set of JAX-RS
+    *         providers were delivered.
+    */
+   public String getApplication()
+   {
+      return applicationId;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected void init()
+   {
+   }
+
+}


Property changes on: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationProviders.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationRegistry.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationRegistry.java	                        (rev 0)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationRegistry.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -0,0 +1,171 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.services.rest.impl;
+
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.rest.Filter;
+import org.exoplatform.services.rest.PerRequestObjectFactory;
+import org.exoplatform.services.rest.RequestFilter;
+import org.exoplatform.services.rest.ResponseFilter;
+import org.exoplatform.services.rest.SingletonObjectFactory;
+import org.exoplatform.services.rest.impl.resource.ApplicationResource;
+import org.exoplatform.services.rest.impl.resource.ResourceDescriptorValidator;
+import org.exoplatform.services.rest.method.MethodInvokerFilter;
+import org.exoplatform.services.rest.resource.AbstractResourceDescriptor;
+import org.picocontainer.Startable;
+
+import java.util.List;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Purpose of this class is to get all subclasses of
+ * {@link javax.ws.rs.core.Application} from eXo container and to process set of
+ * object of classes provided by it as JAX-RS components.
+ *
+ * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
+ * @version $Id$
+ */
+public class ApplicationRegistry implements Startable
+{
+   /** Logger. */
+   private static final Log LOG = ExoLogger.getLogger(ApplicationRegistry.class);
+
+   protected final ExoContainer container;
+
+   protected final ResourceBinder resources;
+
+   protected final ProvidersRegistry providers;
+
+   protected final ResourceDescriptorValidator rdv = ResourceDescriptorValidator.getInstance();
+
+   public ApplicationRegistry(ExoContainerContext containerContext, ResourceBinder resources,
+      ProvidersRegistry providers, StartableApplication eXo /* Be sure eXo components are initialized. */)
+   {
+      this.resources = resources;
+      this.providers = providers;
+      this.container = containerContext.getContainer();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @SuppressWarnings("unchecked")
+   public void start()
+   {
+      List<Application> all = container.getComponentInstancesOfType(Application.class);
+      for (Application app : all)
+      {
+         addApplication(app);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   public void addApplication(Application app)
+   {
+      String applicationId = app.getClass().getName();
+      ApplicationProviders appProviders = new ApplicationProviders(applicationId);
+      for (Object obj : app.getSingletons())
+      {
+         Class clazz = obj.getClass();
+         if (clazz.getAnnotation(Path.class) != null)
+         {
+            AbstractResourceDescriptor descriptor = new ApplicationResource(applicationId, obj);
+            descriptor.accept(rdv);
+            resources.addResource(new SingletonObjectFactory<AbstractResourceDescriptor>(descriptor, obj));
+         }
+         else if (clazz.getAnnotation(Provider.class) != null)
+         {
+            if (obj instanceof ContextResolver)
+               appProviders.addContextResolver((ContextResolver)obj);
+            if (obj instanceof ExceptionMapper)
+               appProviders.addExceptionMapper((ExceptionMapper)obj);
+            if (obj instanceof MessageBodyReader)
+               appProviders.addMessageBodyReader((MessageBodyReader)obj);
+            if (obj instanceof MessageBodyWriter)
+               appProviders.addMessageBodyWriter((MessageBodyWriter)obj);
+         }
+         else if (clazz.getAnnotation(Filter.class) != null)
+         {
+            if (obj instanceof MethodInvokerFilter)
+               appProviders.addMethodInvokerFilter((MethodInvokerFilter)obj);
+            if (obj instanceof RequestFilter)
+               appProviders.addRequestFilter((RequestFilter)obj);
+            if (obj instanceof ResponseFilter)
+               appProviders.addResponseFilter((ResponseFilter)obj);
+         }
+         else
+         {
+            LOG.warn("Unknown class type: " + clazz.getName() + " found in " + applicationId);
+         }
+      }
+      for (Class clazz : app.getClasses())
+      {
+         if (clazz.getAnnotation(Path.class) != null)
+         {
+            AbstractResourceDescriptor descriptor = new ApplicationResource(applicationId, clazz);
+            descriptor.accept(rdv);
+            resources.addResource(new PerRequestObjectFactory<AbstractResourceDescriptor>(descriptor));
+         }
+         else if (clazz.getAnnotation(Provider.class) != null)
+         {
+            if (ContextResolver.class.isAssignableFrom(clazz))
+               appProviders.addContextResolver(clazz);
+            if (ExceptionMapper.class.isAssignableFrom(clazz))
+               appProviders.addExceptionMapper(clazz);
+            if (MessageBodyReader.class.isAssignableFrom(clazz))
+               appProviders.addMessageBodyReader(clazz);
+            if (MessageBodyWriter.class.isAssignableFrom(clazz))
+               appProviders.addMessageBodyWriter(clazz);
+         }
+         else if (clazz.getAnnotation(Filter.class) != null)
+         {
+            if (MethodInvokerFilter.class.isAssignableFrom(clazz))
+               appProviders.addMethodInvokerFilter(clazz);
+            if (RequestFilter.class.isAssignableFrom(clazz))
+               appProviders.addRequestFilter(clazz);
+            if (ResponseFilter.class.isAssignableFrom(clazz))
+               appProviders.addResponseFilter(clazz);
+         }
+         else
+         {
+            LOG.warn("Unknown class type: " + clazz.getName() + " found in: " + applicationId);
+         }
+      }
+      this.providers.addProviders(appProviders);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void stop()
+   {
+   }
+
+}


Property changes on: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ApplicationRegistry.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProviderBinder.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProviderBinder.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProviderBinder.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -48,6 +48,7 @@
 import org.exoplatform.services.rest.impl.provider.StringEntityProvider;
 import org.exoplatform.services.rest.impl.resource.ResourceDescriptorValidator;
 import org.exoplatform.services.rest.method.MethodInvokerFilter;
+import org.exoplatform.services.rest.provider.ExtendedProviders;
 import org.exoplatform.services.rest.provider.ProviderDescriptor;
 import org.exoplatform.services.rest.resource.ResourceDescriptorVisitor;
 import org.exoplatform.services.rest.uri.UriPattern;
@@ -70,29 +71,33 @@
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Providers;
 
 /**
+ * Prepared set of providers. Users of JAX-RS implementation are not expected to
+ * use this class directly. &#64;Context annotation should be used to obtain
+ * actual set of providers in RESTful services. As alternative method :
+ * <pre>
+ * ApplicationContext context = ApplicationContextImpl.getCurrent();
+ * Providers providers = context.getProviders();
+ * </pre>
+ *
  * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
  * @version $Id: $
  */
-public class ProviderBinder implements Providers
+public class ProviderBinder implements ExtendedProviders
 {
 
-   /**
-    * Logger.
-    */
-   private static final Log LOG = ExoLogger.getLogger("exo.ws.rest.core.ProviderBinder");
+   /** Logger. */
+   private static final Log LOG = ExoLogger.getLogger(ProviderBinder.class);
 
-   /**
-    * Providers instance.
-    *
-    * @see Providers
-    */
+   /** Default providers. */
    private static AtomicReference<ProviderBinder> ainst = new AtomicReference<ProviderBinder>();
 
    /**
-    * @return instance of {@link ProviderBinder}
+    * Get actual set of providers. Users of JAX-RS implementation are not
+    * expected to call this method.
+    *
+    * @return actual set of providers
     */
    public static ProviderBinder getInstance()
    {
@@ -105,6 +110,12 @@
       return t;
    }
 
+   /**
+    * Set actual set of providers. Users of JAX-RS implementation are not
+    * expected to call this method.
+    *
+    * @param inst actual set of providers
+    */
    public static void setInstance(ProviderBinder inst)
    {
       ainst.set(inst);
@@ -120,7 +131,6 @@
     */
    protected void init()
    {
-      // TODO remove this hard code
       ByteEntityProvider baep = new ByteEntityProvider();
       addMessageBodyReader(baep);
       addMessageBodyWriter(baep);
@@ -183,55 +193,66 @@
       addContextResolver(JAXBContextResolver.class, null, ComponentLifecycleScope.CONTAINER);
 
       addExceptionMapper(new DefaultExceptionMapper());
-
    }
 
    /**
-    * Read message body providers. Also see {@link MediaTypeMultivaluedMap}.
+    * Read message body providers.
+    *
+    * @see MediaTypeMultivaluedMap .
     */
-   private final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> writeProviders =
+   protected final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> writeProviders =
       new MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>>();
 
    /**
-    * Read message body providers. Also see {@link MediaTypeMultivaluedMap}.
+    * Read message body providers.
+    *
+    * @see MediaTypeMultivaluedMap .
     */
-   private final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> readProviders =
+   protected final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> readProviders =
       new MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>>();
 
    /**
-    * Exception mappers, see {@link ExceptionMapper}.
+    * Exception mappers.
+    *
+    * @see ExceptionMapper .
     */
-   private final Map<Class<? extends Throwable>, ObjectFactory<ProviderDescriptor>> exceptionMappers =
+   protected final Map<Class<? extends Throwable>, ObjectFactory<ProviderDescriptor>> exceptionMappers =
       new HashMap<Class<? extends Throwable>, ObjectFactory<ProviderDescriptor>>();
 
    /**
     * Context resolvers.
+    *
+    * @see ContextResolver .
     */
-   private final Map<Class<?>, MediaTypeMap<ObjectFactory<ProviderDescriptor>>> contextResolvers =
+   protected final Map<Class<?>, MediaTypeMap<ObjectFactory<ProviderDescriptor>>> contextResolvers =
       new HashMap<Class<?>, MediaTypeMap<ObjectFactory<ProviderDescriptor>>>();
 
    /**
-    * Request filters, see {@link RequestFilter}.
+    * Request filters.
+    *
+    * @see RequestFilter .
     */
-   private final UriPatternMap<ObjectFactory<FilterDescriptor>> requestFilters =
+   protected final UriPatternMap<ObjectFactory<FilterDescriptor>> requestFilters =
       new UriPatternMap<ObjectFactory<FilterDescriptor>>();
 
    /**
-    * Response filters, see {@link ResponseFilter}.
+    * Response filters.
+    *
+    * @see ResponseFilter .
     */
-   private final UriPatternMap<ObjectFactory<FilterDescriptor>> responseFilters =
+   protected final UriPatternMap<ObjectFactory<FilterDescriptor>> responseFilters =
       new UriPatternMap<ObjectFactory<FilterDescriptor>>();
 
    /**
     * Method invoking filters.
+    *
+    * @see MethodInvokerFilter .
     */
-   private final UriPatternMap<ObjectFactory<FilterDescriptor>> invokerFilters =
+   protected final UriPatternMap<ObjectFactory<FilterDescriptor>> invokerFilters =
       new UriPatternMap<ObjectFactory<FilterDescriptor>>();
 
-   /**
-    * Validator.
-    */
-   private final ResourceDescriptorVisitor rdv = ResourceDescriptorValidator.getInstance();
+   /** Validator. */
+   protected final ResourceDescriptorVisitor rdv = ResourceDescriptorValidator.getInstance();
 
    //
 
@@ -408,7 +429,6 @@
             }
          }
       }
-
       Collections.sort(l, MediaTypeHelper.MEDIA_TYPE_COMPARATOR);
       return l;
    }
@@ -424,18 +444,17 @@
       {
          if (mediaType == null)
          {
-            return _getContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE);
+            return doGetContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE);
          }
-
-         resolver = _getContextResolver(pm, contextType, mediaType);
-         if (resolver == null)
+         resolver = doGetContextResolver(pm, contextType, mediaType);
+         if (resolver == null && !mediaType.isWildcardSubtype())
          {
             resolver =
-               _getContextResolver(pm, contextType, new MediaType(mediaType.getType(), MediaType.MEDIA_TYPE_WILDCARD));
+               doGetContextResolver(pm, contextType, new MediaType(mediaType.getType(), MediaType.MEDIA_TYPE_WILDCARD));
          }
-         if (resolver == null)
+         if (resolver == null && !mediaType.isWildcardType())
          {
-            resolver = _getContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE);
+            resolver = doGetContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE);
          }
       }
       return resolver;
@@ -463,21 +482,19 @@
    {
       if (mediaType == null)
       {
-         return _getMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
+         return doGetMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
       }
-
-      MessageBodyReader<T> reader = _getMessageBodyReader(type, genericType, annotations, mediaType);
-      if (reader == null)
+      MessageBodyReader<T> reader = doGetMessageBodyReader(type, genericType, annotations, mediaType);
+      if (reader == null && !mediaType.isWildcardSubtype())
       {
          reader =
-            _getMessageBodyReader(type, genericType, annotations, new MediaType(mediaType.getType(),
+            doGetMessageBodyReader(type, genericType, annotations, new MediaType(mediaType.getType(),
                MediaType.MEDIA_TYPE_WILDCARD));
       }
-      if (reader == null)
+      if (reader == null && !mediaType.isWildcardType())
       {
-         reader = _getMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
+         reader = doGetMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
       }
-
       return reader;
    }
 
@@ -489,19 +506,18 @@
    {
       if (mediaType == null)
       {
-         return _getMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
+         return doGetMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
       }
-
-      MessageBodyWriter<T> writer = _getMessageBodyWriter(type, genericType, annotations, mediaType);
-      if (writer == null)
+      MessageBodyWriter<T> writer = doGetMessageBodyWriter(type, genericType, annotations, mediaType);
+      if (writer == null && !mediaType.isWildcardSubtype())
       {
          writer =
-            _getMessageBodyWriter(type, genericType, annotations, new MediaType(mediaType.getType(),
+            doGetMessageBodyWriter(type, genericType, annotations, new MediaType(mediaType.getType(),
                MediaType.MEDIA_TYPE_WILDCARD));
       }
-      if (writer == null)
+      if (writer == null && !mediaType.isWildcardType())
       {
-         writer = _getMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
+         writer = doGetMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE);
       }
       return writer;
    }
@@ -612,8 +628,7 @@
    }
 
    /**
-    * @param path request path
-    * @return acceptable method invocation filters
+    * {@inheritDoc}
     */
    public List<ObjectFactory<FilterDescriptor>> getMethodInvokerFilters(String path)
    {
@@ -621,8 +636,7 @@
    }
 
    /**
-    * @param path request path
-    * @return acceptable request filters
+    * {@inheritDoc}
     */
    public List<ObjectFactory<FilterDescriptor>> getRequestFilters(String path)
    {
@@ -630,8 +644,7 @@
    }
 
    /**
-    * @param path request path
-    * @return acceptable response filters
+    * {@inheritDoc}
     */
    public List<ObjectFactory<FilterDescriptor>> getResponseFilters(String path)
    {
@@ -646,17 +659,14 @@
     * @see #getRequestFilters(String)
     * @see #getResponseFilters(String)
     */
-   private List<ObjectFactory<FilterDescriptor>> getMatchedFilters(String path,
+   protected List<ObjectFactory<FilterDescriptor>> getMatchedFilters(String path,
       UriPatternMap<ObjectFactory<FilterDescriptor>> m)
    {
-
       List<ObjectFactory<FilterDescriptor>> l = new ArrayList<ObjectFactory<FilterDescriptor>>();
-
       List<String> capturingValues = new ArrayList<String>();
       for (Map.Entry<UriPattern, List<ObjectFactory<FilterDescriptor>>> e : m.entrySet())
       {
          UriPattern uriPattern = e.getKey();
-
          if (uriPattern != null)
          {
             if (e.getKey().match(path, capturingValues))
@@ -671,27 +681,24 @@
             {
                continue; // not matched
             }
-
          }
          // if matched or UriPattern is null
          l.addAll(e.getValue());
       }
-
       return l;
-
    }
 
    /**
     * @param <T> context resolver actual type argument
     * @param pm MediaTypeMap that contains ProviderFactories that may produce
-    *          objects that are instance of T
+    *        objects that are instance of T
     * @param contextType context type
     * @param mediaType media type that can be used to restrict context resolver
-    *          choose
+    *        choose
     * @return ContextResolver or null if nothing was found
     */
    @SuppressWarnings("unchecked")
-   private <T> ContextResolver<T> _getContextResolver(MediaTypeMap<ObjectFactory<ProviderDescriptor>> pm,
+   protected <T> ContextResolver<T> doGetContextResolver(MediaTypeMap<ObjectFactory<ProviderDescriptor>> pm,
       Class<T> contextType, MediaType mediaType)
    {
       for (Map.Entry<MediaType, ObjectFactory<ProviderDescriptor>> e : pm.entrySet())
@@ -716,7 +723,7 @@
     * @return message body reader or null if no one was found.
     */
    @SuppressWarnings("unchecked")
-   private <T> MessageBodyReader<T> _getMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations,
+   protected <T> MessageBodyReader<T> doGetMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations,
       MediaType mediaType)
    {
       for (ObjectFactory pf : readProviders.getList(mediaType))
@@ -742,7 +749,7 @@
     * @return message body writer or null if no one was found.
     */
    @SuppressWarnings("unchecked")
-   private <T> MessageBodyWriter<T> _getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations,
+   protected <T> MessageBodyWriter<T> doGetMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations,
       MediaType mediaType)
    {
       for (ObjectFactory pf : writeProviders.getList(mediaType))
@@ -759,7 +766,7 @@
    /**
     * @param clazz ContextResolver class
     * @param instance ContextResolver instance, may be null if not singleton
-    *          instance
+    *        instance
     * @param scope ComponentLifecycleScope
     */
    @SuppressWarnings("unchecked")
@@ -800,9 +807,7 @@
                      break;
                   case SINGLETON :
                      if (instance == null)
-                     {
                         throw new NullPointerException("ContextResolver instance is null.");
-                     }
                      factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance);
                      break;
                   case CONTAINER :
@@ -848,16 +853,13 @@
             break;
          case SINGLETON :
             if (instance == null)
-            {
                throw new NullPointerException("MessageBodyReader instance is null.");
-            }
             factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance);
             break;
          case CONTAINER :
             factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor);
             break;
       }
-
       // MessageBodyReader is smart component and can determine which type it
       // supports, see method MessageBodyReader.isReadable. So here does not
       // check is reader for the same Java and media type already exists.
@@ -888,16 +890,13 @@
             break;
          case SINGLETON :
             if (instance == null)
-            {
                throw new NullPointerException("MessageBodyWriter instance is null.");
-            }
             factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance);
             break;
          case CONTAINER :
             factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor);
             break;
       }
-
       // MessageBodyWriter is smart component and can determine which type it
       // supports, see method MessageBodyWriter.isWriteable. So here does not
       // check is writer for the same Java and media type already exists.
@@ -911,7 +910,7 @@
    /**
     * @param clazz ExceptionMapper class
     * @param instance ExceptionMapper instance, may be null if not singleton
-    *          instance
+    *        instance
     * @param scope ComponentLifecycleScope
     */
    @SuppressWarnings("unchecked")
@@ -927,9 +926,8 @@
             {
                Type[] atypes = pt.getActualTypeArguments();
                if (atypes.length > 1)
-               {
                   throw new RuntimeException("Unable strong determine actual type argument, more then one type found.");
-               }
+
                Class<? extends Throwable> exc = (Class<? extends Throwable>)atypes[0];
 
                if (exceptionMappers.get(exc) != null)
@@ -949,16 +947,13 @@
                      break;
                   case SINGLETON :
                      if (instance == null)
-                     {
                         throw new NullPointerException("ExceptionMapper instance is null.");
-                     }
                      factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance);
                      break;
                   case CONTAINER :
                      factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor);
                      break;
                }
-
                exceptionMappers.put(exc, factory);
             }
          }
@@ -968,13 +963,12 @@
    /**
     * @param clazz RequestFilter class
     * @param instance RequestFilter instance, may be null if not singleton
-    *          instance
+    *        instance
     * @param scope ComponentLifecycleScope
     */
    public void addRequestFilter(Class<? extends RequestFilter> clazz, RequestFilter instance,
       ComponentLifecycleScope scope)
    {
-
       FilterDescriptor descriptor = new FilterDescriptorImpl(clazz);
       descriptor.accept(rdv);
 
@@ -986,29 +980,25 @@
             break;
          case SINGLETON :
             if (instance == null)
-            {
                throw new NullPointerException("RequestFilter instance is null.");
-            }
             factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance);
             break;
          case CONTAINER :
             factory = new ContainerObjectFactory<FilterDescriptor>(descriptor);
             break;
       }
-
       requestFilters.getList(descriptor.getUriPattern()).add(factory);
    }
 
    /**
     * @param clazz ResponseFilter class
     * @param instance ResponseFilter instance, may be null if not singleton
-    *          instance
+    *        instance
     * @param scope ComponentLifecycleScope
     */
    public void addResponseFilter(Class<? extends ResponseFilter> clazz, ResponseFilter instance,
       ComponentLifecycleScope scope)
    {
-
       FilterDescriptor descriptor = new FilterDescriptorImpl(clazz);
       descriptor.accept(rdv);
 
@@ -1020,29 +1010,25 @@
             break;
          case SINGLETON :
             if (instance == null)
-            {
                throw new NullPointerException("ResponseFilter instance is null.");
-            }
             factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance);
             break;
          case CONTAINER :
             factory = new ContainerObjectFactory<FilterDescriptor>(descriptor);
             break;
       }
-
       responseFilters.getList(descriptor.getUriPattern()).add(factory);
    }
 
    /**
     * @param clazz MethodInvokerFilter class
     * @param instance MethodInvokerFilter instance, may be null if not singleton
-    *          instance
+    *        instance
     * @param scope ComponentLifecycleScope
     */
    public void addMethodInvokerFilter(Class<? extends MethodInvokerFilter> clazz, MethodInvokerFilter instance,
       ComponentLifecycleScope scope)
    {
-
       FilterDescriptor descriptor = new FilterDescriptorImpl(clazz);
       descriptor.accept(rdv);
 
@@ -1054,16 +1040,13 @@
             break;
          case SINGLETON :
             if (instance == null)
-            {
                throw new NullPointerException("MethodInvokerFilter instance is null.");
-            }
             factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance);
             break;
          case CONTAINER :
             factory = new ContainerObjectFactory<FilterDescriptor>(descriptor);
             break;
       }
-
       invokerFilters.getList(descriptor.getUriPattern()).add(factory);
    }
 

Added: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProvidersRegistry.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProvidersRegistry.java	                        (rev 0)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProvidersRegistry.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.rest.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="andrew00x at gmail.com">Andrey Parfonov</a>
+ * @version $Id$
+ */
+public class ProvidersRegistry
+{
+
+   protected Map<String, ApplicationProviders> all = new HashMap<String, ApplicationProviders>();
+
+   public void addProviders(ApplicationProviders ap)
+   {
+      all.put(ap.getApplication(), ap);
+   }
+
+   public ApplicationProviders getProviders(String applicationId)
+   {
+      return all.get(applicationId);
+   }
+
+}


Property changes on: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ProvidersRegistry.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestDispatcher.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestDispatcher.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestDispatcher.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -21,15 +21,21 @@
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.rest.ApplicationContext;
+import org.exoplatform.services.rest.ComponentLifecycleScope;
+import org.exoplatform.services.rest.FilterDescriptor;
 import org.exoplatform.services.rest.GenericContainerRequest;
 import org.exoplatform.services.rest.GenericContainerResponse;
 import org.exoplatform.services.rest.ObjectFactory;
+import org.exoplatform.services.rest.RequestFilter;
+import org.exoplatform.services.rest.ResponseFilter;
 import org.exoplatform.services.rest.SingletonObjectFactory;
 import org.exoplatform.services.rest.impl.header.HeaderHelper;
 import org.exoplatform.services.rest.impl.header.MediaTypeHelper;
 import org.exoplatform.services.rest.impl.method.MethodInvokerFactory;
 import org.exoplatform.services.rest.impl.resource.AbstractResourceDescriptorImpl;
+import org.exoplatform.services.rest.impl.resource.ApplicationResource;
 import org.exoplatform.services.rest.method.MethodInvoker;
+import org.exoplatform.services.rest.method.MethodInvokerFilter;
 import org.exoplatform.services.rest.resource.AbstractResourceDescriptor;
 import org.exoplatform.services.rest.resource.ResourceMethodDescriptor;
 import org.exoplatform.services.rest.resource.ResourceMethodMap;
@@ -39,7 +45,10 @@
 import org.exoplatform.services.rest.resource.SubResourceMethodMap;
 import org.exoplatform.services.rest.uri.UriPattern;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
@@ -52,6 +61,10 @@
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
 
 /**
  * Lookup resource which can serve request.
@@ -62,33 +75,382 @@
 public class RequestDispatcher
 {
 
+   /**
+    * Set of providers which respects providers specified by JAX-RS
+    * Applications. Default (embedded) providers will be used only if
+    * application does not provide own providers with the same purposes.
+    */
+   private class ProvidersAdapter extends ProviderBinder
+   {
+      private ProviderBinder applicationProviders;
+
+      private ProviderBinder defaultProviders;
+
+      private ProvidersAdapter(ProviderBinder applicationProviders, ProviderBinder defaultProviders)
+      {
+         this.applicationProviders = applicationProviders;
+         this.defaultProviders = defaultProviders;
+      }
+
+      @Override
+      protected void init()
+      {
+         // Do not add default providers here.
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addContextResolver(Class<? extends ContextResolver> clazz, ContextResolver instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addContextResolver(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addContextResolver");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addContextResolver(Class<? extends ContextResolver> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addContextResolver(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addContextResolver");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addContextResolver(ContextResolver instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addContextResolver(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addContextResolver");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addExceptionMapper(Class<? extends ExceptionMapper> clazz, ExceptionMapper instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addExceptionMapper(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addExceptionMapper");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addExceptionMapper(Class<? extends ExceptionMapper> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addExceptionMapper(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addExceptionMapper");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addExceptionMapper(ExceptionMapper instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addExceptionMapper(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addExceptionMapper");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyReader(Class<? extends MessageBodyReader> clazz, MessageBodyReader instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyReader(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyReader");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyReader(Class<? extends MessageBodyReader> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyReader(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyReader");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyReader(MessageBodyReader instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyReader(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyReader");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyWriter(Class<? extends MessageBodyWriter> clazz, MessageBodyWriter instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyWriter(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyWriter");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyWriter(Class<? extends MessageBodyWriter> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyWriter(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyWriter");
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public void addMessageBodyWriter(MessageBodyWriter instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMessageBodyWriter(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMessageBodyWriter");
+      }
+
+      @Override
+      public void addMethodInvokerFilter(Class<? extends MethodInvokerFilter> clazz, MethodInvokerFilter instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMethodInvokerFilter(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMethodInvokerFilter");
+      }
+
+      @Override
+      public void addMethodInvokerFilter(Class<? extends MethodInvokerFilter> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMethodInvokerFilter(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMethodInvokerFilter");
+      }
+
+      @Override
+      public void addMethodInvokerFilter(MethodInvokerFilter instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addMethodInvokerFilter(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addMethodInvokerFilter");
+      }
+
+      @Override
+      public void addRequestFilter(Class<? extends RequestFilter> clazz, RequestFilter instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addRequestFilter(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addRequestFilter");
+      }
+
+      @Override
+      public void addRequestFilter(Class<? extends RequestFilter> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addRequestFilter(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addRequestFilter");
+      }
+
+      @Override
+      public void addRequestFilter(RequestFilter instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addRequestFilter(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addRequestFilter");
+      }
+
+      @Override
+      public void addResponseFilter(Class<? extends ResponseFilter> clazz, ResponseFilter instance,
+         ComponentLifecycleScope scope)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addResponseFilter(clazz, instance, scope);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addResponseFilter");
+      }
+
+      @Override
+      public void addResponseFilter(Class<? extends ResponseFilter> clazz)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addResponseFilter(clazz);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addResponseFilter");
+      }
+
+      @Override
+      public void addResponseFilter(ResponseFilter instance)
+      {
+         if (applicationProviders != null)
+            applicationProviders.addResponseFilter(instance);
+         else
+            // Keep default set of providers untouched.
+            throw new UnsupportedOperationException("addResponseFilter");
+      }
+
+      @Override
+      public List<MediaType> getAcceptableWriterMediaTypes(Class<?> type, Type genericType, Annotation[] annotations)
+      {
+         List<MediaType> mediaTypes = null;
+         if (applicationProviders != null)
+            mediaTypes = applicationProviders.getAcceptableWriterMediaTypes(type, genericType, annotations);
+         if (mediaTypes != null)
+         {
+            mediaTypes.addAll(defaultProviders.getAcceptableWriterMediaTypes(type, genericType, annotations));
+            return mediaTypes;
+         }
+         return defaultProviders.getAcceptableWriterMediaTypes(type, genericType, annotations);
+      }
+
+      @Override
+      public <T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType)
+      {
+         ContextResolver<T> resolver = null;
+         if (applicationProviders != null)
+            resolver = applicationProviders.getContextResolver(contextType, mediaType);
+         if (resolver == null)
+            resolver = defaultProviders.getContextResolver(contextType, mediaType);
+         return resolver;
+      }
+
+      @Override
+      public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type)
+      {
+         ExceptionMapper<T> mapper = null;
+         if (applicationProviders != null)
+            mapper = applicationProviders.getExceptionMapper(type);
+         if (mapper == null)
+            mapper = defaultProviders.getExceptionMapper(type);
+         return mapper;
+      }
+
+      @Override
+      public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations,
+         MediaType mediaType)
+      {
+         MessageBodyReader<T> reader = null;
+         if (applicationProviders != null)
+            reader = applicationProviders.getMessageBodyReader(type, genericType, annotations, mediaType);
+         if (reader == null)
+            reader = defaultProviders.getMessageBodyReader(type, genericType, annotations, mediaType);
+         return reader;
+      }
+
+      @Override
+      public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations,
+         MediaType mediaType)
+      {
+         MessageBodyWriter<T> writer = null;
+         if (applicationProviders != null)
+            writer = applicationProviders.getMessageBodyWriter(type, genericType, annotations, mediaType);
+         if (writer == null)
+            writer = defaultProviders.getMessageBodyWriter(type, genericType, annotations, mediaType);
+         return writer;
+      }
+
+      @Override
+      public List<ObjectFactory<FilterDescriptor>> getMethodInvokerFilters(String path)
+      {
+         List<ObjectFactory<FilterDescriptor>> filters = defaultProviders.getMethodInvokerFilters(path);
+         if (applicationProviders != null)
+            filters.addAll(applicationProviders.getMethodInvokerFilters(path));
+         return filters;
+      }
+
+      @Override
+      public List<ObjectFactory<FilterDescriptor>> getRequestFilters(String path)
+      {
+         // NOTE!!! Return only application specific filters. Default filters
+         // should be already applied to request.
+         if (applicationProviders == null)
+            return Collections.emptyList();
+         return applicationProviders.getRequestFilters(path);
+      }
+
+      @Override
+      public List<ObjectFactory<FilterDescriptor>> getResponseFilters(String path)
+      {
+         // NOTE!!! Return only application specific filters. Default filters
+         // should be applied to response later.
+         if (applicationProviders == null)
+            return Collections.emptyList();
+         return applicationProviders.getResponseFilters(path);
+      }
+
+   }
+
    /** Logger. */
    private static final Log LOG = ExoLogger.getLogger("exo.ws.rest.core.RequestDispatcher");
 
    /** See {@link ResourceBinder}. */
    protected final ResourceBinder resourceBinder;
 
-   private final MethodInvokerFactory invokerFactory;
+   protected final MethodInvokerFactory invokerFactory;
 
-   /**
-    * Constructs new instance of RequestDispatcher.
-    *
-    * @param resourceBinder See {@link ResourceBinder}
-    */
-   public RequestDispatcher(ResourceBinder resourceBinder, MethodInvokerFactory invokerFactory)
+   protected final ProvidersRegistry providersRegistry;
+
+   public RequestDispatcher(ResourceBinder resourceBinder, ProvidersRegistry providersRegistry,
+      MethodInvokerFactory invokerFactory)
    {
       this.resourceBinder = resourceBinder;
+      this.providersRegistry = providersRegistry;
       this.invokerFactory = invokerFactory;
    }
 
-   /**
-    * Constructs new instance of RequestDispatcher.
-    *
-    * @param resourceBinder See {@link ResourceBinder}
-    */
+   public RequestDispatcher(ResourceBinder resourceBinder, ProvidersRegistry providers)
+   {
+      this(resourceBinder, providers, null);
+   }
+
+   @Deprecated
+   public RequestDispatcher(ResourceBinder resourceBinder, MethodInvokerFactory invokerFactory)
+   {
+      this(resourceBinder, null, invokerFactory);
+   }
+
+   @Deprecated
    public RequestDispatcher(ResourceBinder resourceBinder)
    {
-      this(resourceBinder, null);
+      this(resourceBinder, null, null);
    }
 
    /**
@@ -105,20 +467,51 @@
 
       // Get root resource
       ObjectFactory<AbstractResourceDescriptor> resourceFactory = getRootResourse(parameterValues, requestPath);
+      AbstractResourceDescriptor resourceDescriptor = resourceFactory.getObjectModel();
 
+      if (providersRegistry != null)
+      {
+         // Be sure instance of ProvidersRegistry injected if this class is extended.
+         String applicationId = null;
+         if (resourceDescriptor instanceof ApplicationResource)
+         {
+            // If resource delivered with subclass of javax.ws.rs.core.Application
+            // it must be instance of ApplicationResource which provide application's identifier.
+            applicationId = ((ApplicationResource)resourceDescriptor).getApplication();
+         }
+         ProviderBinder applicationProviders = providersRegistry.getProviders(applicationId);
+         ((ApplicationContextImpl)context).setProviders(new ProvidersAdapter(applicationProviders, ProviderBinder
+            .getInstance()));
+      }
+      else
+      {
+         LOG.warn("ProvidersRegistry must set. ");
+      }
+
+      // Apply application specific request filters if any
+      for (ObjectFactory<FilterDescriptor> factory : context.getProviders().getRequestFilters(context.getPath()))
+      {
+         RequestFilter f = (RequestFilter)factory.getInstance(context);
+         f.doFilter(request);
+      }
+
       // Take the tail of the request path, the tail will be requested path
       // for lower resources, e. g. ResourceClass -> Sub-resource method/locator
       String newRequestPath = getPathTail(parameterValues);
-
       // save the resource class URI in hierarchy
       context.addMatchedURI(requestPath.substring(0, requestPath.lastIndexOf(newRequestPath)));
-
       context.setParameterNames(resourceFactory.getObjectModel().getUriPattern().getParameterNames());
 
       // may thrown WebApplicationException
       Object resource = resourceFactory.getInstance(context);
+      dispatch(request, response, context, resourceFactory, resource, newRequestPath);
 
-      dispatch(request, response, context, resourceFactory, resource, newRequestPath);
+      // Apply application specific response filters if any
+      for (ObjectFactory<FilterDescriptor> factory : context.getProviders().getResponseFilters(context.getPath()))
+      {
+         ResponseFilter f = (ResponseFilter)factory.getInstance(context);
+         f.doFilter(response);
+      }
    }
 
    /**
@@ -154,34 +547,24 @@
       ApplicationContext context, ObjectFactory<AbstractResourceDescriptor> resourceFactory, Object resource,
       String requestPath)
    {
-
       List<String> parameterValues = context.getParameterValues();
       int len = parameterValues.size();
-
       // resource method or sub-resource method or sub-resource locator
-
       ResourceMethodMap<ResourceMethodDescriptor> rmm = resourceFactory.getObjectModel().getResourceMethods();
       SubResourceMethodMap srmm = resourceFactory.getObjectModel().getSubResourceMethods();
       SubResourceLocatorMap srlm = resourceFactory.getObjectModel().getSubResourceLocators();
       if ((parameterValues.get(len - 1) == null || "/".equals(parameterValues.get(len - 1))) && rmm.size() > 0)
       {
-         // resource method, then process HTTP method and consume/produce media
-         // types
-
+         // resource method, then process HTTP method and consume/produce media types
          List<ResourceMethodDescriptor> methods = new ArrayList<ResourceMethodDescriptor>();
          boolean match = processResourceMethod(rmm, request, response, methods);
          if (!match)
          {
             if (LOG.isDebugEnabled())
-            {
                LOG.debug("Not found resource method for method " + request.getMethod());
-            }
-
             return; // Error Response is preset
          }
-
          invokeResourceMethod(methods.get(0), resource, context, request, response);
-
       }
       else
       { // sub-resource method/locator
@@ -202,11 +585,8 @@
          if (!match && !hasAcceptableLocator)
          {
             if (LOG.isDebugEnabled())
-            {
                LOG.debug("Not found sub-resource methods nor sub-resource locators for path " + requestPath
                   + " and method " + request.getMethod());
-            }
-
             return; // Error Response is preset
          }
 
@@ -228,7 +608,6 @@
             invokeSuResourceLocator(requestPath, locators.get(0), resource, context, request, response);
          }
       }
-
    }
 
    /**
@@ -246,7 +625,6 @@
    {
       // save resource in hierarchy
       context.addMatchedResource(resource);
-
       Class<?> returnType = rmd.getResponseType();
       MethodInvoker invoker = rmd.getMethodInvoker();
       Object o = invoker.invokeMethod(resource, rmd, context);
@@ -271,8 +649,7 @@
       context.addMatchedResource(resource);
       // save the sub-resource method URI in hierarchy
       context.addMatchedURI(requestPath);
-      // save parameters values, actually parameters was save before, now just
-      // map parameter's names to values
+      // save parameters values, actually parameters was save before, now just map parameter's names to values
       context.setParameterNames(srmd.getUriPattern().getParameterNames());
 
       Class<?> returnType = srmd.getResponseType();
@@ -296,13 +673,11 @@
       ApplicationContext context, GenericContainerRequest request, GenericContainerResponse response)
    {
       context.addMatchedResource(resource);
-      // take the tail of the request path, the tail will be new request path
-      // for lower resources
+      // take the tail of the request path, the tail will be new request path for lower resources
       String newRequestPath = getPathTail(context.getParameterValues());
       // save the resource class URI in hierarchy
       context.addMatchedURI(requestPath.substring(0, requestPath.lastIndexOf(newRequestPath)));
-      // save parameters values, actually parameters was save before, now just
-      // map parameter's names to values
+      // save parameters values, actually parameters was save before, now just map parameter's names to values
       context.setParameterNames(srld.getUriPattern().getParameterNames());
 
       // NOTE Locators can't accept entity
@@ -385,7 +760,6 @@
       {
          response.setResponse(Response.ok(o, contentType).build());
       }
-
    }
 
    /**
@@ -465,12 +839,12 @@
                }
             }
          }
-
          return true;
       }
 
       response.setResponse(Response.status(Response.Status.NOT_ACCEPTABLE).entity("Not Acceptable").type(
          MediaType.TEXT_PLAIN).build());
+
       return false;
    }
 
@@ -550,7 +924,6 @@
             locators.add(e.getValue());
          }
       }
-
       return !locators.isEmpty();
    }
 
@@ -570,9 +943,7 @@
       if (resourceFactory == null)
       {
          if (LOG.isDebugEnabled())
-         {
             LOG.debug("Root resource not found for " + requestPath);
-         }
          // Stop here, there is no matched root resource
          throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).entity(
             "There is no any resources matched to request path " + requestPath).type(MediaType.TEXT_PLAIN).build());

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestHandlerImpl.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestHandlerImpl.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/RequestHandlerImpl.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -23,7 +23,6 @@
 import org.exoplatform.container.xml.ValueParam;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
-import org.exoplatform.services.rest.ApplicationContext;
 import org.exoplatform.services.rest.ExtHttpHeaders;
 import org.exoplatform.services.rest.FilterDescriptor;
 import org.exoplatform.services.rest.GenericContainerRequest;
@@ -66,8 +65,9 @@
    private static final Log LOG = ExoLogger.getLogger("exo.ws.rest.core.RequestHandlerImpl");
 
    /**
-    * Application properties. Properties from this map will be copied to ApplicationContext
-    * and may be accessible via method {@link ApplicationContextImpl#getProperties()}.
+    * Application properties. Properties from this map will be copied to
+    * ApplicationContext and may be accessible via method
+    * {@link ApplicationContextImpl#getProperties()}.
     */
    private static final Map<String, String> properties = new HashMap<String, String>();
 
@@ -84,8 +84,13 @@
    public static final void setProperty(String name, String value)
    {
       if (value == null)
+      {
          properties.remove(name);
-      properties.put(name, value);
+      }
+      else
+      {
+         properties.put(name, value);
+      }
    }
 
    /**
@@ -104,9 +109,7 @@
             properties.put(vp.getName(), vp.getValue());
          }
       }
-
       this.dispatcher = dispatcher;
-
    }
 
    // RequestHandler
@@ -119,12 +122,13 @@
    {
       try
       {
-         ApplicationContext context = new ApplicationContextImpl(request, response, ProviderBinder.getInstance());
+         ProviderBinder defaultProviders = ProviderBinder.getInstance();
+         ApplicationContextImpl context = new ApplicationContextImpl(request, response, defaultProviders);
          context.getProperties().putAll(properties);
          ApplicationContextImpl.setCurrent(context);
 
-         for (ObjectFactory<FilterDescriptor> factory : ProviderBinder.getInstance().getRequestFilters(
-            context.getPath()))
+         // Apply default filters only.
+         for (ObjectFactory<FilterDescriptor> factory : defaultProviders.getRequestFilters(context.getPath()))
          {
             RequestFilter f = (RequestFilter)factory.getInstance(context);
             f.doFilter(request);
@@ -132,7 +136,6 @@
 
          try
          {
-
             dispatcher.dispatch(request, response);
             if (response.getHttpHeaders().getFirst(ExtHttpHeaders.JAXRS_BODY_PROVIDED) == null)
             {
@@ -142,16 +145,13 @@
                   response.getHttpHeaders().putSingle(ExtHttpHeaders.JAXRS_BODY_PROVIDED, jaxrsHeader);
                }
             }
-
          }
          catch (Exception e)
          {
             if (e instanceof WebApplicationException)
             {
-
                Response errorResponse = ((WebApplicationException)e).getResponse();
-               ExceptionMapper excmap = ProviderBinder.getInstance().getExceptionMapper(WebApplicationException.class);
-
+               ExceptionMapper excmap = context.getProviders().getExceptionMapper(WebApplicationException.class);
                int errorStatus = errorResponse.getStatus();
                // should be some of 4xx status
                if (errorStatus < 500)
@@ -169,7 +169,6 @@
                      LOG.warn("WebApplication exception occurs.", e.getCause());
                   }
                }
-               // -----
                if (errorResponse.getEntity() == null)
                {
                   if (excmap != null)
@@ -201,12 +200,14 @@
             {
                Throwable cause = e.getCause();
                Class causeClazz = cause.getClass();
-               ExceptionMapper excmap = ProviderBinder.getInstance().getExceptionMapper(causeClazz);
+               ExceptionMapper excmap = context.getProviders().getExceptionMapper(causeClazz);
                while (causeClazz != null && excmap == null)
                {
-                  excmap = ProviderBinder.getInstance().getExceptionMapper(causeClazz);
+                  excmap = context.getProviders().getExceptionMapper(causeClazz);
                   if (excmap == null)
+                  {
                      causeClazz = causeClazz.getSuperclass();
+                  }
                }
                if (excmap != null)
                {
@@ -229,15 +230,14 @@
             }
          }
 
-         for (ObjectFactory<FilterDescriptor> factory : ProviderBinder.getInstance().getResponseFilters(
-            context.getPath()))
+         // Apply default filters only.
+         for (ObjectFactory<FilterDescriptor> factory : defaultProviders.getResponseFilters(context.getPath()))
          {
             ResponseFilter f = (ResponseFilter)factory.getInstance(context);
             f.doFilter(response);
          }
 
          response.writeResponse();
-
       }
       finally
       {

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ResourceBinder.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ResourceBinder.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/ResourceBinder.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -23,20 +23,15 @@
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.rest.ApplicationContext;
-import org.exoplatform.services.rest.Filter;
 import org.exoplatform.services.rest.ObjectFactory;
 import org.exoplatform.services.rest.ObjectModel;
 import org.exoplatform.services.rest.PerRequestObjectFactory;
-import org.exoplatform.services.rest.RequestFilter;
-import org.exoplatform.services.rest.ResponseFilter;
 import org.exoplatform.services.rest.SingletonObjectFactory;
 import org.exoplatform.services.rest.impl.method.DefaultMethodInvoker;
 import org.exoplatform.services.rest.impl.method.MethodInvokerFactory;
 import org.exoplatform.services.rest.impl.resource.AbstractResourceDescriptorImpl;
 import org.exoplatform.services.rest.impl.resource.ResourceDescriptorValidator;
-import org.exoplatform.services.rest.method.MethodInvokerFilter;
 import org.exoplatform.services.rest.resource.AbstractResourceDescriptor;
-import org.exoplatform.services.rest.resource.ResourceContainer;
 import org.exoplatform.services.rest.resource.ResourceDescriptorVisitor;
 import org.exoplatform.services.rest.uri.UriPattern;
 import org.picocontainer.Startable;
@@ -50,11 +45,6 @@
 import javax.ws.rs.Path;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.ContextResolver;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
 import javax.ws.rs.ext.RuntimeDelegate;
 
 /**
@@ -176,6 +166,7 @@
    protected final ResourceDescriptorVisitor rdv = ResourceDescriptorValidator.getInstance();
 
    /** @see RuntimeDelegate */
+   @Deprecated
    protected final RuntimeDelegate rd;
 
    /**
@@ -191,11 +182,14 @@
    /** Resource listeners. */
    protected final List<ResourceListener> resourceListeners = new ArrayList<ResourceListener>();
 
+   /**
+    * @deprecated Do not need container here any more.
+    */
    protected final ExoContainer container;
 
    public ResourceBinder(ExoContainerContext containerContext) throws Exception
    {
-      this(containerContext, null);
+      this(containerContext, (MethodInvokerFactory)null);
    }
 
    /**
@@ -218,97 +212,16 @@
    /**
     * @param application Application
     * @see Application
+    * @deprecated Use
+    *             {@link org.exoplatform.services.rest.impl.ApplicationRegistry#addApplication(Application)}
+    *             instead of using this method .
     */
-   @SuppressWarnings("unchecked")
    public void addApplication(Application application)
    {
-      ProviderBinder providers = ProviderBinder.getInstance();
-      for (Object obj : application.getSingletons())
-      {
-         if (obj.getClass().getAnnotation(Provider.class) != null)
-         {
-            // singleton provider
-            if (obj instanceof ContextResolver)
-            {
-               providers.addContextResolver((ContextResolver)obj);
-            }
-            if (obj instanceof ExceptionMapper)
-            {
-               providers.addExceptionMapper((ExceptionMapper)obj);
-            }
-            if (obj instanceof MessageBodyReader)
-            {
-               providers.addMessageBodyReader((MessageBodyReader)obj);
-            }
-            if (obj instanceof MessageBodyWriter)
-            {
-               providers.addMessageBodyWriter((MessageBodyWriter)obj);
-            }
-         }
-         else if (obj.getClass().getAnnotation(Filter.class) != null)
-         {
-            // singleton filter
-            if (obj instanceof MethodInvokerFilter)
-            {
-               providers.addMethodInvokerFilter((MethodInvokerFilter)obj);
-            }
-            if (obj instanceof RequestFilter)
-            {
-               providers.addRequestFilter((RequestFilter)obj);
-            }
-            if (obj instanceof ResponseFilter)
-            {
-               providers.addResponseFilter((ResponseFilter)obj);
-            }
-         }
-         else
-         {
-            addResource(obj, null); // singleton resource
-         }
-      }
-      for (Class clazz : application.getClasses())
-      {
-         if (clazz.getAnnotation(Provider.class) != null)
-         {
-            // per-request provider
-            if (ContextResolver.class.isAssignableFrom(clazz))
-            {
-               providers.addContextResolver(clazz);
-            }
-            if (ExceptionMapper.class.isAssignableFrom(clazz))
-            {
-               providers.addExceptionMapper(clazz);
-            }
-            if (MessageBodyReader.class.isAssignableFrom(clazz))
-            {
-               providers.addMessageBodyReader(clazz);
-            }
-            if (MessageBodyWriter.class.isAssignableFrom(clazz))
-            {
-               providers.addMessageBodyWriter(clazz);
-            }
-         }
-         else if (clazz.getAnnotation(Filter.class) != null)
-         {
-            // per-request filter
-            if (MethodInvokerFilter.class.isAssignableFrom(clazz))
-            {
-               providers.addMethodInvokerFilter(clazz);
-            }
-            if (RequestFilter.class.isAssignableFrom(clazz))
-            {
-               providers.addRequestFilter(clazz);
-            }
-            if (ResponseFilter.class.isAssignableFrom(clazz))
-            {
-               providers.addResponseFilter(clazz);
-            }
-         }
-         else
-         {
-            addResource(clazz, null); // per-request resource
-         }
-      }
+      org.exoplatform.services.rest.impl.ApplicationRegistry appRegistry =
+         (org.exoplatform.services.rest.impl.ApplicationRegistry)container
+            .getComponentInstanceOfType(org.exoplatform.services.rest.impl.ApplicationRegistry.class);
+      appRegistry.addApplication(application);
    }
 
    /**
@@ -347,7 +260,9 @@
          // validate AbstractResourceDescriptor
          descriptor.accept(rdv);
          if (properties != null)
+         {
             descriptor.getProperties().putAll(properties);
+         }
          addResource(new PerRequestObjectFactory<AbstractResourceDescriptor>(descriptor));
       }
       catch (Exception e)
@@ -392,7 +307,9 @@
          // validate AbstractResourceDescriptor
          descriptor.accept(rdv);
          if (properties != null)
+         {
             descriptor.getProperties().putAll(properties);
+         }
          addResource(new SingletonObjectFactory<AbstractResourceDescriptor>(descriptor, resource));
       }
       catch (Exception e)
@@ -534,7 +451,9 @@
                      resource.getObjectModel().getSubResourceMethods().size()
                         + resource.getObjectModel().getSubResourceLocators().size();
                   if (subresnum == 0)
+                  {
                      continue;
+                  }
                }
                resourceFactory = resource;
                break;
@@ -681,37 +600,8 @@
    /**
     * {@inheritDoc}
     */
-   @SuppressWarnings("unchecked")
    public void start()
    {
-      // Lookup Applications
-      List<Application> al = container.getComponentInstancesOfType(Application.class);
-      for (Application a : al)
-      {
-         try
-         {
-            addApplication(a);
-         }
-         catch (Exception e)
-         {
-            LOG.error("Failed add JAX-RS application " + a.getClass().getName(), e);
-         }
-      }
-
-      // Lookup all object which implements ResourceContainer interface and
-      // process them to be add as root resources.
-      for (Object resource : container.getComponentInstancesOfType(ResourceContainer.class))
-      {
-         try
-         {
-            addResource(resource, null);
-         }
-         catch (Exception e)
-         {
-            LOG.error("Failed add JAX-RS resource " + resource.getClass().getName(), e);
-         }
-      }
-
       startResourceCleaner();
    }
 
@@ -745,4 +635,5 @@
       thread.setDaemon(true);
       thread.start();
    }
+
 }

Added: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/StartableApplication.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/StartableApplication.java	                        (rev 0)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/StartableApplication.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.services.rest.impl;
+
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.services.rest.RequestFilter;
+import org.exoplatform.services.rest.ResponseFilter;
+import org.exoplatform.services.rest.method.MethodInvokerFilter;
+import org.exoplatform.services.rest.resource.ResourceContainer;
+import org.picocontainer.Startable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+/**
+ * Purpose of this component is deliver all JAX-RS components registered in eXo
+ * container to {@link org.exoplatform.services.rest.impl.ApplicationRegistry}.
+ *
+ * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
+ * @version $Id$
+ */
+public class StartableApplication extends Application implements Startable
+{
+
+   private ExoContainer container;
+
+   private Set<Class<?>> cls = new HashSet<Class<?>>();
+
+   private Set<Object> singletons = new HashSet<Object>();
+
+   public StartableApplication(ExoContainerContext containerContext)
+   {
+      container = containerContext.getContainer();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<Class<?>> getClasses()
+   {
+      return cls;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<Object> getSingletons()
+   {
+      return singletons;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void start()
+   {
+      for (Object resource : container.getComponentInstancesOfType(ResourceContainer.class))
+         singletons.add(resource);
+      for (Object resolver : container.getComponentInstancesOfType(ContextResolver.class))
+         singletons.add(resolver);
+      for (Object mapper : container.getComponentInstancesOfType(ExceptionMapper.class))
+         singletons.add(mapper);
+      for (Object reader : container.getComponentInstancesOfType(MessageBodyReader.class))
+         singletons.add(reader);
+      for (Object writer : container.getComponentInstancesOfType(MessageBodyWriter.class))
+         singletons.add(writer);
+      for (Object filter : container.getComponentInstancesOfType(RequestFilter.class))
+         singletons.add(filter);
+      for (Object filter : container.getComponentInstancesOfType(ResponseFilter.class))
+         singletons.add(filter);
+      for (Object filter : container.getComponentInstancesOfType(MethodInvokerFilter.class))
+         singletons.add(filter);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void stop()
+   {
+   }
+
+}


Property changes on: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/StartableApplication.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBContextResolver.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBContextResolver.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBContextResolver.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -36,7 +36,7 @@
 
 /**
  * Provide cache for {@link JAXBContext}.
- * 
+ *
  * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
  * @version $Id: $
  */
@@ -68,7 +68,7 @@
    /**
     * Return JAXBContext according to supplied type. If no one context found then
     * try create new context and save it in cache.
-    * 
+    *
     * @param classes classes to be bound
     * @return JAXBContext
     * @throws JAXBException if JAXBContext creation failed
@@ -86,7 +86,7 @@
 
    /**
     * Create and add in cache JAXBContext for supplied set of classes.
-    * 
+    *
     * @param classes set of java classes to be bound
     * @return JAXBContext
     * @throws JAXBException if JAXBContext for supplied classes can't be created
@@ -102,7 +102,7 @@
    /**
     * Add prepared JAXBContext that will be mapped to set of class. In this case
     * this class works as cache for JAXBContexts.
-    * 
+    *
     * @param jaxbctx JAXBContext
     * @param classes set of java classes to be bound
     */
@@ -124,6 +124,7 @@
             try
             {
                createJAXBContext(c);
+               //System.out.printf("\nContext for class: {%s}\n\n ", c);
             }
             catch (JAXBException e)
             {

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBElementEntityProvider.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBElementEntityProvider.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBElementEntityProvider.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -63,7 +63,7 @@
     * @see Providers
     */
    @Context
-   private Providers providers;
+   Providers providers;
 
    /**
     * {@inheritDoc}

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBObjectEntityProvider.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBObjectEntityProvider.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/provider/JAXBObjectEntityProvider.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -62,7 +62,7 @@
     * @see Providers
     */
    @Context
-   private Providers providers;
+   Providers providers;
 
    /**
     * {@inheritDoc}

Modified: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/AbstractResourceDescriptorImpl.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/AbstractResourceDescriptorImpl.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/AbstractResourceDescriptorImpl.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -224,7 +224,7 @@
          {
             fields.add(new FieldInjectorImpl(resourceClass, jfield));
          }
-         Class<?> sc = resourceClass;
+         Class<?> sc = resourceClass.getSuperclass();
          while (sc != Object.class)
          {
             for (java.lang.reflect.Field jfield : sc.getDeclaredFields())

Added: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/ApplicationResource.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/ApplicationResource.java	                        (rev 0)
+++ ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/ApplicationResource.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -0,0 +1,96 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.services.rest.impl.resource;
+
+import org.exoplatform.services.rest.impl.method.MethodInvokerFactory;
+
+/**
+ * @author <a href="mailto:andrew00x at gmail.com">Andrey Parfonov</a>
+ * @version $Id$
+ */
+public class ApplicationResource extends AbstractResourceDescriptorImpl
+{
+
+   /**
+    * Identifier of application-supplied subclass of
+    * {@link javax.ws.rs.core.Application} via this component was delivered.
+    */
+   private final String applicationId;
+
+   /**
+    * @param applicationId identifier of application-supplied subclass of
+    *        {@link javax.ws.rs.core.Application} via this component was
+    *        delivered.
+    * @param resourceClass resource class
+    */
+   public ApplicationResource(String applicationId, Class<?> resourceClass)
+   {
+      super(resourceClass);
+      this.applicationId = applicationId;
+   }
+
+   /**
+    * @param applicationId identifier of application-supplied subclass of
+    *        {@link javax.ws.rs.core.Application} via this component was
+    *        delivered.
+    * @param resourceClass resource class
+    * @param invokerFactory invoker factory
+    */
+   public ApplicationResource(String applicationId, Class<?> resourceClass, MethodInvokerFactory invokerFactory)
+   {
+      super(resourceClass, invokerFactory);
+      this.applicationId = applicationId;
+   }
+
+   /**
+    * @param applicationId identifier of application-supplied subclass of
+    *        {@link javax.ws.rs.core.Application} via this component was
+    *        delivered.
+    * @param resource resource instance
+    * @param invokerFactory invoker factory
+    */
+   public ApplicationResource(String applicationId, Object resource, MethodInvokerFactory invokerFactory)
+   {
+      super(resource, invokerFactory);
+      this.applicationId = applicationId;
+   }
+
+   /**
+    * @param applicationId identifier of application-supplied subclass of
+    *        {@link javax.ws.rs.core.Application} via this component was
+    *        delivered.
+    * @param resource resource instance
+    */
+   public ApplicationResource(String applicationId, Object resource)
+   {
+      super(resource);
+      this.applicationId = applicationId;
+   }
+
+   /**
+    * @return identifier (suppose to use FQN) of application-supplied subclass
+    *         of {@link javax.ws.rs.core.Application} via this component was
+    *         delivered.
+    */
+   public String getApplication()
+   {
+      return applicationId;
+   }
+}


Property changes on: ws/trunk/exo.ws.rest.core/src/main/java/org/exoplatform/services/rest/impl/resource/ApplicationResource.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: ws/trunk/exo.ws.rest.core/src/main/resources/conf/portal/configuration.xml
===================================================================
--- ws/trunk/exo.ws.rest.core/src/main/resources/conf/portal/configuration.xml	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/main/resources/conf/portal/configuration.xml	2010-11-02 08:56:55 UTC (rev 3375)
@@ -22,6 +22,15 @@
 <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
    xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
    <component>
+      <type>org.exoplatform.services.rest.impl.ApplicationRegistry</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.StartableApplication</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.ProvidersRegistry</type>
+   </component>
+   <component>
       <type>org.exoplatform.services.rest.impl.RequestHandlerImpl</type>
    </component>
    <component>

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/BaseTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/BaseTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/BaseTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -22,7 +22,9 @@
 
 import org.exoplatform.container.StandaloneContainer;
 import org.exoplatform.services.rest.impl.ApplicationContextImpl;
+import org.exoplatform.services.rest.impl.ApplicationRegistry;
 import org.exoplatform.services.rest.impl.ProviderBinder;
+import org.exoplatform.services.rest.impl.ProvidersRegistry;
 import org.exoplatform.services.rest.impl.RequestHandlerImpl;
 import org.exoplatform.services.rest.impl.ResourceBinder;
 import org.exoplatform.services.rest.tools.ResourceLauncher;
@@ -44,18 +46,29 @@
 
    protected ResourceLauncher launcher;
 
+   protected ApplicationRegistry applicationRegistry;
+
+   protected ProvidersRegistry providersRegistry;
+
    public void setUp() throws Exception
    {
-      StandaloneContainer.setConfigurationPath("src/test/resources/conf/standalone/test-configuration.xml");
+      String conf = getClass().getResource("/conf/standalone/test-configuration.xml").toString();
+      //StandaloneContainer.setConfigurationPath("src/test/resources/conf/standalone/test-configuration.xml");
+      StandaloneContainer.setConfigurationURL(conf);
       container = StandaloneContainer.getInstance();
+
+      applicationRegistry = (ApplicationRegistry)container.getComponentInstanceOfType(ApplicationRegistry.class);
       binder = (ResourceBinder)container.getComponentInstanceOfType(ResourceBinder.class);
       requestHandler = (RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
-      // reset providers to be sure it is clean
+      providersRegistry = (ProvidersRegistry)container.getComponentInstanceOfType(ProvidersRegistry.class);
+
+      // reset default providers to be sure it is clean.
       ProviderBinder.setInstance(new ProviderBinder());
       providers = ProviderBinder.getInstance();
-      //    System.out.println("##########################"+providers);
+
+      binder.clear();
+
       ApplicationContextImpl.setCurrent(new ApplicationContextImpl(null, null, providers));
-      binder.clear();
       launcher = new ResourceLauncher(requestHandler);
    }
 

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/VariantsHandlerTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/VariantsHandlerTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/VariantsHandlerTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -84,7 +84,7 @@
       h.putSingle("Accept-Language", "uk");
       r = new ContainerRequest("GET", null, null, null, h);
       v = VariantsHandler.handleVariants(r, vs);
-      // no language 'uk' in variants and '*/*;q=0.5' removed 
+      // no language 'uk' in variants and '*/*;q=0.5' removed
       assertNull(v); // 'Not Acceptable' (406) will be generated here
       // ---
       h.putSingle("Accept", glue("text/xml", "application/xml", "image/*", "text/html;q=0.9", "text/plain;q=0.8"));

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/OtherEntityTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/OtherEntityTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/OtherEntityTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -23,6 +23,7 @@
 import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
 import org.exoplatform.services.rest.tools.ByteArrayContainerResponseWriter;
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 import org.xml.sax.InputSource;
 
 import java.io.ByteArrayInputStream;
@@ -95,8 +96,11 @@
       @Consumes("application/xml")
       public void m5(DOMSource dom) throws Exception
       {
-         assertEquals("root", dom.getNode().getFirstChild().getNodeName());
-         assertEquals("hello world", dom.getNode().getFirstChild().getFirstChild().getTextContent());
+         Node root = dom.getNode().getFirstChild();
+         assertEquals("root", root.getNodeName());
+         Node data = root.getFirstChild();
+         assertEquals("data", data.getNodeName());
+         assertEquals("hello world", data.getFirstChild().getNodeValue());
       }
 
       @POST
@@ -105,9 +109,11 @@
       public void m6(SAXSource sax) throws Exception
       {
          Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(sax.getInputSource());
-         assertEquals("root", doc.getDocumentElement().getNodeName());
-         assertEquals("data", doc.getDocumentElement().getFirstChild().getNodeName());
-         assertEquals("hello world", doc.getDocumentElement().getFirstChild().getTextContent());
+         Node root = doc.getDocumentElement();
+         assertEquals("root", root.getNodeName());
+         Node data = root.getFirstChild();
+         assertEquals("data", data.getNodeName());
+         assertEquals("hello world", data.getFirstChild().getNodeValue());
       }
 
       @POST
@@ -116,9 +122,11 @@
       public void m7(StreamSource ss) throws Exception
       {
          Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ss.getInputStream());
-         assertEquals("root", doc.getDocumentElement().getNodeName());
-         assertEquals("data", doc.getDocumentElement().getFirstChild().getNodeName());
-         assertEquals("hello world", doc.getDocumentElement().getFirstChild().getTextContent());
+         Node root = doc.getDocumentElement();
+         assertEquals("root", root.getNodeName());
+         Node data = root.getFirstChild();
+         assertEquals("data", data.getNodeName());
+         assertEquals("hello world", data.getFirstChild().getNodeValue());
       }
    }
 

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/SourceEntityProviderTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/SourceEntityProviderTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/provider/SourceEntityProviderTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -128,8 +128,9 @@
             new ByteArrayInputStream(data));
       Node root = src.getNode().getFirstChild();
       assertEquals("root", root.getNodeName());
-      assertEquals("message", root.getFirstChild().getNodeName());
-      assertEquals("to be or not to be", root.getFirstChild().getTextContent());
+      Node message = root.getFirstChild();
+      assertEquals("message", message.getNodeName());
+      assertEquals("to be or not to be", message.getFirstChild().getNodeValue());
    }
 
    @SuppressWarnings("unchecked")

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/resource/ApplicationTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/resource/ApplicationTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/impl/resource/ApplicationTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -24,15 +24,27 @@
 import org.exoplatform.services.rest.GenericContainerResponse;
 import org.exoplatform.services.rest.RequestFilter;
 import org.exoplatform.services.rest.ResponseFilter;
+import org.exoplatform.services.rest.impl.ApplicationProviders;
 import org.exoplatform.services.rest.impl.ContainerResponse;
+import org.exoplatform.services.rest.impl.provider.StringEntityProvider;
 import org.exoplatform.services.rest.method.MethodInvokerFilter;
 import org.exoplatform.services.rest.resource.GenericMethodResource;
+import org.exoplatform.services.rest.tools.ByteArrayContainerResponseWriter;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.util.HashSet;
 import java.util.Set;
 
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
@@ -187,22 +199,28 @@
 
    public void testRegistry()
    {
-      binder.addApplication(new Application1());
+      Application app = new Application1();
+      //binder.addApplication(app);
+      applicationRegistry.addApplication(app);
       assertEquals(4, binder.getSize());
-      assertEquals(1, providers.getRequestFilters(null).size());
-      assertEquals(1, providers.getResponseFilters(null).size());
-      assertEquals(1, providers.getMethodInvokerFilters(null).size());
-      assertNotNull(providers.getExceptionMapper(RuntimeException.class));
-      assertNotNull(providers.getExceptionMapper(IllegalStateException.class));
+      ApplicationProviders appProviders = providersRegistry.getProviders(app.getClass().getName());
+      assertEquals(1, appProviders.getRequestFilters(null).size());
+      assertEquals(1, appProviders.getResponseFilters(null).size());
+      assertEquals(1, appProviders.getMethodInvokerFilters(null).size());
+      assertNotNull(appProviders.getExceptionMapper(RuntimeException.class));
+      assertNotNull(appProviders.getExceptionMapper(IllegalStateException.class));
    }
 
    private static boolean requestFilter = false;
+
    private static boolean responseFilter = false;
+
    private static boolean invFilter = false;
 
    public void testAsResources() throws Exception
    {
-      binder.addApplication(new Application1());
+      //binder.addApplication(new Application1());
+      applicationRegistry.addApplication(new Application1());
       // per-request
       ContainerResponse resp = launcher.service("GET", "/a", "", null, null, null);
       assertEquals(200, resp.getStatus());
@@ -239,4 +257,76 @@
       assertTrue(invFilter);
    }
 
+   public static class Application2 extends Application
+   {
+
+      private final Set<Class<?>> perreq = new HashSet<Class<?>>();
+
+      private final Set<Object> singletons = new HashSet<Object>();
+
+      public Application2()
+      {
+         perreq.add(Resource5.class);
+         singletons.add(new StringEntityProvider1());
+      }
+
+      @Override
+      public Set<Class<?>> getClasses()
+      {
+         return perreq;
+      }
+
+      @Override
+      public Set<Object> getSingletons()
+      {
+         return singletons;
+      }
+
+   }
+
+   @Path("abc")
+   public static class Resource5
+   {
+      @POST
+      public String m0(String m)
+      {
+         assertEquals(message.toUpperCase(), m);
+         return m;
+      }
+   }
+
+   @Provider
+   public static class StringEntityProvider1 extends StringEntityProvider
+   {
+      @Override
+      public String readFrom(Class<String> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+         MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException
+      {
+         return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream)
+            .toUpperCase();
+      }
+
+      @Override
+      public void writeTo(String t, Class<?> type, Type genericType, Annotation[] annotations,
+         MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+         throws IOException
+      {
+         super.writeTo(t.toLowerCase(), type, genericType, annotations, mediaType, httpHeaders, entityStream);
+      }
+   }
+
+   private static final String message = "prOVIDers preFERence";
+
+   public void testProvidersPreference() throws Exception
+   {
+      applicationRegistry.addApplication(new Application2());
+      // If StringEntityProvider1 override default reader/writer for String
+      // then string must be in upper case in service's method.
+      ByteArrayContainerResponseWriter writer = new ByteArrayContainerResponseWriter();
+      ContainerResponse resp = launcher.service("POST", "/abc", "", null, message.getBytes(), writer, null);
+      assertEquals(200, resp.getStatus());
+      // Must be returned in lower case.
+      assertEquals(message.toLowerCase(), new String(writer.getBody()));
+   }
+
 }

Modified: ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/wadl/WadlProcessorTest.java
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/wadl/WadlProcessorTest.java	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/java/org/exoplatform/services/rest/wadl/WadlProcessorTest.java	2010-11-02 08:56:55 UTC (rev 3375)
@@ -164,7 +164,8 @@
       // boolean head = false;
       for (int i = 0; i < nl.getLength(); i++)
       {
-         String t = nl.item(i).getTextContent();
+//System.out.println("\n\n\n\n"+nl.item(i).getClass()+"\n\n\n\n");
+         String t = nl.item(i).getNodeValue();
          // if (t.equals("HEAD"))
          // head = true;
          if (t.equals("GET"))
@@ -173,7 +174,7 @@
       // assertTrue(head && get);
       assertTrue(get);
       for (int i = 0; i < nl.getLength(); i++)
-         System.out.println(">>>>> resource method : " + nl.item(i).getTextContent());
+         System.out.println(">>>>> resource method : " + nl.item(i).getNodeValue());
       str =
          (String)xp.evaluate("//wadl:resource[@path='a/{b}']/wadl:method[@id='m2']/@name", doc, XPathConstants.STRING);
       assertEquals("POST", str);
@@ -199,7 +200,7 @@
       // boolean subhead = false;
       for (int i = 0; i < nl.getLength(); i++)
       {
-         String t = nl.item(i).getTextContent();
+         String t = nl.item(i).getNodeValue();
          // if (t.equals("HEAD"))
          // subhead = true;
          if (t.equals("GET"))
@@ -208,7 +209,7 @@
       // assertTrue(subhead && subget);
       assertTrue(subget);
       for (int i = 0; i < nl.getLength(); i++)
-         System.out.println(">>>>> sub-resource method : " + nl.item(i).getTextContent());
+         System.out.println(">>>>> sub-resource method : " + nl.item(i).getNodeValue());
       str =
          (String)xp.evaluate("count(//wadl:resource[@path='a/{b}']/wadl:resource[@path='{c}/{d}/{e}']/wadl:method)",
             doc, XPathConstants.STRING);
@@ -251,7 +252,7 @@
       boolean childopt = false;
       for (int i = 0; i < nl.getLength(); i++)
       {
-         String t = nl.item(i).getTextContent();
+         String t = nl.item(i).getNodeValue();
          // if (t.equals("HEAD"))
          // childhead = true;
          if (t.equals("GET"))
@@ -262,7 +263,7 @@
       // assertTrue(childhead && childget && childopt);
       assertTrue(childget && childopt);
       for (int i = 0; i < nl.getLength(); i++)
-         System.out.println(">>>>> child resource method : " + nl.item(i).getTextContent());
+         System.out.println(">>>>> child resource method : " + nl.item(i).getNodeValue());
 
       str =
          (String)xp.evaluate("count(//wadl:resource[@path='a/{b}']/wadl:resource[@path='sub/{x}']/wadl:method)", doc,

Modified: ws/trunk/exo.ws.rest.core/src/test/resources/conf/standalone/test-configuration.xml
===================================================================
--- ws/trunk/exo.ws.rest.core/src/test/resources/conf/standalone/test-configuration.xml	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.core/src/test/resources/conf/standalone/test-configuration.xml	2010-11-02 08:56:55 UTC (rev 3375)
@@ -52,6 +52,15 @@
    </component>
 
    <component>
+      <type>org.exoplatform.services.rest.impl.ApplicationRegistry</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.StartableApplication</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.ProvidersRegistry</type>
+   </component>
+   <component>
       <type>org.exoplatform.services.rest.impl.RequestHandlerImpl</type>
    </component>
    <component>

Modified: ws/trunk/exo.ws.rest.ext/src/test/resources/conf/standalone/test-configuration.xml
===================================================================
--- ws/trunk/exo.ws.rest.ext/src/test/resources/conf/standalone/test-configuration.xml	2010-11-02 08:53:25 UTC (rev 3374)
+++ ws/trunk/exo.ws.rest.ext/src/test/resources/conf/standalone/test-configuration.xml	2010-11-02 08:56:55 UTC (rev 3375)
@@ -37,6 +37,15 @@
 		</init-params>
 	</component>
 
+   <component>
+      <type>org.exoplatform.services.rest.impl.ApplicationRegistry</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.StartableApplication</type>
+   </component>
+   <component>
+      <type>org.exoplatform.services.rest.impl.ProvidersRegistry</type>
+   </component>
 	<component>
 		<type>org.exoplatform.services.rest.impl.RequestHandlerImpl</type>
 	</component>



More information about the exo-jcr-commits mailing list