portals-pluto-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From msnickl...@apache.org
Subject [14/34] portals-pluto git commit: Completed initial implementation of resource phase async support
Date Fri, 08 Apr 2016 13:40:26 GMT
Completed initial implementation of resource phase async support


Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/4b054ada
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/4b054ada
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/4b054ada

Branch: refs/heads/V3Prototype
Commit: 4b054ada7b90310e35ed95779805e06436634e69
Parents: ae766fd
Author: Scott Nicklous <msnicklous@apache.org>
Authored: Fri Mar 25 15:35:05 2016 +0100
Committer: Scott Nicklous <msnicklous@apache.org>
Committed: Fri Mar 25 15:35:05 2016 +0100

----------------------------------------------------------------------
 .../pluto/container/PortletInvokerService.java  |   6 +
 .../PortletResourceRequestContext.java          |  14 ++
 .../pluto/container/driver/PortletServlet3.java |  20 ++-
 .../bean/processor/PortletInvoker.java          |  65 +++++++--
 .../impl/HttpServletPortletRequestWrapper.java  |  49 +++++++
 .../impl/PortletAsyncRequestWrapper.java        |  75 +++++++++++
 .../container/impl/ResourceRequestImpl.java     |  47 +------
 .../container/PortletAsyncListener.java         | 132 +++++++++++++++++++
 .../PortletResourceRequestContextImpl.java      |  88 +++++++++++++
 .../container/DefaultPortletInvokerService.java |   1 +
 10 files changed, 437 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
index 2dddf78..9552fa6 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
@@ -63,6 +63,12 @@ public interface PortletInvokerService {
     String PORTLET_CONFIG = "javax.portlet.config";
 
     /**
+     * The key used to bind the <code>MethodIdentifier</code> to the ResourceRequest
+     * for asyc processing
+     */
+    String ASYNC_METHOD = "javax.portlet.asyncMethod";
+
+    /**
      * The request attribute key used to retrieve the <code>PortletRequestContext</code>
instance
      */
     String REQUEST_CONTEXT = PortletRequestContext.class.getName();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
index 242d8a6..f8d50f9 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
@@ -19,7 +19,10 @@ package org.apache.pluto.container;
 import java.util.Map;
 
 import javax.portlet.ResourceParameters;
+import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 
 /**
  * @version $Id$
@@ -54,4 +57,15 @@ public interface PortletResourceRequestContext extends PortletRequestContext
      * @return
      */
     void setResponse(ResourceResponse response);
+    
+    /**
+     * For async support
+     */
+    
+    AsyncContext startAsync(ResourceRequest request) throws IllegalStateException;
+    AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException;
+    boolean isAsyncStarted();
+    boolean isAsyncSupported();
+    AsyncContext getAsyncContext() throws IllegalStateException;
+    DispatcherType getDispatcherType();
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
----------------------------------------------------------------------
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
index 7155e04..d835746 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
@@ -35,6 +35,7 @@ import javax.portlet.RenderResponse;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.portlet.UnavailableException;
+import javax.servlet.DispatcherType;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -261,12 +262,8 @@ public class PortletServlet3 extends HttpServlet {
       final PortletResponseContext responseContext = (PortletResponseContext) portletRequest
             .getAttribute(PortletInvokerService.RESPONSE_CONTEXT);
 
-      final FilterManager filterManager = (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
-
-      request.removeAttribute(PortletInvokerService.METHOD_ID);
-      request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
-      request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
-      request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+      final FilterManager filterManager = 
+            (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
 
       requestContext.init(portletConfig, getServletContext(), request, response);
       responseContext.init(request, response);
@@ -371,6 +368,17 @@ public class PortletServlet3 extends HttpServlet {
          notify(event, false, ex);
          throw new ServletException(ex);
 
+      } finally {
+         // If an async request is running or has been dispatched, resources will
+         // be released by the PortletAsyncListener. Otherwise release here.
+         if (!request.isAsyncStarted() && (request.getDispatcherType() != DispatcherType.ASYNC))
{
+
+            request.removeAttribute(PortletInvokerService.METHOD_ID);
+            request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+            request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+            request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+
+         }
       }
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
index c4d1adc..f9a592b 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
@@ -22,6 +22,7 @@ import static javax.portlet.ActionRequest.ACTION_NAME;
 
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.portlet.ActionRequest;
@@ -47,8 +48,10 @@ import javax.portlet.StateAwareResponse;
 import javax.portlet.annotations.HeaderMethod;
 import javax.portlet.annotations.RenderMethod;
 import javax.portlet.annotations.ServeResourceMethod;
+import javax.servlet.DispatcherType;
 import javax.xml.namespace.QName;
 
+import org.apache.pluto.container.PortletInvokerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -260,7 +263,28 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet,
EventPor
       String id = (req.getResourceID() != null) ? req.getResourceID() : "";
       MethodIdentifier mi = new MethodIdentifier(portletName, id, MethodType.RESOURCE);
 
-      List<AnnotatedMethod> meths = getMethods(mi);
+      List<AnnotatedMethod> meths = new ArrayList<AnnotatedMethod>();
+      if (req.getDispatcherType() == DispatcherType.ASYNC) {
+         
+         // Handle AsyncContest#dispatch() case
+         
+         MethodIdentifier ami = (MethodIdentifier) req.getAttribute(PortletInvokerService.ASYNC_METHOD);
+         AnnotatedMethod meth = null;
+         if (ami != null) {
+            meth = acb.getMethodStore().getMethod(mi);
+         }
+         if (meth == null) {
+            StringBuilder txt = new StringBuilder(128);
+            txt.append("Async processing error. ServeResource method not found for method
identifier: ");
+            txt.append((ami == null) ? "null" : ami.toString());
+            LOG.warn(txt.toString());
+            return;
+         }
+         meths.add(meth);
+      } else {
+         meths = getMethods(mi);
+      }
+      
       if (meths.size() == 0) {
 
          // If a resource URL was activated, but no resource method could be
@@ -302,21 +326,36 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet,
EventPor
             // invoke the resource method
 
             result = invokePortletMethod(meth, args);
-
-            // If output is to be expected, write it to the writer
-
-            if (meth.getDescription().getVariant() == SignatureVariant.STRING_VOID) {
-               if (result != null) {
-                  assert result instanceof String;
-                  resp.getWriter().write((String) result);
+            
+            if (req.isAsyncStarted()) {
+               
+               // If async processing was started, handle the special case.
+               // It doesn't make sense to write output, as the resource method may
+               // be writing output through an async thread. Set up to process async dispatch.
+               // also, after async is started, no further methods can be invoked.
+               
+               LOG.debug("Async processing was started during method: " + meth.toString());
+               req.setAttribute(PortletInvokerService.ASYNC_METHOD, meth);
+               break;
+               
+            } else {
+
+               // No async processing.
+               // If output is to be expected, write it to the writer
+
+               if (meth.getDescription().getVariant() == SignatureVariant.STRING_VOID) {
+                  if (result != null) {
+                     assert result instanceof String;
+                     resp.getWriter().write((String) result);
+                  }
                }
-            }
 
-            // If an include resource is provided, include it
+               // If an include resource is provided, include it
 
-            if ((rm != null) && (rm.include().length() > 0)) {
-               PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(rm.include());
-               prd.include(req, resp);
+               if ((rm != null) && (rm.include().length() > 0)) {
+                  PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(rm.include());
+                  prd.include(req, resp);
+               }
             }
          }
       } finally {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container/src/main/java/org/apache/pluto/container/impl/HttpServletPortletRequestWrapper.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/HttpServletPortletRequestWrapper.java
b/pluto-container/src/main/java/org/apache/pluto/container/impl/HttpServletPortletRequestWrapper.java
index 74a7fb7..b5af74d 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/HttpServletPortletRequestWrapper.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/HttpServletPortletRequestWrapper.java
@@ -34,9 +34,15 @@ import java.util.NoSuchElementException;
 
 import javax.portlet.ClientDataRequest;
 import javax.portlet.PortletRequest;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
@@ -1459,4 +1465,47 @@ public class HttpServletPortletRequestWrapper extends HttpServletRequestWrapper
     {
         return portletRequest.isSecure();
     }
+
+    /**
+     * The async methods can't be used
+     */
+
+    @Override
+    public AsyncContext startAsync() throws IllegalStateException {
+       StringBuilder txt = new StringBuilder(128);
+       txt.append("The async context cannot be initialized after a ");
+       txt.append("include or forward from a portlet reqource request method. ");
+       txt.append("The first async context initialization must be performed within the portlet
resource method.");
+       throw new IllegalStateException(txt.toString());
+    }
+
+    @Override
+    public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws
IllegalStateException {
+       StringBuilder txt = new StringBuilder(128);
+       txt.append("The async context cannot be initialized after a ");
+       txt.append("include or forward from a portlet reqource request method. ");
+       txt.append("The first async context initialization must be performed within the portlet
resource method.");
+       throw new IllegalStateException(txt.toString());
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+       return false;
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+       return false;
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+       return super.getAsyncContext();
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+       return super.getDispatcherType();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
new file mode 100644
index 0000000..dd259c9
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
@@ -0,0 +1,75 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+
+package org.apache.pluto.container.impl;
+
+import javax.portlet.PortletRequest;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author Scott Nicklous
+ *
+ */
+public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper {
+
+   /**
+    * Modifies the behavior of the underlying wrapper to allow access to the
+    * async methods.
+    * 
+    * @param request
+    * @param servletContext
+    * @param session
+    * @param portletRequest
+    */
+   public PortletAsyncRequestWrapper(HttpServletRequest request, ServletContext servletContext,
HttpSession session,
+         PortletRequest portletRequest) {
+      super(request, servletContext, session, portletRequest, false, false);
+      
+   }
+   
+
+
+   @Override
+   public AsyncContext startAsync() throws IllegalStateException {
+      return getRequest().startAsync();
+   }
+
+   @Override
+   public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws
IllegalStateException {
+      return getRequest().startAsync(request, response);
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return getRequest().isAsyncStarted();
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return getRequest().isAsyncSupported();
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
b/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
index b73a29b..721c5e8 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
@@ -127,66 +127,31 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements
Resour
 
    @Override
    public AsyncContext startAsync() throws IllegalStateException {
-      ResourceResponse resp = getRequestContext().getResponse();
-      return startAsync(this, resp);
+      return getRequestContext().startAsync(this);
    }
 
    @Override
    public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws
IllegalStateException {
-      
-      HttpServletRequest hreq = getRequestContext().getServletRequest();
-      HttpServletResponse hresp = getRequestContext().getServletResponse();
-      ServletContext ctx = getRequestContext().getServletContext();
-      HttpSession sess = getSession();
-      PortletConfig cfg =getRequestContext().getPortletConfig(); 
-      
-      HttpServletRequest wreq = new HttpServletPortletRequestWrapper(hreq, ctx, sess, request,
false, false);
-      HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response,
false);
-   
-      request.setAttribute(PortletInvokerService.PORTLET_CONFIG, cfg);
-      request.setAttribute(PortletInvokerService.PORTLET_REQUEST, request);
-      request.setAttribute(PortletInvokerService.PORTLET_RESPONSE, response);
-      
-      AsyncContext actx = hreq.startAsync(wreq, wresp);
-
-      return actx;
+      return getRequestContext().startAsync(request, response);
    }
 
    @Override
    public boolean isAsyncStarted() {
-      return getRequestContext().getServletRequest().isAsyncStarted();
+      return getRequestContext().isAsyncStarted();
    }
 
    @Override
    public boolean isAsyncSupported() {
-      return getRequestContext().getServletRequest().isAsyncSupported();
+      return getRequestContext().isAsyncSupported();
    }
 
    @Override
    public AsyncContext getAsyncContext() {
-      return getRequestContext().getServletRequest().getAsyncContext();
+      return getRequestContext().getAsyncContext();
    }
 
    @Override
    public DispatcherType getDispatcherType() {
-      return getRequestContext().getServletRequest().getDispatcherType();
-   }
-
-   // For use within the wrapper. 
-   // PLT.10.4.3. Proxied session is created and passed if 
-   // javax.portlet.servletDefaultSessionScope == PORTLET_SCOPE
-   private HttpSession getSession() {
-      HttpSession sess = null;
-
-      PortletConfig portletConfig = getRequestContext().getPortletConfig();
-      Map<String, String[]> containerRuntimeOptions = portletConfig.getContainerRuntimeOptions();
-      String[] values = containerRuntimeOptions.get("javax.portlet.servletDefaultSessionScope");
-
-      if ((values != null) && (values.length > 0) && "PORTLET_SCOPE".equals(values[0]))
{
-         String portletWindowId = getRequestContext().getPortletWindow().getId().getStringId();
-         sess = ServletPortletSessionProxy.createProxy(getRequestContext().getServletRequest(),
portletWindowId);
-      }
-
-      return sess;
+      return getRequestContext().getDispatcherType();
    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
new file mode 100644
index 0000000..9474a10
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
@@ -0,0 +1,132 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+
+package org.apache.pluto.driver.services.container;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.logging.Logger;
+
+import javax.portlet.ResourceRequest;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.pluto.container.PortletInvokerService;
+import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.PortletResourceResponseContext;
+
+/**
+ * Releases portal resources when the async request completes.
+ *  
+ * @author Scott Nicklous
+ */
+public class PortletAsyncListener implements AsyncListener {
+   private static final Logger LOGGER = Logger.getLogger(PortletAsyncListener.class.getName());
+
+   private long start = System.currentTimeMillis();
+   
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onComplete(AsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Completed. Execution time: ").append(delta).append(" milliseconds.");
+      txt.append(" Releasing: ");
+      
+      // remove portlet-scoped barnacles
+      
+      AsyncContext ctx = evt.getAsyncContext();
+      HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
+      ResourceRequest rreq = (ResourceRequest) hreq.getAttribute(PortletInvokerService.PORTLET_REQUEST);
+      if (rreq != null) {
+         txt.append("portlet-scoped attributes; ");
+         rreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+         rreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+         rreq.removeAttribute(PortletInvokerService.PORTLET_CONFIG);
+         rreq.removeAttribute(PortletInvokerService.ASYNC_METHOD);
+         
+         PortletResourceResponseContext respctx = (PortletResourceResponseContext)
+               rreq.getAttribute(PortletInvokerService.RESPONSE_CONTEXT);
+         if (respctx != null) {
+            txt.append("response context resources; ");
+            respctx.close();
+            respctx.release();
+         }
+      }
+      
+      // Release and remove container request attributes
+      
+      HttpServletRequest containerRequest = (HttpServletRequest) evt.getSuppliedRequest();
+      if (containerRequest != null) {
+         txt.append("container-scoped attributes; ");
+         containerRequest.removeAttribute(PortletInvokerService.METHOD_ID);
+         containerRequest.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+         containerRequest.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+         containerRequest.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+      }
+      
+      LOGGER.fine(txt.toString());
+
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onError(AsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Error after ").append(delta).append(" milliseconds.");
+      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
+      LOGGER.fine(txt.toString());
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onStartAsync(AsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Async started again after ").append(delta).append(" milliseconds.");
+      LOGGER.fine(txt.toString());
+      
+      // need to add this listener again so it gets called when finally complete.
+      
+      AsyncContext ctx = evt.getAsyncContext();
+      ctx.addListener(this);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncListener#onTimeout(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onTimeout(AsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Timeout after ").append(delta).append(" milliseconds.");
+      LOGGER.fine(txt.toString());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
index 1a6bf5e..c361dcd 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
@@ -18,15 +18,26 @@ package org.apache.pluto.driver.services.container;
 
 import java.util.Map;
 
+import javax.portlet.PortletConfig;
 import javax.portlet.ResourceParameters;
+import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 
 import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.impl.HttpServletPortletRequestWrapper;
+import org.apache.pluto.container.impl.HttpServletPortletResponseWrapper;
+import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.apache.pluto.container.impl.ResourceParametersImpl;
+import org.apache.pluto.container.impl.ServletPortletSessionProxy;
 
 /**
  * @version $Id$
@@ -96,4 +107,81 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    public void setResponse(ResourceResponse response) {
       this.response = response;
    }
+
+    @Override
+    public AsyncContext startAsync(ResourceRequest request) throws IllegalStateException
{
+       return startAsync(request, response);
+    }
+
+    @Override
+    public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws
IllegalStateException {
+       
+       HttpServletRequest hreq = getServletRequest();
+       HttpServletResponse hresp = getServletResponse();
+       ServletContext ctx = getServletContext();
+       HttpSession sess = getSession();
+       PortletConfig cfg = getPortletConfig(); 
+
+       // Set portlet-scoped attributes directly on resource request
+       
+       request.setAttribute(PortletInvokerService.PORTLET_CONFIG, cfg);
+       request.setAttribute(PortletInvokerService.PORTLET_REQUEST, request);
+       request.setAttribute(PortletInvokerService.PORTLET_RESPONSE, response);
+
+       // Wrap http req & response. 
+       
+       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, ctx, sess, request);
+       HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request,
response, false);
+
+       // get the original container req & resp to pass to listener for resource releasing
+
+       HttpServletRequest creq = getContainerRequest();     
+       HttpServletResponse cresp = getContainerResponse();
+
+       // Attach listener to release resources upon async complete.
+       
+       AsyncContext actx = hreq.startAsync(wreq, wresp);
+       PortletAsyncListener pal = new PortletAsyncListener();
+       actx.addListener(pal, creq, cresp);
+
+       return actx;
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+       return getServletRequest().isAsyncStarted();
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+       return getServletRequest().isAsyncSupported();
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+       return getServletRequest().getAsyncContext();
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+       return getServletRequest().getDispatcherType();
+    }
+
+    // For use within the wrapper. 
+    // PLT.10.4.3. Proxied session is created and passed if 
+    // javax.portlet.servletDefaultSessionScope == PORTLET_SCOPE
+    private HttpSession getSession() {
+       HttpSession sess = null;
+
+       PortletConfig portletConfig = getPortletConfig();
+       Map<String, String[]> containerRuntimeOptions = portletConfig.getContainerRuntimeOptions();
+       String[] values = containerRuntimeOptions.get("javax.portlet.servletDefaultSessionScope");
+
+       if ((values != null) && (values.length > 0) && "PORTLET_SCOPE".equals(values[0]))
{
+          String portletWindowId = getPortletWindow().getId().getStringId();
+          sess = ServletPortletSessionProxy.createProxy(getServletRequest(), portletWindowId);
+       }
+
+       return sess;
+    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/4b054ada/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
index 20d8a8b..0e86231 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
@@ -280,6 +280,7 @@ public class DefaultPortletInvokerService implements PortletInvokerService
{
                 }
 
             } finally {
+                // If async is running, resources will be released by the PortletAsyncListener
                 if (!containerRequest.isAsyncSupported() || !containerRequest.isAsyncStarted())
{
                    LOG.debug("After invocation, removing attributes.");
                    containerRequest.removeAttribute(PortletInvokerService.METHOD_ID);


Mime
View raw message