You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by ms...@apache.org on 2016/04/08 15:40:13 UTC

[01/34] portals-pluto git commit: Added fields and methods as described in PORTLETSPEC3-63 and PORTLETSPEC3-64: PortletRequest#USER_AGENT, PortletRequest#getPortletContext, and ClientDataRequest#getContentLengthLong. Implemented the methods in the Pluto

Repository: portals-pluto
Updated Branches:
  refs/heads/V3Prototype 5a59b412e -> 0e71c8ab7


Added fields and methods as described in PORTLETSPEC3-63
and PORTLETSPEC3-64: PortletRequest#USER_AGENT,
PortletRequest#getPortletContext, and
ClientDataRequest#getContentLengthLong. Implemented the methods in the Pluto
RI. Implemented functionality in the PortletV3AnnotatedDemo to display the
user agent string obtained from PortletRequest#getProperty(USER_AGENT).


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

Branch: refs/heads/V3Prototype
Commit: 7e04857a7340819c64ff8547e0877febe26669e5
Parents: 5a59b41
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 10 15:48:51 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 10 15:48:51 2016 +0100

----------------------------------------------------------------------
 .../portals/samples/HelloWorldRender.java       |   8 +-
 .../org/apache/portals/samples/PathDisplay.java | 188 +++++++
 .../apache/portals/samples/PathInfoPortlet.java | 100 ++++
 .../src/main/webapp/WEB-INF/jsp/pathinfo.jsp    |  21 +
 .../container/impl/ClientDataRequestImpl.java   | 224 ++++----
 .../container/impl/PortletRequestImpl.java      |  15 +-
 .../fixtures/mocks/MockClientDataRequest.java   |   5 +
 .../fixtures/mocks/MockPortletRequest.java      |   6 +
 .../apache/pluto/tags/DefineObjectsTag286.java  | 526 ++++++++++---------
 .../java/javax/portlet/ClientDataRequest.java   |  21 +-
 .../main/java/javax/portlet/PortletRequest.java |  32 +-
 .../portlet/annotations/PortletListener.java    |   2 +-
 .../filter/ClientDataRequestWrapper.java        |  11 +
 .../portlet/filter/PortletRequestWrapper.java   |   6 +
 portlet-api/src/main/javadoc/overview.html      |  11 +
 15 files changed, 797 insertions(+), 379 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/HelloWorldRender.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/HelloWorldRender.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/HelloWorldRender.java
index 4c08a1b..b9c1394 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/HelloWorldRender.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/HelloWorldRender.java
@@ -20,7 +20,8 @@
 package org.apache.portals.samples;
 
 import javax.inject.Inject;
-
+import javax.portlet.PortletRequest;
+import javax.portlet.RenderRequest;
 import javax.portlet.annotations.RenderMethod;
 
 /**
@@ -50,6 +51,9 @@ public class HelloWorldRender {
    
    @Inject
    private ApplicationRandomNumberBean apprn;
+   
+   @Inject
+   private RenderRequest req;
 
    /**
     * Bean portlet render method for "BeanHelloWorld" portlet.
@@ -85,6 +89,8 @@ public class HelloWorldRender {
       txt.append("Request number:</td><td>").append(reqrn.getRandomNumber());
       txt.append("</td></tr></table></p>\n");
       
+      txt.append("<p>User agent: ").append(req.getProperty(PortletRequest.USER_AGENT)).append("</p>");
+      
       return txt.toString();
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
new file mode 100644
index 0000000..dbf1cf4
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
@@ -0,0 +1,188 @@
+/*  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.portals.samples;
+
+import javax.portlet.PortletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author Scott Nicklous
+ * 
+ */
+public class PathDisplay {
+
+   private String async_request_uri;
+   private String async_context_path;
+   private String async_servlet_path;
+   private String async_path_info;
+   private String async_query_string;
+
+   private String forward_request_uri;
+   private String forward_context_path;
+   private String forward_servlet_path;
+   private String forward_path_info;
+   private String forward_query_string;
+
+   private String include_request_uri;
+   private String include_context_path;
+   private String include_servlet_path;
+   private String include_path_info;
+   private String include_query_string;
+
+   private String method_request_uri;
+   private String method_context_path;
+   private String method_servlet_path;
+   private String method_path_info;
+   private String method_query_string;
+   
+   private String type;
+   private String caller;
+
+   public PathDisplay(HttpServletRequest req, String caller) {
+      this.caller = caller;
+      
+      async_request_uri = (String) req.getAttribute("javax.servlet.async.request_uri");
+      async_context_path = (String) req.getAttribute("javax.servlet.async.context_path");
+      async_servlet_path = (String) req.getAttribute("javax.servlet.async.servlet_path");
+      async_path_info = (String) req.getAttribute("javax.servlet.async.path_info");
+      async_query_string = (String) req.getAttribute("javax.servlet.async.query_string");
+
+      forward_request_uri = (String) req.getAttribute("javax.servlet.forward.request_uri");
+      forward_context_path = (String) req.getAttribute("javax.servlet.forward.context_path");
+      forward_servlet_path = (String) req.getAttribute("javax.servlet.forward.servlet_path");
+      forward_path_info = (String) req.getAttribute("javax.servlet.forward.path_info");
+      forward_query_string = (String) req.getAttribute("javax.servlet.forward.query_string");
+
+      include_request_uri = (String) req.getAttribute("javax.servlet.include.request_uri");
+      include_context_path = (String) req.getAttribute("javax.servlet.include.context_path");
+      include_servlet_path = (String) req.getAttribute("javax.servlet.include.servlet_path");
+      include_path_info = (String) req.getAttribute("javax.servlet.include.path_info");
+      include_query_string = (String) req.getAttribute("javax.servlet.include.query_string");
+
+      method_request_uri = req.getRequestURI();
+      method_context_path = req.getContextPath();
+      method_servlet_path = req.getServletPath();
+      method_path_info = req.getPathInfo();
+      method_query_string = req.getQueryString();
+      
+      type = req.getDispatcherType().name();
+}
+
+   public PathDisplay(PortletRequest req, String caller) {
+      this.caller = caller;
+      
+      async_request_uri = (String) req.getAttribute("javax.servlet.async.request_uri");
+      async_context_path = (String) req.getAttribute("javax.servlet.async.context_path");
+      async_servlet_path = (String) req.getAttribute("javax.servlet.async.servlet_path");
+      async_path_info = (String) req.getAttribute("javax.servlet.async.path_info");
+      async_query_string = (String) req.getAttribute("javax.servlet.async.query_string");
+
+      forward_request_uri = (String) req.getAttribute("javax.servlet.forward.request_uri");
+      forward_context_path = (String) req.getAttribute("javax.servlet.forward.context_path");
+      forward_servlet_path = (String) req.getAttribute("javax.servlet.forward.servlet_path");
+      forward_path_info = (String) req.getAttribute("javax.servlet.forward.path_info");
+      forward_query_string = (String) req.getAttribute("javax.servlet.forward.query_string");
+
+      include_request_uri = (String) req.getAttribute("javax.servlet.include.request_uri");
+      include_context_path = (String) req.getAttribute("javax.servlet.include.context_path");
+      include_servlet_path = (String) req.getAttribute("javax.servlet.include.servlet_path");
+      include_path_info = (String) req.getAttribute("javax.servlet.include.path_info");
+      include_query_string = (String) req.getAttribute("javax.servlet.include.query_string");
+
+      method_request_uri = "undefined";
+      method_context_path = req.getContextPath();
+      method_servlet_path = "undefined";
+      method_path_info = "undefined";
+      method_query_string = "undefined";
+      
+      type = "undefined";
+}
+
+   public String toMarkup() {
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("<hr>");
+      txt.append("<h5>").append(caller).append(" Path Info:</h5>");
+      txt.append("<table border='0' cellpadding='0'><tr>");
+
+      txt.append("<td>Dispatch type:</td><td>").append(type).append("</td>\n");
+      txt.append("</tr><tr><td style='padding-top:8px;'/></tr><tr>");
+
+      if ((async_request_uri == null) && (async_context_path == null) && (async_servlet_path == null)
+            && (async_path_info == null) && (async_query_string == null)) {
+         txt.append("<td>Async values:</td><td>null.</td>\n");
+      } else {
+         txt.append("<td>async_request_uri:</td><td>").append(async_request_uri).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>async_context_path:</td><td>").append(async_context_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>async_servlet_path:</td><td>").append(async_servlet_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>async_path_info:</td><td>").append(async_path_info).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>async_query_string:</td><td>").append(async_query_string).append("</td>\n");
+      }
+      txt.append("</tr><tr><td style='padding-top:8px;'/></tr><tr>");
+
+      if ((forward_request_uri == null) && (forward_context_path == null) && (forward_servlet_path == null)
+            && (forward_path_info == null) && (forward_query_string == null)) {
+         txt.append("<td>Forward values:</td><td>null.</td>\n");
+      } else {
+         txt.append("<td>forward_request_uri:</td><td>").append(forward_request_uri).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>forward_context_path:</td><td>").append(forward_context_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>forward_servlet_path:</td><td>").append(forward_servlet_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>forward_path_info:</td><td>").append(forward_path_info).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>forward_query_string:</td><td>").append(forward_query_string).append("</td>\n");
+      }
+      txt.append("</tr><tr><td style='padding-top:8px;'/></tr><tr>");
+
+      if ((include_request_uri == null) && (include_context_path == null) && (include_servlet_path == null)
+            && (include_path_info == null) && (include_query_string == null)) {
+         txt.append("<td>Include values:</td><td>null.</td>\n");
+      } else {
+         txt.append("<td>include_request_uri:</td><td>").append(include_request_uri).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>include_context_path:</td><td>").append(include_context_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>include_servlet_path:</td><td>").append(include_servlet_path).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>include_path_info:</td><td>").append(include_path_info).append("</td>\n");
+         txt.append("</tr><tr>");
+         txt.append("<td>include_query_string:</td><td>").append(include_query_string).append("</td>\n");
+      }
+      txt.append("</tr><tr><td style='padding-top:8px;'/></tr><tr>");
+
+      txt.append("<td>method_request_uri:</td><td>").append(method_request_uri).append("</td>\n");
+      txt.append("</tr><tr>");
+      txt.append("<td>method_context_path:</td><td>").append(method_context_path).append("</td>\n");
+      txt.append("</tr><tr>");
+      txt.append("<td>method_servlet_path:</td><td>").append(method_servlet_path).append("</td>\n");
+      txt.append("</tr><tr>");
+      txt.append("<td>method_path_info:</td><td>").append(method_path_info).append("</td>\n");
+      txt.append("</tr><tr>");
+      txt.append("<td>method_query_string:</td><td>").append(method_query_string).append("</td>\n");
+
+      txt.append("</tr></table>");
+      return txt.toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
new file mode 100644
index 0000000..1f42b14
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
@@ -0,0 +1,100 @@
+/*  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.portals.samples;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceURL;
+import javax.portlet.annotations.Namespace;
+import javax.portlet.annotations.RenderMethod;
+import javax.portlet.annotations.ServeResourceMethod;
+import javax.portlet.annotations.URLFactory;
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * Resource portlet for viewing path information.
+ */
+public class PathInfoPortlet {
+
+   public static final String RESPARAM_DISPLAY = "display";
+   
+   // Injecting the namespace & URLFactory
+   @Inject @Namespace private String pid;
+   @Inject private            URLFactory uf;
+
+   @RenderMethod(portletNames = {"PathInfoPortlet"}, ordinal=100)
+   public String getImageInclude() {
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("<h3>Path Info Portlet</h3>");
+      
+      ResourceURL resurl = uf.createResourceURL();
+      
+      txt.append("<div class='infobox' id='").append(pid).append("-putResourceHere'></div>\n");
+      txt.append("<script>\n");
+      txt.append("(function () {\n");
+      txt.append("   var xhr = new XMLHttpRequest();\n");
+      txt.append("   xhr.onreadystatechange=function() {\n");
+      txt.append("      if (xhr.readyState==4 && xhr.status==200) {\n");
+      txt.append("         document.getElementById('").append(pid).append("-putResourceHere').innerHTML=xhr.responseText;\n");
+      txt.append("      }\n");
+      txt.append("   };\n");
+      txt.append("   xhr.open(\"GET\",\"").append(resurl.toString()).append("\",true);\n");
+      txt.append("   xhr.send();\n");
+      txt.append("})();\n");
+      txt.append("</script>\n");
+
+      return txt.toString();
+   }
+   
+   @Inject private ResourceRequest resReq;
+   
+   /**
+    *  This resource method generates some output directly, then includes output
+    *  from a JSP as specified in the annotation.
+    *  
+    * @return  The string for inclusion in the output.
+    */
+   @ServeResourceMethod(portletNames={"PathInfoPortlet"}, include="/WEB-INF/jsp/pathinfo.jsp")
+   public void getPathInfo() {
+      
+      @SuppressWarnings("unchecked")
+      ArrayList<String> pathInfo = (ArrayList<String>) resReq.getAttribute("pathInfo");
+      if (pathInfo == null) {
+         pathInfo = new ArrayList<String>();
+      }
+      
+      HttpServletRequest hreq = (HttpServletRequest) resReq.getAttribute("javax.portlet.debug.ServletRequest");
+      PathDisplay pd;
+      if (hreq != null) {
+         pd = new PathDisplay(hreq, "Resource Method (Servlet)");
+      } else {
+         pd = new PathDisplay(resReq, "Resource Method (Resource)");
+      }
+      pathInfo.add(pd.toMarkup());
+      
+      resReq.setAttribute("pathInfo", pathInfo);
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
new file mode 100644
index 0000000..099b153
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
@@ -0,0 +1,21 @@
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="org.apache.portals.samples.*" %>
+<%@ page import="java.util.*" %>
+
+<portlet:defineObjects />
+
+<p>Message from included JSP.</p>
+<%
+ArrayList<String> pathInfo = (ArrayList<String>) request.getAttribute("pathInfo");
+if (pathInfo != null) {
+   for (String item : pathInfo) {
+      out.append(item);
+   }
+}
+
+PathDisplay pd = new PathDisplay(request, "JSP");
+out.append(pd.toMarkup());
+ %>
+<hr>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/pluto-container/src/main/java/org/apache/pluto/container/impl/ClientDataRequestImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/ClientDataRequestImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/ClientDataRequestImpl.java
index 6606089..0fff3a6 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/ClientDataRequestImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/ClientDataRequestImpl.java
@@ -1,109 +1,115 @@
-/*
- * 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 java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-
-import javax.portlet.ClientDataRequest;
-
-import org.apache.pluto.container.PortletRequestContext;
-import org.apache.pluto.container.PortletResponseContext;
-
-/**
- * Implementation of the <code>javax.portlet.ClientDataRequest</code> interface.
- */
-public abstract class ClientDataRequestImpl extends PortletRequestImpl implements ClientDataRequest
-{
-    /** Flag indicating if the HTTP body reader has been accessed. */
-    protected boolean readerAccessed = false;
-
-    public ClientDataRequestImpl(PortletRequestContext requestContext, PortletResponseContext responseContext, String lifecyclePhase)
-    {
-        super(requestContext, responseContext, lifecyclePhase);
-    }
-
-    private void checkPostedFormData() 
-    {
-        if (getMethod().equals("POST"))
-        {
-            String contentType = getContentType();
-            if (contentType == null || contentType.equals("application/x-www-form-urlencoded"))
-            {
-                throw new IllegalStateException("User request HTTP POST data is of type "
-                                                + "application/x-www-form-urlencoded. "
-                                                + "This data has been already processed "
-                                                + "by the portlet-container and is available "
-                                                + "as request parameters.");
-            }
-        }
-    }
-        
-    public java.lang.String getCharacterEncoding()
-    {
-        return getServletRequest().getCharacterEncoding();
-    }
-
-    public int getContentLength()
-    {
-        return getServletRequest().getContentLength();
-    }
-
-    public java.lang.String getContentType()
-    {
-        return getServletRequest().getContentType();
-    }
-    
-    public String getMethod()
-    {
-        return getServletRequest().getMethod();
-    }
-
-    public InputStream getPortletInputStream() throws IOException
-    {
-        checkPostedFormData();
-        // the HttpServletRequest will ensure that a IllegalStateException is thrown
-        //   if getReader() was called earlier        
-        return getServletRequest().getInputStream();
-    }
-
-    public BufferedReader getReader()
-    throws UnsupportedEncodingException, IOException 
-    {
-        checkPostedFormData();
-        // the HttpServletRequest will ensure that a IllegalStateException is thrown
-        //   if getInputStream() was called earlier
-        BufferedReader reader = getServletRequest().getReader();
-        readerAccessed = true;
-        return reader;
-
-    }
-    
-    public void setCharacterEncoding(String encoding)
-    throws UnsupportedEncodingException 
-    {
-        if (readerAccessed) 
-        {
-            throw new IllegalStateException("Cannot set character encoding "
-                    + "after HTTP body reader is accessed.");
-        }
-        getServletRequest().setCharacterEncoding(encoding);
-    }
-}
+/*
+ * 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import javax.portlet.ClientDataRequest;
+
+import org.apache.pluto.container.PortletRequestContext;
+import org.apache.pluto.container.PortletResponseContext;
+
+/**
+ * Implementation of the <code>javax.portlet.ClientDataRequest</code> interface.
+ */
+public abstract class ClientDataRequestImpl extends PortletRequestImpl implements ClientDataRequest
+{
+    /** Flag indicating if the HTTP body reader has been accessed. */
+    protected boolean readerAccessed = false;
+
+    public ClientDataRequestImpl(PortletRequestContext requestContext, PortletResponseContext responseContext, String lifecyclePhase)
+    {
+        super(requestContext, responseContext, lifecyclePhase);
+    }
+
+    private void checkPostedFormData() 
+    {
+        if (getMethod().equals("POST"))
+        {
+            String contentType = getContentType();
+            if (contentType == null || contentType.equals("application/x-www-form-urlencoded"))
+            {
+                throw new IllegalStateException("User request HTTP POST data is of type "
+                                                + "application/x-www-form-urlencoded. "
+                                                + "This data has been already processed "
+                                                + "by the portlet-container and is available "
+                                                + "as request parameters.");
+            }
+        }
+    }
+        
+    public java.lang.String getCharacterEncoding()
+    {
+        return getServletRequest().getCharacterEncoding();
+    }
+
+    public int getContentLength()
+    {
+        return getServletRequest().getContentLength();
+    }
+
+    @Override
+    public long getContentLengthLong()
+    {
+        return getServletRequest().getContentLengthLong();
+    }
+
+    public java.lang.String getContentType()
+    {
+        return getServletRequest().getContentType();
+    }
+    
+    public String getMethod()
+    {
+        return getServletRequest().getMethod();
+    }
+
+    public InputStream getPortletInputStream() throws IOException
+    {
+        checkPostedFormData();
+        // the HttpServletRequest will ensure that a IllegalStateException is thrown
+        //   if getReader() was called earlier        
+        return getServletRequest().getInputStream();
+    }
+
+    public BufferedReader getReader()
+    throws UnsupportedEncodingException, IOException 
+    {
+        checkPostedFormData();
+        // the HttpServletRequest will ensure that a IllegalStateException is thrown
+        //   if getInputStream() was called earlier
+        BufferedReader reader = getServletRequest().getReader();
+        readerAccessed = true;
+        return reader;
+
+    }
+    
+    public void setCharacterEncoding(String encoding)
+    throws UnsupportedEncodingException 
+    {
+        if (readerAccessed) 
+        {
+            throw new IllegalStateException("Cannot set character encoding "
+                    + "after HTTP body reader is accessed.");
+        }
+        getServletRequest().setCharacterEncoding(encoding);
+    }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
index ee05621..c25b437 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
@@ -181,11 +181,6 @@ public abstract class PortletRequestImpl implements PortletRequest
         return requestContext;
     }
 
-    protected PortletContext getPortletContext()
-    {
-        return requestContext.getPortletConfig().getPortletContext();
-    }
-
     protected PortletWindow getPortletWindow()
     {
         return requestContext.getPortletWindow();
@@ -262,6 +257,10 @@ public abstract class PortletRequestImpl implements PortletRequest
             }
             return ccppProfile;
         }
+        else if (name.equals("javax.portlet.debug.ServletRequest"))
+        {
+            return requestContext.getServletRequest();
+        }
         return requestContext.getAttribute(name);
     }
 
@@ -352,6 +351,12 @@ public abstract class PortletRequestImpl implements PortletRequest
         return portalContext;
     }
 
+    @Override
+    public PortletContext getPortletContext()
+    {
+        return requestContext.getPortletConfig().getPortletContext();
+    }
+
     public PortletMode getPortletMode()
     {
         return getPortletWindow().getPortletMode();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockClientDataRequest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockClientDataRequest.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockClientDataRequest.java
index 3a48052..fdfc572 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockClientDataRequest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockClientDataRequest.java
@@ -48,6 +48,11 @@ public class MockClientDataRequest extends MockPortletRequest implements ClientD
       return 0;
    }
 
+   @Override
+   public long getContentLengthLong() {
+      return 0;
+   }
+
    /* (non-Javadoc)
     * @see javax.portlet.ClientDataRequest#getContentType()
     */

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockPortletRequest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockPortletRequest.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockPortletRequest.java
index 6826522..c259aaa 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockPortletRequest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockPortletRequest.java
@@ -25,6 +25,7 @@ import java.util.Locale;
 import java.util.Map;
 
 import javax.portlet.PortalContext;
+import javax.portlet.PortletContext;
 import javax.portlet.PortletMode;
 import javax.portlet.PortletPreferences;
 import javax.portlet.PortletRequest;
@@ -176,6 +177,11 @@ public class MockPortletRequest implements PortletRequest {
       return null;
    }
 
+   @Override
+   public PortletContext getPortletContext() {
+      return null;
+   }
+
    /* (non-Javadoc)
     * @see javax.portlet.PortletRequest#getPortletSession()
     */

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/pluto-taglib/src/main/java/org/apache/pluto/tags/DefineObjectsTag286.java
----------------------------------------------------------------------
diff --git a/pluto-taglib/src/main/java/org/apache/pluto/tags/DefineObjectsTag286.java b/pluto-taglib/src/main/java/org/apache/pluto/tags/DefineObjectsTag286.java
index 8185e7c..73cd2d3 100644
--- a/pluto-taglib/src/main/java/org/apache/pluto/tags/DefineObjectsTag286.java
+++ b/pluto-taglib/src/main/java/org/apache/pluto/tags/DefineObjectsTag286.java
@@ -1,260 +1,266 @@
-/*
- * 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.tags;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.portlet.ActionRequest;
-import javax.portlet.ActionResponse;
-import javax.portlet.EventRequest;
-import javax.portlet.EventResponse;
-import javax.portlet.PortletConfig;
-import javax.portlet.PortletPreferences;
-import javax.portlet.PortletRequest;
-import javax.portlet.PortletResponse;
-import javax.portlet.PortletSession;
-import javax.portlet.RenderRequest;
-import javax.portlet.RenderResponse;
-import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
-import javax.servlet.ServletRequest;
-import javax.servlet.jsp.JspException;
-import javax.servlet.jsp.PageContext;
-import javax.servlet.jsp.tagext.TagData;
-import javax.servlet.jsp.tagext.TagExtraInfo;
-import javax.servlet.jsp.tagext.TagSupport;
-import javax.servlet.jsp.tagext.VariableInfo;
-
-/**
- * A tag handler for the <CODE>defineObjects</CODE> tag as defined in the JSR 286. 
- * Creates the following variables to be used in the JSP: 
- * <UL> 
- * <LI><CODE>{@link RenderRequest} renderRequest</CODE>, 
- * 	when included from within the <CODE>render</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link ResourceRequest} resourceRequest</CODE>, 
- *  when included from within the <CODE>serveResource</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link ActionRequest} actionRequest</CODE>, 
- *  when included from within the <CODE>processAction</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link EventRequest} eventRequest</CODE>, 
- *  when included from within the <CODE>processEvent</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link RenderResponse} renderResponse</CODE>, 
- *  when included from within the <CODE>render</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link ResourceResponse} resourceResponse</CODE>, 
- *  when included from within the <CODE>serveResource</CODE> method, <code>null</code> otherwise 
- * <LI><CODE>{@link ActionResponse} actionResponse</CODE>, 
- *  when included from within the <CODE>processAction</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link EventResponse} eventResponse</CODE>, 
- *  when included from within the <CODE>processEvent</CODE> method, <code>null</code> otherwise
- * <LI><CODE>{@link PortletConfig} portletConfig</CODE>
- * <LI><CODE>{@link PortletSession} portletSession</CODE>, providing access to the portletSession,
- *  does not create a new session, only returns an existing session
- * <LI><CODE>{@link Map<String, Object>} portletSessionScope</CODE>, providing access to the 
- *  portletSession attributes as a Map.
- * <LI><CODE>{@link PortletPreferences} portletPreferences</CODE>, providing access to 
- *  the portlet preferences
- * <LI> <CODE>{@link Map<String, String[]>} portletPreferencesValues</CODE>, providing access to the
- *  portlet preferences as a Map
- * </UL>
- * 
- * @version 2.0
- */
-public class DefineObjectsTag286 extends TagSupport {
-	
-	private static final long serialVersionUID = 286L;
-
-	/**
-	 * Helper method.
-	 * <p>
-     * Sets an pageContext attribute with <CODE>PAGE_SCOPE</CODE>.
-     * 
-     * @param attribute - the attribute object to set
-     * @param attributeName - the name of the attribute object
-     * 
-     * @return void
-     */
-	private void setAttribute(Object attribute, String attributeName){
-		if (pageContext.getAttribute(attributeName) == null){   //Set attributes only once
- 
-            pageContext.setAttribute(attributeName,
-            						 attribute,
-                                     PageContext.PAGE_SCOPE);
-        }
-	}
-	
-	/**
-     * Helper method.
-     * <p>
-     * Sets the portlet render and request attribute with 
-     * the names described in the JSR 286 - PLT 26.1 (defineObjects Tag).
-     * 
-     * @param request PortletRequest
-     * @param response PortletResponse
-     */
-    private void setPortletRequestResponseAttribute(PortletRequest request, 
-    		PortletResponse response ){
-    	
-    	String phase = (
-    			String)request.getAttribute(PortletRequest.LIFECYCLE_PHASE);
-    	
-    	//check where request and response where included from
-    	if(PortletRequest.ACTION_PHASE.equals(phase)){
-    		setAttribute(request, "actionRequest");
-    		setAttribute(response, "actionResponse");
-    	}    	
-    	else if(PortletRequest.EVENT_PHASE.equals(phase)){
-    		setAttribute(request, "eventRequest");
-    		setAttribute(response, "eventResponse");
-    	}
-    	else if(PortletRequest.RENDER_PHASE.equals(phase)){
-    		setAttribute(request, "renderRequest");
-    		setAttribute(response, "renderResponse");
-    	}    	
-    	else if(PortletRequest.RESOURCE_PHASE.equals(phase)){
-    		setAttribute(request, "resourceRequest");
-    		setAttribute(response, "resourceResponse");
-    	}
-    }
-    
-     
-	/**
-     * Processes the <CODE>defineObjects</CODE> tag.
-     * @return <CODE>SKIP_BODY</CODE>
-     */
-    public int doStartTag() throws JspException {
-    	
-    	ServletRequest servletRequest = pageContext.getRequest();
-    	
-    	PortletRequest portletRequest = 
-    		(PortletRequest) servletRequest.getAttribute(Constants.PORTLET_REQUEST);
-    	
-    	PortletResponse portletResponse = 
-    		(PortletResponse) servletRequest.getAttribute(Constants.PORTLET_RESPONSE);
-    	
-    	PortletConfig portletConfig = 
-    		(PortletConfig) servletRequest.getAttribute(Constants.PORTLET_CONFIG);
-    	
-    	PortletSession portletSession = portletRequest.getPortletSession(false);
-    	
-    	Map<String, Object> portletSessionScope = null;
-    	if(portletSession != null){
-    		portletSessionScope = (Map<String, Object>)portletSession.getAttributeMap();// getMap();
-    	}
-    	else{
-    		portletSessionScope = new HashMap<String, Object>();
-    	}
-    	
-    	PortletPreferences portletPreferences = portletRequest.getPreferences();
-    	
-    	Map<String, String[]> portletPreferencesValues = null;
-    	if(portletPreferences != null){
-    		portletPreferencesValues = portletPreferences.getMap();
-    	}
-    	else{
-    		portletPreferencesValues = new HashMap<String, String[]>();
-    	}
-    	
-    	// set attributes render and request
-    	setPortletRequestResponseAttribute(portletRequest, portletResponse);
-    	
-    	// set attribute portletConfig
-    	setAttribute(portletConfig, "portletConfig");
-    	
-    	// set attribute portletSession
-    	setAttribute(portletSession, "portletSession");
-    	
-    	//set attribute portletSession
-    	setAttribute(portletSessionScope, "portletSessionScope");
-    	
-    	// set attribute portletPreferences
-    	setAttribute(portletPreferences, "portletPreferences");
-    	
-    	// set attribute portletPreferences
-    	setAttribute(portletPreferencesValues, "portletPreferencesValues");    	
-    	
-        return SKIP_BODY;
-    }
-
-    
-    
-    /**
-     * TagExtraInfo class for DefineObjectsTag.
-     *
-     */
-    public static class TEI extends TagExtraInfo {
-
-        public VariableInfo[] getVariableInfo(TagData tagData) {
-            VariableInfo[] info = new VariableInfo[]{
-                new VariableInfo("actionRequest",
-                                 "javax.portlet.ActionRequest",
-                                 true,
-                                 VariableInfo.AT_BEGIN),            		
-                new VariableInfo("actionResponse",
-            	                 "javax.portlet.ActionResponse",
-                                 true,
-                                 VariableInfo.AT_BEGIN),
-                new VariableInfo("eventRequest",
-                                 "javax.portlet.EventRequest",
-                                 true,
-                                 VariableInfo.AT_BEGIN),
-                new VariableInfo("eventResponse",
-                                 "javax.portlet.EventResponse",
-                                 true,
-                                 VariableInfo.AT_BEGIN),              		
-            	new VariableInfo("renderRequest",
-            					 "javax.portlet.RenderRequest",
-            					 true,
-            					 VariableInfo.AT_BEGIN),
-                new VariableInfo("renderResponse",
-                   				 "javax.portlet.RenderResponse",
-                   				 true,
-                  				 VariableInfo.AT_BEGIN),
-                new VariableInfo("resourceRequest",
-                                 "javax.portlet.ResourceRequest",
-                                 true,
-                                 VariableInfo.AT_BEGIN),
-                new VariableInfo("resourceResponse",
-                                 "javax.portlet.ResourceResponse",
-                                 true,
-                                 VariableInfo.AT_BEGIN),                            
-                new VariableInfo("portletConfig",
-                                 "javax.portlet.PortletConfig",
-                                 true,
-                                 VariableInfo.AT_BEGIN),
-                new VariableInfo("portletSession",
-                                 "javax.portlet.PortletSession",
-                                 true,
-                                 VariableInfo.AT_BEGIN),
-                new VariableInfo("portletSessionScope",
-                          		 "java.util.Map",
-                          		 true,
-                           		 VariableInfo.AT_BEGIN),                                		 
-                new VariableInfo("portletPreferences",
-                                "javax.portlet.PortletPreferences",
-                                true,
-                                VariableInfo.AT_BEGIN),   
-                new VariableInfo("portletPreferencesValues",
-                                 "java.util.Map",
-                                 true,
-                                 VariableInfo.AT_BEGIN),                                
-                
-            };
-            return info;
-        }
-    }
-}
-
+/*
+ * 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.tags;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletPreferences;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletSession;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.ServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.TagSupport;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+/**
+ * A tag handler for the <CODE>defineObjects</CODE> tag as defined in the JSR 286. 
+ * Creates the following variables to be used in the JSP: 
+ * <UL> 
+ * <LI><CODE>{@link RenderRequest} renderRequest</CODE>, 
+ * 	when included from within the <CODE>render</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link ResourceRequest} resourceRequest</CODE>, 
+ *  when included from within the <CODE>serveResource</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link ActionRequest} actionRequest</CODE>, 
+ *  when included from within the <CODE>processAction</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link EventRequest} eventRequest</CODE>, 
+ *  when included from within the <CODE>processEvent</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link RenderResponse} renderResponse</CODE>, 
+ *  when included from within the <CODE>render</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link ResourceResponse} resourceResponse</CODE>, 
+ *  when included from within the <CODE>serveResource</CODE> method, <code>null</code> otherwise 
+ * <LI><CODE>{@link ActionResponse} actionResponse</CODE>, 
+ *  when included from within the <CODE>processAction</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link EventResponse} eventResponse</CODE>, 
+ *  when included from within the <CODE>processEvent</CODE> method, <code>null</code> otherwise
+ * <LI><CODE>{@link PortletConfig} portletConfig</CODE>
+ * <LI><CODE>{@link PortletSession} portletSession</CODE>, providing access to the portletSession,
+ *  does not create a new session, only returns an existing session
+ * <LI><CODE>{@link Map<String, Object>} portletSessionScope</CODE>, providing access to the 
+ *  portletSession attributes as a Map.
+ * <LI><CODE>{@link PortletPreferences} portletPreferences</CODE>, providing access to 
+ *  the portlet preferences
+ * <LI> <CODE>{@link Map<String, String[]>} portletPreferencesValues</CODE>, providing access to the
+ *  portlet preferences as a Map
+ * </UL>
+ * 
+ * @version 2.0
+ */
+public class DefineObjectsTag286 extends TagSupport {
+	
+	private static final long serialVersionUID = 286L;
+
+	/**
+	 * Helper method.
+	 * <p>
+     * Sets an pageContext attribute with <CODE>PAGE_SCOPE</CODE>.
+     * 
+     * @param attribute - the attribute object to set
+     * @param attributeName - the name of the attribute object
+     * 
+     * @return void
+     */
+	private void setAttribute(Object attribute, String attributeName){
+		if (pageContext.getAttribute(attributeName) == null){   //Set attributes only once
+ 
+            pageContext.setAttribute(attributeName,
+            						 attribute,
+                                     PageContext.PAGE_SCOPE);
+        }
+	}
+	
+	/**
+     * Helper method.
+     * <p>
+     * Sets the portlet render and request attribute with 
+     * the names described in the JSR 286 - PLT 26.1 (defineObjects Tag).
+     * 
+     * @param request PortletRequest
+     * @param response PortletResponse
+     */
+    private void setPortletRequestResponseAttribute(PortletRequest request, 
+    		PortletResponse response ){
+    	
+    	String phase = (String)request.getAttribute(PortletRequest.LIFECYCLE_PHASE);
+    	
+      setAttribute(request, "portletRequest");
+      setAttribute(response, "portletResponse");
+    	
+    	//check where request and response where included from
+    	if(PortletRequest.ACTION_PHASE.equals(phase)){
+    		setAttribute(request, "actionRequest");
+    		setAttribute(response, "actionResponse");
+    	}    	
+    	else if(PortletRequest.EVENT_PHASE.equals(phase)){
+    		setAttribute(request, "eventRequest");
+    		setAttribute(response, "eventResponse");
+    	}
+    	else if(PortletRequest.RENDER_PHASE.equals(phase)){
+    		setAttribute(request, "renderRequest");
+    		setAttribute(response, "renderResponse");
+    	}    	
+      else if(PortletRequest.HEADER_PHASE.equals(phase)){
+         setAttribute(request, "headerRequest");
+         setAttribute(response, "headerResponse");
+      }     
+    	else if(PortletRequest.RESOURCE_PHASE.equals(phase)){
+    		setAttribute(request, "resourceRequest");
+    		setAttribute(response, "resourceResponse");
+    	}
+    }
+    
+     
+	/**
+     * Processes the <CODE>defineObjects</CODE> tag.
+     * @return <CODE>SKIP_BODY</CODE>
+     */
+    public int doStartTag() throws JspException {
+    	
+    	ServletRequest servletRequest = pageContext.getRequest();
+    	
+    	PortletRequest portletRequest = 
+    		(PortletRequest) servletRequest.getAttribute(Constants.PORTLET_REQUEST);
+    	
+    	PortletResponse portletResponse = 
+    		(PortletResponse) servletRequest.getAttribute(Constants.PORTLET_RESPONSE);
+    	
+    	PortletConfig portletConfig = 
+    		(PortletConfig) servletRequest.getAttribute(Constants.PORTLET_CONFIG);
+    	
+    	PortletSession portletSession = portletRequest.getPortletSession(false);
+    	
+    	Map<String, Object> portletSessionScope = null;
+    	if(portletSession != null){
+    		portletSessionScope = (Map<String, Object>)portletSession.getAttributeMap();// getMap();
+    	}
+    	else{
+    		portletSessionScope = new HashMap<String, Object>();
+    	}
+    	
+    	PortletPreferences portletPreferences = portletRequest.getPreferences();
+    	
+    	Map<String, String[]> portletPreferencesValues = null;
+    	if(portletPreferences != null){
+    		portletPreferencesValues = portletPreferences.getMap();
+    	}
+    	else{
+    		portletPreferencesValues = new HashMap<String, String[]>();
+    	}
+    	
+    	// set attributes render and request
+    	setPortletRequestResponseAttribute(portletRequest, portletResponse);
+    	
+    	// set attribute portletConfig
+    	setAttribute(portletConfig, "portletConfig");
+    	
+    	// set attribute portletSession
+    	setAttribute(portletSession, "portletSession");
+    	
+    	//set attribute portletSession
+    	setAttribute(portletSessionScope, "portletSessionScope");
+    	
+    	// set attribute portletPreferences
+    	setAttribute(portletPreferences, "portletPreferences");
+    	
+    	// set attribute portletPreferences
+    	setAttribute(portletPreferencesValues, "portletPreferencesValues");    	
+    	
+        return SKIP_BODY;
+    }
+
+    
+    
+    /**
+     * TagExtraInfo class for DefineObjectsTag.
+     *
+     */
+    public static class TEI extends TagExtraInfo {
+
+        public VariableInfo[] getVariableInfo(TagData tagData) {
+            VariableInfo[] info = new VariableInfo[]{
+                new VariableInfo("actionRequest",
+                                 "javax.portlet.ActionRequest",
+                                 true,
+                                 VariableInfo.AT_BEGIN),            		
+                new VariableInfo("actionResponse",
+            	                 "javax.portlet.ActionResponse",
+                                 true,
+                                 VariableInfo.AT_BEGIN),
+                new VariableInfo("eventRequest",
+                                 "javax.portlet.EventRequest",
+                                 true,
+                                 VariableInfo.AT_BEGIN),
+                new VariableInfo("eventResponse",
+                                 "javax.portlet.EventResponse",
+                                 true,
+                                 VariableInfo.AT_BEGIN),              		
+            	new VariableInfo("renderRequest",
+            					 "javax.portlet.RenderRequest",
+            					 true,
+            					 VariableInfo.AT_BEGIN),
+                new VariableInfo("renderResponse",
+                   				 "javax.portlet.RenderResponse",
+                   				 true,
+                  				 VariableInfo.AT_BEGIN),
+                new VariableInfo("resourceRequest",
+                                 "javax.portlet.ResourceRequest",
+                                 true,
+                                 VariableInfo.AT_BEGIN),
+                new VariableInfo("resourceResponse",
+                                 "javax.portlet.ResourceResponse",
+                                 true,
+                                 VariableInfo.AT_BEGIN),                            
+                new VariableInfo("portletConfig",
+                                 "javax.portlet.PortletConfig",
+                                 true,
+                                 VariableInfo.AT_BEGIN),
+                new VariableInfo("portletSession",
+                                 "javax.portlet.PortletSession",
+                                 true,
+                                 VariableInfo.AT_BEGIN),
+                new VariableInfo("portletSessionScope",
+                          		 "java.util.Map",
+                          		 true,
+                           		 VariableInfo.AT_BEGIN),                                		 
+                new VariableInfo("portletPreferences",
+                                "javax.portlet.PortletPreferences",
+                                true,
+                                VariableInfo.AT_BEGIN),   
+                new VariableInfo("portletPreferencesValues",
+                                 "java.util.Map",
+                                 true,
+                                 VariableInfo.AT_BEGIN),                                
+                
+            };
+            return info;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java b/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
index 4b837a9..e51a318 100644
--- a/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
+++ b/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
@@ -140,8 +140,7 @@ public interface ClientDataRequest extends PortletRequest {
     /**
      * Returns the length, in bytes, of the request body 
      * which is made available by the input stream, or -1 if the
-     * length is not known. 
-     *
+     * length is not known.
      *
      * @return      an integer containing the length of the 
      *          request body or -1 if the length is not known
@@ -149,6 +148,24 @@ public interface ClientDataRequest extends PortletRequest {
      */
 
     public int getContentLength();
+
+
+    /**
+     * <div class="changed_added_3_0">
+     * Returns the length, in bytes, of the request body 
+     * which is made available by the input stream, or -1 if the
+     * length is not known. 
+     * </div> 
+     *
+     *
+     * @return      a <code>long</code> containing the length of the 
+     *          request body or -1 if the length is not known
+     *          
+     * @since  3.0
+     *
+     */
+
+    public long getContentLengthLong();
       
     /**
      * Returns the name of the HTTP method with which this request was made, 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/java/javax/portlet/PortletRequest.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletRequest.java b/portlet-api/src/main/java/javax/portlet/PortletRequest.java
index 001f277..780d9c3 100644
--- a/portlet-api/src/main/java/javax/portlet/PortletRequest.java
+++ b/portlet-api/src/main/java/javax/portlet/PortletRequest.java
@@ -303,7 +303,20 @@ public interface PortletRequest extends RenderState
    * @since 2.0
    */
   public static final String ACTION_SCOPE_ID = "javax.portlet.as";
-  
+
+  /**
+   * <div class="changed_added_3_0">
+   * A constant that can be used as the property name to obtain 
+   * the user agent string 
+   * through the <code>getProperty</code> and <code>getProperties</code>
+   * methods.
+   * </div>
+   * <p>
+   * The value is <code>User-Agent</code>.
+   * @since 3.0
+   */
+  public static final String USER_AGENT = "User-Agent";
+ 
   
   
  /**
@@ -480,6 +493,23 @@ public interface PortletRequest extends RenderState
 
 
   /**
+   * <div class="changed_added_3_0">
+   * Returns the <code>PortletContext</code> of the portlet application 
+   * the portlet is in.
+   * </div>
+   *
+   * @return   a <code>PortletContext</code> object, used by the 
+   *           caller to interact with its portlet container
+   *
+   * @see PortletContext
+   * @since 3.0
+   * 
+   */
+
+  public PortletContext getPortletContext ();
+
+
+  /**
    * Returns the name of the authentication scheme used for the 
    * connection between client and portal,
    * for example, <code>BASIC_AUTH</code>, <code>CLIENT_CERT_AUTH</code>, 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java b/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
index 77ead30..d5d9a99 100644
--- a/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
+++ b/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
@@ -37,7 +37,7 @@ import static java.lang.annotation.RetentionPolicy.*;
  * The listener method will be invoked before a URL of the corresponding type is
  * generated.
  * <p>
- * The annotated method must implement the <code>PortletListener</code> interface.
+ * The annotated method must implement the <code>PortletURLGenerationListener</code> interface.
  * </div>
  *    
  * @see javax.portlet.PortletURLGenerationListener

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
index 95e0deb..cddd18e 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
 import javax.portlet.ClientDataRequest;
+import javax.portlet.PortletContext;
 
 /**
  * <div class="changed_added_3_0"> The <code>ClientDataRequestWrapper</code>
@@ -117,6 +118,11 @@ public class ClientDataRequestWrapper extends PortletRequestWrapper implements C
       return ((ClientDataRequest)wrapped).getContentLength();
    }
 
+   @Override
+   public long getContentLengthLong() {
+      return ((ClientDataRequest)wrapped).getContentLengthLong();
+   }
+
    /*
     * (non-Javadoc)
     * 
@@ -126,4 +132,9 @@ public class ClientDataRequestWrapper extends PortletRequestWrapper implements C
       return ((ClientDataRequest)wrapped).getMethod();
    }
 
+   @Override
+   public PortletContext getPortletContext() {
+      return null;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/java/javax/portlet/filter/PortletRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/PortletRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/PortletRequestWrapper.java
index 57bd3d6..46fdd25 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/PortletRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/PortletRequestWrapper.java
@@ -30,6 +30,7 @@ import java.util.Locale;
 import java.util.Map;
 
 import javax.portlet.PortalContext;
+import javax.portlet.PortletContext;
 import javax.portlet.PortletMode;
 import javax.portlet.PortletPreferences;
 import javax.portlet.PortletRequest;
@@ -184,6 +185,11 @@ public class PortletRequestWrapper extends RenderStateWrapper implements Portlet
       return ((PortletRequest)wrapped).getPortalContext();
    }
 
+   @Override
+   public PortletContext getPortletContext() {
+      return ((PortletRequest)wrapped).getPortletContext();
+   }
+
    /**
     * The default behavior of this method is to call 
     * <code>getPortletMode()</code> on the wrapped request object.

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/7e04857a/portlet-api/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/overview.html b/portlet-api/src/main/javadoc/overview.html
index f76f263..1a8e986 100644
--- a/portlet-api/src/main/javadoc/overview.html
+++ b/portlet-api/src/main/javadoc/overview.html
@@ -21,6 +21,17 @@
     <div class="indexContainer-not">
     <ul>
     <li>
+    20160315:
+    Added new methods to implement 
+    <a href="https://java.net/jira/browse/PORTLETSPEC3-63">PORTLETSPEC3-63</a>
+    and
+    <a href="https://java.net/jira/browse/PORTLETSPEC3-64">PORTLETSPEC3-64</a>:
+    {@link javax.portlet.PortletRequest#USER_AGENT PortletRequest#USER_AGENT}, 
+    {@link javax.portlet.PortletRequest#getPortletContext() PortletRequest#getPortletContext()} and 
+    {@link javax.portlet.annotations.ClientDataRequest#getContentLengthLong() ClientDataRequest#getContentLengthLong()}.
+    Updated affected wrapper classes accordingly.
+    </li>
+    <li>
     20160226:
     Renamed PortletState to RenderState and MutablePortletState to MutableRenderState.
     Updated references in affected files.


[15/34] portals-pluto git commit: worked on async portlet

Posted by ms...@apache.org.
worked on async portlet


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

Branch: refs/heads/V3Prototype
Commit: f0e0b11c175fdf74555884a5baeb656987cf60d6
Parents: 4b054ad
Author: Scott Nicklous <ms...@apache.org>
Authored: Mon Mar 28 23:01:23 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Mon Mar 28 23:01:23 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java | 224 +++++++++++++++++++
 .../portals/samples/AsyncPortletResource.java   | 117 ++++++++++
 .../samples/CSSIncludingHeaderMethod.java       |   2 +-
 .../src/main/webapp/WEB-INF/jsp/asyncDialog.jsp |  72 ++++++
 .../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp |   9 +
 .../src/main/webapp/resources/css/infobox.css   |   2 +-
 6 files changed, 424 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
new file mode 100644
index 0000000..5f824a2
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -0,0 +1,224 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Named;
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletException;
+import javax.portlet.annotations.ActionMethod;
+import javax.portlet.annotations.PortletSerializable;
+import javax.portlet.annotations.RenderMethod;
+import javax.portlet.annotations.RenderStateScoped;
+
+/**
+ * Render state scoped bean. The bean is stored as a render parameter, so it
+ * needs to be portlet serializable.
+ */
+@RenderStateScoped @Named("adb")
+public class AsyncDialogBean implements PortletSerializable {
+   private static final Logger LOGGER = Logger.getLogger(AsyncDialogBean.class.getName());
+   
+   public enum OutputType {TEXT, INC, FWD, DISPATCH, AUTO}
+   
+   public static final String PARAM_MSG = "msg";
+   public static final String PARAM_DELAY = "delay";
+   public static final String PARAM_REPS = "reps";
+   public static final String PARAM_AUTO = "auto";
+   public static final String PARAM_TYPE = "type";
+   public static final String PARAM_TYPE_TXT = OutputType.TEXT.toString();
+   public static final String PARAM_TYPE_INC = OutputType.INC.toString();
+   public static final String PARAM_TYPE_FWD = OutputType.FWD.toString();
+   public static final String PARAM_TYPE_DIS = OutputType.DISPATCH.toString();
+
+   
+   private int delay;
+   private int reps;
+   private OutputType type;
+   private String msg;
+   private boolean autoDispatch;
+
+   /**
+    * This method is called by the portlet container to initialize the bean at
+    * the beginning of a request.
+    */
+   @Override
+   public void deserialize(String[] state) {
+      if (state.length == 0) {
+         delay = 1000;
+         reps = 1;
+         type = OutputType.TEXT;
+         msg = null;
+         autoDispatch = true;
+      } else {
+         delay = Integer.parseInt(state[0]);
+         reps = Integer.parseInt(state[1]);
+         type = OutputType.valueOf(state[2]);
+         msg = state[3];
+         autoDispatch = Boolean.parseBoolean(state[4]);
+      }
+      LOGGER.fine("deserialized: " + Arrays.asList(state).toString());
+   }
+
+   /**
+    * Called by the portlet container at the end of an action or event request
+    * to store the serialized data as a portlet render parameter.
+    */
+   @Override
+   public String[] serialize() {
+      String[] state = {""+delay, ""+reps, type.toString(), msg, ""+autoDispatch};
+      LOGGER.fine("serialized: " + Arrays.asList(state).toString());
+      return state;
+   }
+
+
+   /**
+    * @return the delay
+    */
+   public int getDelay() {
+      return delay;
+   }
+
+   /**
+    * @param delay the delay to set
+    */
+   public void setDelay(int delay) {
+      this.delay = delay;
+   }
+
+   /**
+    * @return the reps
+    */
+   public int getReps() {
+      return reps;
+   }
+
+   /**
+    * @param reps the reps to set
+    */
+   public void setReps(int reps) {
+      this.reps = reps;
+   }
+
+   /**
+    * @return the type
+    */
+   public OutputType getType() {
+      return type;
+   }
+
+   /**
+    * @param type the type to set
+    */
+   public void setType(OutputType type) {
+      this.type = type;
+   }
+
+   /**
+    * @return the msg
+    */
+   public String getMsg() {
+      return msg == null ? "" : msg;
+   }
+
+   /**
+    * @param msg the msg to set
+    */
+   public void setMsg(String msg) {
+      this.msg = msg;
+   }
+
+   /**
+    * @return the autoDispatch
+    */
+   public boolean isAutoDispatch() {
+      return autoDispatch;
+   }
+
+   /**
+    * @param autoDispatch the autoDispatch to set
+    */
+   public void setAutoDispatch(boolean autoDispatch) {
+      this.autoDispatch = autoDispatch;
+   }
+
+   /**
+    * Displays the dialog
+    * 
+    * @return the action form as string
+    */
+   @RenderMethod(portletNames = "AsyncPortlet", ordinal = 100, 
+         include = "/WEB-INF/jsp/asyncDialog.jsp")
+   public void getDialog() {
+   }
+
+   /**
+    * Sets values based on form input
+    */
+   @ActionMethod(portletName = "AsyncPortlet")
+   public void handleDialog(ActionRequest req, ActionResponse resp) throws PortletException, IOException {
+      
+      msg = null;
+      
+      String strType = req.getActionParameters().getValue(PARAM_TYPE);
+      if (strType != null) {
+         try {
+            type = OutputType.valueOf(strType);
+         } catch (Exception e) {
+            msg = "try again. bad type: " + strType;
+         }
+      }
+      
+      String strReps = req.getActionParameters().getValue(PARAM_REPS);
+      if (strReps != null) {
+         try {
+            reps = Integer.parseInt(strReps);
+            if (reps <= 0 || reps > 8) throw new Exception("broken");
+         } catch (Exception e) {
+            msg = "try again. bad repetitions.";
+         }
+      }
+      
+      String strDelay = req.getActionParameters().getValue(PARAM_DELAY);
+      if (strDelay != null) {
+         try {
+            delay = Integer.parseInt(strDelay);
+            if (delay < 0) throw new Exception("broken");
+         } catch (Exception e) {
+            msg = "try again. bad delay.";
+         }
+      }
+
+      String auto = req.getActionParameters().getValue(PARAM_AUTO);
+      if (auto != null) {
+         autoDispatch = true;
+      } else {
+         autoDispatch = false;
+      }
+
+      String[] state = {""+delay, ""+reps, type.toString(), msg, ""+autoDispatch};
+      LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
new file mode 100644
index 0000000..221de53
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -0,0 +1,117 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.annotations.ServeResourceMethod;
+import javax.servlet.AsyncContext;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.portals.samples.AsyncDialogBean.OutputType;
+
+/**
+ * Implements the async resource method for the async portlet.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+public class AsyncPortletResource {
+   private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
+   
+   private final static String JSP = "/WEB-INF/jsp/asyncOutput.jsp";
+
+   private class AsyncRunnable implements Runnable {
+      
+      private final AsyncContext ctx;
+      private final int delay;
+      private final OutputType type;
+      private final boolean done;
+
+      public AsyncRunnable(AsyncContext ctx, int delay, OutputType type, boolean done) {
+         this.ctx = ctx;
+         this.delay = delay;
+         this.type = type;
+         this.done = done;
+      }
+
+      @Override
+      public void run() {
+         try {
+            Thread.sleep(delay);
+
+            HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
+            HttpServletResponse hresp = (HttpServletResponse) ctx.getResponse();
+            RequestDispatcher rd;
+
+            switch (type) {
+               case TEXT:
+                  StringBuilder txt = new StringBuilder(128);
+                  txt.append("<p>AsyncRunnable:");
+                  txt.append(" dispatcher type: ").append(hreq.getDispatcherType().toString());
+                  txt.append("</p>");
+                  hresp.getWriter().write(txt.toString());
+                  if (done) {
+                     ctx.complete();
+                  }
+                  break;
+               case AUTO:
+                  ctx.dispatch();
+                  break;
+               case DISPATCH:
+                  ctx.dispatch(JSP);
+                  break;
+               case FWD:
+                  rd = hreq.getRequestDispatcher(JSP);
+                  rd.forward(hreq, hresp);
+                  if (done) {
+                     ctx.complete();
+                  }
+                  break;
+               case INC:
+                  rd = hreq.getRequestDispatcher(JSP);
+                  rd.include(hreq, hresp);
+                  if (done) {
+                     ctx.complete();
+                  }
+                  break;
+            }
+
+         } catch (Exception e) {
+            LOGGER.warning("Exception during async processing: " + e.toString());
+         }
+      }
+
+   }
+
+   @Inject
+   private AsyncDialogBean adb;
+
+   @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
+   public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException {
+      resp.getWriter().write("<p>Hello from the resource method!</p>");
+   }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/CSSIncludingHeaderMethod.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/CSSIncludingHeaderMethod.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/CSSIncludingHeaderMethod.java
index f5f56b6..5fda1b8 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/CSSIncludingHeaderMethod.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/CSSIncludingHeaderMethod.java
@@ -43,7 +43,7 @@ public class CSSIncludingHeaderMethod {
       String contextRoot = req.getContextPath();
       StringBuilder txt = new StringBuilder(128);
       txt.append("<link href='").append(contextRoot);
-      txt.append("/resources/css/styles.css' rel='stylesheet' type='text/css'>");
+      txt.append("/resources/css/infobox.css' rel='stylesheet' type='text/css'>");
       
       resp.getWriter().write(txt.toString());
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
new file mode 100644
index 0000000..9c59c35
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
@@ -0,0 +1,72 @@
+<%--
+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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://xmlns.jcp.org/portlet_3_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="static org.apache.portals.samples.AsyncDialogBean.*" %>
+
+<portlet:defineObjects />
+
+<h3>Async Portlet</h3>
+<div class='parmbox'>
+${adb.getMsg()}
+<FORM  ACTION='<portlet:actionURL/>' id='<portlet:namespace/>-setParams' method='POST' enctype='application/x-www-form-urlencoded'>
+   <table style='width:100%;'><tr><td align='left'>
+
+   Delay:
+   </td><td>
+   <input id='<portlet:namespace/>-delay' name='<%=PARAM_DELAY%>' type='text' value='${adb.getDelay() }' size='5' maxlength='5'>
+   </td><td>
+   Repetitions:
+   </td><td>
+   <input id='<portlet:namespace/>-reps' name='<%=PARAM_REPS%>' type='text' value='${adb.getReps() }' size='5' maxlength='5'>
+   </td><td>
+   <input name='<%=PARAM_AUTO%>' value='<%=PARAM_AUTO%>' type='checkbox' ${adb.isAutoDispatch() ? "checked" : "" } >recursive
+
+   </td></tr><tr><td>
+   Output type:
+   </td><td>
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_TXT%>' ${adb.getType() == "TEXT" ? "checked" : "" } >text
+   </td><td>
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_INC%>' ${adb.getType() == "INC" ? "checked" : "" } >include
+   </td><td>
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_FWD%>' ${adb.getType() == "FWD" ? "checked" : "" } >forward
+   </td><td>
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_DIS%>' ${adb.getType() == "DISPATCH" ? "checked" : "" } >dispatch
+
+   </td></tr><tr><td>
+   <INPUT id ='<portlet:namespace/>-send' VALUE='execute' TYPE='submit'>
+   </td></tr></table>
+</FORM>
+</div>
+<div class='infobox' id='<portlet:namespace/>putResourceHere'></div>
+
+
+<script>
+(function () {
+   var xhr = new XMLHttpRequest();
+   xhr.onreadystatechange=function() {
+      if (xhr.readyState==4 && xhr.status==200) {
+         document.getElementById('<portlet:namespace/>putResourceHere').innerHTML=xhr.responseText;
+      }
+   };
+   xhr.open('GET', '<portlet:resourceURL/>', true);
+   xhr.send();
+})();
+</script>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
new file mode 100644
index 0000000..fbffdb2
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -0,0 +1,9 @@
+<%@ page session="false" %>
+<%@ page isELIgnored ="false" %> 
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+
+
+<h5>Async JSP Output</h5>
+<p>Dispatch type: <%=request.getDispatcherType() %></p>
+<hr>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/f0e0b11c/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
index e38c4e9..4629532 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
+++ b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
@@ -12,7 +12,7 @@
    border-style:solid; 
    border-width:2px; 
    padding:4px; 
-   margin:3px;
+   margin:0 0 3px 0;
    overflow:auto;
    border-color:#008800; 
    background:#E0FFE0;


[12/34] portals-pluto git commit: added code to path infor portlet for extended display

Posted by ms...@apache.org.
added code to path infor portlet for extended display


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

Branch: refs/heads/V3Prototype
Commit: 70f96425712712ee199fe07a5ef28277254b2b03
Parents: ba9ee3b
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 24 16:19:59 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 24 16:19:59 2016 +0100

----------------------------------------------------------------------
 .../apache/portals/samples/PathInfoPortlet.java | 31 ++++++++++++++++++++
 1 file changed, 31 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/70f96425/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
index 2b1391c..473a943 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
@@ -22,6 +22,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.portlet.ResourceURL;
@@ -50,6 +52,7 @@ public class PathInfoPortlet {
 
       StringBuilder txt = new StringBuilder(128);
       txt.append("<h3>Path Info Portlet</h3>");
+      txt.append("<h5>Include:</h5>");
 
       ResourceURL resurl = uf.createResourceURL();
 
@@ -68,6 +71,26 @@ public class PathInfoPortlet {
       txt.append("})();\n");
       txt.append("</script>\n");
 
+      txt.append("<h5>Forward:</h5>");
+
+      resurl = uf.createResourceURL();
+      resurl.setResourceID("fwd");
+
+      txt.append("<div class='infobox' id='").append(pid).append("-puReHe'></div>\n");
+      txt.append("<script>\n");
+      txt.append("(function () {\n");
+      txt.append("   var xhr = new XMLHttpRequest();\n");
+      txt.append("   xhr.onreadystatechange=function() {\n");
+      txt.append("      if (xhr.readyState==4 && xhr.status==200) {\n");
+      txt.append("         document.getElementById('").append(pid)
+            .append("-puReHe').innerHTML=xhr.responseText;\n");
+      txt.append("      }\n");
+      txt.append("   };\n");
+      txt.append("   xhr.open(\"GET\",\"").append(resurl.toString()).append("\",true);\n");
+      txt.append("   xhr.send();\n");
+      txt.append("})();\n");
+      txt.append("</script>\n");
+
       return txt.toString();
    }
 
@@ -100,4 +123,12 @@ public class PathInfoPortlet {
 
    }
 
+   @ServeResourceMethod(portletNames = { "PathInfoPortlet" }, resourceID="fwd")
+   public void getPathInfo2(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
+
+      PortletRequestDispatcher prd = req.getPortletContext().getRequestDispatcher("/WEB-INF/jsp/pathinfo.jsp");
+      prd.forward(req, resp);
+
+   }
+
 }


[21/34] portals-pluto git commit: basic async functionality works

Posted by ms...@apache.org.
basic async functionality works


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

Branch: refs/heads/V3Prototype
Commit: c4a9c5387647a653ed0f3d258977948a6a2400bc
Parents: 3a6b398
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 31 18:26:45 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 31 18:26:45 2016 +0200

----------------------------------------------------------------------
 .../portals/samples/AsyncPortletResource.java   | 136 +++++---------
 .../src/main/resources/logging.properties       |   2 +-
 .../impl/PortletAsyncRequestWrapper.java        | 184 +++++++++++++++----
 .../PortletResourceRequestContextImpl.java      |  59 +++---
 4 files changed, 226 insertions(+), 155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c4a9c538/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 65fea26..72b681b 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -21,6 +21,7 @@ package org.apache.portals.samples;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -44,31 +45,30 @@ import org.apache.portals.samples.AsyncDialogBean.OutputType;
  * 
  */
 public class AsyncPortletResource {
-   private static final Logger LOGGER      = Logger.getLogger(AsyncPortletResource.class.getName());
-
+   private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
+   private static final boolean isDebug = LOGGER.isLoggable(Level.FINE);
+   private static final boolean isTrace = LOGGER.isLoggable(Level.FINEST);
+   
    private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
    private final static String ATTRIB_REPS = "reps";
    private final static String ATTRIB_AUTO = "auto";
-   private final static String ATTRIB_TITLE = "title";
+   public  final static String ATTRIB_TITLE = "title";
 
    private class AsyncRunnable implements Runnable {
 
       private final AsyncContext ctx;
       private final int          delay;
       private final OutputType   type;
-      private final boolean      done;
 
-      public AsyncRunnable(AsyncContext ctx, int delay, OutputType type, boolean done) {
+      public AsyncRunnable(AsyncContext ctx, int delay, OutputType type) {
          this.ctx = ctx;
          this.delay = delay;
          this.type = type;
-         this.done = done;
          
          StringBuilder txt = new StringBuilder(128);
          txt.append("Constructing runnable.");
          txt.append(" delay: ").append(delay);
          txt.append(", type: ").append(type);
-         txt.append(", done: ").append(done);
          LOGGER.fine(txt.toString());
       }
 
@@ -81,34 +81,7 @@ public class AsyncPortletResource {
             HttpServletResponse hresp = (HttpServletResponse) ctx.getResponse();
             RequestDispatcher rd;
             
-            {
-               List<String> attrNames = Collections.list(hreq.getAttributeNames());
-               StringBuilder txt = new StringBuilder(128);
-               txt.append("Runnable:");
-               txt.append("\nAttribute names: ").append(attrNames);
-               txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-               txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-               txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-               txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-               txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-               txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-               txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-               txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-               txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-               txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-               txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-               txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-               txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-               txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-               txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-               txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-               txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-               txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-               txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-               txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
-               LOGGER.fine(txt.toString());
-            }
-
+            AsyncPortletResource.trace(hreq, "Runnable: ");
             
             PortletConfig config = (PortletConfig) hreq.getAttribute("javax.portlet.config");
             String portletName = "Could not get PortletConfig";
@@ -124,11 +97,7 @@ public class AsyncPortletResource {
                txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
                txt.append("</p>");
                hresp.getWriter().write(txt.toString());
-               if (done) {
-                  ctx.complete();
-               } else {
-                  hresp.flushBuffer();
-               }
+               ctx.complete();
                break;
             case AUTO:
                StringBuilder str = new StringBuilder(128);
@@ -145,26 +114,19 @@ public class AsyncPortletResource {
                ctx.dispatch(hreq.getServletContext(), JSP);
                break;
             case FWD:
-               LOGGER.fine("Doing request dispatcher forward to JSP.");
+               LOGGER.fine("Doing request dispatcher forward to JSP: " + JSP);
                hreq.setAttribute(ATTRIB_TITLE, "Thread forwarding to JSP");
                rd = hreq.getRequestDispatcher(JSP);
                rd.forward(hreq, hresp);
-               if (done) {
-                  ctx.complete();
-               } else {
-                  hresp.flushBuffer();
-               }
+               LOGGER.fine("After request dispatcher forward to JSP.");
+               ctx.complete();
                break;
             case INC:
-               LOGGER.fine("Doing request dispatcher include of JSP.");
+               LOGGER.fine("Including JSP: " + JSP);
                hreq.setAttribute(ATTRIB_TITLE, "Thread including JSP");
                rd = hreq.getRequestDispatcher(JSP);
                rd.include(hreq, hresp);
-               if (done) {
-                  ctx.complete();
-               } else {
-                  hresp.flushBuffer();
-               }
+               ctx.complete();
                break;
             }
 
@@ -188,13 +150,9 @@ public class AsyncPortletResource {
       req.removeAttribute(ATTRIB_AUTO);
 
       Integer reps = (Integer) req.getAttribute(ATTRIB_REPS);
-      boolean done = false;
       if (reps == null) {
          reps = adb.getReps();
       }
-      if (reps <= 0) {
-         done = true;
-      }
       
       StringBuilder txt = new StringBuilder(128);
       txt.append("Resource method.");
@@ -204,12 +162,11 @@ public class AsyncPortletResource {
       txt.append(", total reps: ").append(adb.getReps());
       txt.append(", auto: ").append(adb.isAutoDispatch());
       txt.append(", auto-dispatch: ").append(auto);
-      txt.append(", done: ").append(done);
       LOGGER.fine(txt.toString());
       
       AsyncContext ctx = null;
 
-      if (!done) {
+      if (reps > 0) {
          reps--;
          req.setAttribute(ATTRIB_REPS, reps);
          
@@ -225,6 +182,7 @@ public class AsyncPortletResource {
          
          if (ctx == null) {
             // last iteration of auto-dispatch
+            LOGGER.fine("Retrieving async context for the last run.");
             try {
                ctx = req.getAsyncContext();
             } catch (Exception e) {
@@ -237,35 +195,7 @@ public class AsyncPortletResource {
          }
 
          HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
-         
-         {
-            List<String> attrNames = Collections.list(hreq.getAttributeNames());
-            StringBuilder txt2 = new StringBuilder(128);
-            txt2.append("During content generation:");
-            txt2.append("\nAttribute names: ").append(attrNames);
-            txt2.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-            txt2.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-            txt2.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-            txt2.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-            txt2.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-            txt2.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-            txt2.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-            txt2.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-            txt2.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-            txt2.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-            txt2.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-            txt2.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-            txt2.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-            txt2.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-            txt2.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-            txt2.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-            txt2.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-            txt2.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-            txt2.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-            txt2.append("\nmethod_query_string:      ").append(hreq.getQueryString());
-            LOGGER.fine(txt2.toString());
-         }
-
+         trace(hreq, "Resource method: ");
          
          // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
          PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
@@ -323,9 +253,39 @@ public class AsyncPortletResource {
             type = OutputType.AUTO;
          }
 
-         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type, (reps<=0));
+         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type);
          ctx.start(ar);
       }
+   }
+   
+   public static void trace(HttpServletRequest hreq, String src) {
+      if (isTrace) {
+         List<String> attrNames = Collections.list(hreq.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append(src);
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+         txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+         txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+         txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+         txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+         LOGGER.fine(txt.toString());
+      }
 
    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c4a9c538/PortletV3AnnotatedDemo/src/main/resources/logging.properties
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/resources/logging.properties b/PortletV3AnnotatedDemo/src/main/resources/logging.properties
index 9a479f9..ef8a5c4 100644
--- a/PortletV3AnnotatedDemo/src/main/resources/logging.properties
+++ b/PortletV3AnnotatedDemo/src/main/resources/logging.properties
@@ -34,4 +34,4 @@ org.apache.juli.FileHandler.directory = ${catalina.base}/logs
 org.apache.juli.FileHandler.prefix = PortletV3AnnotatedDemo.
 
 org.apache.pluto.level=FINE
-org.apache.portals.samples.level=FINEST
+org.apache.portals.samples.level=FINER

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c4a9c538/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
index f2f6c2b..aec96ef 100644
--- 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
@@ -19,63 +19,173 @@
 
 package org.apache.pluto.container.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
 
-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.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpSession;
+
+import org.apache.pluto.container.NamespaceMapper;
+import org.apache.pluto.container.PortletRequestContext;
+import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.PortletWindowID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author Scott Nicklous
  *
  */
-public class PortletAsyncRequestWrapper extends HttpServletRequestWrapper {
+public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper {
+   
+   /** Logger. */
+   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncRequestWrapper.class);
+   @SuppressWarnings("unused")
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   private static final boolean isTrace = LOG.isTraceEnabled();
    
-   private final PortletRequest preq;
+   
+   private final ResourceRequest preq;
+   private final PortletResourceRequestContext reqctx;
+   private final NamespaceMapper mapper;
+   private final PortletWindowID winId;
 
-   public PortletAsyncRequestWrapper(HttpServletRequest hreq, PortletRequest preq) {
-      super(hreq);
+   public PortletAsyncRequestWrapper(HttpServletRequest hreq, ResourceRequest preq, PortletResourceRequestContext reqctx) {
+      super(hreq, reqctx.getServletContext(), null, preq, true, false);
       this.preq = preq;
+      this.reqctx = reqctx;
+      this.mapper = reqctx.getContainer().getContainerServices().getNamespaceMapper();
+      this.winId = reqctx.getPortletWindow().getId();
    }
    
    
    
    @Override
    public Object getAttribute(String name) {
-      return preq.getAttribute(name);
+      boolean encoded = true;
+      Object val = getRequest().getAttribute(mapper.encode(winId, name));
+      if (val == null) {
+         val = getRequest().getAttribute(name);
+         encoded = false;
+      }
+      if (isTrace) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Getting: ");
+         txt.append(name).append(", value: ").append((val == null) ? "null" : val.toString());
+         txt.append(", encoded: ").append(encoded);
+         LOG.debug(txt.toString());
+      }
+      return val;
    }
    
    @Override
    public Enumeration<String> getAttributeNames() {
-      return preq.getAttributeNames();
+      Enumeration<String> enames = getRequest().getAttributeNames();
+      ArrayList<String> snames = new ArrayList<String>();
+      for (String name : Collections.list(enames)) {
+         String dn = mapper.decode(winId, name);
+         if (dn != null) {
+            snames.add(dn);
+         } else {
+            snames.add(name);
+         }
+      }
+      return Collections.enumeration(snames);
    }
    
    @Override
    public void setAttribute(String name, Object o) {
-      preq.setAttribute(name, o);
+      boolean encoded = false;
+      Object val = getRequest().getAttribute(mapper.encode(winId, name));
+      if (val != null) {
+         getRequest().setAttribute(mapper.encode(winId, name), o);
+         encoded = true;
+      } else {
+         getRequest().setAttribute(name, o);
+      }
+
+      if (isTrace) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Setting: ");
+         txt.append(name).append(", value: ").append((o == null) ? "null" : o.toString());
+         txt.append(", encoded: ").append(encoded);
+         LOG.debug(txt.toString());
+      }
    }
    
    @Override
    public void removeAttribute(String name) {
-      preq.removeAttribute(name);
+      boolean encoded = false;
+      Object val = getRequest().getAttribute(mapper.encode(winId, name));
+      if (val != null) {
+         getRequest().removeAttribute(mapper.encode(winId, name));
+         encoded = true;
+      } else {
+         getRequest().removeAttribute(name);
+      }
+
+      if (isTrace) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Removing: ");
+         txt.append(name);
+         txt.append(", encoded: ").append(encoded);
+         LOG.debug(txt.toString());
+      }
    }
    
    @Override
-   public RequestDispatcher getRequestDispatcher(String path) {
-      RequestDispatcher rd = super.getRequestDispatcher(path);
-      if (rd != null) {
-         return new PortletRequestDispatcherImpl(rd, false);
+   public String getServletPath() {
+      String path = ((HttpServletRequest)getRequest()).getServletPath();
+      if (isTrace) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Servlet path: ");
+         txt.append(path);
+         LOG.debug(txt.toString());
       }
-      return null;
+      return path;
    }
    
+   @Override
+   public String getPathInfo() {
+      String info = ((HttpServletRequest)getRequest()).getPathInfo();
+      if (isTrace) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Path info: ");
+         txt.append(info);
+         LOG.debug(txt.toString());
+      }
+      return info;
+   }
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+//    @Override
+//    public RequestDispatcher getRequestDispatcher(String path) {
+//       RequestDispatcher rd = super.getRequestDispatcher(path);
+//       if (rd != null) {
+//          PortletRequestDispatcherImpl prd =  new PortletRequestDispatcherImpl(rd, false);
+//          prd.setPortletRequest(preq);
+//          prd.setPortletResponse(reqctx.getResponse());
+//          return prd;
+//       }
+//       return null;
+//    }
+   
    
    
    
@@ -101,25 +211,25 @@ public class PortletAsyncRequestWrapper extends HttpServletRequestWrapper {
 //    
 // 
 // 
-//    @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();
-//    }
-// 
+   @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/c4a9c538/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 a441c29..35909c0 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
@@ -26,7 +26,6 @@ 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;
@@ -35,7 +34,6 @@ 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;
@@ -53,6 +51,7 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    
    /** Logger. */
    private static final Logger LOG = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
+   @SuppressWarnings("unused")
    private static final boolean isDebug = LOG.isDebugEnabled();
    private static final boolean isTrace = LOG.isTraceEnabled();
    
@@ -130,11 +129,11 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
        
        HttpServletRequest hreq = getServletRequest();
        HttpServletResponse hresp = getServletResponse();
-       ServletContext ctx = getServletContext();
-       HttpSession sess = getSession();
+//       ServletContext ctx = getServletContext();
+//       HttpSession sess = getSession();
        PortletConfig cfg = getPortletConfig(); 
        
-       if (isDebug) {
+       if (isTrace) {
           List<String> attrNames = Collections.list(hreq.getAttributeNames());
           StringBuilder txt = new StringBuilder(128);
           txt.append("Start async before:");
@@ -171,7 +170,8 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
 
        // Wrap http req & response. 
        
-       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request);
+       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request, this);
+//       HttpServletRequest wreq = new HttpServletPortletRequestWrapper(hreq, ctx, sess, request, true, false);
        HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
 
        // get the original container req & resp to pass to listener for resource releasing
@@ -192,31 +192,31 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
        }
 
        
-       if (isDebug) {
+       if (isTrace) {
           List<String> attrNames = Collections.list(hreq.getAttributeNames());
           StringBuilder txt = new StringBuilder(128);
-          txt.append("Start async after:");
+          txt.append("Start async after (wreq):");
           txt.append("\nAttribute names: ").append(attrNames);
-          txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-          txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-          txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-          txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-          txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-          txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-          txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-          txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-          txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-          txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-          txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-          txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-          txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-          txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-          txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-          txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-          txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-          txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-          txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-          txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+          txt.append("\nasync_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.async.request_uri"));
+          txt.append("\nasync_context_path:      ").append((String) wreq.getAttribute("javax.servlet.async.context_path"));
+          txt.append("\nasync_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.async.servlet_path"));
+          txt.append("\nasync_path_info:      ").append((String) wreq.getAttribute("javax.servlet.async.path_info"));
+          txt.append("\nasync_query_string:      ").append((String) wreq.getAttribute("javax.servlet.async.query_string"));
+          txt.append("\nforward_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.forward.request_uri"));
+          txt.append("\nforward_context_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.context_path"));
+          txt.append("\nforward_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.servlet_path"));
+          txt.append("\nforward_path_info:      ").append((String) wreq.getAttribute("javax.servlet.forward.path_info"));
+          txt.append("\nforward_query_string:      ").append((String) wreq.getAttribute("javax.servlet.forward.query_string"));
+          txt.append("\ninclude_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.include.request_uri"));
+          txt.append("\ninclude_context_path:      ").append((String) wreq.getAttribute("javax.servlet.include.context_path"));
+          txt.append("\ninclude_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.include.servlet_path"));
+          txt.append("\ninclude_path_info:      ").append((String) wreq.getAttribute("javax.servlet.include.path_info"));
+          txt.append("\ninclude_query_string:      ").append((String) wreq.getAttribute("javax.servlet.include.query_string"));
+          txt.append("\nmethod_request_uri:      ").append(wreq.getRequestURI());
+          txt.append("\nmethod_context_path:      ").append(wreq.getContextPath());
+          txt.append("\nmethod_servlet_path:      ").append(wreq.getServletPath());
+          txt.append("\nmethod_path_info:      ").append(wreq.getPathInfo());
+          txt.append("\nmethod_query_string:      ").append(wreq.getQueryString());
           LOG.debug(txt.toString());
        }
 
@@ -246,7 +246,8 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
     // For use within the wrapper. 
     // PLT.10.4.3. Proxied session is created and passed if 
     // javax.portlet.servletDefaultSessionScope == PORTLET_SCOPE
-    private HttpSession getSession() {
+    @SuppressWarnings("unused")
+   private HttpSession getSession() {
        HttpSession sess = null;
 
        PortletConfig portletConfig = getPortletConfig();


[24/34] portals-pluto git commit: Fixed bug where portlet request context was initialized with the wrong wrapped request. Introduced code to display proper dispatcher type during processing.

Posted by ms...@apache.org.
Fixed bug where portlet request context was initialized with the wrong
wrapped request. Introduced code to display proper dispatcher type during
processing.


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

Branch: refs/heads/V3Prototype
Commit: 8d98baf2d1aa903ac108653b2a022c861055096e
Parents: 78dee92
Author: Scott Nicklous <ms...@apache.org>
Authored: Sat Apr 2 21:29:41 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sat Apr 2 21:29:41 2016 +0200

----------------------------------------------------------------------
 .../pluto/container/PortletAsyncContext.java    |  2 +-
 .../pluto/container/PortletRequestContext.java  |  6 +++
 .../pluto/container/driver/PortletServlet3.java | 31 ++++++++------
 .../bean/processor/PortletInvoker.java          | 27 ++++++------
 .../impl/PortletRequestDispatcherImpl.java      |  5 +++
 .../container/PortletAsyncContextImpl.java      |  2 +-
 .../container/PortletRequestContextImpl.java    | 45 +++++++++++++++++++-
 .../PortletResourceRequestContextImpl.java      |  5 ---
 8 files changed, 91 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
index 1567767..709306e 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
@@ -4,7 +4,7 @@ import javax.servlet.AsyncContext;
 
 public interface PortletAsyncContext extends AsyncContext {
 
-   void requestComplete(PortletResourceRequestContext prctx);
+   void init(PortletResourceRequestContext prctx);
 
    /**
     * @param actx the async context to set

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/pluto-container-api/src/main/java/org/apache/pluto/container/PortletRequestContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletRequestContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletRequestContext.java
index 322e427..185f940 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletRequestContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletRequestContext.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import javax.portlet.ActionParameters;
 import javax.portlet.PortletConfig;
 import javax.portlet.RenderParameters;
+import javax.servlet.DispatcherType;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.http.Cookie;
@@ -80,4 +81,9 @@ public interface PortletRequestContext
     // for render headers support
     void setRenderHeaders(String renderHeaders);
     String getRenderHeaders();
+    
+    // for async support
+    DispatcherType getDispatcherType();
+    boolean isExecutingRequestBody();
+    void setExecutingRequestBody(boolean executingRequestBody);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/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 b936626..c831773 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
@@ -336,6 +336,7 @@ public class PortletServlet3 extends HttpServlet {
          
          // the contexts are already initialized if this is part of a resource request async sequence
          requestContext.init(portletConfig, getServletContext(), request, response);
+         requestContext.setExecutingRequestBody(true);
          responseContext.init(request, response);
       
       }
@@ -343,12 +344,8 @@ public class PortletServlet3 extends HttpServlet {
       PortletWindow window = requestContext.getPortletWindow();
 
       PortletInvocationEvent event = new PortletInvocationEvent(portletRequest, window, methodId.intValue());
-
       notify(event, true, null);
-
-      // FilterManager filtermanager = (FilterManager) request.getAttribute(
-      // "filter-manager");
-
+      
       try {
 
          // The requested method is RENDER: call Portlet.render(..)
@@ -441,15 +438,25 @@ public class PortletServlet3 extends HttpServlet {
          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)) {
+         
+         // If an async request is running or has been dispatched, resources
+         // will be released by the PortletAsyncListener. Otherwise release here.
+         
+         requestContext.setExecutingRequestBody(false);
+         if (!request.isAsyncStarted()) {
+            
+            LOG.debug("Async not started, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
+            
+            if (request.getDispatcherType() != DispatcherType.ASYNC) {
 
-            request.removeAttribute(PortletInvokerService.METHOD_ID);
-            request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
-            request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
-            request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+               request.removeAttribute(PortletInvokerService.METHOD_ID);
+               request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+               request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+               request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
 
+            }
+         } else {
+            LOG.debug("Async started, not releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
          }
       }
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/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 982cee5..7507f2c 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
@@ -54,7 +54,6 @@ import javax.xml.namespace.QName;
 import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceRequestContext;
-import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -335,20 +334,24 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
                
                LOG.debug("Async processing was started during method: " + meth.toString());
                req.setAttribute(PortletInvokerService.ASYNC_METHOD, meth);
+
+               // Initialize the async context after the request during which async is 
+               // first started.
                
-               PortletResourceRequestContext reqctx = (PortletResourceRequestContext) req.getAttribute(PortletInvokerService.REQUEST_CONTEXT);
-               if (reqctx != null) {
-                  PortletAsyncContext pac = reqctx.getPortletAsyncContext();
-                  if (pac != null) {
-                     pac.requestComplete(reqctx);
+               if (req.getDispatcherType() != DispatcherType.ASYNC) {
+                  PortletResourceRequestContext reqctx = (PortletResourceRequestContext) req
+                        .getAttribute(PortletInvokerService.REQUEST_CONTEXT);
+                  if (reqctx != null) {
+                     PortletAsyncContext pac = reqctx.getPortletAsyncContext();
+                     if (pac != null) {
+                        pac.init(reqctx);
+                     } else {
+                        LOG.warn("Couldn't get portlet async context.");
+                     }
                   } else {
-                     LOG.warn("Couldn't get portlet async context.");
+                     LOG.warn("Couldn't get request context.");
                   }
-               } else {
-                  LOG.warn("Couldn't get request context.");
-               }
-            
-               
+               }            
                
                break;
                

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
index 90c6904..29a939a 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
@@ -159,6 +159,10 @@ public class PortletRequestDispatcherImpl implements PortletRequestDispatcher, R
                                                                                       request,
                                                                                       response,
                                                                                       included);
+        
+        boolean executingReqBody = requestContext.isExecutingRequestBody();
+        requestContext.setExecutingRequestBody(false);
+        
         try
         {
             request.setAttribute(PortletInvokerService.PORTLET_CONFIG, requestContext.getPortletConfig());
@@ -192,6 +196,7 @@ public class PortletRequestDispatcherImpl implements PortletRequestDispatcher, R
             request.removeAttribute(PortletInvokerService.PORTLET_CONFIG);
             request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
             request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+            requestContext.setExecutingRequestBody(executingReqBody);
         }
     }
     

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
index 2e0288d..d638db1 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -53,7 +53,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
     * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.PortletResourceRequestContext)
     */
    @Override
-   public void requestComplete(PortletResourceRequestContext prctx) {
+   public void init(PortletResourceRequestContext prctx) {
 
       // get the original container req & resp to pass to listener for resource releasing
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRequestContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRequestContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRequestContextImpl.java
index 694b955..a059fef 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRequestContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRequestContextImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import javax.portlet.ActionParameters;
 import javax.portlet.PortletConfig;
 import javax.portlet.RenderParameters;
+import javax.servlet.DispatcherType;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.http.Cookie;
@@ -46,12 +47,18 @@ import org.apache.pluto.container.impl.ResourceParametersImpl;
 import org.apache.pluto.driver.core.PortalRequestContext;
 import org.apache.pluto.driver.url.PortalURL;
 import org.apache.pluto.driver.url.PortletParameterFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @version $Id$
  *
  */
 public class PortletRequestContextImpl implements PortletRequestContext {
+   private static final Logger LOG = LoggerFactory.getLogger(PortletRequestContextImpl.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
 
    private PortletContainer    container;
    private HttpServletRequest  containerRequest;
@@ -62,7 +69,8 @@ public class PortletRequestContextImpl implements PortletRequestContext {
    private PortletConfig       portletConfig;
    private ServletContext      servletContext;
    private Cookie              cookies[];
-   private String              renderHeaders = null;      
+   private String              renderHeaders = null; 
+   private boolean             executingRequestBody = false;
    
    // make sure these classes are loaded first by the container classloader
    // so that the logs from these classes land in the Pluto log file.
@@ -244,4 +252,39 @@ public class PortletRequestContextImpl implements PortletRequestContext {
    public ActionParameters getActionParameters() {
       return new ActionParametersImpl(urlProvider, windowId);
    }
+
+   /**
+    * Make it look like request type while the portlet request body is executing.
+    */
+   @Override
+   public DispatcherType getDispatcherType() {
+      DispatcherType type = getServletRequest().getDispatcherType();
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Dispatcher type: ").append(type);
+         txt.append(", executing request body: ").append(executingRequestBody);
+         LOG.debug(txt.toString());
+      }
+      if (executingRequestBody && (type != DispatcherType.ASYNC)) {
+         type = DispatcherType.REQUEST;
+      }
+      return type;
+   }
+
+   /**
+    * @return the executingRequestBody
+    */
+   @Override
+   public boolean isExecutingRequestBody() {
+      return executingRequestBody;
+   }
+
+   /**
+    * @param executingRequestBody the executingRequestBody to set
+    */
+   @Override
+   public void setExecutingRequestBody(boolean executingRequestBody) {
+      this.executingRequestBody = executingRequestBody;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8d98baf2/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 cadc36f..f607449 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
@@ -274,11 +274,6 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
       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


[03/34] portals-pluto git commit: Fixed documentation bugs in overview-html, ClientDataRequest.java, PortletListener.java

Posted by ms...@apache.org.
Fixed documentation bugs in overview-html, ClientDataRequest.java, PortletListener.java


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

Branch: refs/heads/V3Prototype
Commit: c19723e731d633a1c51796e361c237bcbc543464
Parents: 16cb7b3
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 10 16:31:13 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 10 16:31:13 2016 +0100

----------------------------------------------------------------------
 portlet-api/src/main/java/javax/portlet/ClientDataRequest.java    | 3 ++-
 .../src/main/java/javax/portlet/annotations/PortletListener.java  | 2 +-
 portlet-api/src/main/javadoc/overview.html                        | 2 +-
 portlet-api/src/main/javadoc/portlet-api.css                      | 1 +
 4 files changed, 5 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c19723e7/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java b/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
index e51a318..b5136ac 100644
--- a/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
+++ b/portlet-api/src/main/java/javax/portlet/ClientDataRequest.java
@@ -25,7 +25,8 @@
 package javax.portlet;
 
 /**
- * The <CODE>ClientDataRequest</CODE> represents the request information 
+ * <span class="changed_modified_3_0">The</span>
+ * <CODE>ClientDataRequest</CODE> represents the request information 
  * of the HTTP request issued from the client to the portal.<BR>
  * It extends the PortletRequest interface.
  * 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c19723e7/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java b/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
index d5d9a99..77ead30 100644
--- a/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
+++ b/portlet-api/src/main/java/javax/portlet/annotations/PortletListener.java
@@ -37,7 +37,7 @@ import static java.lang.annotation.RetentionPolicy.*;
  * The listener method will be invoked before a URL of the corresponding type is
  * generated.
  * <p>
- * The annotated method must implement the <code>PortletURLGenerationListener</code> interface.
+ * The annotated method must implement the <code>PortletListener</code> interface.
  * </div>
  *    
  * @see javax.portlet.PortletURLGenerationListener

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c19723e7/portlet-api/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/overview.html b/portlet-api/src/main/javadoc/overview.html
index 1a8e986..4c1eaf7 100644
--- a/portlet-api/src/main/javadoc/overview.html
+++ b/portlet-api/src/main/javadoc/overview.html
@@ -28,7 +28,7 @@
     <a href="https://java.net/jira/browse/PORTLETSPEC3-64">PORTLETSPEC3-64</a>:
     {@link javax.portlet.PortletRequest#USER_AGENT PortletRequest#USER_AGENT}, 
     {@link javax.portlet.PortletRequest#getPortletContext() PortletRequest#getPortletContext()} and 
-    {@link javax.portlet.annotations.ClientDataRequest#getContentLengthLong() ClientDataRequest#getContentLengthLong()}.
+    {@link javax.portlet.ClientDataRequest#getContentLengthLong() ClientDataRequest#getContentLengthLong()}.
     Updated affected wrapper classes accordingly.
     </li>
     <li>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c19723e7/portlet-api/src/main/javadoc/portlet-api.css
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/portlet-api.css b/portlet-api/src/main/javadoc/portlet-api.css
index e144058..3a84aa1 100644
--- a/portlet-api/src/main/javadoc/portlet-api.css
+++ b/portlet-api/src/main/javadoc/portlet-api.css
@@ -514,6 +514,7 @@ h1.hidden {
 .indexContainer a[href*="PortletContext.html"],
 .indexContainer a[href*="PortletPreferences.html"],
 .indexContainer a[href*="GenericPortlet.html"],
+.indexContainer a[href*="ClientDataRequest.html"],
 .indexContainer a[href*="ActionRequest.html"],
 .indexContainer a[href*="ActionResponse.html"],
 .indexContainer a[href*="PortletResponse.html"],


[23/34] portals-pluto git commit: Refactoring to make sure that the portal listener is the last listener to execute. Added code to re-initialize the portlet request context properly during the async dispatch.

Posted by ms...@apache.org.
Refactoring to make sure that the portal listener is the last listener to
execute. Added  code to re-initialize the portlet request context properly
during the async dispatch.


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

Branch: refs/heads/V3Prototype
Commit: 78dee92d5b47c84c854db7c1aba19d0e12fd1f7f
Parents: 75119d2
Author: Scott Nicklous <ms...@apache.org>
Authored: Fri Apr 1 22:11:07 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Fri Apr 1 22:11:07 2016 +0200

----------------------------------------------------------------------
 .../portals/samples/AsyncPortletResource.java   |  15 +-
 .../pluto/container/PortletAsyncContext.java    |  14 +
 .../PortletResourceRequestContext.java          |   7 +
 .../pluto/container/driver/PortletServlet3.java |  64 ++-
 .../bean/processor/PortletInvoker.java          |  19 +
 .../impl/PortletAsyncRequestWrapper.java        |  20 +-
 .../container/impl/ResourceRequestImpl.java     |   7 -
 .../container/PortletAsyncContextImpl.java      | 181 ++++++++
 .../PortletResourceRequestContextImpl.java      | 412 ++++++++++---------
 9 files changed, 528 insertions(+), 211 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 0868f58..59cc599 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -46,7 +46,6 @@ import org.apache.portals.samples.AsyncDialogBean.OutputType;
  */
 public class AsyncPortletResource {
    private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
-   private static final boolean isDebug = LOGGER.isLoggable(Level.FINE);
    private static final boolean isTrace = LOGGER.isLoggable(Level.FINEST);
    
    private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
@@ -106,12 +105,12 @@ public class AsyncPortletResource {
                str.append(", Servlet patch: ").append(hreq.getServletPath());
                LOGGER.fine(str.toString());
                hreq.setAttribute(ATTRIB_AUTO, new Boolean(true));
-               ctx.dispatch(hreq.getServletContext(), hreq.getServletPath());
+               ctx.dispatch();
                break;
             case DISPATCH:
                LOGGER.fine("Dispatching to JSP.");
                hreq.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
-               ctx.dispatch(hreq.getServletContext(), JSP);
+               ctx.dispatch(JSP);
                break;
             case FWD:
                LOGGER.fine("Doing request dispatcher forward to JSP: " + JSP);
@@ -178,8 +177,7 @@ public class AsyncPortletResource {
          
          PortletRequestDispatcher rd;
 
-         HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
-         trace(hreq, "Resource method: ");
+         trace(req, "Resource method: ");
          
          // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
          PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
@@ -192,7 +190,7 @@ public class AsyncPortletResource {
          case DISPATCH:
             LOGGER.fine("Dispatching to JSP.");
             req.setAttribute(ATTRIB_TITLE, "Resource Method dispatching to JSP");
-            ctx.dispatch(hreq.getServletContext(), JSP);
+            ctx.dispatch(JSP);
             break;
          case FWD:
             LOGGER.fine("Doing request dispatcher forward to JSP.");
@@ -243,6 +241,11 @@ public class AsyncPortletResource {
       }
    }
    
+   public static void trace(ResourceRequest req, String src) {
+      HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
+      trace(hreq, src);
+   }
+   
    public static void trace(HttpServletRequest hreq, String src) {
       if (isTrace) {
          List<String> attrNames = Collections.list(hreq.getAttributeNames());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
new file mode 100644
index 0000000..1567767
--- /dev/null
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
@@ -0,0 +1,14 @@
+package org.apache.pluto.container;
+
+import javax.servlet.AsyncContext;
+
+public interface PortletAsyncContext extends AsyncContext {
+
+   void requestComplete(PortletResourceRequestContext prctx);
+
+   /**
+    * @param actx the async context to set
+    */
+   void setWrapped(AsyncContext actx);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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 f8d50f9..20adad4 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
@@ -23,6 +23,9 @@ import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpSession;
 
 /**
  * @version $Id$
@@ -68,4 +71,8 @@ public interface PortletResourceRequestContext extends PortletRequestContext
     boolean isAsyncSupported();
     AsyncContext getAsyncContext() throws IllegalStateException;
     DispatcherType getDispatcherType();
+    HttpSession getSession();
+    AsyncContext startAsync();
+    AsyncContext startAsync(ServletRequest request, ServletResponse response);
+    PortletAsyncContext getPortletAsyncContext();
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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 7aed69d..b936626 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
@@ -39,6 +39,10 @@ import javax.servlet.DispatcherType;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletRequestWrapper;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -52,6 +56,7 @@ import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.PortletWindow;
 import org.apache.pluto.container.bean.processor.AnnotatedConfigBean;
 import org.apache.pluto.container.bean.processor.PortletInvoker;
+import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -272,10 +277,67 @@ public class PortletServlet3 extends HttpServlet {
       final FilterManager filterManager = 
             (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
 
-      if (request.getDispatcherType() != DispatcherType.ASYNC) {
+      if (LOG.isTraceEnabled()) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("\nRequest wrapper stack: ");
+         ServletRequest wreq = request;
+         ServletRequest tstreq = requestContext.getServletRequest();
+         int n = 1;
+         while (wreq instanceof ServletRequestWrapper) {
+            txt.append("\nLevel ").append(n++).append(": ").append(wreq.getClass().getCanonicalName());
+            txt.append(", dispatch type: ").append(wreq.getDispatcherType());
+            txt.append(", equal to req context req: ").append(wreq == tstreq);
+            wreq = ((ServletRequestWrapper) wreq).getRequest();
+         }
+         txt.append("\nLevel ").append(n++).append(": ").append(wreq.getClass().getCanonicalName());
+         txt.append(", dispatch type: ").append(wreq.getDispatcherType());
+         txt.append(", equal to req context req: ").append(wreq == tstreq);
+
+         txt.append("\n\nResponse wrapper stack: ");
+         ServletResponse wresp = response;
+         ServletResponse tstresp = requestContext.getServletResponse();
+         n = 1;
+         while (wresp instanceof ServletResponseWrapper) {
+            txt.append("\nLevel ").append(n++).append(": ").append(wresp.getClass().getCanonicalName());
+            txt.append(", equal to req context resp: ").append(wresp == tstresp);
+            wresp = ((ServletResponseWrapper) wresp).getResponse();
+         }
+         txt.append("\nLevel ").append(n++).append(": ").append(wresp.getClass().getCanonicalName());
+         txt.append(", equal to req context resp: ").append(wresp == tstresp);
+         LOG.debug(txt.toString());
+      }
+      
+      if (request.getDispatcherType() == DispatcherType.ASYNC) {
+         
+         // have to reinitialize the request context with the request under our wrapper.
+         
+         ServletRequest wreq = request;
+         while ((wreq instanceof ServletRequestWrapper) &&
+               !(wreq instanceof PortletAsyncRequestWrapper) ) {
+            wreq = ((ServletRequestWrapper) wreq).getRequest();
+         }
+         
+         
+         if (wreq instanceof PortletAsyncRequestWrapper) {
+            
+            HttpServletRequest hreq = (HttpServletRequest) ((PortletAsyncRequestWrapper) wreq).getRequest();
+            HttpServletResponse hresp = requestContext.getServletResponse();
+            
+            LOG.debug("Extracted wrapped request. Dispatch type: " + hreq.getDispatcherType());
+
+            requestContext.init(portletConfig, getServletContext(), hreq, hresp);
+            responseContext.init(hreq, hresp);
+            
+         } else {
+            LOG.debug("Couldn't find the portlet async wrapper.");
+         }
+         
+      } else {
+         
          // the contexts are already initialized if this is part of a resource request async sequence
          requestContext.init(portletConfig, getServletContext(), request, response);
          responseContext.init(request, response);
+      
       }
 
       PortletWindow window = requestContext.getPortletWindow();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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 fd090da..982cee5 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
@@ -51,7 +51,10 @@ import javax.portlet.annotations.ServeResourceMethod;
 import javax.servlet.DispatcherType;
 import javax.xml.namespace.QName;
 
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
+import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -275,6 +278,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
             LOG.warn(txt.toString());
             return;
          }
+         LOG.debug("Processing async dispatch. method: " + meth.toString());
          meths.add(meth);
       } else {
          meths = getMethods(mi);
@@ -331,6 +335,21 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
                
                LOG.debug("Async processing was started during method: " + meth.toString());
                req.setAttribute(PortletInvokerService.ASYNC_METHOD, meth);
+               
+               PortletResourceRequestContext reqctx = (PortletResourceRequestContext) req.getAttribute(PortletInvokerService.REQUEST_CONTEXT);
+               if (reqctx != null) {
+                  PortletAsyncContext pac = reqctx.getPortletAsyncContext();
+                  if (pac != null) {
+                     pac.requestComplete(reqctx);
+                  } else {
+                     LOG.warn("Couldn't get portlet async context.");
+                  }
+               } else {
+                  LOG.warn("Couldn't get request context.");
+               }
+            
+               
+               
                break;
                
             } else {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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
index aec96ef..353b49f 100644
--- 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
@@ -24,16 +24,12 @@ import java.util.Collections;
 import java.util.Enumeration;
 
 import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
-import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
 
 import org.apache.pluto.container.NamespaceMapper;
-import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletWindowID;
 import org.slf4j.Logger;
@@ -52,13 +48,14 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
    private static final boolean isTrace = LOG.isTraceEnabled();
    
    
+   @SuppressWarnings("unused")
    private final ResourceRequest preq;
    private final PortletResourceRequestContext reqctx;
    private final NamespaceMapper mapper;
    private final PortletWindowID winId;
 
    public PortletAsyncRequestWrapper(HttpServletRequest hreq, ResourceRequest preq, PortletResourceRequestContext reqctx) {
-      super(hreq, reqctx.getServletContext(), null, preq, true, false);
+      super(hreq, reqctx.getServletContext(), reqctx.getSession(), preq, true, false);
       this.preq = preq;
       this.reqctx = reqctx;
       this.mapper = reqctx.getContainer().getContainerServices().getNamespaceMapper();
@@ -213,22 +210,27 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
 // 
    @Override
    public AsyncContext startAsync() throws IllegalStateException {
-      return getRequest().startAsync();
+      return reqctx.startAsync();
    }
 
    @Override
    public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws IllegalStateException {
-      return getRequest().startAsync(request, response);
+      return reqctx.startAsync(request, response);
    }
 
    @Override
    public boolean isAsyncStarted() {
-      return getRequest().isAsyncStarted();
+      return reqctx.isAsyncStarted();
    }
 
    @Override
    public boolean isAsyncSupported() {
-      return getRequest().isAsyncSupported();
+      return reqctx.isAsyncSupported();
+   }
+   
+   @Override
+   public AsyncContext getAsyncContext() {
+      return reqctx.getAsyncContext();
    }
 
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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 721c5e8..fdd2145 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
@@ -20,20 +20,13 @@ import java.util.Enumeration;
 import java.util.Map;
 
 import javax.portlet.CacheControl;
-import javax.portlet.PortletConfig;
 import javax.portlet.PortletRequest;
 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.PortletInvokerService;
-import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResourceResponseContext;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
new file mode 100644
index 0000000..2e0288d
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -0,0 +1,181 @@
+/*  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 javax.servlet.AsyncContext;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletResourceRequestContext;
+
+/**
+ * Wrapper class for the AsyncContext obtained from the servlet container. Provides
+ * a couple of work-arounds for Tomcat async bugs as well as portlet-specific listener
+ * support.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+public class PortletAsyncContextImpl implements PortletAsyncContext {
+
+   private AsyncContext actx;
+   private final HttpServletRequest hreq;
+
+   public PortletAsyncContextImpl(AsyncContext actx, HttpServletRequest hreq) {
+      this.actx = actx;
+      this.hreq = hreq;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.PortletResourceRequestContext)
+    */
+   @Override
+   public void requestComplete(PortletResourceRequestContext prctx) {
+
+      // get the original container req & resp to pass to listener for resource releasing
+
+      HttpServletRequest creq = prctx.getContainerRequest();
+      HttpServletResponse cresp = prctx.getContainerResponse();
+
+      PortletAsyncListener pal = new PortletAsyncListener();
+      actx.addListener(pal, creq, cresp);
+   }
+   
+   /* (non-Javadoc)
+    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#setWrapped(javax.servlet.AsyncContext)
+    */
+   @Override
+   public void setWrapped(AsyncContext actx) {
+      this.actx = actx;
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener)
+    */
+   @Override
+   public void addListener(AsyncListener l) {
+      actx.addListener(l);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+    */
+   @Override
+   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
+      actx.addListener(l, req, resp);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#complete()
+    */
+   @Override
+   public void complete() {
+      actx.complete();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#createListener(java.lang.Class)
+    */
+   @Override
+   public <T extends AsyncListener> T createListener(Class<T> cls) throws ServletException {
+      return actx.createListener(cls);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch()
+    */
+   @Override
+   public void dispatch() {
+      // workaround for Tomcat bug 59213
+      actx.dispatch(hreq.getServletContext(), hreq.getServletPath());
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch(java.lang.String)
+    */
+   @Override
+   public void dispatch(String path) {
+      // workaround for Tomcat bug 59213
+      actx.dispatch(hreq.getServletContext(), path);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch(javax.servlet.ServletContext, java.lang.String)
+    */
+   @Override
+   public void dispatch(ServletContext sctx, String path) {
+      actx.dispatch(sctx, path);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getRequest()
+    */
+   @Override
+   public ServletRequest getRequest() {
+      return actx.getRequest();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getResponse()
+    */
+   @Override
+   public ServletResponse getResponse() {
+      return actx.getResponse();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getTimeout()
+    */
+   @Override
+   public long getTimeout() {
+      return actx.getTimeout();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#hasOriginalRequestAndResponse()
+    */
+   @Override
+   public boolean hasOriginalRequestAndResponse() {
+      return actx.hasOriginalRequestAndResponse();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#setTimeout(long)
+    */
+   @Override
+   public void setTimeout(long time) {
+      actx.setTimeout(time);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#start(java.lang.Runnable)
+    */
+   @Override
+   public void start(Runnable run) {
+      actx.start(run);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/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 35909c0..cadc36f 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
@@ -26,10 +26,13 @@ import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceRequestContext;
@@ -43,62 +46,61 @@ import org.slf4j.LoggerFactory;
 
 /**
  * @version $Id$
- *
+ * 
  */
 public class PortletResourceRequestContextImpl extends PortletRequestContextImpl implements
-                PortletResourceRequestContext
-{
-   
+      PortletResourceRequestContext {
+
    /** Logger. */
-   private static final Logger LOG = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
+   private static final Logger  LOG     = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
    @SuppressWarnings("unused")
    private static final boolean isDebug = LOG.isDebugEnabled();
    private static final boolean isTrace = LOG.isTraceEnabled();
+
+   private String               pageState;
+   private ResourceResponse     response;
+   private PortletAsyncContextImpl  actx;
+
+   public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+         HttpServletResponse containerResponse, PortletWindow window, String pageState) {
+      // if pageState != null, we're dealing with a Partial Action request, so
+      // the servlet parameters are not to be used. Otherwise, resource params could be
+      // passed as servlet parameters.
+      super(container, containerRequest, containerResponse, window, (pageState == null));
+      this.pageState = pageState;
+   }
    
-   
-   private String pageState;
-   private ResourceResponse response;
-   private AsyncContext actx = null;
-   
-   
-    public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                             HttpServletResponse containerResponse, PortletWindow window,
-                                             String pageState)
-    {
-       // if pageState != null, we're dealing with a Partial Action request, so 
-       // the servlet parameters are not to be used. Otherwise, resource params could be
-       // passed as servlet parameters.
-        super(container, containerRequest, containerResponse, window, (pageState==null));
-        this.pageState = pageState;
-    }
-
-    @Override
-    public String getCacheability()
-    {
-        return getPortalURL().getCacheability();
-    }
-
-    @Override
-    public Map<String, String[]> getPrivateRenderParameterMap()
-    {
-        return paramFactory.getResourceRenderParameterMap(window.getId().getStringId());
-    }
-
-    @Override
-    public String getResourceID()
-    {
-        return getPortalURL().getResourceID();
-    }
-
-   /* (non-Javadoc)
+   @Override
+   public PortletAsyncContext getPortletAsyncContext() {
+      return actx;
+   }
+
+   @Override
+   public String getCacheability() {
+      return getPortalURL().getCacheability();
+   }
+
+   @Override
+   public Map<String, String[]> getPrivateRenderParameterMap() {
+      return paramFactory.getResourceRenderParameterMap(window.getId().getStringId());
+   }
+
+   @Override
+   public String getResourceID() {
+      return getPortalURL().getResourceID();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
     * @see org.apache.pluto.container.PortletResourceRequestContext#getPageState()
     */
-    @Override
+   @Override
    public String getPageState() {
       return pageState;
    }
 
-    @Override
+   @Override
    public ResourceParameters getResourceParameters() {
       return new ResourceParametersImpl(urlProvider, windowId);
    }
@@ -106,159 +108,193 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    /**
     * @return the response
     */
-    @Override
+   @Override
    public ResourceResponse getResponse() {
       return response;
    }
 
    /**
-    * @param response the response to set
+    * @param response
+    *           the response to set
     */
-    @Override
+   @Override
    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(); 
-       
-       if (isTrace) {
-          List<String> attrNames = Collections.list(hreq.getAttributeNames());
-          StringBuilder txt = new StringBuilder(128);
-          txt.append("Start async before:");
-          txt.append("\nAttribute names: ").append(attrNames);
-          txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-          txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-          txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-          txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-          txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-          txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-          txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-          txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-          txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-          txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-          txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-          txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-          txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-          txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-          txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-          txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-          txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-          txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-          txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-          txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
-          LOG.debug(txt.toString());
-       }
-
-
-       // 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, request, this);
-//       HttpServletRequest wreq = new HttpServletPortletRequestWrapper(hreq, ctx, sess, request, true, false);
-       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();
-
-       // Start async, add listener to release resources upon async complete only once.
-       
-       if (actx == null) {
-          actx = hreq.startAsync(wreq, wresp);
-//          actx = hreq.startAsync(hreq, hresp);
-          PortletAsyncListener pal = new PortletAsyncListener();
-          actx.addListener(pal, creq, cresp);
-       } else {
-//          actx = hreq.startAsync(hreq, hresp);
-          actx = hreq.startAsync(wreq, wresp);
-       }
-
-       
-       if (isTrace) {
-          List<String> attrNames = Collections.list(hreq.getAttributeNames());
-          StringBuilder txt = new StringBuilder(128);
-          txt.append("Start async after (wreq):");
-          txt.append("\nAttribute names: ").append(attrNames);
-          txt.append("\nasync_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.async.request_uri"));
-          txt.append("\nasync_context_path:      ").append((String) wreq.getAttribute("javax.servlet.async.context_path"));
-          txt.append("\nasync_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.async.servlet_path"));
-          txt.append("\nasync_path_info:      ").append((String) wreq.getAttribute("javax.servlet.async.path_info"));
-          txt.append("\nasync_query_string:      ").append((String) wreq.getAttribute("javax.servlet.async.query_string"));
-          txt.append("\nforward_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.forward.request_uri"));
-          txt.append("\nforward_context_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.context_path"));
-          txt.append("\nforward_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.servlet_path"));
-          txt.append("\nforward_path_info:      ").append((String) wreq.getAttribute("javax.servlet.forward.path_info"));
-          txt.append("\nforward_query_string:      ").append((String) wreq.getAttribute("javax.servlet.forward.query_string"));
-          txt.append("\ninclude_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.include.request_uri"));
-          txt.append("\ninclude_context_path:      ").append((String) wreq.getAttribute("javax.servlet.include.context_path"));
-          txt.append("\ninclude_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.include.servlet_path"));
-          txt.append("\ninclude_path_info:      ").append((String) wreq.getAttribute("javax.servlet.include.path_info"));
-          txt.append("\ninclude_query_string:      ").append((String) wreq.getAttribute("javax.servlet.include.query_string"));
-          txt.append("\nmethod_request_uri:      ").append(wreq.getRequestURI());
-          txt.append("\nmethod_context_path:      ").append(wreq.getContextPath());
-          txt.append("\nmethod_servlet_path:      ").append(wreq.getServletPath());
-          txt.append("\nmethod_path_info:      ").append(wreq.getPathInfo());
-          txt.append("\nmethod_query_string:      ").append(wreq.getQueryString());
-          LOG.debug(txt.toString());
-       }
-
-       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
-    @SuppressWarnings("unused")
-   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;
-    }
+   @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();
+      PortletConfig cfg = getPortletConfig();
+
+      if (isTrace) {
+         List<String> attrNames = Collections.list(hreq.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Start async before:");
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+         txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+         txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+         txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+         txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+         LOG.debug(txt.toString());
+      }
+
+      // 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, request, this);
+      HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
+
+      // Start async, add listener to release resources upon async complete only once.
+
+      actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), wreq);
+
+      if (isTrace) {
+         List<String> attrNames = Collections.list(hreq.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Start async after (wreq):");
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) wreq.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) wreq.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) wreq.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_request_uri:      ").append(wreq.getRequestURI());
+         txt.append("\nmethod_context_path:      ").append(wreq.getContextPath());
+         txt.append("\nmethod_servlet_path:      ").append(wreq.getServletPath());
+         txt.append("\nmethod_path_info:      ").append(wreq.getPathInfo());
+         txt.append("\nmethod_query_string:      ").append(wreq.getQueryString());
+         LOG.debug(txt.toString());
+      }
+
+      return actx;
+   }
+
+   // For wrapper use
+   @Override
+   public AsyncContext startAsync() {
+      AsyncContext ac = getServletRequest().startAsync();
+      if (actx == null) {
+         // this should not happen, the wrapper is created during the resource request
+         LOG.error("====>>> Wrapper invocation invalid before resource async started.");
+      } else {
+         actx.setWrapped(ac);
+      }
+      return actx;
+   }
+
+   // for wrapper use
+   @Override
+   public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
+      AsyncContext ac = getServletRequest().startAsync(request, response);
+      if (actx == null) {
+         // this should not happen, the wrapper is created during the resource request
+         LOG.error("====>>> Wrapper invocation invalid before resource async started.");
+      } else {
+         actx.setWrapped(ac);
+      }
+      return actx;
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return getServletRequest().isAsyncStarted();
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return getServletRequest().isAsyncSupported();
+   }
+
+   @Override
+   public AsyncContext getAsyncContext() {
+      if (actx != null) {
+         return actx;
+      }
+      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
+   @Override
+   public 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;
+   }
 }


[14/34] portals-pluto git commit: Completed initial implementation of resource phase async support

Posted by ms...@apache.org.
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 <ms...@apache.org>
Authored: Fri Mar 25 15:35:05 2016 +0100
Committer: Scott Nicklous <ms...@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);


[09/34] portals-pluto git commit: worked on Resource phase async implementation

Posted by ms...@apache.org.
worked on Resource phase async implementation


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

Branch: refs/heads/V3Prototype
Commit: 60c741fb133d61551c3a2de9c1b74b9751734c4c
Parents: ae198fe
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Mar 23 16:25:50 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Mar 23 16:25:50 2016 +0100

----------------------------------------------------------------------
 .../PortletResourceRequestContext.java          | 13 +++++++++
 .../container/impl/PortletContainerImpl.java    |  1 +
 .../container/impl/ResourceRequestImpl.java     | 30 +++++++++++++-------
 .../PortletResourceRequestContextImpl.java      | 24 ++++++++++++++++
 4 files changed, 57 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/60c741fb/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 bf69dac..242d8a6 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,6 +19,7 @@ package org.apache.pluto.container;
 import java.util.Map;
 
 import javax.portlet.ResourceParameters;
+import javax.portlet.ResourceResponse;
 
 /**
  * @version $Id$
@@ -41,4 +42,16 @@ public interface PortletResourceRequestContext extends PortletRequestContext
      * @return
      */
     ResourceParameters getResourceParameters();
+    
+    /**
+     * Returns the resource response needed for async support. V3 method.
+     * @return
+     */
+    ResourceResponse getResponse();
+    
+    /**
+     * Sets the resource response needed for async support. V3 method.
+     * @return
+     */
+    void setResponse(ResourceResponse response);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/60c741fb/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
index 44f2035..ce60f2e 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
@@ -265,6 +265,7 @@ public class PortletContainerImpl implements PortletContainer
         responseContext.setPropsAllowed(true);
         ResourceRequest portletRequest = envService.createResourceRequest(requestContext, responseContext);
         ResourceResponse portletResponse = envService.createResourceResponse(responseContext, requestContext.getCacheability());
+        requestContext.setResponse(portletResponse);     // for async support
 
         FilterManager filterManager = filterInitialisation(portletWindow,PortletRequest.RESOURCE_PHASE);
         

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/60c741fb/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 96aa81e..aafbbee 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
@@ -38,17 +38,24 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    /** Internal logger. */
    private static final Logger LOG = LoggerFactory.getLogger(ResourceRequestImpl.class);
 
-    private PortletResourceRequestContext requestContext;
     private CacheControl cacheControl;
     
     public ResourceRequestImpl(PortletResourceRequestContext requestContext, PortletResourceResponseContext responseContext)
     {
         super(requestContext, responseContext, PortletRequest.RESOURCE_PHASE);
-        this.requestContext = requestContext;
         this.cacheControl = responseContext.getCacheControl();
     }
     
     @Override
+    protected PortletResourceRequestContext getRequestContext() {
+       return (PortletResourceRequestContext) requestContext;
+    }
+    
+    protected PortletResourceResponseContext getResponseContext() {
+       return (PortletResourceResponseContext) responseContext;
+    }
+    
+    @Override
     public String getProperty(String name)
     {
         String result = getMimeRequestProperty(name, cacheControl);
@@ -57,7 +64,7 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
 
     public String getCacheability()
     {
-        return requestContext.getCacheability();
+        return getRequestContext().getCacheability();
     }
 
     public String getETag()
@@ -67,12 +74,12 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
 
     public Map<String, String[]> getPrivateRenderParameterMap()
     {
-        return cloneParameterMap(requestContext.getPrivateRenderParameterMap());
+        return cloneParameterMap(getRequestContext().getPrivateRenderParameterMap());
     }
 
     public String getResourceID()
 	{
-		return requestContext.getResourceID();
+		return getRequestContext().getResourceID();
 	}
 
     public String getResponseContentType()
@@ -108,12 +115,13 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    }
 
    public ResourceParameters getResourceParameters() {
-      return requestContext.getResourceParameters();
+      return getRequestContext().getResourceParameters();
    }
 
    @Override
    public AsyncContext startAsync() throws IllegalStateException {
-      return null;
+      ResourceResponse resp = getRequestContext().getResponse();
+      return startAsync(this, resp);
    }
 
    @Override
@@ -123,21 +131,21 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
 
    @Override
    public boolean isAsyncStarted() {
-      return false;
+      return getRequestContext().getServletRequest().isAsyncStarted();
    }
 
    @Override
    public boolean isAsyncSupported() {
-      return false;
+      return getRequestContext().getServletRequest().isAsyncSupported();
    }
 
    @Override
    public AsyncContext getAsyncContext() {
-      return null;
+      return getRequestContext().getServletRequest().getAsyncContext();
    }
 
    @Override
    public DispatcherType getDispatcherType() {
-      return null;
+      return getRequestContext().getServletRequest().getDispatcherType();
    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/60c741fb/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 b008e51..1a6bf5e 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
@@ -19,6 +19,7 @@ package org.apache.pluto.driver.services.container;
 import java.util.Map;
 
 import javax.portlet.ResourceParameters;
+import javax.portlet.ResourceResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -35,6 +36,8 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
                 PortletResourceRequestContext
 {
    private String pageState;
+   private ResourceResponse response;
+   
    
     public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
                                              HttpServletResponse containerResponse, PortletWindow window,
@@ -47,16 +50,19 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
         this.pageState = pageState;
     }
 
+    @Override
     public String getCacheability()
     {
         return getPortalURL().getCacheability();
     }
 
+    @Override
     public Map<String, String[]> getPrivateRenderParameterMap()
     {
         return paramFactory.getResourceRenderParameterMap(window.getId().getStringId());
     }
 
+    @Override
     public String getResourceID()
     {
         return getPortalURL().getResourceID();
@@ -65,11 +71,29 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    /* (non-Javadoc)
     * @see org.apache.pluto.container.PortletResourceRequestContext#getPageState()
     */
+    @Override
    public String getPageState() {
       return pageState;
    }
 
+    @Override
    public ResourceParameters getResourceParameters() {
       return new ResourceParametersImpl(urlProvider, windowId);
    }
+
+   /**
+    * @return the response
+    */
+    @Override
+   public ResourceResponse getResponse() {
+      return response;
+   }
+
+   /**
+    * @param response the response to set
+    */
+    @Override
+   public void setResponse(ResourceResponse response) {
+      this.response = response;
+   }
 }


[06/34] portals-pluto git commit: Activated async mode in portal driver servlet. activated async mode for the servlets representing portlets that are configured for async"

Posted by ms...@apache.org.
Activated async mode in portal driver servlet. activated async mode for
the servlets representing portlets that are configured for async"


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

Branch: refs/heads/V3Prototype
Commit: 45fb2a6ff36870ff752386522a7d6ff0909a5663
Parents: 914a968
Author: Scott Nicklous <ms...@apache.org>
Authored: Sun Mar 20 21:39:52 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sun Mar 20 21:39:52 2016 +0100

----------------------------------------------------------------------
 .../org/apache/portals/samples/PathDisplay.java |  5 +
 .../apache/portals/samples/PathInfoPortlet.java | 97 ++++++++++++++------
 .../src/main/webapp/WEB-INF/jsp/pathinfo.jsp    |  2 +-
 .../driver/PortletContainerInitializer.java     |  1 +
 .../container/impl/PortletRequestImpl.java      |  8 ++
 pluto-portal/src/main/webapp/WEB-INF/web.xml    |  3 +
 6 files changed, 89 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
index dbf1cf4..ae0f61f 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathDisplay.java
@@ -53,6 +53,7 @@ public class PathDisplay {
    
    private String type;
    private String caller;
+   private boolean isAsyncSupported = false;
 
    public PathDisplay(HttpServletRequest req, String caller) {
       this.caller = caller;
@@ -82,6 +83,7 @@ public class PathDisplay {
       method_query_string = req.getQueryString();
       
       type = req.getDispatcherType().name();
+      isAsyncSupported = req.isAsyncSupported();
 }
 
    public PathDisplay(PortletRequest req, String caller) {
@@ -137,6 +139,9 @@ public class PathDisplay {
          txt.append("</tr><tr>");
          txt.append("<td>async_query_string:</td><td>").append(async_query_string).append("</td>\n");
       }
+      txt.append("</tr><tr>");
+      txt.append("<td>isAsyncSupported:</td><td>").append(isAsyncSupported).append("</td>\n");
+
       txt.append("</tr><tr><td style='padding-top:8px;'/></tr><tr>");
 
       if ((forward_request_uri == null) && (forward_context_path == null) && (forward_servlet_path == null)

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
index 1f42b14..aa87980 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
@@ -16,20 +16,25 @@
  *  under the License.
  */
 
-
 package org.apache.portals.samples;
 
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
 import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
 import javax.portlet.ResourceURL;
 import javax.portlet.annotations.Namespace;
 import javax.portlet.annotations.RenderMethod;
 import javax.portlet.annotations.ServeResourceMethod;
 import javax.portlet.annotations.URLFactory;
+import javax.servlet.AsyncContext;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
-
+import javax.servlet.http.HttpServletResponse;
 
 /**
  * Resource portlet for viewing path information.
@@ -37,26 +42,30 @@ import javax.servlet.http.HttpServletRequest;
 public class PathInfoPortlet {
 
    public static final String RESPARAM_DISPLAY = "display";
-   
+
    // Injecting the namespace & URLFactory
-   @Inject @Namespace private String pid;
-   @Inject private            URLFactory uf;
+   @Inject
+   @Namespace
+   private String             pid;
+   @Inject
+   private URLFactory         uf;
 
-   @RenderMethod(portletNames = {"PathInfoPortlet"}, ordinal=100)
+   @RenderMethod(portletNames = { "PathInfoPortlet" }, ordinal = 100)
    public String getImageInclude() {
-      
+
       StringBuilder txt = new StringBuilder(128);
       txt.append("<h3>Path Info Portlet</h3>");
-      
+
       ResourceURL resurl = uf.createResourceURL();
-      
+
       txt.append("<div class='infobox' id='").append(pid).append("-putResourceHere'></div>\n");
       txt.append("<script>\n");
       txt.append("(function () {\n");
       txt.append("   var xhr = new XMLHttpRequest();\n");
       txt.append("   xhr.onreadystatechange=function() {\n");
       txt.append("      if (xhr.readyState==4 && xhr.status==200) {\n");
-      txt.append("         document.getElementById('").append(pid).append("-putResourceHere').innerHTML=xhr.responseText;\n");
+      txt.append("         document.getElementById('").append(pid)
+            .append("-putResourceHere').innerHTML=xhr.responseText;\n");
       txt.append("      }\n");
       txt.append("   };\n");
       txt.append("   xhr.open(\"GET\",\"").append(resurl.toString()).append("\",true);\n");
@@ -66,34 +75,70 @@ public class PathInfoPortlet {
 
       return txt.toString();
    }
-   
-   @Inject private ResourceRequest resReq;
-   
+
    /**
-    *  This resource method generates some output directly, then includes output
-    *  from a JSP as specified in the annotation.
-    *  
-    * @return  The string for inclusion in the output.
+    * This resource method generates some output directly, then includes output
+    * from a JSP as specified in the annotation.
+    * 
+    * @return The string for inclusion in the output.
+    * @throws IOException
     */
-   @ServeResourceMethod(portletNames={"PathInfoPortlet"}, include="/WEB-INF/jsp/pathinfo.jsp")
-   public void getPathInfo() {
-      
+   @ServeResourceMethod(portletNames = { "PathInfoPortlet" }, asyncSupported = true)
+   public void getPathInfo(ResourceRequest req, ResourceResponse resp) throws IOException {
+
       @SuppressWarnings("unchecked")
-      ArrayList<String> pathInfo = (ArrayList<String>) resReq.getAttribute("pathInfo");
+      ArrayList<String> pathInfo = (ArrayList<String>) req.getAttribute("pathInfo");
       if (pathInfo == null) {
          pathInfo = new ArrayList<String>();
       }
-      
-      HttpServletRequest hreq = (HttpServletRequest) resReq.getAttribute("javax.portlet.debug.ServletRequest");
+
+      HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
+      HttpServletResponse hresp = (HttpServletResponse) req.getAttribute("javax.portlet.debug.ServletResponse");
       PathDisplay pd;
       if (hreq != null) {
          pd = new PathDisplay(hreq, "Resource Method (Servlet)");
       } else {
-         pd = new PathDisplay(resReq, "Resource Method (Resource)");
+         pd = new PathDisplay(req, "Resource Method (Resource)");
       }
       pathInfo.add(pd.toMarkup());
-      
-      resReq.setAttribute("pathInfo", pathInfo);
+
+      req.setAttribute("pathInfo", pathInfo);
+
+      PrintWriter writer = resp.getWriter();
+      writer.append("<h5>Async Hack Resource Request</h5>");
+      writer.append("<p>");
+      writer.append("Trying to start async. Servlet context = ").append(hreq.getServletContext().getContextPath())
+            .append(". ");
+      resp.flushBuffer();
+
+      RequestDispatcher rd = null;
+      String jsp = "/WEB-INF/jsp/pathinfo.jsp";
+      rd = hreq.getRequestDispatcher(jsp);
+      if (hreq != null && hresp != null) {
+         try {
+            AsyncContext context = hreq.startAsync(hreq, hresp);
+            context.setTimeout(3000);
+            writer = context.getResponse().getWriter();
+            writer.append("worked. Async context: ").append((context == null) ? "null." : "not null.");
+            writer.append(" Now dispatching ... ");
+            resp.flushBuffer();
+            context.dispatch(jsp);
+            writer.append(" done. ");
+         } catch (Exception e) {
+            writer.append(" ... didn't work. Exception: ").append(e.toString());
+            resp.flushBuffer();
+         }
+      }
+
+      writer.append("</p><hr>");
+      resp.flushBuffer();
+      try {
+         writer.append("<p>Now doing request dispatcher include.</p>");
+         rd.include(hreq, hresp);
+      } catch (ServletException e) {
+         writer.append("<p>Exception including jsp. ").append(e.toString());
+         writer.append("</p>");
+      }
 
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
index 099b153..b5d8e1a 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/pathinfo.jsp
@@ -4,7 +4,7 @@
 <%@ page import="org.apache.portals.samples.*" %>
 <%@ page import="java.util.*" %>
 
-<portlet:defineObjects />
+<!--   portlet:defineObjects /  -->
 
 <p>Message from included JSP.</p>
 <%

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContainerInitializer.java
----------------------------------------------------------------------
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContainerInitializer.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContainerInitializer.java
index 7b5e8fc..0fb20a6 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContainerInitializer.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContainerInitializer.java
@@ -160,6 +160,7 @@ public class PortletContainerInitializer implements ServletContainerInitializer
                ServletRegistration.Dynamic sr = ctx.addServlet(servletName, PortletServlet3.class);
                sr.addMapping(mapping);
                sr.setInitParameter(PortletServlet3.PORTLET_NAME, pn);
+               sr.setAsyncSupported(pd.isAsyncSupported());
                sr.setLoadOnStartup(100);
 
             }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
index c25b437..af3dbb4 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestImpl.java
@@ -261,6 +261,14 @@ public abstract class PortletRequestImpl implements PortletRequest
         {
             return requestContext.getServletRequest();
         }
+        else if (name.equals("javax.portlet.debug.ServletResponse"))
+        {
+            return requestContext.getServletResponse();
+        }
+        else if (name.equals("javax.portlet.debug.ServletContext"))
+        {
+            return requestContext.getServletContext();
+        }
         return requestContext.getAttribute(name);
     }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/45fb2a6f/pluto-portal/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/pluto-portal/src/main/webapp/WEB-INF/web.xml b/pluto-portal/src/main/webapp/WEB-INF/web.xml
index 60fdba0..283560b 100644
--- a/pluto-portal/src/main/webapp/WEB-INF/web.xml
+++ b/pluto-portal/src/main/webapp/WEB-INF/web.xml
@@ -34,6 +34,7 @@ limitations under the License.
   <filter>
     <filter-name>plutoPortalDriver</filter-name>
     <filter-class>org.apache.pluto.driver.PortalDriverFilter</filter-class>
+    <async-supported>true</async-supported>
   </filter>
 
   <filter-mapping>
@@ -55,6 +56,7 @@ limitations under the License.
     <display-name>Pluto Portal Driver</display-name>
     <servlet-name>plutoPortalDriver</servlet-name>
     <servlet-class>org.apache.pluto.driver.PortalDriverServlet</servlet-class>
+    <async-supported>true</async-supported>
   </servlet>
 
   <servlet>
@@ -62,6 +64,7 @@ limitations under the License.
     <display-name>Pluto Portal Driver</display-name>
     <servlet-name>plutoPortalDriverLogout</servlet-name>
     <servlet-class>org.apache.pluto.driver.PortalDriverLogoutServlet</servlet-class>
+    <async-supported>true</async-supported>
   </servlet>
 
   <servlet>


[26/34] portals-pluto git commit: Changed FilterChain to instantiate filters through the bean manager when possible in order to enable contextual support in filters. Extended the PortletAsyncFilter to use dependency injection. Structured the PortletServl

Posted by ms...@apache.org.
Changed FilterChain to instantiate filters through the bean manager when
possible in order to enable contextual support in filters. Extended the
PortletAsyncFilter to use dependency injection. Structured the
PortletServlet3 code to minimize dependency on CDI 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/5c26ec41
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/5c26ec41
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/5c26ec41

Branch: refs/heads/V3Prototype
Commit: 5c26ec41ce72d9fbcfb542d4fb9215663d76e377
Parents: 0ff1c51
Author: Scott Nicklous <ms...@apache.org>
Authored: Sun Apr 3 18:44:35 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sun Apr 3 18:44:35 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java | 32 ++++++++-
 .../portals/samples/AsyncPortletFilter.java     | 21 +++++-
 .../src/main/webapp/WEB-INF/jsp/asyncDialog.jsp | 12 ++--
 .../src/main/webapp/resources/css/infobox.css   | 14 +++-
 .../apache/pluto/container/FilterManager.java   |  6 ++
 .../pluto/container/driver/PortletServlet3.java |  9 ++-
 .../services/container/FilterChainImpl.java     | 72 +++++++++++++++++---
 .../services/container/FilterManagerImpl.java   | 15 ++++
 8 files changed, 159 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index 3e1f003..5fa7245 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -30,6 +30,7 @@ import javax.portlet.annotations.ActionMethod;
 import javax.portlet.annotations.PortletSerializable;
 import javax.portlet.annotations.RenderMethod;
 import javax.portlet.annotations.RenderStateScoped;
+import javax.servlet.DispatcherType;
 
 /**
  * Render state scoped bean. The bean is stored as a render parameter, so it
@@ -48,6 +49,7 @@ public class AsyncDialogBean implements PortletSerializable {
    public static final String PARAM_DELAY    = "delay";
    public static final String PARAM_REPS     = "reps";
    public static final String PARAM_AUTO     = "auto";
+   public static final String PARAM_FILTER   = "filter";
    public static final String PARAM_TYPE     = "type";
    public static final String PARAM_TYPE_TXT = OutputType.TEXT.toString();
    public static final String PARAM_TYPE_INC = OutputType.INC.toString();
@@ -59,6 +61,7 @@ public class AsyncDialogBean implements PortletSerializable {
    private OutputType         type;
    private String             msg;
    private boolean            autoDispatch;
+   private boolean            useFilter;
 
    /**
     * This method is called by the portlet container to initialize the bean at
@@ -72,12 +75,14 @@ public class AsyncDialogBean implements PortletSerializable {
          type = OutputType.TEXT;
          msg = null;
          autoDispatch = true;
+         useFilter = false;
       } else {
          delay = Integer.parseInt(state[0]);
          reps = Integer.parseInt(state[1]);
          type = OutputType.valueOf(state[2]);
          msg = state[3];
          autoDispatch = Boolean.parseBoolean(state[4]);
+         useFilter = Boolean.parseBoolean(state[5]);
       }
       LOGGER.fine("deserialized: " + Arrays.asList(state).toString());
    }
@@ -88,7 +93,7 @@ public class AsyncDialogBean implements PortletSerializable {
     */
    @Override
    public String[] serialize() {
-      String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
+      String[] state = { "" + delay, "" + reps, type.toString(), msg, ""+autoDispatch, ""+useFilter };
       LOGGER.fine("serialized: " + Arrays.asList(state).toString());
       return state;
    }
@@ -169,6 +174,20 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
+    * @return the useFilter
+    */
+   public boolean isUseFilter() {
+      return useFilter;
+   }
+
+   /**
+    * @param useFilter the useFilter to set
+    */
+   public void setUseFilter(boolean useFilter) {
+      this.useFilter = useFilter;
+   }
+
+   /**
     * Displays the dialog
     * 
     * @return the action form as string
@@ -233,6 +252,17 @@ public class AsyncDialogBean implements PortletSerializable {
          }
       }
 
+      String filter = req.getActionParameters().getValue(PARAM_FILTER);
+      if (filter != null) {
+         useFilter = true;
+         if ((type == OutputType.FWD)) {
+            msg = "Filter can't generate output with forward processing.";
+            useFilter = false;
+         }
+      } else {
+         useFilter = false;
+      }
+
       String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
       LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
index 75c664d..be096c5 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
 import javax.portlet.PortletException;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
@@ -29,6 +30,7 @@ import javax.portlet.annotations.PortletRequestFilter;
 import javax.portlet.filter.FilterChain;
 import javax.portlet.filter.FilterConfig;
 import javax.portlet.filter.ResourceFilter;
+import javax.servlet.DispatcherType;
 
 /**
  * Filter for the async portlet. logs the dispatcher type and sometimes
@@ -40,6 +42,9 @@ import javax.portlet.filter.ResourceFilter;
 @PortletRequestFilter(portletNames="AsyncPortlet")
 public class AsyncPortletFilter implements ResourceFilter {
    private static final Logger LOGGER = Logger.getLogger(AsyncPortletFilter.class.getName());
+   
+   @Inject private PortletRequestRandomNumberBean reqnum;
+   @Inject private AsyncDialogBean adb;
 
    @Override
    public void init(FilterConfig filterConfig) throws PortletException {
@@ -53,7 +58,21 @@ public class AsyncPortletFilter implements ResourceFilter {
    public void doFilter(ResourceRequest request, ResourceResponse response, FilterChain chain) throws IOException,
          PortletException {
       
-      LOGGER.fine("Entering request. Dispatcher type: " + request.getDispatcherType());
+      DispatcherType type = request.getDispatcherType();
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Entering request. Dispatcher type: ").append(type);
+      txt.append(", request #: ").append(reqnum.getRandomNumber());
+      LOGGER.fine(txt.toString());
+      
+      if (type != DispatcherType.ASYNC && adb.isUseFilter()) {
+         txt.setLength(0);
+         txt.append("<div class='msgbox'>");
+         txt.append("Filter: Request number: ").append(reqnum.getRandomNumber());
+         txt.append(", dispatcher type: ").append(request.getDispatcherType());
+         txt.append("</div>");
+         response.getWriter().write(txt.toString());
+      }
       
       chain.doFilter(request, response);
       

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
index 9c59c35..fd7e941 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
@@ -37,21 +37,23 @@ ${adb.getMsg()}
    </td><td>
    <input id='<portlet:namespace/>-reps' name='<%=PARAM_REPS%>' type='text' value='${adb.getReps() }' size='5' maxlength='5'>
    </td><td>
-   <input name='<%=PARAM_AUTO%>' value='<%=PARAM_AUTO%>' type='checkbox' ${adb.isAutoDispatch() ? "checked" : "" } >recursive
+   <input name='<%=PARAM_AUTO%>' value='<%=PARAM_AUTO%>' type='checkbox' ${adb.isAutoDispatch() ? "checked" : "" } > recursive
 
    </td></tr><tr><td>
    Output type:
    </td><td>
-   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_TXT%>' ${adb.getType() == "TEXT" ? "checked" : "" } >text
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_TXT%>' ${adb.getType() == "TEXT" ? "checked" : "" } > text
    </td><td>
-   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_INC%>' ${adb.getType() == "INC" ? "checked" : "" } >include
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_INC%>' ${adb.getType() == "INC" ? "checked" : "" } > include
    </td><td>
-   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_FWD%>' ${adb.getType() == "FWD" ? "checked" : "" } >forward
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_FWD%>' ${adb.getType() == "FWD" ? "checked" : "" } > forward
    </td><td>
-   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_DIS%>' ${adb.getType() == "DISPATCH" ? "checked" : "" } >dispatch
+   <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_DIS%>' ${adb.getType() == "DISPATCH" ? "checked" : "" } > dispatch
 
    </td></tr><tr><td>
    <INPUT id ='<portlet:namespace/>-send' VALUE='execute' TYPE='submit'>
+   </td><td>
+   <input name='<%=PARAM_FILTER%>' value='<%=PARAM_FILTER%>' type='checkbox' ${adb.isUseFilter() ? "checked" : "" } > show filter
    </td></tr></table>
 </FORM>
 </div>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
index 4629532..3cafd6c 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
+++ b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
@@ -2,17 +2,27 @@
    border-style:solid; 
    border-width:2px; 
    padding:4px; 
-   margin-bottom:10px;
+   margin-bottom:4px;
    overflow:auto;
    border-color:#000088; 
    background:#E0E0FF;
 }
 
+.msgbox {
+   border-style:solid; 
+   border-width:2px; 
+   padding:4px; 
+   margin-bottom:4px;
+   overflow:auto;
+   border-color:#800080; 
+   background:#ddaadd;
+}
+
 .parmbox {
    border-style:solid; 
    border-width:2px; 
    padding:4px; 
-   margin:0 0 3px 0;
+   margin:0 0 4px 0;
    overflow:auto;
    border-color:#008800; 
    background:#E0FFE0;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/pluto-container-api/src/main/java/org/apache/pluto/container/FilterManager.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/FilterManager.java b/pluto-container-api/src/main/java/org/apache/pluto/container/FilterManager.java
index bc95ad7..e2fae3d 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/FilterManager.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/FilterManager.java
@@ -18,6 +18,7 @@ package org.apache.pluto.container;
 
 import java.io.IOException;
 
+import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
 import javax.portlet.EventPortlet;
@@ -48,4 +49,9 @@ public interface FilterManager {
     void processFilter(RenderRequest req, RenderResponse res, Portlet portlet, PortletContext portletContext) throws PortletException, IOException;
     void processFilter(ResourceRequest req, ResourceResponse res, ResourceServingPortlet resourceServingPortlet, PortletContext portletContext)throws PortletException, IOException;
     void processFilter(EventRequest req, EventResponse res, EventPortlet eventPortlet, PortletContext portletContext)throws PortletException, IOException;
+
+    /**
+    * To enable contextual support in filters
+    */
+   void setBeanManager(BeanManager bm);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/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 b324f57..c48ee4d 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
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.util.Timer;
 import java.util.TimerTask;
 
+import javax.enterprise.inject.spi.BeanManager;
 import javax.inject.Inject;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
@@ -87,8 +88,8 @@ public class PortletServlet3 extends HttpServlet {
 
    // Private Member Variables ------------------------------------------------
    
-   @Inject
-   private AnnotatedConfigBean acb;
+   @Inject private AnnotatedConfigBean acb;
+   @Inject private BeanManager beanmgr;
 
    /**
     * The portlet name as defined in the portlet app descriptor.
@@ -283,6 +284,7 @@ public class PortletServlet3 extends HttpServlet {
 
       final FilterManager filterManager = 
             (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
+      filterManager.setBeanManager(beanmgr);
 
       if (LOG.isTraceEnabled()) {
          StringBuilder txt = new StringBuilder(128);
@@ -521,6 +523,8 @@ public class PortletServlet3 extends HttpServlet {
 
       // Set up the artifact producer with request, response, and portlet config
       PortletArtifactProducer.setPrecursors(req, resp, config);
+      
+      LOG.debug("CDI context is now set up.");
    }
 
    /**
@@ -548,5 +552,6 @@ public class PortletServlet3 extends HttpServlet {
       // remove the portlet artifact producer
       PortletArtifactProducer.remove();
 
+      LOG.debug("CDI context is now deactivated.");
    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
index cfc24a6..7d48212 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
@@ -19,7 +19,10 @@ package org.apache.pluto.driver.services.container;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
 import javax.portlet.EventPortlet;
@@ -45,17 +48,23 @@ import javax.portlet.filter.RenderFilter;
 import javax.portlet.filter.ResourceFilter;
 
 import org.apache.pluto.container.om.portlet.Filter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * A <code>FilterChain</code> is an object provided by the portlet container to the developer giving a view into the
- * invocation chain of a filtered request for a portlet. Filters use the <code>FilterChain</code> to invoke the next
- * filter in the chain, or if the calling filter is the last filter in the chain, to invoke the portlet at the end of
- * the chain.
+ * A <code>FilterChain</code> is an object provided by the portlet container to
+ * the developer giving a view into the invocation chain of a filtered request
+ * for a portlet. Filters use the <code>FilterChain</code> to invoke the next
+ * filter in the chain, or if the calling filter is the last filter in the
+ * chain, to invoke the portlet at the end of the chain.
  * 
  * @since 29/05/2007
  * @version 2.0
  */
 public class FilterChainImpl implements FilterChain, HeaderFilterChain {
+   private static final Logger LOG = LoggerFactory.getLogger(FilterChainImpl.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   
 
    private List<Filter>   filterList      = new ArrayList<Filter>();
    @SuppressWarnings("unused")
@@ -68,12 +77,53 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
    PortletContext         portletContext;
    int                    filterListIndex = 0;
 
+   private BeanManager    beanmgr;
+
    public FilterChainImpl(String lifeCycle) {
       this.lifeCycle = lifeCycle;
    }
-   
+
+   /** 
+    * enables contextual support
+    */
+   public void setBeanManager(BeanManager bm) {
+      beanmgr = bm;
+   }
+
+   private Object loadFilter(Filter filter) throws InstantiationException, IllegalAccessException,
+         ClassNotFoundException {
+      Object obj = null;
+      Class<?> fcls = loader.loadClass(filter.getFilterClass());
+      if (fcls != null) {
+         if (beanmgr == null) {
+            // CDI is not active
+            obj = fcls.newInstance();
+         } else {
+            // CDI active ... instantiate as bean to enable contextual features
+            Set<Bean<?>> beans = beanmgr.getBeans(fcls);
+            Bean<?> bean = beanmgr.resolve(beans);
+            if (bean != null) {
+               obj = beanmgr.getReference(bean, bean.getBeanClass(), beanmgr.createCreationalContext(bean));
+            } else {
+               LOG.warn("Could not get bean reference: " + filter.getFilterClass());
+               obj = fcls.newInstance();
+            }
+         }
+         if (isDebug) {
+            StringBuilder txt = new StringBuilder();
+            txt.append("Loaded filter for: ").append(fcls.getCanonicalName());
+            txt.append(", bean manager active: ").append(beanmgr != null);
+            LOG.debug(txt.toString());
+         }
+      } else {
+         LOG.error("Could not load class: " + filter.getFilterClass());
+      }
+      return obj;
+   }
+
    /**
-    * For async processing, the filter chain needs to be executed multiple times.
+    * For async processing, the filter chain needs to be executed multiple
+    * times.
     */
    public void reset() {
       filterListIndex = 0;
@@ -129,7 +179,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
          Filter filter = filterList.get(filterListIndex);
          filterListIndex++;
          try {
-            ActionFilter actionFilter = (ActionFilter) loader.loadClass(filter.getFilterClass()).newInstance();
+            ActionFilter actionFilter = (ActionFilter) loadFilter(filter);
             FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(),
                   portletContext);
             actionFilter.init(filterConfig);
@@ -153,7 +203,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
          Filter filter = filterList.get(filterListIndex);
          filterListIndex++;
          try {
-            EventFilter eventFilter = (EventFilter) loader.loadClass(filter.getFilterClass()).newInstance();
+            EventFilter eventFilter = (EventFilter) loadFilter(filter);;
             FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(),
                   portletContext);
             eventFilter.init(filterConfig);
@@ -177,7 +227,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
          Filter filter = filterList.get(filterListIndex);
          filterListIndex++;
          try {
-            RenderFilter renderFilter = (RenderFilter) loader.loadClass(filter.getFilterClass()).newInstance();
+            RenderFilter renderFilter = (RenderFilter) loadFilter(filter);;
             FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(),
                   portletContext);
             renderFilter.init(filterConfig);
@@ -201,7 +251,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
          Filter filter = filterList.get(filterListIndex);
          filterListIndex++;
          try {
-            HeaderFilter headerFilter = (HeaderFilter) loader.loadClass(filter.getFilterClass()).newInstance();
+            HeaderFilter headerFilter = (HeaderFilter) loadFilter(filter);;
             FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(),
                   portletContext);
             headerFilter.init(filterConfig);
@@ -225,7 +275,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
          Filter filter = filterList.get(filterListIndex);
          filterListIndex++;
          try {
-            ResourceFilter resourceFilter = (ResourceFilter) loader.loadClass(filter.getFilterClass()).newInstance();
+            ResourceFilter resourceFilter = (ResourceFilter) loadFilter(filter);;
             FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(),
                   portletContext);
             resourceFilter.init(filterConfig);

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/5c26ec41/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
index 66f6c1d..1b076a3 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
@@ -18,7 +18,10 @@ package org.apache.pluto.driver.services.container;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Set;
 
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
 import javax.portlet.EventPortlet;
@@ -42,6 +45,8 @@ import org.apache.pluto.container.om.portlet.Filter;
 import org.apache.pluto.container.om.portlet.FilterMapping;
 import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
 import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -51,6 +56,8 @@ import org.apache.pluto.container.om.portlet.PortletDefinition;
  * @version 2.0
  */
 public class FilterManagerImpl implements FilterManager{
+   private static final Logger LOG = LoggerFactory.getLogger(FilterManagerImpl.class);
+   
     private FilterChainImpl filterchain;
     private PortletApplicationDefinition portletApp;
     private String portletName;
@@ -64,6 +71,14 @@ public class FilterManagerImpl implements FilterManager{
         filterchain = new FilterChainImpl(lifeCycle);
         initFilterChain();
     }
+    
+    /**
+     * passing thru bean manager to enable contextual support in filters.
+     */
+    @Override
+    public void setBeanManager(BeanManager bm) {
+       filterchain.setBeanManager(bm);
+    }
 
     private void initFilterChain(){
         List<? extends FilterMapping> filterMappingList = portletApp.getFilterMappings();


[25/34] portals-pluto git commit: Added async portlet test filter. Made filter chain work properly for async requests. Refactored portlet servlet and portlet invoker to move bean holder initialization to the front of the execution chain.

Posted by ms...@apache.org.
Added async portlet test filter. Made filter chain work properly for
async requests. Refactored portlet servlet and portlet invoker to move
bean holder initialization to the front of the execution chain.


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

Branch: refs/heads/V3Prototype
Commit: 0ff1c51b09f43de2581435142c22c3bdb39a25aa
Parents: 8d98baf
Author: Scott Nicklous <ms...@apache.org>
Authored: Sat Apr 2 23:27:02 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sat Apr 2 23:27:02 2016 +0200

----------------------------------------------------------------------
 .../portals/samples/AsyncPortletFilter.java     |  64 ++++
 .../pluto/container/driver/PortletServlet3.java |  77 ++++-
 .../bean/processor/PortletInvoker.java          | 334 +++++++------------
 .../processor/PortletSessionBeanHolder.java     |  14 +-
 .../impl/JSR286ConfigurationProcessor.java      |  18 +-
 .../impl/JSR362ConfigurationProcessor.java      |   4 +-
 .../services/container/FilterChainImpl.java     |  12 +
 .../services/container/FilterManagerImpl.java   |   6 +
 8 files changed, 297 insertions(+), 232 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
new file mode 100644
index 0000000..75c664d
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
@@ -0,0 +1,64 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.PortletException;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.annotations.PortletRequestFilter;
+import javax.portlet.filter.FilterChain;
+import javax.portlet.filter.FilterConfig;
+import javax.portlet.filter.ResourceFilter;
+
+/**
+ * Filter for the async portlet. logs the dispatcher type and sometimes
+ * generates output.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+@PortletRequestFilter(portletNames="AsyncPortlet")
+public class AsyncPortletFilter implements ResourceFilter {
+   private static final Logger LOGGER = Logger.getLogger(AsyncPortletFilter.class.getName());
+
+   @Override
+   public void init(FilterConfig filterConfig) throws PortletException {
+   }
+
+   @Override
+   public void destroy() {
+   }
+
+   @Override
+   public void doFilter(ResourceRequest request, ResourceResponse response, FilterChain chain) throws IOException,
+         PortletException {
+      
+      LOGGER.fine("Entering request. Dispatcher type: " + request.getDispatcherType());
+      
+      chain.doFilter(request, response);
+      
+      LOGGER.fine("Exiting request. Dispatcher type: " + request.getDispatcherType());
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/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 c831773..b324f57 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
@@ -27,6 +27,7 @@ import javax.portlet.EventRequest;
 import javax.portlet.EventResponse;
 import javax.portlet.HeaderRequest;
 import javax.portlet.HeaderResponse;
+import javax.portlet.PortletConfig;
 import javax.portlet.PortletException;
 import javax.portlet.PortletRequest;
 import javax.portlet.PortletResponse;
@@ -34,6 +35,7 @@ import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
+import javax.portlet.StateAwareResponse;
 import javax.portlet.UnavailableException;
 import javax.servlet.DispatcherType;
 import javax.servlet.ServletConfig;
@@ -48,6 +50,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.FilterManager;
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletContainerException;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletRequestContext;
@@ -55,7 +58,11 @@ import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.PortletWindow;
 import org.apache.pluto.container.bean.processor.AnnotatedConfigBean;
+import org.apache.pluto.container.bean.processor.PortletArtifactProducer;
 import org.apache.pluto.container.bean.processor.PortletInvoker;
+import org.apache.pluto.container.bean.processor.PortletRequestScopedBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletSessionBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletStateScopedBeanHolder;
 import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -348,6 +355,8 @@ public class PortletServlet3 extends HttpServlet {
       
       try {
 
+         beforeInvoke(portletRequest, portletResponse, portletConfig);
+         
          // The requested method is RENDER: call Portlet.render(..)
          if (methodId == PortletInvokerService.METHOD_RENDER) {
             RenderRequest renderRequest = (RenderRequest) portletRequest;
@@ -439,10 +448,12 @@ public class PortletServlet3 extends HttpServlet {
 
       } finally {
          
+         requestContext.setExecutingRequestBody(false);
+         afterInvoke(portletResponse);
+         
          // If an async request is running or has been dispatched, resources
          // will be released by the PortletAsyncListener. Otherwise release here.
          
-         requestContext.setExecutingRequestBody(false);
          if (!request.isAsyncStarted()) {
             
             LOG.debug("Async not started, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
@@ -457,6 +468,24 @@ public class PortletServlet3 extends HttpServlet {
             }
          } else {
             LOG.debug("Async started, not releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
+
+            // Initialize the async context after the request during which async is 
+            // first started.
+            
+            if (request.getDispatcherType() != DispatcherType.ASYNC) {
+               if (requestContext instanceof PortletResourceRequestContext) {
+                  PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
+                  PortletAsyncContext pac = resctx.getPortletAsyncContext();
+                  if (pac != null) {
+                     pac.init(resctx);
+                  } else {
+                     LOG.warn("Couldn't get portlet async context.");
+                  }
+               } else {
+                  LOG.warn("Wrong kind of request context: " + requestContext.getClass().getCanonicalName());
+               }
+            }            
+            
          }
       }
    }
@@ -474,4 +503,50 @@ public class PortletServlet3 extends HttpServlet {
          }
       }
    }
+
+
+   /**
+    * To be called before bean method invocation begins
+    */
+   private void beforeInvoke(PortletRequest req, PortletResponse resp, PortletConfig config) {
+
+      // Set the portlet session bean holder for the thread & session
+      PortletRequestScopedBeanHolder.setBeanHolder();
+
+      // Set the portlet session bean holder for the thread & session
+      PortletSessionBeanHolder.setBeanHolder(req, acb.getSessionScopedConfig());
+
+      // Set the render state scoped bean holder
+      PortletStateScopedBeanHolder.setBeanHolder(req, acb.getStateScopedConfig());
+
+      // Set up the artifact producer with request, response, and portlet config
+      PortletArtifactProducer.setPrecursors(req, resp, config);
+   }
+
+   /**
+    * must be called after all method invocations have taken place, even if an
+    * exception occurs.
+    */
+   private void afterInvoke(PortletResponse resp) {
+
+      // Remove the portlet session bean holder for the thread
+      PortletRequestScopedBeanHolder.removeBeanHolder();
+
+      // Remove the portlet session bean holder for the thread
+      PortletSessionBeanHolder.removeBeanHolder();
+
+      // Remove the render state bean holder. pass response if we're
+      // dealing with a StateAwareResponse. The response is used for state
+      // storage.
+
+      StateAwareResponse sar = null;
+      if (resp instanceof StateAwareResponse) {
+         sar = (StateAwareResponse) resp;
+      }
+      PortletStateScopedBeanHolder.removeBeanHolder(sar);
+
+      // remove the portlet artifact producer
+      PortletArtifactProducer.remove();
+
+   }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/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 7507f2c..b8b1972 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
@@ -36,24 +36,19 @@ import javax.portlet.HeaderResponse;
 import javax.portlet.Portlet;
 import javax.portlet.PortletConfig;
 import javax.portlet.PortletException;
-import javax.portlet.PortletRequest;
 import javax.portlet.PortletRequestDispatcher;
-import javax.portlet.PortletResponse;
 import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.portlet.ResourceServingPortlet;
-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.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
-import org.apache.pluto.container.PortletResourceRequestContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,13 +59,13 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPortlet, HeaderPortlet {
-   private static final Logger             LOG     = LoggerFactory.getLogger(PortletInvoker.class);
-   private static final boolean            isDebug = LOG.isDebugEnabled();
+   private static final Logger       LOG     = LoggerFactory.getLogger(PortletInvoker.class);
+   private static final boolean      isDebug = LOG.isDebugEnabled();
 
    private final AnnotatedConfigBean acb;
-   private final String                    portletName;
-   private PortletConfig                   config;
-   
+   private final String              portletName;
+   private PortletConfig             config;
+
    /**
     * Construct for given portlet name.
     */
@@ -101,7 +96,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       List<AnnotatedMethod> meths = acb.getMethodStore().getMethods(mi);
       if (meths.isEmpty()) {
          Object id = mi.getId();
-         if ((id != null) && (id instanceof String) && ((String)id).length() > 0) {
+         if ((id != null) && (id instanceof String) && ((String) id).length() > 0) {
             mi.setId("");
             if (isDebug) {
                LOG.debug("Retrying retrieval with method identifier: " + mi.toString());
@@ -114,51 +109,6 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
    }
 
    /**
-    * To be called before bean method invocation begins
-    */
-   private void beforeInvoke(PortletRequest req, PortletResponse resp) {
-
-      // Set the portlet session bean holder for the thread & session
-      PortletRequestScopedBeanHolder.setBeanHolder();
-
-      // Set the portlet session bean holder for the thread & session
-      PortletSessionBeanHolder.setBeanHolder(req, acb.getSessionScopedConfig());
-
-      // Set the render state scoped bean holder
-      PortletStateScopedBeanHolder.setBeanHolder(req, acb.getStateScopedConfig());
-
-      // Set up the artifact producer with request, response, and portlet config
-      PortletArtifactProducer.setPrecursors(req, resp, config);
-   }
-
-   /**
-    * must be called after all method invocations have taken place, even if an
-    * exception occurs.
-    */
-   private void afterInvoke(PortletResponse resp) {
-
-      // Remove the portlet session bean holder for the thread
-      PortletRequestScopedBeanHolder.removeBeanHolder();
-
-      // Remove the portlet session bean holder for the thread
-      PortletSessionBeanHolder.removeBeanHolder();
-
-      // Remove the render state bean holder. pass response if we're
-      // dealing with a StateAwareResponse. The response is used for state
-      // storage.
-
-      StateAwareResponse sar = null;
-      if (resp instanceof StateAwareResponse) {
-         sar = (StateAwareResponse) resp;
-      }
-      PortletStateScopedBeanHolder.removeBeanHolder(sar);
-
-      // remove the portlet artifact producer
-      PortletArtifactProducer.remove();
-
-   }
-
-   /**
     * Invokes the given method, handling exceptions.
     * 
     * @param meth
@@ -227,7 +177,8 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       Object[] args = new Object[] { config };
       try {
          invokePortletMethod(meth, args);
-      } catch (Exception e) {}
+      } catch (Exception e) {
+      }
 
    }
 
@@ -256,7 +207,8 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       Object[] args = new Object[] {};
       try {
          invokePortletMethod(meth, args);
-      } catch (Exception e) {}
+      } catch (Exception e) {
+      }
    }
 
    @Override
@@ -267,14 +219,15 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
 
       List<AnnotatedMethod> meths = new ArrayList<AnnotatedMethod>();
       if (req.getDispatcherType() == DispatcherType.ASYNC) {
-         
+
          // Handle AsyncContest#dispatch() case
-         
-         AnnotatedMethod meth = (AnnotatedMethod) req.getAttribute(PortletInvokerService.ASYNC_METHOD);;
+
+         AnnotatedMethod meth = (AnnotatedMethod) req.getAttribute(PortletInvokerService.ASYNC_METHOD);
+         ;
          if (meth == null) {
             StringBuilder txt = new StringBuilder(128);
-            txt.append("Async processing error. ServeResource method not found for method identifier: ");
-            LOG.warn(txt.toString());
+            txt.append("Async processing error. ServeResource method attribute could not be retrieved.");
+            LOG.error(txt.toString());
             return;
          }
          LOG.debug("Processing async dispatch. method: " + meth.toString());
@@ -282,7 +235,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       } else {
          meths = getMethods(mi);
       }
-      
+
       if (meths.size() == 0) {
 
          // If a resource URL was activated, but no resource method could be
@@ -296,87 +249,63 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
 
       // now do the invocation
 
-      try {
-         beforeInvoke(req, resp);
+      for (AnnotatedMethod meth : meths) {
 
-         for (AnnotatedMethod meth : meths) {
+         // Set the character encoding & content type, if available
 
-            // Set the character encoding & content type, if available
-
-            ServeResourceMethod rm = (ServeResourceMethod) meth.getAnnotation();
-            if (rm != null) {
-               if (rm.characterEncoding().length() > 0) {
-                  resp.setCharacterEncoding(rm.characterEncoding());
-               }
-               if (rm.contentType().length() > 0) {
-                  resp.setContentType(rm.contentType());
-               }
+         ServeResourceMethod rm = (ServeResourceMethod) meth.getAnnotation();
+         if (rm != null) {
+            if (rm.characterEncoding().length() > 0) {
+               resp.setCharacterEncoding(rm.characterEncoding());
             }
+            if (rm.contentType().length() > 0) {
+               resp.setContentType(rm.contentType());
+            }
+         }
 
-            // Set up the method arguments based on the signature variant
+         // Set up the method arguments based on the signature variant
 
-            Object[] args = {};
-            Object result;
-            if (meth.getDescription().getVariant() == SignatureVariant.VOID_RESOURCEREQ_RESOURCERESP) {
-               args = new Object[] { req, resp };
-            }
+         Object[] args = {};
+         Object result;
+         if (meth.getDescription().getVariant() == SignatureVariant.VOID_RESOURCEREQ_RESOURCERESP) {
+            args = new Object[] { req, resp };
+         }
 
-            // invoke the resource method
-
-            result = invokePortletMethod(meth, args);
-            
-            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);
-
-               // Initialize the async context after the request during which async is 
-               // first started.
-               
-               if (req.getDispatcherType() != DispatcherType.ASYNC) {
-                  PortletResourceRequestContext reqctx = (PortletResourceRequestContext) req
-                        .getAttribute(PortletInvokerService.REQUEST_CONTEXT);
-                  if (reqctx != null) {
-                     PortletAsyncContext pac = reqctx.getPortletAsyncContext();
-                     if (pac != null) {
-                        pac.init(reqctx);
-                     } else {
-                        LOG.warn("Couldn't get portlet async context.");
-                     }
-                  } else {
-                     LOG.warn("Couldn't get request context.");
-                  }
-               }            
-               
-               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);
-                  }
-               }
+         // invoke the resource method
 
-               // If an include resource is provided, include it
+         result = invokePortletMethod(meth, args);
 
-               if ((rm != null) && (rm.include().length() > 0)) {
-                  PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(rm.include());
-                  prd.include(req, resp);
+         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 ((rm != null) && (rm.include().length() > 0)) {
+               PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(rm.include());
+               prd.include(req, resp);
+            }
          }
-      } finally {
-         afterInvoke(resp);
       }
    }
 
@@ -388,8 +317,9 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
 
       List<AnnotatedMethod> meths = getMethods(mi);
       if (meths.size() == 0) {
-         
-         // retry with empty string (for portlet class processEvent method, for example)
+
+         // retry with empty string (for portlet class processEvent method, for
+         // example)
          mi.setId("");
          meths = getMethods(mi);
          if (meths.size() == 0) {
@@ -409,12 +339,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       // Set up the method arguments and do the incovation
 
       Object[] args = new Object[] { req, resp };
-      try {
-         beforeInvoke(req, resp);
-         invokePortletMethod(meth, args);
-      } finally {
-         afterInvoke(resp);
-      }
+      invokePortletMethod(meth, args);
    }
 
    @Override
@@ -427,7 +352,8 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       List<AnnotatedMethod> meths = getMethods(mi);
       if (meths.size() == 0) {
 
-         // If an action URL was activated, but action method could not be found,
+         // If an action URL was activated, but action method could not be
+         // found,
          // add appropriate error string.
 
          StringBuilder txt = new StringBuilder(128);
@@ -441,12 +367,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
       // Set up the method arguments and do the incovation
 
       Object[] args = new Object[] { req, resp };
-      try {
-         beforeInvoke(req, resp);
-         invokePortletMethod(meth, args);
-      } finally {
-         afterInvoke(resp);
-      }
+      invokePortletMethod(meth, args);
 
    }
 
@@ -466,52 +387,44 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
          return;
       }
 
-      try {
-         beforeInvoke(req, resp);
+      for (AnnotatedMethod meth : meths) {
 
-         for (AnnotatedMethod meth : meths) {
+         // Set the content type, if available (determined by first render
+         // method)
 
-            // Set the content type, if available (determined by first render
-            // method)
-
-            RenderMethod rm = (RenderMethod) meth.getAnnotation();
-            if ((rm != null) && rm.contentType().length() > 0) {
-               resp.setContentType(rm.contentType());
-            }
+         RenderMethod rm = (RenderMethod) meth.getAnnotation();
+         if ((rm != null) && rm.contentType().length() > 0) {
+            resp.setContentType(rm.contentType());
+         }
 
-            // Set up the method arguments based on the signature variant
+         // Set up the method arguments based on the signature variant
 
-            Object[] args = {};
-            Object result;
-            if (meth.getDescription().getVariant() == SignatureVariant.VOID_RENDERREQ_RENDERRESP) {
-               args = new Object[] { req, resp };
-            }
+         Object[] args = {};
+         Object result;
+         if (meth.getDescription().getVariant() == SignatureVariant.VOID_RENDERREQ_RENDERRESP) {
+            args = new Object[] { req, resp };
+         }
 
-            // invoke the render method
+         // invoke the render method
 
-            result = invokePortletMethod(meth, args);
+         result = invokePortletMethod(meth, args);
 
-            // If output is to be expected, write it to the writer
+         // 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 (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 {
-         afterInvoke(resp);
       }
-
    }
 
    @Override
@@ -530,50 +443,43 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
          return;
       }
 
-      try {
-         beforeInvoke(req, resp);
-
-         for (AnnotatedMethod meth : meths) {
+      for (AnnotatedMethod meth : meths) {
 
-            // Set the content type, if available (determined by first render
-            // method)
+         // Set the content type, if available (determined by first render
+         // method)
 
-            HeaderMethod hm = (HeaderMethod) meth.getAnnotation();
-            if ((hm != null) && hm.contentType().length() > 0) {
-               resp.setContentType(hm.contentType());
-            }
+         HeaderMethod hm = (HeaderMethod) meth.getAnnotation();
+         if ((hm != null) && hm.contentType().length() > 0) {
+            resp.setContentType(hm.contentType());
+         }
 
-            // Set up the method arguments based on the signature variant
+         // Set up the method arguments based on the signature variant
 
-            Object[] args = {};
-            Object result;
-            if (meth.getDescription().getVariant() == SignatureVariant.VOID_HEADERREQ_HEADERRESP) {
-               args = new Object[] { req, resp };
-            }
+         Object[] args = {};
+         Object result;
+         if (meth.getDescription().getVariant() == SignatureVariant.VOID_HEADERREQ_HEADERRESP) {
+            args = new Object[] { req, resp };
+         }
 
-            // invoke the render method
+         // invoke the render method
 
-            result = invokePortletMethod(meth, args);
+         result = invokePortletMethod(meth, args);
 
-            // If output is to be expected, write it to the writer
+         // 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 (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 ((hm != null) && (hm.include().length() > 0)) {
-               PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(hm.include());
-               prd.include(req, resp);
-            }
+         if ((hm != null) && (hm.include().length() > 0)) {
+            PortletRequestDispatcher prd = config.getPortletContext().getRequestDispatcher(hm.include());
+            prd.include(req, resp);
          }
-
-      } finally {
-         afterInvoke(resp);
       }
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
index 949610b..6d97539 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
@@ -35,12 +35,12 @@ import org.slf4j.LoggerFactory;
  * 
  */
 public class PortletSessionBeanHolder implements Serializable {
-   private static final Logger                                LOG              = LoggerFactory
-                                                                                     .getLogger(PortletSessionBeanHolder.class);
-   private static final boolean                               isDebug          = LOG.isDebugEnabled();
+   private static final Logger  LOG              = LoggerFactory
+                                                       .getLogger(PortletSessionBeanHolder.class);
+   private static final boolean isTrace          = LOG.isTraceEnabled();
 
-   private static final long                                  serialVersionUID = 4713451590109713169L;
-   private static final String                                ATTRIBNAME       = "portletSessionBeanHolder";
+   private static final long    serialVersionUID = 4713451590109713169L;
+   private static final String  ATTRIBNAME       = "portletSessionBeanHolder";
 
    // The ThreadLocal manages the holders so that there is one holder per thread.
    private static final ThreadLocal<PortletSessionBeanHolder> holders          = new ThreadLocal<PortletSessionBeanHolder>();
@@ -87,7 +87,7 @@ public class PortletSessionBeanHolder implements Serializable {
       PortletSessionBeanHolder holder = new PortletSessionBeanHolder(map, windowId, config);
       holders.set(holder);
 
-      if (isDebug) {
+      if (isTrace) {
          StringBuilder txt = new StringBuilder(80);
          txt.append("Set portlet session bean holder.");
          txt.append(" ThreadId: ").append(Thread.currentThread().getId());
@@ -104,7 +104,7 @@ public class PortletSessionBeanHolder implements Serializable {
    public static void removeBeanHolder() {
       holders.remove();
 
-      if (isDebug) {
+      if (isTrace) {
          StringBuilder txt = new StringBuilder(80);
          txt.append("Removed portlet session bean holder.");
          txt.append(" ThreadId=").append(Thread.currentThread().getId());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR286ConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR286ConfigurationProcessor.java b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR286ConfigurationProcessor.java
index 7cbb18f..eaccf25 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR286ConfigurationProcessor.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR286ConfigurationProcessor.java
@@ -922,14 +922,16 @@ public class JSR286ConfigurationProcessor extends JSR168ConfigurationProcessor {
             LOG.warn(txt.toString());
             pad.removeFilterMapping(fm);
          }
-         for (String pn : fm.getPortletNames()) {
-            if (pad.getMatchingPortlets(pn).isEmpty()) {
-               txt.setLength(0);
-               txt.append("Bad filter mapping definition. Filter name: ").append(fm.getFilterName());
-               txt.append(", Portlet names: ").append(fm.getPortletNames().toString());
-               txt.append(", Portlet definition not found: ").append(pn);
-               LOG.warn(txt.toString());
-               pad.removeFilterMapping(fm);
+         if (pad.getVersion().equals("2.0")) {
+            for (String pn : fm.getPortletNames()) {
+               if (pad.getMatchingPortlets(pn).isEmpty()) {
+                  txt.setLength(0);
+                  txt.append("Bad filter mapping definition. Filter name: ").append(fm.getFilterName());
+                  txt.append(", Portlet names: ").append(fm.getPortletNames().toString());
+                  txt.append(", Portlet definition not found: ").append(pn);
+                  LOG.warn(txt.toString());
+                  pad.removeFilterMapping(fm);
+               }
             }
          }
       }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
index eae8230..5cced2e 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
@@ -460,12 +460,12 @@ public class JSR362ConfigurationProcessor extends JSR286ConfigurationProcessor {
          List<PortletModeType> pmlist = st.getPortletMode();
          if (pmlist.size() == 0) {
             String info = "No portlet modes found in Supports block.";
-            LOG.debug(info);
+            LOG.trace(info);
          }
          List<WindowStateType> wslist = st.getWindowState();
          if (wslist.size() == 0) {
             String info = "No window states found in Supports block.";
-            LOG.debug(info);
+            LOG.trace(info);
          }
 
          // set up Supports

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
index 55c928e..cfc24a6 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterChainImpl.java
@@ -71,6 +71,13 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
    public FilterChainImpl(String lifeCycle) {
       this.lifeCycle = lifeCycle;
    }
+   
+   /**
+    * For async processing, the filter chain needs to be executed multiple times.
+    */
+   public void reset() {
+      filterListIndex = 0;
+   }
 
    public void processFilter(EventRequest req, EventResponse res, EventPortlet eventPortlet,
          PortletContext portletContext) throws IOException, PortletException {
@@ -116,6 +123,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
       filterList.add(filter);
    }
 
+   @Override
    public void doFilter(ActionRequest request, ActionResponse response) throws IOException, PortletException {
       if (filterListIndex < filterList.size()) {
          Filter filter = filterList.get(filterListIndex);
@@ -139,6 +147,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
       }
    }
 
+   @Override
    public void doFilter(EventRequest request, EventResponse response) throws IOException, PortletException {
       if (filterListIndex < filterList.size()) {
          Filter filter = filterList.get(filterListIndex);
@@ -162,6 +171,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
       }
    }
 
+   @Override
    public void doFilter(RenderRequest request, RenderResponse response) throws IOException, PortletException {
       if (filterListIndex < filterList.size()) {
          Filter filter = filterList.get(filterListIndex);
@@ -185,6 +195,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
       }
    }
 
+   @Override
    public void doFilter(HeaderRequest request, HeaderResponse response) throws IOException, PortletException {
       if (filterListIndex < filterList.size()) {
          Filter filter = filterList.get(filterListIndex);
@@ -208,6 +219,7 @@ public class FilterChainImpl implements FilterChain, HeaderFilterChain {
       }
    }
 
+   @Override
    public void doFilter(ResourceRequest request, ResourceResponse response) throws IOException, PortletException {
       if (filterListIndex < filterList.size()) {
          Filter filter = filterList.get(filterListIndex);

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0ff1c51b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
index 0d28f45..66f6c1d 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
@@ -90,6 +90,7 @@ public class FilterManagerImpl implements FilterManager{
     /**
      * @see org.apache.pluto.container.FilterManager#processFilter(javax.portlet.EventRequest, javax.portlet.EventResponse, javax.portlet.EventPortlet, javax.portlet.PortletContext)
      */
+    @Override
     public void processFilter(EventRequest req, EventResponse res, EventPortlet eventPortlet,PortletContext portletContext)throws PortletException, IOException{
         filterchain.processFilter(req, res, eventPortlet, portletContext);
     }
@@ -97,13 +98,16 @@ public class FilterManagerImpl implements FilterManager{
     /**
      * @see org.apache.pluto.container.FilterManager#processFilter(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse, javax.portlet.ResourceServingPortlet, javax.portlet.PortletContext)
      */
+    @Override
     public void processFilter(ResourceRequest req, ResourceResponse res, ResourceServingPortlet resourceServingPortlet,PortletContext portletContext)throws PortletException, IOException{
+        filterchain.reset();     // for async processing
         filterchain.processFilter(req, res, resourceServingPortlet, portletContext);
     }
 
     /**
      * @see org.apache.pluto.container.FilterManager#processFilter(javax.portlet.RenderRequest, javax.portlet.RenderResponse, javax.portlet.Portlet, javax.portlet.PortletContext)
      */
+    @Override
     public void processFilter(RenderRequest req, RenderResponse res, Portlet portlet,PortletContext portletContext) throws PortletException, IOException{
         filterchain.processFilter(req, res, portlet, portletContext);
     }
@@ -111,6 +115,7 @@ public class FilterManagerImpl implements FilterManager{
     /**
      * @see org.apache.pluto.container.FilterManager#processFilter(javax.portlet.RenderRequest, javax.portlet.HeaderResponse, javax.portlet.HeaderPortlet, javax.portlet.PortletContext)
      */
+    @Override
     public void processFilter(HeaderRequest req, HeaderResponse res, HeaderPortlet portlet,PortletContext portletContext) throws PortletException, IOException{
         filterchain.processFilter(req, res, portlet, portletContext);
     }
@@ -118,6 +123,7 @@ public class FilterManagerImpl implements FilterManager{
     /**
      * @see org.apache.pluto.container.FilterManager#processFilter(javax.portlet.ActionRequest, javax.portlet.ActionResponse, javax.portlet.Portlet, javax.portlet.PortletContext)
      */
+    @Override
     public void processFilter(ActionRequest req, ActionResponse res, Portlet portlet,PortletContext portletContext) throws PortletException, IOException{
         filterchain.processFilter(req, res, portlet, portletContext);
     }


[22/34] portals-pluto git commit: fixed bugs in async portlet

Posted by ms...@apache.org.
fixed bugs in async portlet


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

Branch: refs/heads/V3Prototype
Commit: 75119d2ed7d4645bebf22183435517a22bf155e6
Parents: c4a9c53
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 31 21:18:59 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 31 21:18:59 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java | 77 +++++++++++---------
 .../portals/samples/AsyncPortletResource.java   | 47 ++++--------
 2 files changed, 59 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/75119d2e/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index a74af06..3e1f003 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -35,28 +35,30 @@ import javax.portlet.annotations.RenderStateScoped;
  * Render state scoped bean. The bean is stored as a render parameter, so it
  * needs to be portlet serializable.
  */
-@RenderStateScoped @Named("adb")
+@RenderStateScoped
+@Named("adb")
 public class AsyncDialogBean implements PortletSerializable {
    private static final Logger LOGGER = Logger.getLogger(AsyncDialogBean.class.getName());
-   
-   public enum OutputType {TEXT, INC, FWD, DISPATCH, AUTO}
-   
-   public static final String PARAM_MSG = "msg";
-   public static final String PARAM_DELAY = "delay";
-   public static final String PARAM_REPS = "reps";
-   public static final String PARAM_AUTO = "auto";
-   public static final String PARAM_TYPE = "type";
+
+   public enum OutputType {
+      TEXT, INC, FWD, DISPATCH, AUTO
+   }
+
+   public static final String PARAM_MSG      = "msg";
+   public static final String PARAM_DELAY    = "delay";
+   public static final String PARAM_REPS     = "reps";
+   public static final String PARAM_AUTO     = "auto";
+   public static final String PARAM_TYPE     = "type";
    public static final String PARAM_TYPE_TXT = OutputType.TEXT.toString();
    public static final String PARAM_TYPE_INC = OutputType.INC.toString();
    public static final String PARAM_TYPE_FWD = OutputType.FWD.toString();
    public static final String PARAM_TYPE_DIS = OutputType.DISPATCH.toString();
 
-   
-   private int delay;
-   private int reps;
-   private OutputType type;
-   private String msg;
-   private boolean autoDispatch;
+   private int                delay;
+   private int                reps;
+   private OutputType         type;
+   private String             msg;
+   private boolean            autoDispatch;
 
    /**
     * This method is called by the portlet container to initialize the bean at
@@ -86,12 +88,11 @@ public class AsyncDialogBean implements PortletSerializable {
     */
    @Override
    public String[] serialize() {
-      String[] state = {""+delay, ""+reps, type.toString(), msg, ""+autoDispatch};
+      String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
       LOGGER.fine("serialized: " + Arrays.asList(state).toString());
       return state;
    }
 
-
    /**
     * @return the delay
     */
@@ -100,7 +101,8 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @param delay the delay to set
+    * @param delay
+    *           the delay to set
     */
    public void setDelay(int delay) {
       this.delay = delay;
@@ -114,7 +116,8 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @param reps the reps to set
+    * @param reps
+    *           the reps to set
     */
    public void setReps(int reps) {
       this.reps = reps;
@@ -128,7 +131,8 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @param type the type to set
+    * @param type
+    *           the type to set
     */
    public void setType(OutputType type) {
       this.type = type;
@@ -142,7 +146,8 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @param msg the msg to set
+    * @param msg
+    *           the msg to set
     */
    public void setMsg(String msg) {
       this.msg = msg;
@@ -156,7 +161,8 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @param autoDispatch the autoDispatch to set
+    * @param autoDispatch
+    *           the autoDispatch to set
     */
    public void setAutoDispatch(boolean autoDispatch) {
       this.autoDispatch = autoDispatch;
@@ -167,8 +173,7 @@ public class AsyncDialogBean implements PortletSerializable {
     * 
     * @return the action form as string
     */
-   @RenderMethod(portletNames = "AsyncPortlet", ordinal = 100, 
-         include = "/WEB-INF/jsp/asyncDialog.jsp")
+   @RenderMethod(portletNames = "AsyncPortlet", ordinal = 100, include = "/WEB-INF/jsp/asyncDialog.jsp")
    public void getDialog() {
    }
 
@@ -177,36 +182,40 @@ public class AsyncDialogBean implements PortletSerializable {
     */
    @ActionMethod(portletName = "AsyncPortlet")
    public void handleDialog(ActionRequest req, ActionResponse resp) throws PortletException, IOException {
-      
+
       msg = null;
-      
+
       String strReps = req.getActionParameters().getValue(PARAM_REPS);
       if (strReps != null) {
          try {
             reps = Integer.parseInt(strReps);
-            if (reps <= 0 || reps > 8) throw new Exception("broken");
+            if (reps <= 0 || reps > 8)
+               throw new Exception("broken");
          } catch (Exception e) {
             msg = "try again. bad repetitions.";
          }
       }
-      
+
       String strDelay = req.getActionParameters().getValue(PARAM_DELAY);
       if (strDelay != null) {
          try {
             delay = Integer.parseInt(strDelay);
-            if (delay < 0) throw new Exception("broken");
+            if (delay < 0)
+               throw new Exception("broken");
          } catch (Exception e) {
             msg = "try again. bad delay.";
          }
       }
-      
+
       String strType = req.getActionParameters().getValue(PARAM_TYPE);
       if (strType != null) {
          try {
             type = OutputType.valueOf(strType);
-            if (type == OutputType.FWD && reps > 1) {
-               msg = "Repetitions cannot be > 1 for forwards.";
-               reps = 1;
+            if (reps > 1) {
+               if ((type == OutputType.FWD) || (type == OutputType.DISPATCH)) {
+                  msg = "Repetitions cannot be > 1 for forwards or dispatches.";
+                  reps = 1;
+               }
             }
          } catch (Exception e) {
             msg = "try again. bad type: " + strType;
@@ -224,7 +233,7 @@ public class AsyncDialogBean implements PortletSerializable {
          }
       }
 
-      String[] state = {""+delay, ""+reps, type.toString(), msg, ""+autoDispatch};
+      String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
       LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/75119d2e/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 72b681b..0868f58 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -95,7 +95,7 @@ public class AsyncPortletResource {
                StringBuilder txt = new StringBuilder(128);
                txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
                txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
-               txt.append("</p>");
+               txt.append("</p><hr>");
                hresp.getWriter().write(txt.toString());
                ctx.complete();
                break;
@@ -154,6 +154,11 @@ public class AsyncPortletResource {
          reps = adb.getReps();
       }
       
+      boolean done = (reps <= 0) || (adb.getDelay() <= 0);
+
+      reps--;
+      req.setAttribute(ATTRIB_REPS, reps);
+      
       StringBuilder txt = new StringBuilder(128);
       txt.append("Resource method.");
       txt.append(" delay: ").append(adb.getDelay());
@@ -164,35 +169,14 @@ public class AsyncPortletResource {
       txt.append(", auto-dispatch: ").append(auto);
       LOGGER.fine(txt.toString());
       
-      AsyncContext ctx = null;
-
-      if (reps > 0) {
-         reps--;
-         req.setAttribute(ATTRIB_REPS, reps);
-         
-         ctx = req.startAsync();
-         ctx.setTimeout(4000);
-      }
+      AsyncContext ctx = req.startAsync();
+      ctx.setTimeout(4000);
 
       if (auto || (adb.getDelay() <= 0)) {
          
          // produce output if dispatched from work thread or if there is no delay requested
          
          PortletRequestDispatcher rd;
-         
-         if (ctx == null) {
-            // last iteration of auto-dispatch
-            LOGGER.fine("Retrieving async context for the last run.");
-            try {
-               ctx = req.getAsyncContext();
-            } catch (Exception e) {
-               txt.setLength(0);
-               txt.append("Could not get AsyncContext. Exception: ").append(e.toString());
-               LOGGER.warning(txt.toString());
-               resp.getWriter().write(txt.toString());
-               return;
-            }
-         }
 
          HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
          trace(hreq, "Resource method: ");
@@ -207,7 +191,8 @@ public class AsyncPortletResource {
          switch (adb.getType()) {
          case DISPATCH:
             LOGGER.fine("Dispatching to JSP.");
-            ctx.dispatch(JSP);
+            req.setAttribute(ATTRIB_TITLE, "Resource Method dispatching to JSP");
+            ctx.dispatch(hreq.getServletContext(), JSP);
             break;
          case FWD:
             LOGGER.fine("Doing request dispatcher forward to JSP.");
@@ -215,7 +200,7 @@ public class AsyncPortletResource {
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.forward(req, resp);
             resp.flushBuffer();
-            if (!auto) {
+            if (done) {
                ctx.complete();
             }
             break;
@@ -225,26 +210,26 @@ public class AsyncPortletResource {
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.include(req, resp);
             resp.flushBuffer();
-            if (!auto) {
+            if (done) {
                ctx.complete();
             }
             break;
          default:
             LOGGER.fine("Producing text output.");
             txt.setLength(0);
-            txt.append("<h5>Async portlet resource method producing text output for portlet: " + portletName + "</h5>");
+            txt.append("<h5>Resource method producing text output for portlet: " + portletName + "</h5>");
             txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
-            txt.append("</p>");
+            txt.append("</p><hr>");
             resp.getWriter().write(txt.toString());
             resp.flushBuffer();
-            if (!auto) {
+            if (done) {
                ctx.complete();
             }
             break;
          }
       }
       
-      if (adb.getDelay() > 0 && req.isAsyncStarted()) {
+      if (!done) {
          
          // now start the executor thread 
          


[31/34] portals-pluto git commit: Started work to add portlet-specific async interfaces

Posted by ms...@apache.org.
Started work to add portlet-specific async interfaces


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

Branch: refs/heads/V3Prototype
Commit: 593f7ce85c4780b1b9cc6b26518bbba8d6916d31
Parents: 9fa76db
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Apr 5 20:48:55 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Apr 5 20:48:55 2016 +0200

----------------------------------------------------------------------
 .../java/javax/portlet/PortletAsyncContext.java |  81 +++++++++
 .../java/javax/portlet/PortletAsyncEvent.java   | 168 +++++++++++++++++++
 .../javax/portlet/PortletAsyncListener.java     | 143 ++++++++++++++++
 3 files changed, 392 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/593f7ce8/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
new file mode 100644
index 0000000..d77f5c4
--- /dev/null
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
@@ -0,0 +1,81 @@
+/*  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 javax.portlet;
+
+import javax.servlet.ServletContext;
+
+
+/**
+ * <div class="changed_added_3_0">
+ * Class representing the execution context for an asynchronous operation that was
+ * initiated on a ResourceRequest.
+ * <p>
+ * A PortletAsyncContext is created and initialized by a call to
+ * ResourceRequest#startAsync() or ResourceRequest#startAsync(ServletRequest,
+ * ServletResponse). Repeated invocations of these methods will return the same
+ * AsyncContext instance, reinitialized as appropriate.
+ * <p>
+ * In the event that an asynchronous operation has timed out, the container must
+ * invoke, at their onTimeout method, all PortletAsyncListener instances registered
+ * with the ResourceRequest on which the asynchronous operation was initiated.
+ * If none of the listeners called complete() or any of the dispatch() methods,
+ * complete the request on behalf of the application. * 
+ * </div>
+ * 
+ * @see     javax.servlet.AsyncContext
+ * @since   3.0
+ */
+public interface PortletAsyncContext {
+
+   public void addListener(PortletAsyncListener listener);
+
+   public void addListener(PortletAsyncListener listener, ResourceRequest request, ResourceResponse response);
+
+   public void complete();
+
+   public <T extends PortletAsyncListener> T createListener(Class<T> cls) throws PortletException;
+
+   public void dispatch();
+
+   public void dispatch(String path);
+
+   public void dispatch(ServletContext context, String path);
+
+   public ResourceRequest getRequest();
+
+   public ResourceResponse getResponse();
+
+   public long getTimeout();
+
+   public boolean hasOriginalRequestAndResponse();
+
+   public void setTimeout(long time);
+
+   /**
+    * <div class="changed_added_3_0">
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param run
+    */
+   public void start(Runnable run);
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/593f7ce8/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
new file mode 100644
index 0000000..66182dd
--- /dev/null
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
@@ -0,0 +1,168 @@
+/*  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 javax.portlet;
+
+
+/**
+ * <div class="changed_added_3_0">
+ * Event that gets fired when the asynchronous operation initiated on a
+ * ResourceRequest (via a call to ResourceRequest#startAsync or
+ * ResourceRequest#startAsync(ResourceRequest, ResouceResponse)) has completed, timed
+ * out, or produced an error.
+ * </div>
+ * 
+ * @since   3.0
+ */
+public class PortletAsyncEvent {
+
+   PortletAsyncContext  context;
+   ResourceRequest      request;
+   ResourceResponse     response;
+   Throwable            throwable;
+   
+   /**
+    * <div class="changed_added_3_0">
+    * Constructs a PortletAsyncEvent from the given 
+    * PortletAsyncContext, ResourceRequest, ResourceResponse, and Throwable.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param context
+    * @param request
+    * @param response
+    * @param throwable
+    */
+   public PortletAsyncEvent(PortletAsyncContext context, ResourceRequest request, ResourceResponse response, Throwable throwable) {
+      this.context = context;
+      this.request = request;
+      this.response = response;
+      this.throwable = throwable;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Constructs a PortletAsyncEvent from the given 
+    * PortletAsyncContext, ResourceRequest, and ResourceResponse.
+    * </div>
+    * 
+    * @since   3.0
+    * @param context
+    * @param request
+    * @param response
+    */
+   public PortletAsyncEvent(PortletAsyncContext context, ResourceRequest request, ResourceResponse response) {
+      this.context = context;
+      this.request = request;
+      this.response = response;
+      this.throwable = null;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Constructs a PortletAsyncEvent from the given 
+    * PortletAsyncContext and Throwable.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param context
+    * @param throwable
+    */
+   public PortletAsyncEvent(PortletAsyncContext context, Throwable throwable) {
+      this.context = context;
+      this.request = null;
+      this.response = null;
+      this.throwable = throwable;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Constructs a PortletAsyncEvent from the given 
+    * PortletAsyncContext.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param context
+    */
+   public PortletAsyncEvent(PortletAsyncContext context) {
+      this.context = context;
+      this.request = null;
+      this.response = null;
+      this.throwable = null;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the portlet asynchronous context object associated with the event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return the portlet asynchronous context
+    */
+   public PortletAsyncContext getPortletAsyncContext() {
+      return context;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the resource request associated with the event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return the resource request provided to the constructor, or <code>null</code>
+    * if no resource request was provided.
+    */
+   public ResourceRequest getSuppliedRequest() {
+      return request;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the resource response associated with the event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return the resource response provided to the constructor, or <code>null</code>
+    * if no resource response was provided.
+    */
+   public ResourceResponse getSuppliedResponse() {
+      return response;
+   }
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the <code>Throwable</code> associated with the event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return The <code>Throwable</code> that was used to initialize the event, or <code>null</code>
+    * if no <code>Throwable</code> was provided.
+    */
+   public Throwable getThrowable() {
+      return throwable;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/593f7ce8/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
new file mode 100644
index 0000000..0865365
--- /dev/null
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
@@ -0,0 +1,143 @@
+/*  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 javax.portlet;
+
+import java.io.IOException;
+
+/**
+ * <div class="changed_added_3_0">
+ * Listener that will be notified in the event that an asynchronous operation
+ * initiated on a ResourceRequest to which the listener had been added has
+ * completed, timed out, or resulted in an error.
+ * </div>
+ * 
+ * @since   3.0
+ */
+public interface PortletAsyncListener {
+
+   /**
+    * <div class="changed_added_3_0">
+    * Notifies this <code>PortletAsyncListener</code> that an asynchronous operation
+    * has been completed.
+    * <p>
+    * The <code>PortletAsyncContext</code> corresponding to the asynchronous
+    * operation that has been completed may be obtained by calling
+    * <code>getAsyncContext</code> on the given event.
+    * <p>
+    * In addition, if this <code>PortletAsyncListener</code> had been registered
+    * via a call to <code>PortletAsyncContext#addListener(PortletAsyncListener,
+    * ResourceRequest, ResourceResponse)</code>, the supplied
+    * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
+    * be retrieved by calling <code>getSuppliedRequest</code> and
+    * <code>getSuppliedResponse</code>, respectively, on the given event.
+    *
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param evt  the PortletAsyncEvent indicating that an asynchronous operation has been completed 
+    * @throws IOException  if an I/O related error has occurred during the processing
+    */
+   public void onComplete(PortletAsyncEvent evt) throws IOException;
+
+   /**
+    * <div class="changed_added_3_0">
+    * Notifies this <code>PortletAsyncListener</code> that an asynchronous
+    * operation has failed to complete.
+    * <p>
+    * The <code>PortletAsyncContext</code> corresponding to the asynchronous
+    * operation that failed to complete may be obtained by calling
+    * <code>getAsyncContext</code> on the given event.
+    * <p>
+    * In addition, if this <code>PortletAsyncListener</code> had been registered
+    * via a call to <code>PortletAsyncContext#addListener(PortletAsyncListener,
+    * ResourceRequest, ResourceResponse)</code>, the supplied
+    * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
+    * be retrieved by calling <code>getSuppliedRequest</code> and
+    * <code>getSuppliedResponse</code>, respectively, on the given event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param evt  the PortletAsyncEvent indicating that an asynchronous operation has 
+    * encountered an error
+    * @throws IOException  if an I/O related error has occurred during the processing
+    */
+   public void onError(PortletAsyncEvent evt) throws IOException;
+
+   /**
+    * <div class="changed_added_3_0">
+    * Notifies this <code>PortletAsyncListener</code> that a new asynchronous cycle is
+    * being initiated via a call to one of the <code>ResourceRequest</code>#startAsync
+    * methods.
+    * <p>
+    * The <code>PortletAsyncContext</code> corresponding to the asynchronous
+    * operation that is being reinitialized may be obtained by calling
+    * <code>getAsyncContext</code> on the given event.
+    * <p>
+    * In addition, if this <code>PortletAsyncListener</code> had been registered
+    * via a call to <code>PortletAsyncContext#addListener(PortletAsyncListener,
+    * ResourceRequest, ResourceResponse)</code>, the supplied
+    * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
+    * be retrieved by calling <code>getSuppliedRequest</code> and
+    * <code>getSuppliedResponse</code>, respectively, on the given event.
+    * <p> 
+    * This <code>PortletAsyncListener</code> will not receive any events related
+    * to the new asynchronous cycle unless it registers itself (via a call to
+    * <code>PortletAsyncContext</code>#addListener) with the
+    * <code>PortletAsyncContext</code> that is delivered as part of the given
+    * event.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param evt  the PortletAsyncEvent indicating that an asynchronous operation 
+    * is being initiated
+    * @throws IOException  if an I/O related error has occurred during the processing
+    */
+   public void onStartAsync(PortletAsyncEvent evt) throws IOException;
+
+   /**
+    * <div class="changed_added_3_0">
+    * Notifies this <code>PortletAsyncListener</code> that an asynchronous operation
+    * has timed out.
+    * <p>
+    * The <code>PortletAsyncContext</code> corresponding to the asynchronous
+    * operation that has timed out may be obtained by calling
+    * <code>getAsyncContext</code> on the given event.
+    * <p>
+    * In addition, if this <code>PortletAsyncListener</code> had been registered
+    * via a call to <code>PortletAsyncContext#addListener(PortletAsyncListener,
+    * ResourceRequest, ResourceResponse)</code>, the supplied
+    * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
+    * be retrieved by calling <code>getSuppliedRequest</code> and
+    * <code>getSuppliedResponse</code>, respectively, on the given event.
+    * 
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param evt  the PortletAsyncEvent indicating that an asynchronous operation has
+    * timed out
+    * @throws IOException  if an I/O related error has occurred during the processing
+    */
+   public void onTimeout(PortletAsyncEvent evt) throws IOException;
+
+}


[17/34] portals-pluto git commit: Work on async portlet

Posted by ms...@apache.org.
Work on async portlet


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

Branch: refs/heads/V3Prototype
Commit: 46a03a15ff7c47cfb6b9d0c8ea31d68bd166828b
Parents: 870277c
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Mar 29 15:26:30 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Mar 29 15:26:30 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java |  5 +-
 .../portals/samples/AsyncPortletResource.java   | 49 ++++++++++++++------
 .../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp |  2 +-
 3 files changed, 38 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/46a03a15/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index 08389b2..f0d76f9 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -20,7 +20,6 @@ package org.apache.portals.samples;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Named;
@@ -213,12 +212,12 @@ public class AsyncDialogBean implements PortletSerializable {
       String auto = req.getActionParameters().getValue(PARAM_AUTO);
       if (auto != null) {
          autoDispatch = true;
+      } else {
+         autoDispatch = false;
          if (reps > 1) {
             msg = "Repetitions cannot be > 1 for non-recursive use.";
             reps = 1;
          }
-      } else {
-         autoDispatch = false;
       }
 
       String[] state = {""+delay, ""+reps, type.toString(), msg, ""+autoDispatch};

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/46a03a15/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index a61550d..792601f 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -19,7 +19,6 @@
 package org.apache.portals.samples;
 
 import java.io.IOException;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -47,6 +46,7 @@ public class AsyncPortletResource {
    private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
    private final static String ATTRIB_REPS = "reps";
    private final static String ATTRIB_AUTO = "auto";
+   private final static String ATTRIB_TITLE = "title";
 
    private class AsyncRunnable implements Runnable {
 
@@ -60,6 +60,13 @@ public class AsyncPortletResource {
          this.delay = delay;
          this.type = type;
          this.done = done;
+         
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Constructing runnable.");
+         txt.append(" delay: ").append(delay);
+         txt.append(", type: ").append(type);
+         txt.append(", done: ").append(done);
+         LOGGER.fine(txt.toString());
       }
 
       @Override
@@ -75,8 +82,8 @@ public class AsyncPortletResource {
             case TEXT:
                LOGGER.fine("Producing text output.");
                StringBuilder txt = new StringBuilder(128);
-               txt.append("<p>AsyncRunnable.");
-               txt.append(" dispatcher type: ").append(hreq.getDispatcherType().toString());
+               txt.append("<h5>Thread producing text output</h5>");
+               txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
                txt.append("</p>");
                hresp.getWriter().write(txt.toString());
                if (done) {
@@ -90,10 +97,12 @@ public class AsyncPortletResource {
                break;
             case DISPATCH:
                LOGGER.fine("Dispatching to JSP.");
+               hreq.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
                ctx.dispatch(JSP);
                break;
             case FWD:
                LOGGER.fine("Doing request dispatcher forward to JSP.");
+               hreq.setAttribute(ATTRIB_TITLE, "Thread forwarding to JSP");
                rd = hreq.getRequestDispatcher(JSP);
                rd.forward(hreq, hresp);
                if (done) {
@@ -102,6 +111,7 @@ public class AsyncPortletResource {
                break;
             case INC:
                LOGGER.fine("Doing request dispatcher include of JSP.");
+               hreq.setAttribute(ATTRIB_TITLE, "Thread including JSP");
                rd = hreq.getRequestDispatcher(JSP);
                rd.include(hreq, hresp);
                if (done) {
@@ -144,19 +154,19 @@ public class AsyncPortletResource {
          try {
             ctx = req.getAsyncContext();
          } catch (Exception e) {}
+         
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Producing output.");
+         txt.append(" delay: ").append(adb.getDelay());
+         txt.append(", type: ").append(adb.getType());
+         txt.append(", reps: ").append(reps);
+         txt.append(", total reps: ").append(adb.getReps());
+         txt.append(", recursive: ").append(adb.isAutoDispatch());
+         txt.append(", dispatched from work thread: ").append(auto);
+         txt.append(", asyncContext: ").append((ctx == null) ? "null" : "not null");
+         LOGGER.fine(txt.toString());
 
          switch (adb.getType()) {
-         case TEXT:
-            LOGGER.fine("Producing text output.");
-            StringBuilder txt = new StringBuilder(128);
-            txt.append("<p>AsyncRunnable.");
-            txt.append(" dispatcher type: ").append(req.getDispatcherType().toString());
-            txt.append("</p>");
-            resp.getWriter().write(txt.toString());
-            if (done && ctx != null) {
-               ctx.complete();
-            }
-            break;
          case DISPATCH:
             LOGGER.fine("Dispatching to JSP.");
             if (ctx != null) {
@@ -165,6 +175,7 @@ public class AsyncPortletResource {
             break;
          case FWD:
             LOGGER.fine("Doing request dispatcher forward to JSP.");
+            req.setAttribute(ATTRIB_TITLE, "Resource Method forwarding to JSP");
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.forward(req, resp);
             if (done && ctx != null) {
@@ -173,6 +184,7 @@ public class AsyncPortletResource {
             break;
          case INC:
             LOGGER.fine("Doing request dispatcher include of JSP.");
+            req.setAttribute(ATTRIB_TITLE, "Resource Method including JSP");
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.include(req, resp);
             if (done && ctx != null) {
@@ -180,6 +192,15 @@ public class AsyncPortletResource {
             }
             break;
          default:
+            LOGGER.fine("Producing text output.");
+            txt.setLength(0);
+            txt.append("<h5>Async portlet resource method producing text output</h5>");
+            txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
+            txt.append("</p>");
+            resp.getWriter().write(txt.toString());
+            if (done && ctx != null) {
+               ctx.complete();
+            }
             break;
          }
       }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/46a03a15/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
index fbffdb2..a939991 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -4,6 +4,6 @@
 <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
 
 
-<h5>Async JSP Output</h5>
+<h5><%=request.getAttribute("title") %></h5>
 <p>Dispatch type: <%=request.getDispatcherType() %></p>
 <hr>


[04/34] portals-pluto git commit: Added methods for asynchronous processing on ResourceRequest. Added async configuration items on @PortletConfiguration and @ServeResourceMethod annotations. Added async-supported item to portlet deployment descriptor XSD

Posted by ms...@apache.org.
Added methods for asynchronous processing on ResourceRequest. Added async
configuration items on @PortletConfiguration and @ServeResourceMethod
annotations. Added async-supported item to portlet deployment descriptor
XSD. Added method stubs on ResourceRequestImpl.


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

Branch: refs/heads/V3Prototype
Commit: e14ab8607cb720e10152c1354b3b51345aa9aec6
Parents: c19723e
Author: Scott Nicklous <ms...@apache.org>
Authored: Fri Mar 11 14:55:08 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Fri Mar 11 14:55:08 2016 +0100

----------------------------------------------------------------------
 .../container/impl/ResourceRequestImpl.java     |  33 +++
 .../pluto/container/impl/portlet-app_3_0.xsd    |  16 +-
 .../fixtures/mocks/MockResourceRequest.java     |  33 +++
 .../java/javax/portlet/ResourceRequest.java     | 204 +++++++++++++++++++
 .../annotations/PortletConfiguration.java       |  11 +
 .../annotations/ServeResourceMethod.java        |  11 +
 .../javax/portlet/filter/ResourceFilter.java    |  26 ++-
 .../portlet/filter/ResourceRequestWrapper.java  |  33 +++
 portlet-api/src/main/javadoc/overview.html      |  16 ++
 portlet-api/src/main/javadoc/portlet-api.css    |   1 +
 10 files changed, 380 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/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 e09ce3a..96aa81e 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
@@ -23,6 +23,9 @@ import javax.portlet.CacheControl;
 import javax.portlet.PortletRequest;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResourceResponseContext;
@@ -107,4 +110,34 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    public ResourceParameters getResourceParameters() {
       return requestContext.getResourceParameters();
    }
+
+   @Override
+   public AsyncContext startAsync() throws IllegalStateException {
+      return null;
+   }
+
+   @Override
+   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+      return null;
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return false;
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return false;
+   }
+
+   @Override
+   public AsyncContext getAsyncContext() {
+      return null;
+   }
+
+   @Override
+   public DispatcherType getDispatcherType() {
+      return null;
+   }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/pluto-container/src/main/resources/org/apache/pluto/container/impl/portlet-app_3_0.xsd
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/resources/org/apache/pluto/container/impl/portlet-app_3_0.xsd b/pluto-container/src/main/resources/org/apache/pluto/container/impl/portlet-app_3_0.xsd
index fc0f672..8d97be1 100644
--- a/pluto-container/src/main/resources/org/apache/pluto/container/impl/portlet-app_3_0.xsd
+++ b/pluto-container/src/main/resources/org/apache/pluto/container/impl/portlet-app_3_0.xsd
@@ -142,7 +142,8 @@
 			<element name="default-namespace" type="xs:anyURI" minOccurs="0"/>
 			<element name="event-definition" type="portlet:event-definitionType" minOccurs="0" maxOccurs="unbounded"/>
 			<element name="public-render-parameter" type="portlet:public-render-parameterType" minOccurs="0" maxOccurs="unbounded"/>
-			<element name="listener" type="portlet:listenerType" minOccurs="0" maxOccurs="unbounded"/>
+			<element name="listener" type="portlet:listenerType" minOccurs="0" maxOccurs="unbounded"/>
+
 			<element name="container-runtime-option" type="portlet:container-runtime-optionType" minOccurs="0" maxOccurs="unbounded"/>
 		</sequence>
 		<attribute name="version" type="portlet:string" use="required"/>
@@ -305,7 +306,15 @@
 			<element name="supported-publishing-event" type="portlet:event-definition-referenceType" minOccurs="0" maxOccurs="unbounded"/>
 			<element name="supported-public-render-parameter" type="portlet:string" minOccurs="0" maxOccurs="unbounded"/>
 			<element name="container-runtime-option" type="portlet:container-runtime-optionType" minOccurs="0" maxOccurs="unbounded"/>
-			<element name="dependency" type="portlet:dependencyType" minOccurs="0" maxOccurs="unbounded"/>
+			<element name="dependency" type="portlet:dependencyType" minOccurs="0" maxOccurs="unbounded"/>
+            <element name="async-supported" type="boolean" minOccurs="0" maxOccurs="1">
+               <annotation>
+                  <documentation>
+                     If set to 'true', the portlet will support
+                     asynchronous processing in resource requests.
+                  </documentation>
+               </annotation>
+            </element>
 		</sequence>
 		<attribute name="id" type="portlet:string" use="optional"/>
 	</complexType>
@@ -425,7 +434,8 @@
 			<element name="name" type="xs:NCName"/>
 		</choice>
 		<attribute name="id" type="portlet:string" use="optional"/>
-	</complexType>
+	</complexType>
+
 	<complexType name="listenerType">
 		<annotation>
 			<documentation>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
index 6a36ed5..2b4d1a2 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
@@ -23,6 +23,9 @@ import java.util.Map;
 
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 
 /**
  * @author Scott Nicklous
@@ -86,4 +89,34 @@ public class MockResourceRequest extends MockClientDataRequest implements Resour
       return null;
    }
 
+   @Override
+   public AsyncContext startAsync() throws IllegalStateException {
+      return null;
+   }
+
+   @Override
+   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+      return null;
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return false;
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return false;
+   }
+
+   @Override
+   public AsyncContext getAsyncContext() {
+      return null;
+   }
+
+   @Override
+   public DispatcherType getDispatcherType() {
+      return null;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/ResourceRequest.java b/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
index 7863897..24177a8 100644
--- a/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
+++ b/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
@@ -24,6 +24,9 @@
 
 package javax.portlet;
 
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+
 /**
  * <span class="changed_modified_3_0">The</span>
  * <code>ResourceRequest</code> interface represents the request
@@ -234,4 +237,205 @@ public interface ResourceRequest extends ClientDataRequest {
 
    public WindowState getWindowState ();
 
+
+   /**
+    * <div class="changed_added_3_0">
+    * Puts this request into asynchronous mode and initializes the <code>AsyncContext</code>
+    * object.
+    * <p>
+    * Calling this method will cause committal of the associated response to be delayed until 
+    * <code>AsyncContext#complete</code> is called on the returned <code>AsyncContext</code>,
+    * or the asynchronous operation has timed out.
+    * <p>
+    * This method clears the list of <code>AsyncListener</code> instances (if any) that were
+    * registered with the <code>AsyncContext</code> returned by the previous call to one of the
+    * <code>startAsync</code> methods, after calling each <code>AsyncListener</code> at 
+    * its <code>onStartAsync</code> method.
+    * <p>
+    * Subsequent invocations of this method, or its overloaded variant, will return
+    * the same <code>AsyncContext</code> instance, reinitialized as appropriate.
+    * <p> 
+    * The <code>AsyncContext</code> object can be used as described by the servlet
+    * specification. The <code>ServletRequest</code> and <code>ServletResponse</code> 
+    * objects obtained from the <code>AsyncContext</code> will provide functionality 
+    * appropriate for the portlet environment.
+    * <p>
+    * The original <code>ResourceRequest</code> and <code>ResourceResponse</code> objects
+    * will be made available as request attributes on the code>ServletRequest</code> object 
+    * obtained from the <code>AsyncContext</code> under the names 
+    * <code>javax.portlet.request</code>
+    * and <code>javax.portlet.response</code>, respectively.
+    * The <code>PortletConfig</code> object will be made available on the 
+    * <code>ServletRequest</code> under the name 
+    * <code>javax.portlet.config</code>.
+    * <p>
+    * The <code>AsyncContext#dispatch()</code> method will cause the portlet resource
+    * method to be invoked with the <code>ResourceRequest</code> and <code>ResourceResponse</code>
+    * objects available as attributes on the <code>ServletRequest</code> object obtained from
+    * the <code>AsyncContext</code>.
+    * In this case, the <code>ResourceRequest#isAsyncStarted()</code> method will return 
+    * <code>false</code> and the <code>ResourceRequest#getDispatcherType()</code> method
+    * will return <code>DispatcherType#ASYNC</code>.
+    * <p>
+    * A portlet <code>ResourceFilter</code> that allocates resources and attaches them to the 
+    * <code>ResourceRequest</code> or that wraps the <code>ResourceRequest</code> or
+    * <code>ResourceResponse</code> should not release resources in the outbound direction
+    * if asynchronous mode has been started.
+    * A portlet <code>ResourceFilter</code> can use the values provided by the 
+    * <code>ResourceRequest#isAsyncStarted()</code> and the
+    * <code>ResourceRequest#getDispatcherType()</code> methods to determine when to
+    * allocate and release resources.
+    * </div>
+    * 
+    * @return  the (re)initialized AsyncContext 
+    * @since   3.0
+    * @see     javax.servlet.ServletRequest#startAsync()
+    * @see     javax.servlet.AsyncContext
+    * @see     #isAsyncStarted() 
+    * @see     #getDispatcherType()
+    * @see     javax.portlet.filter.ResourceFilter
+    */
+
+   public AsyncContext startAsync() throws IllegalStateException;
+
+
+   /**
+    * <div class="changed_added_3_0">
+    * Puts this request into asynchronous mode and initializes the <code>AsyncContext</code>
+    * object.
+    * <p>
+    * Calling this method will cause committal of the associated response to be delayed until 
+    * <code>AsyncContext#complete</code> is called on the returned <code>AsyncContext</code>,
+    * or the asynchronous operation has timed out.
+    * <p>
+    * This method clears the list of <code>AsyncListener</code> instances (if any) that were
+    * registered with the <code>AsyncContext</code> returned by the previous call to one of the
+    * <code>startAsync</code> methods, after calling each <code>AsyncListener</code> at 
+    * its <code>onStartAsync</code> method.
+    * <p> 
+    * The <code>AsyncContext</code> object can be used as described by the servlet
+    * specification. The <code>ServletRequest</code> and <code>ServletResponse</code> 
+    * objects obtained from the <code>AsyncContext</code> will provide functionality 
+    * appropriate for the portlet environment.
+    * <p>
+    * The <code>ResourceRequest</code> and <code>ResourceResponse</code> objects
+    * passed as arguments to this method
+    * will be made available as request attributes on the code>ServletRequest</code> object 
+    * obtained from the <code>AsyncContext</code> under the names 
+    * <code>javax.portlet.request</code>
+    * and <code>javax.portlet.response</code>, respectively.
+    * The <code>PortletConfig</code> object will be made available on the 
+    * <code>ServletRequest</code> under the name 
+    * <code>javax.portlet.config</code>.
+    * <p>
+    * Subsequent invocations of this method, or its zero-argument variant, will return
+    * the same <code>AsyncContext</code> instance, reinitialized as appropriate.
+    * If a call to this method is followed by a call to its zero-argument variant, 
+    * the specified (and possibly wrapped) <code>ResourceRequest</code> and 
+    * <code>ResourceResponse</code> objects will remain available  
+    * as request attributes on the <code>ServletRequest</code> object 
+    * obtained from the <code>AsyncContext</code>.
+    * <p>
+    * The <code>AsyncContext#dispatch()</code> method will cause the portlet resource
+    * method to be invoked with the <code>ResourceRequest</code> and <code>ResourceResponse</code>
+    * objects available as attributes on the <code>ServletRequest</code> object obtained from
+    * the <code>AsyncContext</code>.
+    * In this case, the <code>ResourceRequest#isAsyncStarted()</code> method will return 
+    * <code>false</code> and the <code>ResourceRequest#getDispatcherType()</code> method
+    * will return <code>DispatcherType#ASYNC</code>.
+    * <p>
+    * A portlet <code>ResourceFilter</code> that allocates resources and attaches them to the 
+    * <code>ResourceRequest</code> or that wraps the <code>ResourceRequest</code> or
+    * <code>ResourceResponse</code> should not release resources in the outbound direction
+    * if asynchronous mode has been started.
+    * A portlet <code>ResourceFilter</code> can use the values provided by the 
+    * <code>ResourceRequest#isAsyncStarted()</code> and the
+    * <code>ResourceRequest#getDispatcherType()</code> methods to determine when to
+    * allocate and release resources.
+    * </div>
+    * 
+    * @return  the (re)initialized AsyncContext 
+    * @since   3.0
+    * @see     javax.servlet.ServletRequest#startAsync()
+    * @see     javax.servlet.AsyncContext 
+    * @see     #isAsyncStarted() 
+    * @see     #getDispatcherType()
+    * @see     javax.portlet.filter.ResourceFilter
+    */
+
+   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException;
+
+
+   /**
+    * <div class="changed_added_3_0">
+    * Checks if this request has been put into asynchronous mode. 
+    * <p>
+    * A <code>ResourceRequest</code> is put into asynchronous mode by calling 
+    * <code>startAsync()</code> or <code>startAsync(ResourceRequest,ResourceResponse)</code>
+    * on it. 
+    * <p>
+    * This method returns <code>false</code> if this request was put into asynchronous mode, 
+    * but has since been dispatched using one of the <code>AsyncContext#dispatch</code> 
+    * methods or released from asynchronous mode via a call to <code>AsyncContext#complete</code>. 
+    * </div>
+    * 
+    * @return   <code>true</code> if asynchronous mode has been started
+    * @since    3.0
+    * @see      #startAsync()
+    * @see      #startAsync(ResourceRequest, ResourceResponse)
+    */
+
+   public boolean isAsyncStarted();
+   
+
+   /**
+    * <div class="changed_added_3_0">
+    * Checks if this request supports asynchronous operation. 
+    * <p>
+    * Asynchronous operation is disabled for this request if this request is within 
+    * the scope of a filter or servlet that has not been annotated or flagged in 
+    * the portlet configuration as being able to support asynchronous handling. 
+    * </div>
+    * 
+    * @return   <code>true</code> if this request supports asynchronous operation
+    * @since    3.0
+    */
+
+   public boolean isAsyncSupported();
+
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the <code>AsyncContext</code> that was created or reinitialized by the most 
+    * recent invocation of <code>startAsync()</code> or 
+    * <code>startAsync(ResourceRequest,ResourceResponse)</code> on this request. 
+    * </div>
+    * 
+    * @return   the <code>AsyncContext</code> (re)initialized by the most recent <code>startAsync</code> method invocation 
+    * @since    3.0
+    * @see      javax.servlet.ServletRequest#startAsync()
+    * @see      javax.servlet.AsyncContext 
+    */
+   
+   public AsyncContext getAsyncContext();
+
+
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the dispatcher type of this request. 
+    * <p>
+    * The initial dispatcher type of a request is defined as <code>DispatcherType.REQUEST</code>.
+    * The dispatcher type of a request dispatched via a <code>RequestDispatcher</code>
+    * is given as <code>DispatcherType.FORWARD</code> or <code>DispatcherType.INCLUDE</code>, 
+    * while the dispatcher type of an asynchronous request dispatched via one of the
+    * <code>AsyncContext#dispatch</code> methods is given as <code>DispatcherType.ASYNC</code>.
+    * </div>
+    * 
+    * @return   the dispatcher type of this request
+    * @since    3.0
+    * @see      javax.servlet.DispatcherType
+    */
+
+   public DispatcherType getDispatcherType();
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/java/javax/portlet/annotations/PortletConfiguration.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/annotations/PortletConfiguration.java b/portlet-api/src/main/java/javax/portlet/annotations/PortletConfiguration.java
index 7508094..140993f 100644
--- a/portlet-api/src/main/java/javax/portlet/annotations/PortletConfiguration.java
+++ b/portlet-api/src/main/java/javax/portlet/annotations/PortletConfiguration.java
@@ -223,4 +223,15 @@ public @interface PortletConfiguration {
     * @return  The security role references
     */
    SecurityRoleRef[]   roleRefs() default {};
+   
+   /**
+    * Declares whether the portlet supports asynchronous operation mode.
+    * <p>
+    * If this flag is set, any resource method used by this portlet will
+    * be marked as supporting asynchronous operation.
+    * Asynchronous support applies to resource methods only.
+    *  
+    * @return  <code>true</code> if the method supports asynchronous mode.
+    */
+   boolean asyncSupported() default false;
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/java/javax/portlet/annotations/ServeResourceMethod.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/annotations/ServeResourceMethod.java b/portlet-api/src/main/java/javax/portlet/annotations/ServeResourceMethod.java
index af64501..4a05b2c 100644
--- a/portlet-api/src/main/java/javax/portlet/annotations/ServeResourceMethod.java
+++ b/portlet-api/src/main/java/javax/portlet/annotations/ServeResourceMethod.java
@@ -154,4 +154,15 @@ public @interface ServeResourceMethod {
     * @return     The ordinal number
     */
    int        ordinal() default 0;
+   
+   /**
+    * Declares whether the serve resource method supports asynchronous operation mode.
+    * <p>
+    * If this flag is set, any portlet to which this annotated method applies will
+    * be marked as supporting asynchronous operation.
+    * Asynchronous support applies to resource methods only.
+    *  
+    * @return  <code>true</code> if the method supports asynchronous mode.
+    */
+   boolean asyncSupported() default false;
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java b/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
index 96babc3..94ae61d 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
@@ -31,7 +31,8 @@ import javax.portlet.ResourceResponse;
 import javax.portlet.PortletException;
 
 /**
- * The <code>ResourceFilter</code> is an object that performs filtering 
+ * <span class="changed_modified_3_0">The</span>
+ * <code>ResourceFilter</code> is an object that performs filtering 
  * tasks on either the resource request to a portlet, or on the resource response from 
  * a portlet, or both.
  * <p>
@@ -42,6 +43,29 @@ import javax.portlet.PortletException;
  * <p>
  * Filters are configured in the portlet deployment descriptor of a 
  * portlet application. 
+ * <p>
+ * <div class="changed_added_3_0">
+ * <strong>Asynchronous Processing Considerations</strong>
+ * <p>
+ * If the <code>ResourceFilter</code> is to support asynchronous mode, care must be taken
+ * regarding resource allocation and release.
+ * Any resources attached to the <code>ResourceRequest</code> during the inbound portion
+ * of the <code>doFilter</code> invocation
+ * and needed during asynchronous processing should not be released during outbound processing
+ * if asynchronous mode has been started.
+ * <p>
+ * If resources must be allocated in this way during inbound processing, the portlet should
+ * use the <code>AsyncContext#dispatch()</code> method at the end of asynchronous processing
+ * in order to cause the portlet resource method to be invoked again with the same
+ * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects.
+ * The resources can be released during asynchronous dispatch outbound processing.
+ * <p>
+ * The <code>ResourceRequest#isAsyncStarted()</code> method will return <code>true</code>
+ * if the portlet is currently in asynchronous mode.
+ * The <code>ResourceRequest#igetDispatcherType()</code> method will return 
+ * <code>DispatcherType#REQUEST</code> during initial request processing and
+ * <code>DipatcherType#ASYNC</code> during processing resulting from an asynchronous dispatch.
+ * </div>
  * 
  * @since 2.0
  */

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
index 5ce2388..406a8c7 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
@@ -28,6 +28,9 @@ import java.util.Map;
 
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 
 /**
  * <span class="changed_modified_3_0">The</span>  
@@ -115,4 +118,34 @@ public class ResourceRequestWrapper extends ClientDataRequestWrapper implements
       return ((ResourceRequest)wrapped).getResourceParameters();
    }
 
+   @Override
+   public AsyncContext startAsync() throws IllegalStateException {
+      return ((ResourceRequest)wrapped).startAsync();
+   }
+
+   @Override
+   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+      return ((ResourceRequest)wrapped).startAsync(request, response);
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return ((ResourceRequest)wrapped).isAsyncStarted();
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return ((ResourceRequest)wrapped).isAsyncSupported();
+   }
+
+   @Override
+   public AsyncContext getAsyncContext() {
+      return ((ResourceRequest)wrapped).getAsyncContext();
+   }
+
+   @Override
+   public DispatcherType getDispatcherType() {
+      return ((ResourceRequest)wrapped).getDispatcherType();
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/overview.html b/portlet-api/src/main/javadoc/overview.html
index 4c1eaf7..ade4007 100644
--- a/portlet-api/src/main/javadoc/overview.html
+++ b/portlet-api/src/main/javadoc/overview.html
@@ -21,6 +21,22 @@
     <div class="indexContainer-not">
     <ul>
     <li>
+    20160316:
+    Added new methods, configuration elements, and documentation to implement 
+    <a href="https://java.net/jira/browse/PORTLETSPEC3-68">PORTLETSPEC3-68 Add Async Support</a>:
+    {@link javax.portlet.annotations.PortletConfiguration#asyncSupported() PortletConfiguration#asyncSupported()}, 
+    {@link javax.portlet.annotations.ServeResourceMethod#asyncSupported() ServeResourceMethod#asyncSupported()}, 
+    {@link javax.portlet.ResourceRequest#startAsync() ResourceRequest#startAsync()}, 
+    {@link javax.portlet.ResourceRequest#startAsync(ResourceRequest, ResourceResponse) ResourceRequest#startAsync(ResourceRequest, ResourceResponse)}, 
+    {@link javax.portlet.ResourceRequest#isAsyncStarted() ResourceRequest#isAsyncStarted()}, 
+    {@link javax.portlet.ResourceRequest#isAsyncSupported() ResourceRequest#isAsyncSupported()}, 
+    {@link javax.portlet.ResourceRequest#getAsyncContext() ResourceRequest#getAsyncContext()}, and 
+    {@link javax.portlet.ResourceRequest#getDispatcherType() ResourceRequest#getDispatcherType()}.
+    Added appropriate documentation to 
+    {@link javax.portlet.filter.ResourceFilter ResourceFilter}.
+    Updated affected wrapper classes accordingly.
+    </li>
+    <li>
     20160315:
     Added new methods to implement 
     <a href="https://java.net/jira/browse/PORTLETSPEC3-63">PORTLETSPEC3-63</a>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/e14ab860/portlet-api/src/main/javadoc/portlet-api.css
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/portlet-api.css b/portlet-api/src/main/javadoc/portlet-api.css
index 3a84aa1..14cc9ea 100644
--- a/portlet-api/src/main/javadoc/portlet-api.css
+++ b/portlet-api/src/main/javadoc/portlet-api.css
@@ -529,6 +529,7 @@ h1.hidden {
 .indexContainer a[href*="StateAwareResponse.html"],
 .indexContainer a[href*="EventResponse.html"],
 .indexContainer a[href*="MimeResponse.html"],
+.indexContainer a[href*="ResourceFilter.html"],
 .indexContainer a[href*="ResourceURL.html"],
 .indexContainer a[href*="ResourceResponse.html"],
 .indexContainer a[href*="ActionRequestWrapper.html"],


[08/34] portals-pluto git commit: progress on async support. Modifications to portlet container and portal driver servlet

Posted by ms...@apache.org.
progress on async support. Modifications to portlet container and portal driver servlet


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

Branch: refs/heads/V3Prototype
Commit: ae198fe2959f446f0966e7af31c6d2d09f919b72
Parents: 49ca2dd
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Mar 22 16:18:30 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Mar 22 16:18:30 2016 +0100

----------------------------------------------------------------------
 .../portals/samples/AsyncHackPortlet.java       | 32 +++++++++++---
 .../container/impl/PortletContainerImpl.java    | 27 ++++++------
 .../pluto/driver/PortalDriverServlet.java       | 45 --------------------
 .../container/DefaultPortletInvokerService.java | 17 ++++----
 4 files changed, 45 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ae198fe2/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
index 9e2c243..80eba8c 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
@@ -44,6 +44,26 @@ public class AsyncHackPortlet {
 
    public static final String RESPARAM_DISPLAY = "display";
 
+   private AsyncContext context;
+   private static final String jsp = "/WEB-INF/jsp/pathinfo.jsp";
+//   private static final String jsp = "/ais";
+
+   
+   private class AsyncHackRunnable implements Runnable {
+
+      @Override
+      public void run() {
+         try {
+            Thread.sleep(1000);
+         } catch (InterruptedException e) {}
+         LOGGER.fine("Slept, now dispatching.");
+         HttpServletRequest hreq = (HttpServletRequest) context.getRequest();
+         context.dispatch(hreq.getServletContext(), jsp);
+//       context.dispatch(jsp);
+      }
+      
+   }
+
    // Injecting the namespace & URLFactory
    @Inject
    @Namespace
@@ -114,8 +134,6 @@ public class AsyncHackPortlet {
       StringBuilder txt = new StringBuilder(128);
       txt.append("Trying to start async. Servlet context: ").append(hreq.getServletContext().getContextPath());
 
-      String jsp = "/WEB-INF/jsp/pathinfo.jsp";
-//      String jsp = "/ais";
 //      RequestDispatcher rd = null;
 //      rd = hreq.getRequestDispatcher(jsp);
 //      txt.append("Request dispatcher: ").append(rd);
@@ -125,14 +143,14 @@ public class AsyncHackPortlet {
       if (hreq != null && hresp != null) {
          try {
             
-            AsyncContext context = hreq.startAsync(hreq, hresp);
-            context.setTimeout(1000);
+            context = hreq.startAsync(hreq, hresp);
+            context.setTimeout(4000);
             
             txt.append("Async context: ").append((context == null) ? "null." : "not null.");
-            txt.append(" Now dispatching ... ");
+            txt.append(" Now starting thread ... ");
 
-//            context.dispatch(hreq.getServletContext(), jsp);
-            context.dispatch(jsp);
+            AsyncHackRunnable ahr = new AsyncHackRunnable();
+            context.start(ahr);
             
             txt.append(" done. ");
          } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ae198fe2/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
index dc17d7f..44f2035 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
@@ -268,22 +268,19 @@ public class PortletContainerImpl implements PortletContainer
 
         FilterManager filterManager = filterInitialisation(portletWindow,PortletRequest.RESOURCE_PHASE);
         
-        if (portletWindow.getPortletDefinition().isAsyncSupported()) {
-           LOG.debug("invoking for async ... no resource release");
+        try
+        {
            invoker.serveResource(requestContext, portletRequest, portletResponse, filterManager);
-           
-        } else {
-           LOG.debug("invocation through request dispatcher.");
-           try
-           {
-              invoker.serveResource(requestContext, portletRequest, portletResponse, filterManager);
-              // Mark portlet interaction is completed: backend implementation can flush response state now
-              responseContext.close();
-           }
-           finally
-           {
-              responseContext.release();
-           }
+        }
+        finally
+        {
+            if (!request.isAsyncSupported() || !request.isAsyncStarted()) {
+                // Mark portlet interaction is completed: backend implementation can flush response state now
+                responseContext.close();
+                responseContext.release();
+            } else {
+               LOG.debug("Async started for resource request. responseContext not released.");
+            }
         }
 
         debugWithName("Portlet resource done for: " + portletWindow.getPortletDefinition().getPortletName());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ae198fe2/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
index 722b037..81ec5e9 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
@@ -145,51 +145,6 @@ public class PortalDriverServlet extends HttpServlet {
             LOG.debug("Processing " + reqType + " request for window: " + portletWindow.getId().getStringId());
          }
 
-         
-//          String portletName = portletWindow.getPortletName();
-//          if (portletName.equals("AsyncHackPortlet")
-//                && portalURL.getType() == URLType.Resource) {
-// 
-//             String uri =  PortletInvokerService.URIPREFIX + portletWindow.getPortletDefinition().getPortletName();
-//             String ctxpath =  "/PortletV3AnnotatedDemo";
-//             String jsp = "/WEB-INF/jsp/pathinfo.jsp";
-//             
-// //            LOG.debug("Directly doing async dispatch to JSP. uri: " + uri + ", jsp: " + jsp);
-//             LOG.debug("Directly dispatching to portlet servlet. uri: " + uri);
-//             
-//             ServletContext ctx = request.getServletContext().getContext(ctxpath);
-//             RequestDispatcher rd = ctx.getRequestDispatcher(uri);
-//             rd.forward(request, response);
-//             LOG.debug("Completed the dispatch.");
-//             return;
-//             
-// //             ServletContext ctx = request.getServletContext().getContext(ctxpath);
-// //             if (ctx == null) {
-// //                LOG.debug("couldn't get context for uri.");
-// //             } else {
-// //                LOG.debug("Got context, path: >>>" + ctx.getContextPath() + "<<<");
-// // 
-// //                AsyncContext context = request.startAsync();
-// //                context.dispatch(ctx, jsp);
-// //                
-// //                LOG.debug("Completed the dispatch.");
-// //                return;
-// // 
-// //                
-// //               RequestDispatcher rd = ctx.getRequestDispatcher(jsp);
-// //               if (rd == null) {
-// //                  LOG.debug("couldn't get request dispatcher for context.");
-// //               } else {
-// //                  LOG.debug("Got the request dispatcher.");
-// // //                  PrintWriter writer = response.getWriter();
-// // //                  writer.append("<h5>Greetings from portal driver servlet!</h5>");
-// //                  rd.include(request, response);
-// //                  LOG.debug("Dispatch seemed to go OK.");
-// //                  return;
-// //               }
-// //             }
-//          }
-
          try {
             PageState ps;
             String jsondata;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ae198fe2/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 3d1e4ea..20d8a8b 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
@@ -17,6 +17,8 @@
 package org.apache.pluto.driver.container;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
@@ -240,14 +242,8 @@ public class DefaultPortletInvokerService implements PortletInvokerService {
 
                 if (methodID.equals(PortletInvokerService.METHOD_RESOURCE))
                 {
-                    if (portletWindow.getPortletDefinition().isAsyncSupported()) {
-                       LOG.debug("Async dispatching resource request to portlet servlet.");
-                       AsyncContext actx = containerRequest.startAsync(containerRequest, containerResponse);
-                       actx.dispatch(servletContext, uri);
-                    } else {
-                       LOG.debug("Request dispatcher forward resource request to portlet servlet.");
-                       dispatcher.forward(containerRequest, containerResponse);
-                    }
+                    LOG.debug("Request dispatcher forward resource request to portlet servlet.");
+                    dispatcher.forward(containerRequest, containerResponse);
                     LOG.debug("Dispatch complete.");
                 }
                 else
@@ -284,11 +280,14 @@ public class DefaultPortletInvokerService implements PortletInvokerService {
                 }
 
             } finally {
-                if (!portletWindow.getPortletDefinition().isAsyncSupported()) {
+                if (!containerRequest.isAsyncSupported() || !containerRequest.isAsyncStarted()) {
+                   LOG.debug("After invocation, removing attributes.");
                    containerRequest.removeAttribute(PortletInvokerService.METHOD_ID);
                    containerRequest.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
                    containerRequest.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
                    containerRequest.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+                } else {
+                   LOG.debug("After invocation, async started for resource request. attributes not removed.");
                 }
             }
         } else {


[30/34] portals-pluto git commit: Completed contextual support for listeners and threads run by AsyncContext#start(). Expanded async demo portlet to show information from filters and listeners when possible. Fixed several bugs to allow resources to be cl

Posted by ms...@apache.org.
Completed contextual support for listeners and threads run by
AsyncContext#start(). Expanded async demo portlet to show information from
filters and listeners when possible. Fixed several bugs to allow resources
to be cleanly released when a timeout occurs.


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

Branch: refs/heads/V3Prototype
Commit: 9fa76dbe99b6bf5fe169befdbbf520befca68b7f
Parents: 74d5f10
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Apr 5 16:10:12 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Apr 5 16:10:12 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java |  69 +++++++---
 .../portals/samples/AsyncPortletFilter.java     |   3 +-
 .../portals/samples/AsyncPortletListener.java   |  83 +++++++++---
 .../portals/samples/AsyncPortletResource.java   |  28 +++-
 .../src/main/webapp/WEB-INF/jsp/asyncDialog.jsp |   4 +-
 .../src/main/webapp/resources/css/infobox.css   |  10 ++
 .../pluto/container/PortletAsyncContext.java    |  10 +-
 .../PortletResourceRequestContext.java          |   3 +
 .../pluto/container/driver/PortletServlet3.java |  11 +-
 .../container/PortletAsyncContextImpl.java      | 125 +++++++++++++-----
 .../container/PortletAsyncContextualRunner.java |   4 +-
 .../container/PortletAsyncListener.java         | 129 +++++++++++++++++--
 .../PortletResourceRequestContextImpl.java      |  25 +++-
 13 files changed, 407 insertions(+), 97 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index c5717bc..d90af02 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -56,6 +56,7 @@ public class AsyncDialogBean implements PortletSerializable {
    public static final String PARAM_REPS     = "reps";
    public static final String PARAM_AUTO     = "auto";
    public static final String PARAM_FILTER   = "filter";
+   public static final String PARAM_LISTENER = "listener";
    public static final String PARAM_TYPE     = "type";
    public static final String PARAM_TYPE_TXT = OutputType.TEXT.toString();
    public static final String PARAM_TYPE_INC = OutputType.INC.toString();
@@ -71,8 +72,9 @@ public class AsyncDialogBean implements PortletSerializable {
    private OutputType         type;
    private String             msg;
    private boolean            autoDispatch;
-   private boolean            useFilter;
+   private boolean            showFilter;
    private TimeoutType        handleTimeout;
+   private boolean            showListener;
 
    /**
     * This method is called by the portlet container to initialize the bean at
@@ -87,16 +89,18 @@ public class AsyncDialogBean implements PortletSerializable {
          type = OutputType.TEXT;
          msg = null;
          autoDispatch = true;
-         useFilter = false;
+         showFilter = false;
          handleTimeout = TimeoutType.CPL;
+         showListener = false;
       } else {
          delay = Integer.parseInt(state[0]);
          reps = Integer.parseInt(state[1]);
          type = OutputType.valueOf(state[2]);
          msg = state[3];
          autoDispatch = Boolean.parseBoolean(state[4]);
-         useFilter = Boolean.parseBoolean(state[5]);
+         showFilter = Boolean.parseBoolean(state[5]);
          handleTimeout = TimeoutType.valueOf(state[6]);
+         showListener = Boolean.parseBoolean(state[7]);
       }
       LOGGER.fine("deserialized: " + Arrays.asList(state).toString());
    }
@@ -108,7 +112,7 @@ public class AsyncDialogBean implements PortletSerializable {
    @Override
    public String[] serialize() {
       String[] state = { "" + delay, "" + reps, type.toString(), msg, 
-            ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
+            ""+autoDispatch, ""+showFilter, handleTimeout.toString(), ""+showListener };
       LOGGER.fine("serialized: " + Arrays.asList(state).toString());
       return state;
    }
@@ -189,31 +193,45 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
-    * @return the useFilter
+    * @return the handleTimeout
     */
-   public boolean isUseFilter() {
-      return useFilter;
+   public TimeoutType getHandleTimeout() {
+      return handleTimeout;
    }
 
    /**
-    * @param useFilter the useFilter to set
+    * @param handleTimeout the handleTimeout to set
     */
-   public void setUseFilter(boolean useFilter) {
-      this.useFilter = useFilter;
+   public void setHandleTimeout(TimeoutType handleTimeout) {
+      this.handleTimeout = handleTimeout;
    }
 
    /**
-    * @return the handleTimeout
+    * @return the showFilter
     */
-   public TimeoutType getHandleTimeout() {
-      return handleTimeout;
+   public boolean isShowFilter() {
+      return showFilter;
    }
 
    /**
-    * @param handleTimeout the handleTimeout to set
+    * @param showFilter the showFilter to set
     */
-   public void setHandleTimeout(TimeoutType handleTimeout) {
-      this.handleTimeout = handleTimeout;
+   public void setShowFilter(boolean showFilter) {
+      this.showFilter = showFilter;
+   }
+
+   /**
+    * @return the showListener
+    */
+   public boolean isShowListener() {
+      return showListener;
+   }
+
+   /**
+    * @param showListener the showListener to set
+    */
+   public void setShowListener(boolean showListener) {
+      this.showListener = showListener;
    }
 
    /**
@@ -283,13 +301,13 @@ public class AsyncDialogBean implements PortletSerializable {
 
       String filter = req.getActionParameters().getValue(PARAM_FILTER);
       if (filter != null) {
-         useFilter = true;
+         showFilter = true;
          if ((type == OutputType.FWD)) {
             msg = "Filter can't generate output with forward processing.";
-            useFilter = false;
+            showFilter = false;
          }
       } else {
-         useFilter = false;
+         showFilter = false;
       }
 
       String strto = req.getActionParameters().getValue(PARAM_TO);
@@ -301,8 +319,19 @@ public class AsyncDialogBean implements PortletSerializable {
          }
       }
 
+      String lstnr = req.getActionParameters().getValue(PARAM_LISTENER);
+      if (lstnr != null) {
+         showListener = true;
+         if ((type == OutputType.FWD)) {
+            msg = "Listener can't generate output with forward processing.";
+            showListener = false;
+         }
+      } else {
+         showListener = false;
+      }
+
       String[] state = { "" + delay, "" + reps, type.toString(), msg, 
-            ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
+            ""+autoDispatch, ""+showFilter, handleTimeout.toString() };
       LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
index f7c430e..09eff20 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
@@ -19,7 +19,6 @@
 package org.apache.portals.samples;
 
 import java.io.IOException;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -65,7 +64,7 @@ public class AsyncPortletFilter implements ResourceFilter {
       txt.append(", request #: ").append(reqnum.getRandomNumber());
       LOGGER.fine(txt.toString());
       
-      if (adb.isUseFilter()) {
+      if (adb.isShowFilter()) {
          txt.setLength(0);
          txt.append("<div class='msgbox'>");
          txt.append("Filter: Request number: ").append(reqnum.getRandomNumber());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
index ce2086c..d8fd5fb 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
@@ -20,21 +20,32 @@ package org.apache.portals.samples;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
-import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.apache.portals.samples.AsyncDialogBean.TimeoutType;
+import static org.apache.portals.samples.AsyncPortletResource.*;
 
 /**
  * @author Scott Nicklous
- *
+ * 
  */
 public class AsyncPortletListener implements AsyncListener {
-   private static final Logger LOGGER = Logger.getLogger(AsyncPortletListener.class.getName());
+   private static final Logger            LOGGER = Logger.getLogger(AsyncPortletListener.class.getName());
+
+   private long                           start  = System.currentTimeMillis();
 
-   private long                start  = System.currentTimeMillis();
+   @Inject
+   private PortletRequestRandomNumberBean reqnum;
+   @Inject
+   private AsyncDialogBean                adb;
 
    /*
     * (non-Javadoc)
@@ -88,7 +99,33 @@ public class AsyncPortletListener implements AsyncListener {
       // complete.
 
       AsyncContext ctx = evt.getAsyncContext();
-      ctx.addListener(this);
+      // ctx.addListener(this);
+
+      // Try to write some output.
+
+      try {
+         if (adb.isShowListener()) {
+            HttpServletRequest req = (HttpServletRequest) ctx.getRequest();
+            HttpServletResponse resp = (HttpServletResponse) ctx.getResponse();
+            txt.setLength(0);
+            txt.append("<div class='orangebox'>");
+            txt.append("Listener: restarting async.");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Request number: ").append(reqnum.getRandomNumber());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Dispatcher type: ").append(req.getDispatcherType());
+            txt.append("</span>");
+            txt.append("</div>");
+            resp.getWriter().write(txt.toString());
+         }
+      } catch (Exception e) {
+         StringWriter sw = new StringWriter();
+         PrintWriter pw = new PrintWriter(sw);
+         e.printStackTrace(pw);
+         pw.flush();
+         LOGGER.fine("Exception producing output: \n" + sw.toString());
+      }
    }
 
    /*
@@ -100,19 +137,35 @@ public class AsyncPortletListener implements AsyncListener {
    public void onTimeout(AsyncEvent evt) throws IOException {
       long delta = System.currentTimeMillis() - start;
 
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Listener: Timeout after ").append(delta).append(" milliseconds.");
-
       try {
-         PrintWriter writer = evt.getAsyncContext().getResponse().getWriter();
-         writer.println("<p>");
-         writer.println(txt.toString());
-         writer.println("</p>");
-         evt.getAsyncContext().complete();
+         HttpServletRequest req = (HttpServletRequest) evt.getAsyncContext().getRequest();
+         if (adb.isShowListener()) {
+            StringBuilder txt = new StringBuilder(128);
+            txt.append("<div class='orangebox'>");
+            txt.append("AsyncPortletListener: Timeout after ").append(delta).append(" milliseconds.");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Action: ").append(adb.getHandleTimeout().toString());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Request number: ").append(reqnum.getRandomNumber());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Dispatcher type: ").append(req.getDispatcherType());
+            txt.append("</span>");
+            txt.append("</div>");
+            PrintWriter writer = evt.getAsyncContext().getResponse().getWriter();
+            writer.println(txt.toString());
+         }
+         
+         if (adb.getHandleTimeout() == TimeoutType.CPL) {
+            evt.getAsyncContext().complete();
+         } else if (adb.getHandleTimeout() == TimeoutType.DIS) {
+            req.setAttribute(ATTRIB_TIMEOUT, ATTRIB_TIMEOUT);
+            evt.getAsyncContext().dispatch();
+         }
       } catch (Exception e) {
-         txt.append(" Couldn't get response and complete. Exception: " + e.toString());
+         LOGGER.warning(" Couldn't get response to generate output. Exception: " + e.toString());
       }
-      LOGGER.fine(txt.toString());
    }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 6cbaebc..1c25e61 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -19,6 +19,8 @@
 package org.apache.portals.samples;
 
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Collections;
 import java.util.List;
 import java.util.logging.Level;
@@ -33,6 +35,7 @@ import javax.portlet.ResourceResponse;
 import javax.portlet.annotations.ServeResourceMethod;
 import javax.servlet.AsyncContext;
 import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -52,6 +55,7 @@ public class AsyncPortletResource {
    private final static String ATTRIB_REPS = "reps";
    private final static String ATTRIB_AUTO = "auto";
    public  final static String ATTRIB_TITLE = "title";
+   public  final static String ATTRIB_TIMEOUT = "timeout";
 
    public static class AsyncRunnable implements Runnable {
 
@@ -150,6 +154,19 @@ public class AsyncPortletResource {
 
    @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
    public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
+      
+      if (req.getAttribute(ATTRIB_TIMEOUT) != null) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("<p>Resource method: listener reports timout.");
+         txt.append("<span style='margin-left: 2em;'>Request #: ");
+         txt.append("dispatcher type: ").append(req.getDispatcherType().toString());
+         txt.append("</span>");
+         txt.append("<span style='margin-left: 2em;'>Request #: ");
+         txt.append(reqnum.getRandomNumber());
+         txt.append("</span></p><hr>");
+         resp.getWriter().write(txt.toString());
+         return;
+      }
 
       Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
       if (auto == null) {
@@ -179,8 +196,15 @@ public class AsyncPortletResource {
       
       AsyncContext ctx = req.startAsync();
       ctx.setTimeout(4000);
-      AsyncPortletListener apl = new AsyncPortletListener();
-      ctx.addListener(apl);
+      try {
+         ctx.addListener(ctx.createListener(AsyncPortletListener.class));
+      } catch (ServletException e) {
+         StringWriter sw = new StringWriter();
+         PrintWriter pw = new PrintWriter(sw);
+         e.printStackTrace(pw);
+         pw.flush();
+         LOGGER.fine("Exception adding listener: \n" + sw.toString());
+      }
 
       if (auto || (adb.getDelay() <= 0)) {
          

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
index 355ce90..9d5616b 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
@@ -61,7 +61,9 @@ limitations under the License.
    </td></tr><tr><td>
    <INPUT id ='<portlet:namespace/>-send' VALUE='execute' TYPE='submit'>
    </td><td>
-   <input name='<%=PARAM_FILTER%>' value='<%=PARAM_FILTER%>' type='checkbox' ${adb.isUseFilter() ? "checked" : "" } > show filter
+   <input name='<%=PARAM_FILTER%>' value='<%=PARAM_FILTER%>' type='checkbox' ${adb.isShowFilter() ? "checked" : "" } > show filter
+   </td><td>
+   <input name='<%=PARAM_LISTENER%>' value='<%=PARAM_LISTENER%>' type='checkbox' ${adb.isShowListener() ? "checked" : "" } > show listener
    </td></tr></table>
 </FORM>
 <p>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
index 3cafd6c..1486349 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
+++ b/PortletV3AnnotatedDemo/src/main/webapp/resources/css/infobox.css
@@ -18,6 +18,16 @@
    background:#ddaadd;
 }
 
+.orangebox {
+   border-style:solid; 
+   border-width:2px; 
+   padding:4px; 
+   margin-bottom:4px;
+   overflow:auto;
+   border-color:#e68a00; 
+   background:#ffdd99;
+}
+
 .parmbox {
    border-style:solid; 
    border-width:2px; 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
index c4c9966..0892139 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
@@ -1,15 +1,15 @@
 package org.apache.pluto.container;
 
-import javax.enterprise.inject.spi.BeanManager;
-import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 
 public interface PortletAsyncContext extends AsyncContext {
 
-   void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr);
    void setWrapped(AsyncContext actx);
-   void registerContext();
-   void deregisterContext();
+   void registerContext(boolean isListener);
+   void deregisterContext(boolean isListener);
    void removeContext();
+   void launchRunner();
+   boolean isComplete();
+   void setComplete(boolean complete);
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/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 20adad4..b999eee 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
@@ -18,6 +18,7 @@ package org.apache.pluto.container;
 
 import java.util.Map;
 
+import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
@@ -75,4 +76,6 @@ public interface PortletResourceRequestContext extends PortletRequestContext
     AsyncContext startAsync();
     AsyncContext startAsync(ServletRequest request, ServletResponse response);
     PortletAsyncContext getPortletAsyncContext();
+    BeanManager getBeanManager();
+    void setBeanManager(BeanManager beanmgr);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/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 820ab14..3aef3e4 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
@@ -341,7 +341,7 @@ public class PortletServlet3 extends HttpServlet {
          }
 
          // enable contextual support for async
-         ((PortletResourceRequestContext)requestContext).getPortletAsyncContext().registerContext();
+         ((PortletResourceRequestContext)requestContext).getPortletAsyncContext().registerContext(false);
          
       } else {
          
@@ -394,6 +394,8 @@ public class PortletServlet3 extends HttpServlet {
             if (ps != null) {
                resourceRequest.setAttribute(ResourceRequest.PAGE_STATE, ps);
             }
+            
+            rc.setBeanManager(beanmgr);
 
             ResourceResponse resourceResponse = (ResourceResponse) portletResponse;
             filterManager.processFilter(resourceRequest, resourceResponse, invoker, portletContext);
@@ -477,11 +479,8 @@ public class PortletServlet3 extends HttpServlet {
                PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
                PortletAsyncContext pac = resctx.getPortletAsyncContext();
                if (pac != null) {
-                  if (request.getDispatcherType() != DispatcherType.ASYNC) {
-                     // initialize only on the first time thru
-                     pac.init(resctx, (ResourceRequest) portletRequest, beanmgr);
-                  }
-                  pac.deregisterContext();
+                  pac.deregisterContext(false);
+                  pac.launchRunner();
                } else {
                   LOG.warn("Couldn't get portlet async context.");
                }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
index 2df6a2f..ce8e044 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -51,58 +51,81 @@ import org.slf4j.LoggerFactory;
 public class PortletAsyncContextImpl implements PortletAsyncContext {
    private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextImpl.class);
    private static final boolean isDebug = LOG.isDebugEnabled();
+   @SuppressWarnings("unused")
    private static final boolean isTrace = LOG.isTraceEnabled();
    
-   
-
    private AsyncContext                   actx;
+   
    private final HttpServletRequest       hreq;
+   private final PortletAsyncListener     pal;
+   private final PortletResourceRequestContext  prctx;
 
-   private PortletResourceRequestContext  prctx;
    private ResourceRequest                resreq;
    private PortletSessionBeanHolder       sessbh;
    private PortletStateScopedBeanHolder   statebh;
    private PortletRequestScopedBeanHolder reqbh;
    private BeanManager                    beanmgr;
-
    private Runnable                       pendingRunner;
+   private boolean                        doDeregister = true;
+   private boolean                        complete = false;
 
-   public PortletAsyncContextImpl(AsyncContext actx, HttpServletRequest hreq) {
+   public PortletAsyncContextImpl(AsyncContext actx, PortletResourceRequestContext prctx, ResourceRequest resreq) {
       this.actx = actx;
-      this.hreq = hreq;
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.
-    * PortletResourceRequestContext)
-    */
-   @Override
-   public void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr) {
       this.prctx = prctx;
       this.resreq = resreq;
-      this.beanmgr = beanmgr;
+      this.hreq = (HttpServletRequest) actx.getRequest();
+      this.beanmgr = prctx.getBeanManager();
 
       // get the original container req & resp to pass to listener for resource releasing
 
       HttpServletRequest creq = prctx.getContainerRequest();
       HttpServletResponse cresp = prctx.getContainerResponse();
 
-      PortletAsyncListener pal = new PortletAsyncListener(this);
+      pal = new PortletAsyncListener(this);
       actx.addListener(pal, creq, cresp);
+   }
 
+   /**
+    * @return the complete
+    */
+   @Override
+   public boolean isComplete() {
+      return complete;
+   }
+
+   /**
+    * @param complete the complete to set
+    */
+   @Override
+   public void setComplete(boolean complete) {
+      this.complete = complete;
    }
 
    /**
     * Called when a new thread begins running in order to set up contextual support
     */
    @Override
-   public void registerContext() {
-      PortletSessionBeanHolder.register(sessbh);
-      PortletStateScopedBeanHolder.register(statebh);
-      PortletRequestScopedBeanHolder.register(reqbh);
-      PortletArtifactProducer.setPrecursors(resreq, prctx.getResponse(), prctx.getPortletConfig());
+   public void registerContext(boolean isListener) {
+      
+      // if the context is already active, then ignore register / deregister calls.
+      if (complete || (isListener && PortletRequestScopedBeanHolder.getBeanHolder() != null)) {
+         doDeregister = false;
+      } else {
+         doDeregister = true;
+         PortletSessionBeanHolder.register(sessbh);
+         PortletStateScopedBeanHolder.register(statebh);
+         PortletRequestScopedBeanHolder.register(reqbh);
+         PortletArtifactProducer.setPrecursors(resreq, prctx.getResponse(), prctx.getPortletConfig());
+      }
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Registered context.");
+         txt.append(" complete: ").append(complete);
+         txt.append(", isListener: ").append(isListener);
+         txt.append(", doRegister: ").append(doDeregister);
+         LOG.debug(txt.toString());
+      }
    }
 
    /**
@@ -110,11 +133,30 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
     * saved rather than destroyed.
     */
    @Override
-   public void deregisterContext() {
-      this.sessbh = PortletSessionBeanHolder.deregister();
-      this.statebh = PortletStateScopedBeanHolder.deregister();
-      this.reqbh = PortletRequestScopedBeanHolder.deregister();
-      PortletArtifactProducer.remove();
+   public void deregisterContext(boolean isListener) {
+      if (!complete && (!isListener || doDeregister)) {
+         this.sessbh = PortletSessionBeanHolder.deregister();
+         this.statebh = PortletStateScopedBeanHolder.deregister();
+         this.reqbh = PortletRequestScopedBeanHolder.deregister();
+         PortletArtifactProducer.remove();
+      }
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Deregistered context.");
+         txt.append(" complete: ").append(complete);
+         txt.append(", isListener: ").append(isListener);
+         txt.append(", doRegister: ").append(doDeregister);
+         LOG.debug(txt.toString());
+      }
+   }
+
+   /**
+    * Launches any runner that was registered for execution. To be called when 
+    * leaving the portlet servlet. 
+    */
+   @Override
+   public void launchRunner() {
 
       // now if a runner is pending, initialize the contextual runnable and start it
 
@@ -163,7 +205,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
     */
    @Override
    public void addListener(AsyncListener l) {
-      actx.addListener(l);
+      pal.addListener(l);
    }
 
    /*
@@ -174,7 +216,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
     */
    @Override
    public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
-      actx.addListener(l, req, resp);
+      pal.addListener(l, req, resp);
    }
 
    /*
@@ -192,9 +234,30 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
     * 
     * @see javax.servlet.AsyncContext#createListener(java.lang.Class)
     */
+   @SuppressWarnings("unchecked")
    @Override
    public <T extends AsyncListener> T createListener(Class<T> cls) throws ServletException {
-      return actx.createListener(cls);
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Creating listener.");
+         txt.append(" Bean manager: ").append(beanmgr);
+         txt.append(", listener class: ").append(cls.getCanonicalName());
+         LOG.debug(txt.toString());
+      }
+      T lis = null;
+      if (beanmgr != null) {
+         Set<Bean<?>> beans = beanmgr.getBeans(cls);
+         Bean<?> bean = beanmgr.resolve(beans);
+         if (bean != null) {
+            lis = (T) beanmgr.getReference(bean, bean.getBeanClass(), beanmgr.createCreationalContext(bean));
+         } else {
+            LOG.warn("Could not get bean reference for: " + cls.getCanonicalName());
+            lis = actx.createListener(cls);
+         }
+      } else {
+         lis = actx.createListener(cls);
+      }
+      return lis;
    }
 
    /*

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
index 8535a7e..bfbfd34 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
@@ -55,7 +55,7 @@ public class PortletAsyncContextualRunner implements Runnable {
       }
 
       try {
-         pactx.registerContext();
+         pactx.registerContext(false);
          targetRunner.run();
       } catch (Exception e) {
          StringBuilder txt = new StringBuilder(128);
@@ -64,7 +64,7 @@ public class PortletAsyncContextualRunner implements Runnable {
          if (isDebug) {
             LOG.debug("Shutting down contextual environment for thread: " + Thread.currentThread().getId());
          }
-         pactx.deregisterContext();
+         pactx.deregisterContext(false);
       }
 }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/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
index d546986..11069ac 100644
--- 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
@@ -19,32 +19,68 @@
 package org.apache.pluto.driver.services.container;
 
 import java.io.IOException;
-import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceResponseContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * Releases portal resources when the async request completes.
+ * Manages the listeners registered by the application. Releases portal resources when 
+ * the async request completes and provides contextual services for the listeners. 
  * 
  * @author Scott Nicklous
  */
 public class PortletAsyncListener implements AsyncListener {
-   private static final Logger LOGGER = Logger.getLogger(PortletAsyncListener.class.getName());
-
+   
+   /** Logger. */
+   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncListener.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   @SuppressWarnings("unused")
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
+   
+   // Data for one listener
+   private class Entry {
+      public Entry(AsyncListener lis, ServletRequest req, ServletResponse resp) {
+         this.lis = lis;
+         this.req = req;
+         this.resp = resp;
+      }
+      public AsyncListener   lis;
+      public ServletRequest  req;
+      public ServletResponse resp;
+   }
+   
+   // The registered listeners
+   List<Entry> listeners = new ArrayList<Entry>();
+   
    private long start  = System.currentTimeMillis();
    private final PortletAsyncContext pactx;
+   
  
    public PortletAsyncListener(PortletAsyncContext pactx) {
       this.pactx = pactx;
    }
+   
+   public void addListener(AsyncListener l) {
+      listeners.add(new Entry(l, null, null));
+   }
+   
+   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
+      listeners.add(new Entry(l, req, resp));
+   }
 
    /*
     * (non-Javadoc)
@@ -53,6 +89,22 @@ public class PortletAsyncListener implements AsyncListener {
     */
    @Override
    public void onComplete(AsyncEvent evt) throws IOException {
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Firing onComplete event for ");
+         txt.append(listeners.size()).append(" listeners.");
+         LOG.debug(txt.toString());
+      }
+      
+      pactx.registerContext(true);
+      for (Entry listener : listeners) {
+         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
+         listener.lis.onComplete(lisevt);
+      }
+      pactx.deregisterContext(true);
+      pactx.setComplete(true);
+      
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Completed. Execution time: ").append(delta).append(" milliseconds.");
@@ -97,7 +149,9 @@ public class PortletAsyncListener implements AsyncListener {
       txt.append(" Removing contextual info.");
       pactx.removeContext();
 
-      LOGGER.fine(txt.toString());
+      if (isDebug) {
+         LOG.debug(txt.toString());
+      }
 
    }
 
@@ -108,6 +162,21 @@ public class PortletAsyncListener implements AsyncListener {
     */
    @Override
    public void onError(AsyncEvent evt) throws IOException {
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Firing onError event for ");
+         txt.append(listeners.size()).append(" listeners.");
+         LOG.debug(txt.toString());
+      }
+      
+      pactx.registerContext(true);
+      for (Entry listener : listeners) {
+         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp, evt.getThrowable());
+         listener.lis.onError(lisevt);
+      }
+      pactx.deregisterContext(true);
+      
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Error after ").append(delta).append(" milliseconds.");
@@ -124,7 +193,9 @@ public class PortletAsyncListener implements AsyncListener {
       }
 
       txt.append(", Exception: ").append(evt.getThrowable().getMessage());
-      LOGGER.fine(txt.toString());
+      if (isDebug) {
+         LOG.debug(txt.toString());
+      }
    }
 
    /*
@@ -134,10 +205,33 @@ public class PortletAsyncListener implements AsyncListener {
     */
    @Override
    public void onStartAsync(AsyncEvent evt) throws IOException {
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Firing onStartAsync event for ");
+         txt.append(listeners.size()).append(" listeners.");
+         LOG.debug(txt.toString());
+      }
+      
+      // copy & clear the original listener list. If a listener wants to be notified
+      // again, it will add itself again.
+      
+      ArrayList<Entry> entries = new ArrayList<Entry>(listeners);
+      listeners.clear();
+
+      pactx.registerContext(true);
+      for (Entry listener : entries) {
+         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
+         listener.lis.onStartAsync(lisevt);
+      }
+      pactx.deregisterContext(true);
+      
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Async started again after ").append(delta).append(" milliseconds.");
-      LOGGER.fine(txt.toString());
+      if (isDebug) {
+         LOG.debug(txt.toString());
+      }
 
       // need to add this listener again so it gets called when finally complete.
 
@@ -152,6 +246,21 @@ public class PortletAsyncListener implements AsyncListener {
     */
    @Override
    public void onTimeout(AsyncEvent evt) throws IOException {
+      
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Firing onTimeout event for ");
+         txt.append(listeners.size()).append(" listeners.");
+         LOG.debug(txt.toString());
+      }
+      
+      pactx.registerContext(true);
+      for (Entry listener : listeners) {
+         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
+         listener.lis.onTimeout(lisevt);
+      }
+      pactx.deregisterContext(true);
+      
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Timeout after ").append(delta).append(" milliseconds.");
@@ -179,9 +288,11 @@ public class PortletAsyncListener implements AsyncListener {
       }
 
       if (warn) {
-         LOGGER.warning(txt.toString());
+         LOG.warn(txt.toString());
       } else {
-         LOGGER.fine(txt.toString());
+         if (isDebug) {
+            LOG.debug(txt.toString());
+         }
       }
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/9fa76dbe/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 6906a57..c1e8332 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
@@ -20,12 +20,12 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import javax.enterprise.inject.spi.BeanManager;
 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.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
@@ -57,9 +57,10 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    private static final boolean isDebug = LOG.isDebugEnabled();
    private static final boolean isTrace = LOG.isTraceEnabled();
 
-   private String               pageState;
-   private ResourceResponse     response;
+   private String                   pageState;
+   private ResourceResponse         response;
    private PortletAsyncContextImpl  actx;
+   private BeanManager              beanmgr;
 
    public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
          HttpServletResponse containerResponse, PortletWindow window, String pageState) {
@@ -122,6 +123,22 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
       this.response = response;
    }
 
+   /**
+    * @return the beanmgr
+    */
+   @Override
+   public BeanManager getBeanManager() {
+      return beanmgr;
+   }
+
+   /**
+    * @param beanmgr the beanmgr to set
+    */
+   @Override
+   public void setBeanManager(BeanManager beanmgr) {
+      this.beanmgr = beanmgr;
+   }
+
    @Override
    public AsyncContext startAsync(ResourceRequest request) throws IllegalStateException {
       return startAsync(request, response);
@@ -189,7 +206,7 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
       if (actx != null) {
          actx.setWrapped(hreq.startAsync(wreq, wresp));
       } else {
-         actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), wreq);
+         actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), this, request);
       }
 
       if (isTrace) {


[10/34] portals-pluto git commit: added new output display to path info portlet

Posted by ms...@apache.org.
added new output display to path info portlet


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

Branch: refs/heads/V3Prototype
Commit: 51caad74ec62c5dcb87ca53fb562065c7d362f05
Parents: 60c741f
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Mar 23 22:03:27 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Mar 23 22:03:27 2016 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/portals/samples/PathInfoPortlet.java    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/51caad74/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
index 8eb2594..2b1391c 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
@@ -91,9 +91,9 @@ public class PathInfoPortlet {
       PathDisplay pd;
       if (hreq != null) {
          pd = new PathDisplay(hreq, "Resource Method (Servlet)");
-      } else {
-         pd = new PathDisplay(req, "Resource Method (Resource)");
+         pathInfo.add(pd.toMarkup());
       }
+      pd = new PathDisplay(req, "Resource Method (ResourceRequest)");
       pathInfo.add(pd.toMarkup());
 
       req.setAttribute("pathInfo", pathInfo);


[28/34] portals-pluto git commit: worked on contextual enablement in AsyncContext.start() thread.

Posted by ms...@apache.org.
worked on contextual enablement in AsyncContext.start() thread.


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

Branch: refs/heads/V3Prototype
Commit: 27e17ae6445ec12d0d68517e08c379461a382371
Parents: aae89a3
Author: Scott Nicklous <ms...@apache.org>
Authored: Mon Apr 4 17:03:52 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Mon Apr 4 17:03:52 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java |  45 ++++-
 .../portals/samples/AsyncPortletResource.java   |  35 ++--
 .../samples/PortletRequestRandomNumberBean.java |   3 +-
 .../src/main/webapp/WEB-INF/jsp/asyncDialog.jsp |  14 +-
 .../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp |   6 +-
 .../pluto/container/PortletAsyncContext.java    |  11 +-
 .../pluto/container/driver/PortletServlet3.java |  59 +++----
 .../PortletRequestScopedBeanHolder.java         |  25 ++-
 .../processor/PortletSessionBeanHolder.java     |  21 +++
 .../processor/PortletStateScopedBeanHolder.java |  25 ++-
 .../container/PortletAsyncContextImpl.java      | 167 +++++++++++++++----
 .../container/PortletAsyncContextualRunner.java |  68 ++++++++
 .../container/PortletAsyncListener.java         |  27 ++-
 13 files changed, 419 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index 5fa7245..c5717bc 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -30,7 +30,6 @@ import javax.portlet.annotations.ActionMethod;
 import javax.portlet.annotations.PortletSerializable;
 import javax.portlet.annotations.RenderMethod;
 import javax.portlet.annotations.RenderStateScoped;
-import javax.servlet.DispatcherType;
 
 /**
  * Render state scoped bean. The bean is stored as a render parameter, so it
@@ -41,9 +40,16 @@ import javax.servlet.DispatcherType;
 public class AsyncDialogBean implements PortletSerializable {
    private static final Logger LOGGER = Logger.getLogger(AsyncDialogBean.class.getName());
 
+   // defines how output is to be generated
    public enum OutputType {
       TEXT, INC, FWD, DISPATCH, AUTO
    }
+   
+   // defines how timeouts are to be handled by the listener
+   // Ignore, complete, or dispatch
+   public enum TimeoutType {
+      NOP, CPL, DIS;
+   }
 
    public static final String PARAM_MSG      = "msg";
    public static final String PARAM_DELAY    = "delay";
@@ -55,6 +61,10 @@ public class AsyncDialogBean implements PortletSerializable {
    public static final String PARAM_TYPE_INC = OutputType.INC.toString();
    public static final String PARAM_TYPE_FWD = OutputType.FWD.toString();
    public static final String PARAM_TYPE_DIS = OutputType.DISPATCH.toString();
+   public static final String PARAM_TO     = "toType";
+   public static final String PARAM_TO_NOP = TimeoutType.NOP.toString();
+   public static final String PARAM_TO_CPL = TimeoutType.CPL.toString();
+   public static final String PARAM_TO_DIS = TimeoutType.DIS.toString();
 
    private int                delay;
    private int                reps;
@@ -62,6 +72,7 @@ public class AsyncDialogBean implements PortletSerializable {
    private String             msg;
    private boolean            autoDispatch;
    private boolean            useFilter;
+   private TimeoutType        handleTimeout;
 
    /**
     * This method is called by the portlet container to initialize the bean at
@@ -70,12 +81,14 @@ public class AsyncDialogBean implements PortletSerializable {
    @Override
    public void deserialize(String[] state) {
       if (state.length == 0) {
+         // set default values
          delay = 1000;
          reps = 1;
          type = OutputType.TEXT;
          msg = null;
          autoDispatch = true;
          useFilter = false;
+         handleTimeout = TimeoutType.CPL;
       } else {
          delay = Integer.parseInt(state[0]);
          reps = Integer.parseInt(state[1]);
@@ -83,6 +96,7 @@ public class AsyncDialogBean implements PortletSerializable {
          msg = state[3];
          autoDispatch = Boolean.parseBoolean(state[4]);
          useFilter = Boolean.parseBoolean(state[5]);
+         handleTimeout = TimeoutType.valueOf(state[6]);
       }
       LOGGER.fine("deserialized: " + Arrays.asList(state).toString());
    }
@@ -93,7 +107,8 @@ public class AsyncDialogBean implements PortletSerializable {
     */
    @Override
    public String[] serialize() {
-      String[] state = { "" + delay, "" + reps, type.toString(), msg, ""+autoDispatch, ""+useFilter };
+      String[] state = { "" + delay, "" + reps, type.toString(), msg, 
+            ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
       LOGGER.fine("serialized: " + Arrays.asList(state).toString());
       return state;
    }
@@ -188,6 +203,20 @@ public class AsyncDialogBean implements PortletSerializable {
    }
 
    /**
+    * @return the handleTimeout
+    */
+   public TimeoutType getHandleTimeout() {
+      return handleTimeout;
+   }
+
+   /**
+    * @param handleTimeout the handleTimeout to set
+    */
+   public void setHandleTimeout(TimeoutType handleTimeout) {
+      this.handleTimeout = handleTimeout;
+   }
+
+   /**
     * Displays the dialog
     * 
     * @return the action form as string
@@ -263,7 +292,17 @@ public class AsyncDialogBean implements PortletSerializable {
          useFilter = false;
       }
 
-      String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
+      String strto = req.getActionParameters().getValue(PARAM_TO);
+      if (strto != null) {
+         try {
+            handleTimeout = TimeoutType.valueOf(strto);
+         } catch (Exception e) {
+            msg = "try again. bad timeout handling: " + strto;
+         }
+      }
+
+      String[] state = { "" + delay, "" + reps, type.toString(), msg, 
+            ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
       LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 6cad2fb..6cbaebc 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -53,19 +53,21 @@ public class AsyncPortletResource {
    private final static String ATTRIB_AUTO = "auto";
    public  final static String ATTRIB_TITLE = "title";
 
-   private class AsyncRunnable implements Runnable {
+   public static class AsyncRunnable implements Runnable {
 
-      private final AsyncContext ctx;
-      private final int          delay;
-      private final OutputType   type;
+      private AsyncContext ctx;
+      private int          delay;
+      private OutputType   type;
+      
+      @Inject private PortletRequestRandomNumberBean reqnum;
 
-      public AsyncRunnable(AsyncContext ctx, int delay, OutputType type) {
+      public void init(AsyncContext ctx, int delay, OutputType type) {
          this.ctx = ctx;
          this.delay = delay;
          this.type = type;
          
          StringBuilder txt = new StringBuilder(128);
-         txt.append("Constructing runnable.");
+         txt.append("Initializing runnable.");
          txt.append(" delay: ").append(delay);
          txt.append(", type: ").append(type);
          LOGGER.fine(txt.toString());
@@ -93,8 +95,12 @@ public class AsyncPortletResource {
                LOGGER.fine("Producing text output.");
                StringBuilder txt = new StringBuilder(128);
                txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
-               txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
-               txt.append("</p><hr>");
+               txt.append("<p>Dispatcher type: ").append(hreq.getDispatcherType().toString());
+               txt.append("<span style='margin-left: 2em;'>Request #: ");
+               try { // in case context not active
+                  txt.append(reqnum.getRandomNumber());
+               } catch (Exception e) {}
+               txt.append("</span></p><hr>");
                hresp.getWriter().write(txt.toString());
                ctx.complete();
                break;
@@ -138,8 +144,9 @@ public class AsyncPortletResource {
 
    }
 
-   @Inject
-   private AsyncDialogBean adb;
+   @Inject private AsyncDialogBean adb;
+   @Inject private PortletRequestRandomNumberBean reqnum;
+   @Inject private AsyncRunnable runner;
 
    @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
    public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
@@ -221,7 +228,9 @@ public class AsyncPortletResource {
             txt.setLength(0);
             txt.append("<h5>Resource method producing text output for portlet: " + portletName + "</h5>");
             txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
-            txt.append("</p><hr>");
+            txt.append("<span style='margin-left: 2em;'>Request #: ");
+            txt.append(reqnum.getRandomNumber());
+            txt.append("</span></p><hr>");
             resp.getWriter().write(txt.toString());
             resp.flushBuffer();
             if (done) {
@@ -240,8 +249,8 @@ public class AsyncPortletResource {
             type = OutputType.AUTO;
          }
 
-         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type);
-         ctx.start(ar);
+         runner.init(ctx, adb.getDelay(), type);
+         ctx.start(runner);
       }
    }
    

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
index 407d561..4889827 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
@@ -19,6 +19,7 @@
 
 package org.apache.portals.samples;
 
+import javax.inject.Named;
 import javax.portlet.annotations.PortletRequestScoped;
 
 /**
@@ -26,7 +27,7 @@ import javax.portlet.annotations.PortletRequestScoped;
  * @author Scott Nicklous
  *
  */
-@PortletRequestScoped
+@PortletRequestScoped @Named("reqnum")
 public class PortletRequestRandomNumberBean {
    
    private int randomNumber;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
index fd7e941..355ce90 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
@@ -25,7 +25,6 @@ limitations under the License.
 
 <h3>Async Portlet</h3>
 <div class='parmbox'>
-${adb.getMsg()}
 <FORM  ACTION='<portlet:actionURL/>' id='<portlet:namespace/>-setParams' method='POST' enctype='application/x-www-form-urlencoded'>
    <table style='width:100%;'><tr><td align='left'>
 
@@ -40,6 +39,15 @@ ${adb.getMsg()}
    <input name='<%=PARAM_AUTO%>' value='<%=PARAM_AUTO%>' type='checkbox' ${adb.isAutoDispatch() ? "checked" : "" } > recursive
 
    </td></tr><tr><td>
+   Handle timeout:
+   </td><td>
+   <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_NOP%>' ${adb.getHandleTimeout() == "NOP" ? "checked" : "" } > ignore
+   </td><td>
+   <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_CPL%>' ${adb.getHandleTimeout() == "CPL" ? "checked" : "" } > complete
+   </td><td>
+   <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_DIS%>' ${adb.getHandleTimeout() == "DIS" ? "checked" : "" } > dispatch
+
+   </td></tr><tr><td>
    Output type:
    </td><td>
    <input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_TXT%>' ${adb.getType() == "TEXT" ? "checked" : "" } > text
@@ -56,6 +64,10 @@ ${adb.getMsg()}
    <input name='<%=PARAM_FILTER%>' value='<%=PARAM_FILTER%>' type='checkbox' ${adb.isUseFilter() ? "checked" : "" } > show filter
    </td></tr></table>
 </FORM>
+<p>
+Request #: ${reqnum.getRandomNumber()}
+<span style='margin-left: 2em;'>${adb.getMsg()}</span>
+</p>
 </div>
 <div class='infobox' id='<portlet:namespace/>putResourceHere'></div>
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
index 9297b6b..1c7024e 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -7,5 +7,9 @@
 <portlet:defineObjects />
 
 <h5><%=request.getAttribute("title") %> for portlet: <%=portletConfig.getPortletName() %></h5>
-<p>Dispatch type: <%=request.getDispatcherType() %></p>
+<p>Dispatch type: <%=request.getDispatcherType() %>
+<c:catch var ="catchException">
+   <span style='margin-left: 2em;'>Request #: ${reqnum.getRandomNumber()}</span>
+</c:catch>
+</p>
 <hr>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
index 709306e..c4c9966 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
@@ -1,14 +1,15 @@
 package org.apache.pluto.container;
 
+import javax.enterprise.inject.spi.BeanManager;
+import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 
 public interface PortletAsyncContext extends AsyncContext {
 
-   void init(PortletResourceRequestContext prctx);
-
-   /**
-    * @param actx the async context to set
-    */
+   void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr);
    void setWrapped(AsyncContext actx);
+   void registerContext();
+   void deregisterContext();
+   void removeContext();
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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 c48ee4d..820ab14 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
@@ -326,7 +326,6 @@ public class PortletServlet3 extends HttpServlet {
             wreq = ((ServletRequestWrapper) wreq).getRequest();
          }
          
-         
          if (wreq instanceof PortletAsyncRequestWrapper) {
             
             HttpServletRequest hreq = (HttpServletRequest) ((PortletAsyncRequestWrapper) wreq).getRequest();
@@ -340,13 +339,20 @@ public class PortletServlet3 extends HttpServlet {
          } else {
             LOG.debug("Couldn't find the portlet async wrapper.");
          }
+
+         // enable contextual support for async
+         ((PortletResourceRequestContext)requestContext).getPortletAsyncContext().registerContext();
          
       } else {
          
-         // the contexts are already initialized if this is part of a resource request async sequence
+         // Not an async dispatch
+         
          requestContext.init(portletConfig, getServletContext(), request, response);
          requestContext.setExecutingRequestBody(true);
          responseContext.init(request, response);
+
+         // enable contextual support
+         beforeInvoke(portletRequest, portletResponse, portletConfig);
       
       }
 
@@ -356,8 +362,6 @@ public class PortletServlet3 extends HttpServlet {
       notify(event, true, null);
       
       try {
-
-         beforeInvoke(portletRequest, portletResponse, portletConfig);
          
          // The requested method is RENDER: call Portlet.render(..)
          if (methodId == PortletInvokerService.METHOD_RENDER) {
@@ -451,43 +455,40 @@ public class PortletServlet3 extends HttpServlet {
       } finally {
          
          requestContext.setExecutingRequestBody(false);
-         afterInvoke(portletResponse);
          
          // If an async request is running or has been dispatched, resources
          // will be released by the PortletAsyncListener. Otherwise release here.
          
-         if (!request.isAsyncStarted()) {
-            
-            LOG.debug("Async not started, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
-            
-            if (request.getDispatcherType() != DispatcherType.ASYNC) {
+         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);
+            LOG.debug("Async not being processed, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
+
+            request.removeAttribute(PortletInvokerService.METHOD_ID);
+            request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+            request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+            request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+
+            afterInvoke(portletResponse);
 
-            }
          } else {
             LOG.debug("Async started, not releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
 
-            // Initialize the async context after the request during which async is 
-            // first started.
-            
-            if (request.getDispatcherType() != DispatcherType.ASYNC) {
-               if (requestContext instanceof PortletResourceRequestContext) {
-                  PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
-                  PortletAsyncContext pac = resctx.getPortletAsyncContext();
-                  if (pac != null) {
-                     pac.init(resctx);
-                  } else {
-                     LOG.warn("Couldn't get portlet async context.");
+            if (requestContext instanceof PortletResourceRequestContext) {
+               PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
+               PortletAsyncContext pac = resctx.getPortletAsyncContext();
+               if (pac != null) {
+                  if (request.getDispatcherType() != DispatcherType.ASYNC) {
+                     // initialize only on the first time thru
+                     pac.init(resctx, (ResourceRequest) portletRequest, beanmgr);
                   }
+                  pac.deregisterContext();
                } else {
-                  LOG.warn("Wrong kind of request context: " + requestContext.getClass().getCanonicalName());
+                  LOG.warn("Couldn't get portlet async context.");
                }
-            }            
-            
+            } else {
+               LOG.warn("Wrong kind of request context: " + requestContext.getClass().getCanonicalName());
+            }
+
          }
       }
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
index 468e1f0..34538b3 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
@@ -91,7 +91,9 @@ public class PortletRequestScopedBeanHolder implements Serializable {
    public static void removeBeanHolder() {
       
       PortletRequestScopedBeanHolder bh = getBeanHolder();
-      bh.removeAll();
+      if (bh != null) {
+         bh.removeAll();
+      }
       holders.remove();
 
       if (isTrace) {
@@ -110,6 +112,27 @@ public class PortletRequestScopedBeanHolder implements Serializable {
    public static PortletRequestScopedBeanHolder getBeanHolder() {
       return holders.get();
    }
+   
+   /**
+    * Removes the bean holder for the current thread and
+    * returns the removed instance to the caller.
+    * 
+    * @return  the removed bean holder
+    */
+   public static PortletRequestScopedBeanHolder deregister() {
+      PortletRequestScopedBeanHolder holder = holders.get();
+      holders.remove();
+      return holder;
+   }
+   
+   /**
+    * Registers the provided bean holder for the current thread.
+    * 
+    * @param holder the bean holder to register
+    */
+   public static void register(PortletRequestScopedBeanHolder holder) {
+      holders.set(holder);
+   }
 
    /**
     * Returns existing instance of object, or null if no instance exists.

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
index 6d97539..b8d5a23 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
@@ -120,6 +120,27 @@ public class PortletSessionBeanHolder implements Serializable {
    public static PortletSessionBeanHolder getBeanHolder() {
       return holders.get();
    }
+   
+   /**
+    * Removes the bean holder for the current thread and
+    * returns the removed instance to the caller.
+    * 
+    * @return  the removed bean holder
+    */
+   public static PortletSessionBeanHolder deregister() {
+      PortletSessionBeanHolder holder = holders.get();
+      holders.remove();
+      return holder;
+   }
+   
+   /**
+    * Registers the provided bean holder for the current thread.
+    * 
+    * @param holder the bean holder to register
+    */
+   public static void register(PortletSessionBeanHolder holder) {
+      holders.set(holder);
+   }
 
    /**
     * Returns an instance for the contextual type, or null if none available.

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
index d0ec561..24ca9ca 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
@@ -104,7 +104,9 @@ public class PortletStateScopedBeanHolder implements Serializable {
    public static void removeBeanHolder(StateAwareResponse resp) {
       
       PortletStateScopedBeanHolder bh = getBeanHolder();
-      bh.removeAll(resp);
+      if (bh != null) {
+         bh.removeAll(resp);
+      }
       holders.remove();
 
       if (isTrace) {
@@ -123,6 +125,27 @@ public class PortletStateScopedBeanHolder implements Serializable {
    public static PortletStateScopedBeanHolder getBeanHolder() {
       return holders.get();
    }
+   
+   /**
+    * Removes the bean holder for the current thread and
+    * returns the removed instance to the caller.
+    * 
+    * @return  the removed bean holder
+    */
+   public static PortletStateScopedBeanHolder deregister() {
+      PortletStateScopedBeanHolder holder = holders.get();
+      holders.remove();
+      return holder;
+   }
+   
+   /**
+    * Registers the provided bean holder for the current thread.
+    * 
+    * @param holder the bean holder to register
+    */
+   public static void register(PortletStateScopedBeanHolder holder) {
+      holders.set(holder);
+   }
 
    /**
     * Returns existing instance of object, or null if no instance exists.

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
index d638db1..2df6a2f 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -16,9 +16,13 @@
  *  under the License.
  */
 
-
 package org.apache.pluto.driver.services.container;
 
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncListener;
 import javax.servlet.ServletContext;
@@ -30,41 +34,121 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.bean.processor.PortletArtifactProducer;
+import org.apache.pluto.container.bean.processor.PortletRequestScopedBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletSessionBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletStateScopedBeanHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * Wrapper class for the AsyncContext obtained from the servlet container. Provides
- * a couple of work-arounds for Tomcat async bugs as well as portlet-specific listener
- * support.
+ * Wrapper class for the AsyncContext obtained from the servlet container. Provides a couple of work-arounds for Tomcat
+ * async bugs as well as portlet-specific listener support.
  * 
  * @author Scott Nicklous
- *
+ * 
  */
 public class PortletAsyncContextImpl implements PortletAsyncContext {
+   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextImpl.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
+   
+
+   private AsyncContext                   actx;
+   private final HttpServletRequest       hreq;
 
-   private AsyncContext actx;
-   private final HttpServletRequest hreq;
+   private PortletResourceRequestContext  prctx;
+   private ResourceRequest                resreq;
+   private PortletSessionBeanHolder       sessbh;
+   private PortletStateScopedBeanHolder   statebh;
+   private PortletRequestScopedBeanHolder reqbh;
+   private BeanManager                    beanmgr;
+
+   private Runnable                       pendingRunner;
 
    public PortletAsyncContextImpl(AsyncContext actx, HttpServletRequest hreq) {
       this.actx = actx;
       this.hreq = hreq;
    }
 
-   /* (non-Javadoc)
-    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.PortletResourceRequestContext)
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.
+    * PortletResourceRequestContext)
     */
    @Override
-   public void init(PortletResourceRequestContext prctx) {
+   public void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr) {
+      this.prctx = prctx;
+      this.resreq = resreq;
+      this.beanmgr = beanmgr;
 
       // get the original container req & resp to pass to listener for resource releasing
 
       HttpServletRequest creq = prctx.getContainerRequest();
       HttpServletResponse cresp = prctx.getContainerResponse();
 
-      PortletAsyncListener pal = new PortletAsyncListener();
+      PortletAsyncListener pal = new PortletAsyncListener(this);
       actx.addListener(pal, creq, cresp);
+
    }
-   
-   /* (non-Javadoc)
+
+   /**
+    * Called when a new thread begins running in order to set up contextual support
+    */
+   @Override
+   public void registerContext() {
+      PortletSessionBeanHolder.register(sessbh);
+      PortletStateScopedBeanHolder.register(statebh);
+      PortletRequestScopedBeanHolder.register(reqbh);
+      PortletArtifactProducer.setPrecursors(resreq, prctx.getResponse(), prctx.getPortletConfig());
+   }
+
+   /**
+    * Called when exiting portlet handling for this thread. The bean holders are deregistered from the thread but are
+    * saved rather than destroyed.
+    */
+   @Override
+   public void deregisterContext() {
+      this.sessbh = PortletSessionBeanHolder.deregister();
+      this.statebh = PortletStateScopedBeanHolder.deregister();
+      this.reqbh = PortletRequestScopedBeanHolder.deregister();
+      PortletArtifactProducer.remove();
+
+      // now if a runner is pending, initialize the contextual runnable and start it
+
+      if (pendingRunner != null) {
+         PortletAsyncContextualRunner runner = new PortletAsyncContextualRunner();
+
+         if (isDebug) {
+            StringBuilder txt = new StringBuilder();
+            txt.append("Executing Portlet Runnable: " + pendingRunner.getClass().getCanonicalName());
+            LOG.debug(txt.toString());
+         }
+
+         runner.init(this, pendingRunner);
+         pendingRunner = null;
+         actx.start(runner);
+      }
+
+   }
+
+   /**
+    * Called when exiting portlet handling for this thread. The bean holders are deregistered from the thread and any
+    * beans contained are destroyed.
+    */
+   @Override
+   public void removeContext() {
+      PortletSessionBeanHolder.removeBeanHolder();
+      PortletStateScopedBeanHolder.removeBeanHolder(null);
+      PortletRequestScopedBeanHolder.removeBeanHolder();
+      PortletArtifactProducer.remove();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
     * @see org.apache.pluto.driver.services.container.PortletAsyncContext#setWrapped(javax.servlet.AsyncContext)
     */
    @Override
@@ -72,7 +156,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       this.actx = actx;
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener)
     */
    @Override
@@ -80,15 +166,20 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.addListener(l);
    }
 
-   /* (non-Javadoc)
-    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener, javax.servlet.ServletRequest,
+    * javax.servlet.ServletResponse)
     */
    @Override
    public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
       actx.addListener(l, req, resp);
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#complete()
     */
    @Override
@@ -96,7 +187,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.complete();
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#createListener(java.lang.Class)
     */
    @Override
@@ -104,7 +197,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       return actx.createListener(cls);
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#dispatch()
     */
    @Override
@@ -113,7 +208,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.dispatch(hreq.getServletContext(), hreq.getServletPath());
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#dispatch(java.lang.String)
     */
    @Override
@@ -122,7 +219,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.dispatch(hreq.getServletContext(), path);
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#dispatch(javax.servlet.ServletContext, java.lang.String)
     */
    @Override
@@ -130,7 +229,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.dispatch(sctx, path);
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#getRequest()
     */
    @Override
@@ -138,7 +239,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       return actx.getRequest();
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#getResponse()
     */
    @Override
@@ -146,7 +249,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       return actx.getResponse();
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#getTimeout()
     */
    @Override
@@ -154,7 +259,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       return actx.getTimeout();
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#hasOriginalRequestAndResponse()
     */
    @Override
@@ -162,7 +269,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       return actx.hasOriginalRequestAndResponse();
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#setTimeout(long)
     */
    @Override
@@ -170,12 +279,14 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       actx.setTimeout(time);
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncContext#start(java.lang.Runnable)
     */
    @Override
    public void start(Runnable run) {
-      actx.start(run);
+      pendingRunner = run;
    }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
new file mode 100644
index 0000000..6dcac04
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
@@ -0,0 +1,68 @@
+/*  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 org.apache.pluto.container.PortletAsyncContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Runner that is launched in thread on behalf of the portlet application runnable 
+ * in order to initialize contextual information.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+public class PortletAsyncContextualRunner implements Runnable {
+   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextualRunner.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   @SuppressWarnings("unused")
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
+
+   private PortletAsyncContext pactx;
+   private Runnable targetRunner; 
+
+   public PortletAsyncContextualRunner() {
+   }
+   
+   public void init(PortletAsyncContext pactx, Runnable targetRunner) {
+      this.pactx = pactx;
+      this.targetRunner = targetRunner;
+   }
+
+   @Override
+   public void run() {
+      if (isDebug) {
+         LOG.debug("Initializing contextual environment and launching runner in thread: " + Thread.currentThread().getId());
+      }
+
+      pactx.registerContext();
+      try {
+         targetRunner.run();
+      } finally {
+         if (isDebug) {
+            LOG.debug("Shutting down contextual environment for thread: " + Thread.currentThread().getId());
+         }
+         pactx.deregisterContext();
+      }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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
index 97b77c6..d546986 100644
--- 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
@@ -25,10 +25,9 @@ import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
-import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceResponseContext;
 
@@ -40,7 +39,12 @@ import org.apache.pluto.container.PortletResourceResponseContext;
 public class PortletAsyncListener implements AsyncListener {
    private static final Logger LOGGER = Logger.getLogger(PortletAsyncListener.class.getName());
 
-   private long                start  = System.currentTimeMillis();
+   private long start  = System.currentTimeMillis();
+   private final PortletAsyncContext pactx;
+ 
+   public PortletAsyncListener(PortletAsyncContext pactx) {
+      this.pactx = pactx;
+   }
 
    /*
     * (non-Javadoc)
@@ -87,8 +91,11 @@ public class PortletAsyncListener implements AsyncListener {
          hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);
 
       } else {
-         txt.append("... nothing. Couldn't get servlet request.");
+         txt.append("... no servlet request stuff. Couldn't get servlet request.");
       }
+      
+      txt.append(" Removing contextual info.");
+      pactx.removeContext();
 
       LOGGER.fine(txt.toString());
 
@@ -104,6 +111,18 @@ public class PortletAsyncListener implements AsyncListener {
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Error after ").append(delta).append(" milliseconds.");
+
+      // attempt to complete
+
+      try {
+         AsyncContext ctx = evt.getAsyncContext();
+         ctx.complete();
+         txt.append(" Portlet container completed request processing on behalf of the application.");
+      } catch (IllegalStateException e) {
+         txt.append(" An earlier listener has already dispatched or completed request.");
+      } catch (Exception e) {
+      }
+
       txt.append(", Exception: ").append(evt.getThrowable().getMessage());
       LOGGER.fine(txt.toString());
    }


[34/34] portals-pluto git commit: Added new classes for asynchronous processing and improved async documentation. New classes: PortletAsyncListener, PortletAsyncContext, and PortletAsyncEvent. Modified the Pluto implmentation to use the new interfaces. M

Posted by ms...@apache.org.
Added new classes for asynchronous processing and improved async
documentation. New classes: PortletAsyncListener, PortletAsyncContext, and
PortletAsyncEvent. Modified the Pluto implmentation to use the new
interfaces. Modified AsyncPortlet to used the newly introduced classes and
methods.


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

Branch: refs/heads/V3Prototype
Commit: 0e71c8ab72fe1d57f20a3b1a3ec357bd328930da
Parents: 1cbbbc3
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Apr 6 15:16:53 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Apr 6 15:16:53 2016 +0200

----------------------------------------------------------------------
 .../org/apache/portals/samples/APFilter.java    |  82 +++++
 .../org/apache/portals/samples/APListener.java  | 172 ++++++++++
 .../apache/portals/samples/AsyncPortlet.java    | 304 +++++++++++++++++
 .../portals/samples/AsyncPortletFilter.java     |  82 -----
 .../portals/samples/AsyncPortletListener.java   | 171 ----------
 .../portals/samples/AsyncPortletResource.java   | 316 -----------------
 .../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp |   2 +-
 .../pluto/container/PortletAsyncContext.java    |  15 -
 .../pluto/container/PortletAsyncManager.java    |  15 +
 .../PortletResourceRequestContext.java          |   2 +-
 .../pluto/container/driver/PortletServlet3.java |   4 +-
 .../impl/PortletAsyncRequestWrapper.java        |  56 +---
 .../container/impl/ResourceRequestImpl.java     |  14 +-
 .../fixtures/mocks/MockResourceRequest.java     |   8 +-
 .../services/container/FilterManagerImpl.java   |   3 +-
 .../container/PortletAsyncContextImpl.java      |  94 ++++--
 .../container/PortletAsyncContextListener.java  | 335 +++++++++++++++++++
 .../container/PortletAsyncContextualRunner.java |   6 +-
 .../container/PortletAsyncListener.java         | 299 -----------------
 .../PortletResourceRequestContextImpl.java      |  17 +-
 .../java/javax/portlet/PortletAsyncContext.java | 200 ++++++++---
 .../java/javax/portlet/PortletAsyncEvent.java   |  40 ++-
 .../javax/portlet/PortletAsyncListener.java     |  16 +-
 .../java/javax/portlet/ResourceRequest.java     |   7 +-
 .../filter/ClientDataRequestWrapper.java        |   1 -
 .../javax/portlet/filter/ResourceFilter.java    |   7 +-
 .../portlet/filter/ResourceRequestWrapper.java  |   8 +-
 portlet-api/src/main/javadoc/overview.html      |  13 +
 portlet-api/src/main/javadoc/portlet-api.css    |   6 +-
 29 files changed, 1252 insertions(+), 1043 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APFilter.java
new file mode 100644
index 0000000..cccc71b
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APFilter.java
@@ -0,0 +1,82 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.portlet.PortletException;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.annotations.PortletRequestFilter;
+import javax.portlet.filter.FilterChain;
+import javax.portlet.filter.FilterConfig;
+import javax.portlet.filter.ResourceFilter;
+import javax.servlet.DispatcherType;
+
+/**
+ * Filter for the async portlet. logs the dispatcher type and sometimes
+ * generates output.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+@PortletRequestFilter(portletNames="AsyncPortlet")
+public class APFilter implements ResourceFilter {
+   private static final Logger LOGGER = Logger.getLogger(APFilter.class.getName());
+   
+   @Inject private PortletRequestRandomNumberBean reqnum;
+   @Inject private AsyncDialogBean adb;
+
+   @Override
+   public void init(FilterConfig filterConfig) throws PortletException {
+   }
+
+   @Override
+   public void destroy() {
+   }
+
+   @Override
+   public void doFilter(ResourceRequest request, ResourceResponse response, FilterChain chain) throws IOException,
+         PortletException {
+      
+      DispatcherType type = request.getDispatcherType();
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Entering request. Dispatcher type: ").append(type);
+      txt.append(", request #: ").append(reqnum.getRandomNumber());
+      LOGGER.fine(txt.toString());
+      
+      if (adb.isShowFilter()) {
+         txt.setLength(0);
+         txt.append("<div class='msgbox'>");
+         txt.append("Filter: Request number: ").append(reqnum.getRandomNumber());
+         txt.append(", dispatcher type: ").append(request.getDispatcherType());
+         txt.append("</div>");
+         response.getWriter().write(txt.toString());
+      }
+      
+      chain.doFilter(request, response);
+      
+      LOGGER.fine("Exiting request. Dispatcher type: " + request.getDispatcherType());
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APListener.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APListener.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APListener.java
new file mode 100644
index 0000000..11847a9
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/APListener.java
@@ -0,0 +1,172 @@
+/*  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.portals.samples;
+
+import static org.apache.portals.samples.AsyncPortlet.ATTRIB_TIMEOUT;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.portlet.PortletAsyncContext;
+import javax.portlet.PortletAsyncEvent;
+import javax.portlet.PortletAsyncListener;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.apache.portals.samples.AsyncDialogBean.TimeoutType;
+
+/**
+ * @author Scott Nicklous
+ * 
+ */
+public class APListener implements PortletAsyncListener {
+   private static final Logger            LOGGER = Logger.getLogger(APListener.class.getName());
+
+   private long                           start  = System.currentTimeMillis();
+
+   @Inject
+   private PortletRequestRandomNumberBean reqnum;
+   @Inject
+   private AsyncDialogBean                adb;
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onComplete(PortletAsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Listener: Completed. Execution time: ").append(delta).append(" milliseconds.");
+
+      LOGGER.fine(txt.toString());
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onError(PortletAsyncEvent evt) throws IOException {
+
+      // this doesn't seem to get called when an error occurs in the executor
+      // thread.
+
+      long delta = System.currentTimeMillis() - start;
+
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Listener: Error after ").append(delta).append(" milliseconds.");
+      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
+
+      LOGGER.fine(txt.toString());
+      evt.getPortletAsyncContext().complete();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onStartAsync(PortletAsyncEvent 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.
+
+      PortletAsyncContext ctx = evt.getPortletAsyncContext();
+      // ctx.addListener(this);
+
+      // Try to write some output.
+
+      try {
+         if (adb.isShowListener()) {
+            ResourceRequest req = ctx.getResourceRequest();
+            ResourceResponse resp = ctx.getResourceResponse();
+            txt.setLength(0);
+            txt.append("<div class='orangebox'>");
+            txt.append("Listener: restarting async.");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Request number: ").append(reqnum.getRandomNumber());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Dispatcher type: ").append(req.getDispatcherType());
+            txt.append("</span>");
+            txt.append("</div>");
+            resp.getWriter().write(txt.toString());
+         }
+      } catch (Exception e) {
+         StringWriter sw = new StringWriter();
+         PrintWriter pw = new PrintWriter(sw);
+         e.printStackTrace(pw);
+         pw.flush();
+         LOGGER.fine("Exception producing output: \n" + sw.toString());
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onTimeout(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onTimeout(PortletAsyncEvent evt) throws IOException {
+      long delta = System.currentTimeMillis() - start;
+
+      try {
+         ResourceRequest req = evt.getPortletAsyncContext().getResourceRequest();
+         if (adb.isShowListener()) {
+            StringBuilder txt = new StringBuilder(128);
+            txt.append("<div class='orangebox'>");
+            txt.append("APListener: Timeout after ").append(delta).append(" milliseconds.");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Action: ").append(adb.getHandleTimeout().toString());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Request number: ").append(reqnum.getRandomNumber());
+            txt.append("</span>");
+            txt.append("<span style='margin-left: 2em;'>");
+            txt.append("Dispatcher type: ").append(req.getDispatcherType());
+            txt.append("</span>");
+            txt.append("</div>");
+            PrintWriter writer = evt.getPortletAsyncContext().getResourceResponse().getWriter();
+            writer.println(txt.toString());
+         }
+         
+         if (adb.getHandleTimeout() == TimeoutType.CPL) {
+            evt.getPortletAsyncContext().complete();
+         } else if (adb.getHandleTimeout() == TimeoutType.DIS) {
+            req.setAttribute(ATTRIB_TIMEOUT, ATTRIB_TIMEOUT);
+            evt.getPortletAsyncContext().dispatch();
+         }
+      } catch (Exception e) {
+         LOGGER.warning(" Couldn't get response to generate output. Exception: " + e.toString());
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortlet.java
new file mode 100644
index 0000000..2ae2fae
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortlet.java
@@ -0,0 +1,304 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.portlet.PortletAsyncContext;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.annotations.ServeResourceMethod;
+
+import org.apache.portals.samples.AsyncDialogBean.OutputType;
+
+/**
+ * Implements the async resource method for the async portlet.
+ * 
+ * @author Scott Nicklous
+ * 
+ */
+public class AsyncPortlet {
+   private static final Logger LOGGER = Logger.getLogger(AsyncPortlet.class.getName());
+   private static final boolean isTrace = LOGGER.isLoggable(Level.FINEST);
+   
+   private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
+   private final static String ATTRIB_REPS = "reps";
+   private final static String ATTRIB_AUTO = "auto";
+   public  final static String ATTRIB_TITLE = "title";
+   public  final static String ATTRIB_TIMEOUT = "timeout";
+
+   public static class AsyncRunnable implements Runnable {
+
+      private PortletAsyncContext ctx;
+      private int          delay;
+      private OutputType   type;
+      
+      @Inject private PortletRequestRandomNumberBean reqnum;
+
+      public void init(PortletAsyncContext ctx, int delay, OutputType type) {
+         this.ctx = ctx;
+         this.delay = delay;
+         this.type = type;
+         
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Initializing runnable.");
+         txt.append(" delay: ").append(delay);
+         txt.append(", type: ").append(type);
+         LOGGER.fine(txt.toString());
+      }
+
+      @Override
+      public void run() {
+         try {
+            Thread.sleep(delay);
+
+            ResourceRequest req = ctx.getResourceRequest();
+            ResourceResponse resp = ctx.getResourceResponse();
+            PortletRequestDispatcher rd = req.getPortletContext().getRequestDispatcher(JSP);
+            
+            AsyncPortlet.trace(req, "Runnable: ");
+            
+            PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
+            String portletName = "Could not get PortletConfig";
+            if (config != null) {
+               portletName = config.getPortletName();
+            }
+
+            switch (type) {
+            case TEXT:
+               LOGGER.fine("Producing text output.");
+               StringBuilder txt = new StringBuilder(128);
+               txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
+               txt.append("<p>Dispatcher type: ").append(req.getDispatcherType().toString());
+               txt.append("<span style='margin-left: 2em;'>Request #: ");
+               try { // in case context not active
+                  txt.append(reqnum.getRandomNumber());
+               } catch (Exception e) {}
+               txt.append("</span></p><hr>");
+               resp.getWriter().write(txt.toString());
+               ctx.complete();
+               break;
+            case AUTO:
+               StringBuilder str = new StringBuilder(128);
+               str.append("Dispatching to resource method.");
+               str.append(" context path: ").append(req.getPortletContext().getContextPath());
+               LOGGER.fine(str.toString());
+               req.setAttribute(ATTRIB_AUTO, new Boolean(true));
+               ctx.dispatch();
+               break;
+            case DISPATCH:
+               LOGGER.fine("Dispatching to JSP.");
+               req.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
+               ctx.dispatch(JSP);
+               break;
+            case FWD:
+               LOGGER.fine("Doing request dispatcher forward to JSP: " + JSP);
+               req.setAttribute(ATTRIB_TITLE, "Thread forwarding to JSP");
+               rd.forward(req, resp);
+               LOGGER.fine("After request dispatcher forward to JSP.");
+               ctx.complete();
+               break;
+            case INC:
+               LOGGER.fine("Including JSP: " + JSP);
+               req.setAttribute(ATTRIB_TITLE, "Thread including JSP");
+               rd.include(req, resp);
+               ctx.complete();
+               break;
+            }
+
+         } catch (IllegalStateException e) {
+            LOGGER.warning("Request may have timed out before it could complete. Exception: " + e.toString());
+         } catch (Exception e) {
+            StringWriter sw = new StringWriter();
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            pw.flush();
+            LOGGER.fine("Exception during runner execution: \n" + sw.toString());
+         }
+      }
+
+   }
+
+   @Inject private AsyncDialogBean adb;
+   @Inject private PortletRequestRandomNumberBean reqnum;
+   @Inject private AsyncRunnable runner;
+
+   @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
+   public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
+      
+      if (req.getAttribute(ATTRIB_TIMEOUT) != null) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("<p>Resource method: listener reports timout.");
+         txt.append("<span style='margin-left: 2em;'>Request #: ");
+         txt.append("dispatcher type: ").append(req.getDispatcherType().toString());
+         txt.append("</span>");
+         txt.append("<span style='margin-left: 2em;'>Request #: ");
+         txt.append(reqnum.getRandomNumber());
+         txt.append("</span></p><hr>");
+         resp.getWriter().write(txt.toString());
+         return;
+      }
+
+      Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
+      if (auto == null) {
+         auto = false;
+      }
+      req.removeAttribute(ATTRIB_AUTO);
+
+      Integer reps = (Integer) req.getAttribute(ATTRIB_REPS);
+      if (reps == null) {
+         reps = adb.getReps();
+      }
+      
+      boolean done = (reps <= 0) || (adb.getDelay() <= 0);
+
+      reps--;
+      req.setAttribute(ATTRIB_REPS, reps);
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Resource method.");
+      txt.append(" delay: ").append(adb.getDelay());
+      txt.append(", type: ").append(adb.getType());
+      txt.append(", reps: ").append(reps);
+      txt.append(", total reps: ").append(adb.getReps());
+      txt.append(", auto: ").append(adb.isAutoDispatch());
+      txt.append(", auto-dispatch: ").append(auto);
+      LOGGER.fine(txt.toString());
+      
+      PortletAsyncContext ctx = req.startAsync();
+      ctx.setTimeout(4000);
+      try {
+         ctx.addListener(ctx.createPortletAsyncListener(APListener.class));
+      } catch (PortletException e) {
+         StringWriter sw = new StringWriter();
+         PrintWriter pw = new PrintWriter(sw);
+         e.printStackTrace(pw);
+         pw.flush();
+         LOGGER.fine("Exception adding listener: \n" + sw.toString());
+      }
+
+      if (auto || (adb.getDelay() <= 0)) {
+         
+         // produce output if dispatched from work thread or if there is no delay requested
+         
+         PortletRequestDispatcher rd;
+
+         trace(req, "Resource method: ");
+         
+         // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
+         PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
+         String portletName = "Could not get PortletConfig";
+         if (config != null) {
+            portletName = config.getPortletName();
+         }
+
+         switch (adb.getType()) {
+         case DISPATCH:
+            LOGGER.fine("Dispatching to JSP.");
+            req.setAttribute(ATTRIB_TITLE, "Resource Method dispatching to JSP");
+            ctx.dispatch(JSP);
+            break;
+         case FWD:
+            LOGGER.fine("Doing request dispatcher forward to JSP.");
+            req.setAttribute(ATTRIB_TITLE, "Resource Method forwarding to JSP");
+            rd = req.getPortletContext().getRequestDispatcher(JSP);
+            rd.forward(req, resp);
+            resp.flushBuffer();
+            if (done) {
+               ctx.complete();
+            }
+            break;
+         case INC:
+            LOGGER.fine("Doing request dispatcher include of JSP.");
+            req.setAttribute(ATTRIB_TITLE, "Resource Method including JSP");
+            rd = req.getPortletContext().getRequestDispatcher(JSP);
+            rd.include(req, resp);
+            resp.flushBuffer();
+            if (done) {
+               ctx.complete();
+            }
+            break;
+         default:
+            LOGGER.fine("Producing text output.");
+            txt.setLength(0);
+            txt.append("<h5>Resource method producing text output for portlet: " + portletName + "</h5>");
+            txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
+            txt.append("<span style='margin-left: 2em;'>Request #: ");
+            txt.append(reqnum.getRandomNumber());
+            txt.append("</span></p><hr>");
+            resp.getWriter().write(txt.toString());
+            resp.flushBuffer();
+            if (done) {
+               ctx.complete();
+            }
+            break;
+         }
+      }
+      
+      if (!done) {
+         
+         // now start the executor thread 
+         
+         OutputType type = adb.getType();
+         if (adb.isAutoDispatch()) {
+            type = OutputType.AUTO;
+         }
+
+         runner.init(ctx, adb.getDelay(), type);
+         ctx.start(runner);
+      }
+   }
+   
+   public static void trace(ResourceRequest req, String src) {
+      if (isTrace) {
+         List<String> attrNames = Collections.list(req.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append(src);
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) req.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append((String) req.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append((String) req.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) req.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append((String) req.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append((String) req.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append((String) req.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append((String) req.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) req.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append((String) req.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append((String) req.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append((String) req.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append((String) req.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) req.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append((String) req.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_context_path:      ").append(req.getContextPath());
+         LOGGER.fine(txt.toString());
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
deleted file mode 100644
index 09eff20..0000000
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*  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.portals.samples;
-
-import java.io.IOException;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-import javax.portlet.PortletException;
-import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
-import javax.portlet.annotations.PortletRequestFilter;
-import javax.portlet.filter.FilterChain;
-import javax.portlet.filter.FilterConfig;
-import javax.portlet.filter.ResourceFilter;
-import javax.servlet.DispatcherType;
-
-/**
- * Filter for the async portlet. logs the dispatcher type and sometimes
- * generates output.
- * 
- * @author Scott Nicklous
- *
- */
-@PortletRequestFilter(portletNames="AsyncPortlet")
-public class AsyncPortletFilter implements ResourceFilter {
-   private static final Logger LOGGER = Logger.getLogger(AsyncPortletFilter.class.getName());
-   
-   @Inject private PortletRequestRandomNumberBean reqnum;
-   @Inject private AsyncDialogBean adb;
-
-   @Override
-   public void init(FilterConfig filterConfig) throws PortletException {
-   }
-
-   @Override
-   public void destroy() {
-   }
-
-   @Override
-   public void doFilter(ResourceRequest request, ResourceResponse response, FilterChain chain) throws IOException,
-         PortletException {
-      
-      DispatcherType type = request.getDispatcherType();
-      
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Entering request. Dispatcher type: ").append(type);
-      txt.append(", request #: ").append(reqnum.getRandomNumber());
-      LOGGER.fine(txt.toString());
-      
-      if (adb.isShowFilter()) {
-         txt.setLength(0);
-         txt.append("<div class='msgbox'>");
-         txt.append("Filter: Request number: ").append(reqnum.getRandomNumber());
-         txt.append(", dispatcher type: ").append(request.getDispatcherType());
-         txt.append("</div>");
-         response.getWriter().write(txt.toString());
-      }
-      
-      chain.doFilter(request, response);
-      
-      LOGGER.fine("Exiting request. Dispatcher type: " + request.getDispatcherType());
-      
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
deleted file mode 100644
index d8fd5fb..0000000
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*  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.portals.samples;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-import javax.servlet.AsyncContext;
-import javax.servlet.AsyncEvent;
-import javax.servlet.AsyncListener;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import static org.apache.portals.samples.AsyncDialogBean.TimeoutType;
-import static org.apache.portals.samples.AsyncPortletResource.*;
-
-/**
- * @author Scott Nicklous
- * 
- */
-public class AsyncPortletListener implements AsyncListener {
-   private static final Logger            LOGGER = Logger.getLogger(AsyncPortletListener.class.getName());
-
-   private long                           start  = System.currentTimeMillis();
-
-   @Inject
-   private PortletRequestRandomNumberBean reqnum;
-   @Inject
-   private AsyncDialogBean                adb;
-
-   /*
-    * (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("Listener: Completed. Execution time: ").append(delta).append(" milliseconds.");
-
-      LOGGER.fine(txt.toString());
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
-    */
-   @Override
-   public void onError(AsyncEvent evt) throws IOException {
-
-      // this doesn't seem to get called when an error occurs in the executor
-      // thread.
-
-      long delta = System.currentTimeMillis() - start;
-
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Listener: Error after ").append(delta).append(" milliseconds.");
-      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
-
-      LOGGER.fine(txt.toString());
-      evt.getAsyncContext().complete();
-   }
-
-   /*
-    * (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);
-
-      // Try to write some output.
-
-      try {
-         if (adb.isShowListener()) {
-            HttpServletRequest req = (HttpServletRequest) ctx.getRequest();
-            HttpServletResponse resp = (HttpServletResponse) ctx.getResponse();
-            txt.setLength(0);
-            txt.append("<div class='orangebox'>");
-            txt.append("Listener: restarting async.");
-            txt.append("<span style='margin-left: 2em;'>");
-            txt.append("Request number: ").append(reqnum.getRandomNumber());
-            txt.append("</span>");
-            txt.append("<span style='margin-left: 2em;'>");
-            txt.append("Dispatcher type: ").append(req.getDispatcherType());
-            txt.append("</span>");
-            txt.append("</div>");
-            resp.getWriter().write(txt.toString());
-         }
-      } catch (Exception e) {
-         StringWriter sw = new StringWriter();
-         PrintWriter pw = new PrintWriter(sw);
-         e.printStackTrace(pw);
-         pw.flush();
-         LOGGER.fine("Exception producing output: \n" + sw.toString());
-      }
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see javax.servlet.AsyncListener#onTimeout(javax.servlet.AsyncEvent)
-    */
-   @Override
-   public void onTimeout(AsyncEvent evt) throws IOException {
-      long delta = System.currentTimeMillis() - start;
-
-      try {
-         HttpServletRequest req = (HttpServletRequest) evt.getAsyncContext().getRequest();
-         if (adb.isShowListener()) {
-            StringBuilder txt = new StringBuilder(128);
-            txt.append("<div class='orangebox'>");
-            txt.append("AsyncPortletListener: Timeout after ").append(delta).append(" milliseconds.");
-            txt.append("<span style='margin-left: 2em;'>");
-            txt.append("Action: ").append(adb.getHandleTimeout().toString());
-            txt.append("</span>");
-            txt.append("<span style='margin-left: 2em;'>");
-            txt.append("Request number: ").append(reqnum.getRandomNumber());
-            txt.append("</span>");
-            txt.append("<span style='margin-left: 2em;'>");
-            txt.append("Dispatcher type: ").append(req.getDispatcherType());
-            txt.append("</span>");
-            txt.append("</div>");
-            PrintWriter writer = evt.getAsyncContext().getResponse().getWriter();
-            writer.println(txt.toString());
-         }
-         
-         if (adb.getHandleTimeout() == TimeoutType.CPL) {
-            evt.getAsyncContext().complete();
-         } else if (adb.getHandleTimeout() == TimeoutType.DIS) {
-            req.setAttribute(ATTRIB_TIMEOUT, ATTRIB_TIMEOUT);
-            evt.getAsyncContext().dispatch();
-         }
-      } catch (Exception e) {
-         LOGGER.warning(" Couldn't get response to generate output. Exception: " + e.toString());
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
deleted file mode 100644
index 1c25e61..0000000
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*  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.portals.samples;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-import javax.portlet.PortletConfig;
-import javax.portlet.PortletException;
-import javax.portlet.PortletRequestDispatcher;
-import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
-import javax.portlet.annotations.ServeResourceMethod;
-import javax.servlet.AsyncContext;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.portals.samples.AsyncDialogBean.OutputType;
-
-/**
- * Implements the async resource method for the async portlet.
- * 
- * @author Scott Nicklous
- * 
- */
-public class AsyncPortletResource {
-   private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
-   private static final boolean isTrace = LOGGER.isLoggable(Level.FINEST);
-   
-   private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
-   private final static String ATTRIB_REPS = "reps";
-   private final static String ATTRIB_AUTO = "auto";
-   public  final static String ATTRIB_TITLE = "title";
-   public  final static String ATTRIB_TIMEOUT = "timeout";
-
-   public static class AsyncRunnable implements Runnable {
-
-      private AsyncContext ctx;
-      private int          delay;
-      private OutputType   type;
-      
-      @Inject private PortletRequestRandomNumberBean reqnum;
-
-      public void init(AsyncContext ctx, int delay, OutputType type) {
-         this.ctx = ctx;
-         this.delay = delay;
-         this.type = type;
-         
-         StringBuilder txt = new StringBuilder(128);
-         txt.append("Initializing runnable.");
-         txt.append(" delay: ").append(delay);
-         txt.append(", type: ").append(type);
-         LOGGER.fine(txt.toString());
-      }
-
-      @Override
-      public void run() {
-         try {
-            Thread.sleep(delay);
-
-            HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
-            HttpServletResponse hresp = (HttpServletResponse) ctx.getResponse();
-            RequestDispatcher rd;
-            
-            AsyncPortletResource.trace(hreq, "Runnable: ");
-            
-            PortletConfig config = (PortletConfig) hreq.getAttribute("javax.portlet.config");
-            String portletName = "Could not get PortletConfig";
-            if (config != null) {
-               portletName = config.getPortletName();
-            }
-
-            switch (type) {
-            case TEXT:
-               LOGGER.fine("Producing text output.");
-               StringBuilder txt = new StringBuilder(128);
-               txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
-               txt.append("<p>Dispatcher type: ").append(hreq.getDispatcherType().toString());
-               txt.append("<span style='margin-left: 2em;'>Request #: ");
-               try { // in case context not active
-                  txt.append(reqnum.getRandomNumber());
-               } catch (Exception e) {}
-               txt.append("</span></p><hr>");
-               hresp.getWriter().write(txt.toString());
-               ctx.complete();
-               break;
-            case AUTO:
-               StringBuilder str = new StringBuilder(128);
-               str.append("Dispatching to resource method.");
-               str.append(" context path: ").append(hreq.getServletContext().getContextPath());
-               str.append(", Servlet patch: ").append(hreq.getServletPath());
-               LOGGER.fine(str.toString());
-               hreq.setAttribute(ATTRIB_AUTO, new Boolean(true));
-               ctx.dispatch();
-               break;
-            case DISPATCH:
-               LOGGER.fine("Dispatching to JSP.");
-               hreq.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
-               ctx.dispatch(JSP);
-               break;
-            case FWD:
-               LOGGER.fine("Doing request dispatcher forward to JSP: " + JSP);
-               hreq.setAttribute(ATTRIB_TITLE, "Thread forwarding to JSP");
-               rd = hreq.getRequestDispatcher(JSP);
-               rd.forward(hreq, hresp);
-               LOGGER.fine("After request dispatcher forward to JSP.");
-               ctx.complete();
-               break;
-            case INC:
-               LOGGER.fine("Including JSP: " + JSP);
-               hreq.setAttribute(ATTRIB_TITLE, "Thread including JSP");
-               rd = hreq.getRequestDispatcher(JSP);
-               rd.include(hreq, hresp);
-               ctx.complete();
-               break;
-            }
-
-         } catch (IllegalStateException e) {
-            LOGGER.warning("Request may have timed out before it could complete. Exception: " + e.toString());
-         } catch (Exception e) {
-            LOGGER.warning("Exception during async processing: " + e.toString());
-         }
-      }
-
-   }
-
-   @Inject private AsyncDialogBean adb;
-   @Inject private PortletRequestRandomNumberBean reqnum;
-   @Inject private AsyncRunnable runner;
-
-   @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
-   public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
-      
-      if (req.getAttribute(ATTRIB_TIMEOUT) != null) {
-         StringBuilder txt = new StringBuilder(128);
-         txt.append("<p>Resource method: listener reports timout.");
-         txt.append("<span style='margin-left: 2em;'>Request #: ");
-         txt.append("dispatcher type: ").append(req.getDispatcherType().toString());
-         txt.append("</span>");
-         txt.append("<span style='margin-left: 2em;'>Request #: ");
-         txt.append(reqnum.getRandomNumber());
-         txt.append("</span></p><hr>");
-         resp.getWriter().write(txt.toString());
-         return;
-      }
-
-      Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
-      if (auto == null) {
-         auto = false;
-      }
-      req.removeAttribute(ATTRIB_AUTO);
-
-      Integer reps = (Integer) req.getAttribute(ATTRIB_REPS);
-      if (reps == null) {
-         reps = adb.getReps();
-      }
-      
-      boolean done = (reps <= 0) || (adb.getDelay() <= 0);
-
-      reps--;
-      req.setAttribute(ATTRIB_REPS, reps);
-      
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Resource method.");
-      txt.append(" delay: ").append(adb.getDelay());
-      txt.append(", type: ").append(adb.getType());
-      txt.append(", reps: ").append(reps);
-      txt.append(", total reps: ").append(adb.getReps());
-      txt.append(", auto: ").append(adb.isAutoDispatch());
-      txt.append(", auto-dispatch: ").append(auto);
-      LOGGER.fine(txt.toString());
-      
-      AsyncContext ctx = req.startAsync();
-      ctx.setTimeout(4000);
-      try {
-         ctx.addListener(ctx.createListener(AsyncPortletListener.class));
-      } catch (ServletException e) {
-         StringWriter sw = new StringWriter();
-         PrintWriter pw = new PrintWriter(sw);
-         e.printStackTrace(pw);
-         pw.flush();
-         LOGGER.fine("Exception adding listener: \n" + sw.toString());
-      }
-
-      if (auto || (adb.getDelay() <= 0)) {
-         
-         // produce output if dispatched from work thread or if there is no delay requested
-         
-         PortletRequestDispatcher rd;
-
-         trace(req, "Resource method: ");
-         
-         // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
-         PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
-         String portletName = "Could not get PortletConfig";
-         if (config != null) {
-            portletName = config.getPortletName();
-         }
-
-         switch (adb.getType()) {
-         case DISPATCH:
-            LOGGER.fine("Dispatching to JSP.");
-            req.setAttribute(ATTRIB_TITLE, "Resource Method dispatching to JSP");
-            ctx.dispatch(JSP);
-            break;
-         case FWD:
-            LOGGER.fine("Doing request dispatcher forward to JSP.");
-            req.setAttribute(ATTRIB_TITLE, "Resource Method forwarding to JSP");
-            rd = req.getPortletContext().getRequestDispatcher(JSP);
-            rd.forward(req, resp);
-            resp.flushBuffer();
-            if (done) {
-               ctx.complete();
-            }
-            break;
-         case INC:
-            LOGGER.fine("Doing request dispatcher include of JSP.");
-            req.setAttribute(ATTRIB_TITLE, "Resource Method including JSP");
-            rd = req.getPortletContext().getRequestDispatcher(JSP);
-            rd.include(req, resp);
-            resp.flushBuffer();
-            if (done) {
-               ctx.complete();
-            }
-            break;
-         default:
-            LOGGER.fine("Producing text output.");
-            txt.setLength(0);
-            txt.append("<h5>Resource method producing text output for portlet: " + portletName + "</h5>");
-            txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
-            txt.append("<span style='margin-left: 2em;'>Request #: ");
-            txt.append(reqnum.getRandomNumber());
-            txt.append("</span></p><hr>");
-            resp.getWriter().write(txt.toString());
-            resp.flushBuffer();
-            if (done) {
-               ctx.complete();
-            }
-            break;
-         }
-      }
-      
-      if (!done) {
-         
-         // now start the executor thread 
-         
-         OutputType type = adb.getType();
-         if (adb.isAutoDispatch()) {
-            type = OutputType.AUTO;
-         }
-
-         runner.init(ctx, adb.getDelay(), type);
-         ctx.start(runner);
-      }
-   }
-   
-   public static void trace(ResourceRequest req, String src) {
-      HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
-      trace(hreq, src);
-   }
-   
-   public static void trace(HttpServletRequest hreq, String src) {
-      if (isTrace) {
-         List<String> attrNames = Collections.list(hreq.getAttributeNames());
-         StringBuilder txt = new StringBuilder(128);
-         txt.append(src);
-         txt.append("\nAttribute names: ").append(attrNames);
-         txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-         txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-         txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-         txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-         txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-         txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-         txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-         txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-         txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-         txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-         txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-         txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-         txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-         txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-         txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-         txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-         txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-         txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-         txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-         txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
-         LOGGER.fine(txt.toString());
-      }
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
index 1c7024e..2566242 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -6,7 +6,7 @@
 
 <portlet:defineObjects />
 
-<h5><%=request.getAttribute("title") %> for portlet: <%=portletConfig.getPortletName() %></h5>
+<h5><%=request.getAttribute("title") %> for portlet: ${portletConfig.getPortletName()}</h5>
 <p>Dispatch type: <%=request.getDispatcherType() %>
 <c:catch var ="catchException">
    <span style='margin-left: 2em;'>Request #: ${reqnum.getRandomNumber()}</span>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
deleted file mode 100644
index 0892139..0000000
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.apache.pluto.container;
-
-import javax.servlet.AsyncContext;
-
-public interface PortletAsyncContext extends AsyncContext {
-
-   void setWrapped(AsyncContext actx);
-   void registerContext(boolean isListener);
-   void deregisterContext(boolean isListener);
-   void removeContext();
-   void launchRunner();
-   boolean isComplete();
-   void setComplete(boolean complete);
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncManager.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncManager.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncManager.java
new file mode 100644
index 0000000..cf71a4c
--- /dev/null
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncManager.java
@@ -0,0 +1,15 @@
+package org.apache.pluto.container;
+
+import javax.servlet.AsyncContext;
+
+public interface PortletAsyncManager {
+
+   void setWrapped(AsyncContext actx);
+   void registerContext(boolean isListener);
+   void deregisterContext(boolean isListener);
+   void removeContext();
+   void launchRunner();
+   boolean isComplete();
+   void setComplete(boolean complete);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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 b999eee..c5ef832 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
@@ -75,7 +75,7 @@ public interface PortletResourceRequestContext extends PortletRequestContext
     HttpSession getSession();
     AsyncContext startAsync();
     AsyncContext startAsync(ServletRequest request, ServletResponse response);
-    PortletAsyncContext getPortletAsyncContext();
+    PortletAsyncManager getPortletAsyncContext();
     BeanManager getBeanManager();
     void setBeanManager(BeanManager beanmgr);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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 3aef3e4..b690fb0 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
@@ -51,7 +51,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.FilterManager;
-import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletAsyncManager;
 import org.apache.pluto.container.PortletContainerException;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletRequestContext;
@@ -477,7 +477,7 @@ public class PortletServlet3 extends HttpServlet {
 
             if (requestContext instanceof PortletResourceRequestContext) {
                PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
-               PortletAsyncContext pac = resctx.getPortletAsyncContext();
+               PortletAsyncManager pac = resctx.getPortletAsyncContext();
                if (pac != null) {
                   pac.deregisterContext(false);
                   pac.launchRunner();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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
index 353b49f..cb32bc7 100644
--- 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
@@ -30,6 +30,7 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.pluto.container.NamespaceMapper;
+import org.apache.pluto.container.PortletAsyncManager;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletWindowID;
 import org.slf4j.Logger;
@@ -99,6 +100,10 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
    
    @Override
    public void setAttribute(String name, Object o) {
+      PortletAsyncManager actx = reqctx.getPortletAsyncContext();
+      if (actx != null && actx.isComplete()) {
+         return;
+      }
       boolean encoded = false;
       Object val = getRequest().getAttribute(mapper.encode(winId, name));
       if (val != null) {
@@ -119,6 +124,10 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
    
    @Override
    public void removeAttribute(String name) {
+      PortletAsyncManager actx = reqctx.getPortletAsyncContext();
+      if (actx != null && actx.isComplete()) {
+         return;
+      }
       boolean encoded = false;
       Object val = getRequest().getAttribute(mapper.encode(winId, name));
       if (val != null) {
@@ -161,53 +170,6 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
       return info;
    }
    
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-//    @Override
-//    public RequestDispatcher getRequestDispatcher(String path) {
-//       RequestDispatcher rd = super.getRequestDispatcher(path);
-//       if (rd != null) {
-//          PortletRequestDispatcherImpl prd =  new PortletRequestDispatcherImpl(rd, false);
-//          prd.setPortletRequest(preq);
-//          prd.setPortletResponse(reqctx.getResponse());
-//          return prd;
-//       }
-//       return null;
-//    }
-   
-   
-   
-   
-   
-   
-   
-   // saved methods below.
-
-//    /**
-//     * 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 reqctx.startAsync();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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 fdd2145..1d79fa1 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
@@ -20,11 +20,11 @@ import java.util.Enumeration;
 import java.util.Map;
 
 import javax.portlet.CacheControl;
+import javax.portlet.PortletAsyncContext;
 import javax.portlet.PortletRequest;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
-import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
 
 import org.apache.pluto.container.PortletResourceRequestContext;
@@ -119,13 +119,13 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    }
 
    @Override
-   public AsyncContext startAsync() throws IllegalStateException {
-      return getRequestContext().startAsync(this);
+   public PortletAsyncContext startAsync() throws IllegalStateException {
+      return (PortletAsyncContext) getRequestContext().startAsync(this);
    }
 
    @Override
-   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
-      return getRequestContext().startAsync(request, response);
+   public PortletAsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+      return (PortletAsyncContext) getRequestContext().startAsync(request, response);
    }
 
    @Override
@@ -139,8 +139,8 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    }
 
    @Override
-   public AsyncContext getAsyncContext() {
-      return getRequestContext().getAsyncContext();
+   public PortletAsyncContext getAsyncContext() {
+      return (PortletAsyncContext) getRequestContext().getAsyncContext();
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
index 2b4d1a2..6db56e2 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/mocks/MockResourceRequest.java
@@ -21,10 +21,10 @@ package org.apache.pluto.container.bean.processor.fixtures.mocks;
 
 import java.util.Map;
 
+import javax.portlet.PortletAsyncContext;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
-import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
 
 /**
@@ -90,12 +90,12 @@ public class MockResourceRequest extends MockClientDataRequest implements Resour
    }
 
    @Override
-   public AsyncContext startAsync() throws IllegalStateException {
+   public PortletAsyncContext startAsync() throws IllegalStateException {
       return null;
    }
 
    @Override
-   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+   public PortletAsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
       return null;
    }
 
@@ -110,7 +110,7 @@ public class MockResourceRequest extends MockClientDataRequest implements Resour
    }
 
    @Override
-   public AsyncContext getAsyncContext() {
+   public PortletAsyncContext getAsyncContext() {
       return null;
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
index 1b076a3..37d00f7 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/FilterManagerImpl.java
@@ -18,9 +18,7 @@ package org.apache.pluto.driver.services.container;
 
 import java.io.IOException;
 import java.util.List;
-import java.util.Set;
 
-import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
@@ -56,6 +54,7 @@ import org.slf4j.LoggerFactory;
  * @version 2.0
  */
 public class FilterManagerImpl implements FilterManager{
+   @SuppressWarnings("unused")
    private static final Logger LOG = LoggerFactory.getLogger(FilterManagerImpl.class);
    
     private FilterChainImpl filterchain;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
index ce8e044..1ab34e4 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -22,7 +22,10 @@ import java.util.Set;
 
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
+import javax.portlet.PortletAsyncContext;
+import javax.portlet.PortletException;
 import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncListener;
 import javax.servlet.ServletContext;
@@ -32,7 +35,7 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletAsyncManager;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.bean.processor.PortletArtifactProducer;
 import org.apache.pluto.container.bean.processor.PortletRequestScopedBeanHolder;
@@ -48,7 +51,7 @@ import org.slf4j.LoggerFactory;
  * @author Scott Nicklous
  * 
  */
-public class PortletAsyncContextImpl implements PortletAsyncContext {
+public class PortletAsyncContextImpl implements PortletAsyncManager, AsyncContext, PortletAsyncContext {
    private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextImpl.class);
    private static final boolean isDebug = LOG.isDebugEnabled();
    @SuppressWarnings("unused")
@@ -57,7 +60,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
    private AsyncContext                   actx;
    
    private final HttpServletRequest       hreq;
-   private final PortletAsyncListener     pal;
+   private final PortletAsyncContextListener     pal;
    private final PortletResourceRequestContext  prctx;
 
    private ResourceRequest                resreq;
@@ -81,7 +84,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       HttpServletRequest creq = prctx.getContainerRequest();
       HttpServletResponse cresp = prctx.getContainerResponse();
 
-      pal = new PortletAsyncListener(this);
+      pal = new PortletAsyncContextListener(this);
       actx.addListener(pal, creq, cresp);
    }
 
@@ -237,27 +240,7 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
    @SuppressWarnings("unchecked")
    @Override
    public <T extends AsyncListener> T createListener(Class<T> cls) throws ServletException {
-      if (isDebug) {
-         StringBuilder txt = new StringBuilder();
-         txt.append("Creating listener.");
-         txt.append(" Bean manager: ").append(beanmgr);
-         txt.append(", listener class: ").append(cls.getCanonicalName());
-         LOG.debug(txt.toString());
-      }
-      T lis = null;
-      if (beanmgr != null) {
-         Set<Bean<?>> beans = beanmgr.getBeans(cls);
-         Bean<?> bean = beanmgr.resolve(beans);
-         if (bean != null) {
-            lis = (T) beanmgr.getReference(bean, bean.getBeanClass(), beanmgr.createCreationalContext(bean));
-         } else {
-            LOG.warn("Could not get bean reference for: " + cls.getCanonicalName());
-            lis = actx.createListener(cls);
-         }
-      } else {
-         lis = actx.createListener(cls);
-      }
-      return lis;
+      return (T) createInstance(cls);
    }
 
    /*
@@ -352,4 +335,65 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
       pendingRunner = run;
    }
 
+   @Override
+   public void addListener(javax.portlet.PortletAsyncListener listener) throws IllegalStateException {
+      pal.addListener(listener);
+   }
+
+   @Override
+   public void addListener(javax.portlet.PortletAsyncListener listener, ResourceRequest request,
+         ResourceResponse response) throws IllegalStateException {
+      pal.addListener(listener, request, response);
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <T extends javax.portlet.PortletAsyncListener> T createPortletAsyncListener(Class<T> cls)
+         throws PortletException {
+      return (T) createInstance(cls);
+   }
+
+   @Override
+   public ResourceRequest getResourceRequest() throws IllegalStateException {
+      return resreq;
+   }
+
+   @Override
+   public ResourceResponse getResourceResponse() throws IllegalStateException {
+      return prctx.getResponse();
+   }
+   
+   private Object createInstance(Class<?> cls) {
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Creating listener.");
+         txt.append(" Bean manager: ").append(beanmgr);
+         txt.append(", listener class: ").append(cls.getCanonicalName());
+         LOG.debug(txt.toString());
+      }
+      
+      Object lis = null;
+      if (beanmgr != null) {
+         Set<Bean<?>> beans = beanmgr.getBeans(cls);
+         Bean<?> bean = beanmgr.resolve(beans);
+         if (bean != null) {
+            lis = beanmgr.getReference(bean, bean.getBeanClass(), beanmgr.createCreationalContext(bean));
+         } else {
+            LOG.warn("Could not get bean reference for: " + cls.getCanonicalName());
+         }
+      } 
+      
+      if (lis == null) {
+         LOG.debug("Instantiating class directly: " + cls.getCanonicalName());
+         try {
+            lis = cls.newInstance();
+         } catch (Exception e) {
+            LOG.warn("Could not instantiate class: " + cls.getCanonicalName());
+         }
+      }
+      
+      return lis;
+
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextListener.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextListener.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextListener.java
new file mode 100644
index 0000000..4e85c36
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextListener.java
@@ -0,0 +1,335 @@
+/*  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.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletAsyncEvent;
+import javax.portlet.PortletAsyncListener;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.pluto.container.PortletInvokerService;
+import org.apache.pluto.container.PortletResourceResponseContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the listeners registered by the application. Releases portal resources when 
+ * the async request completes and provides contextual services for the listeners. 
+ * 
+ * @author Scott Nicklous
+ */
+public class PortletAsyncContextListener implements AsyncListener {
+   
+   /** Logger. */
+   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextListener.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   @SuppressWarnings("unused")
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
+   
+   // Data for one listener
+   private class Entry {
+
+      public AsyncListener          hlis;
+      public ServletRequest         hreq;
+      public ServletResponse        hresp;
+      public PortletAsyncListener   plis;
+      public ResourceRequest        preq;
+      public ResourceResponse       presp;
+
+      public Entry(AsyncListener lis, ServletRequest req, ServletResponse resp) {
+         this.hlis  = lis;
+         this.hreq  = req;
+         this.hresp = resp;
+      }
+      
+      public Entry(PortletAsyncListener lis, ResourceRequest req, ResourceResponse resp) {
+         this.plis  = lis;
+         this.preq  = req;
+         this.presp = resp;
+      }
+   }
+   
+   // The registered listeners
+   List<Entry> listeners = new ArrayList<Entry>();
+   
+   private long start  = System.currentTimeMillis();
+   private final PortletAsyncContextImpl pactx;
+   
+ 
+   public PortletAsyncContextListener(PortletAsyncContextImpl pactx) {
+      this.pactx = pactx;
+   }
+   
+   public void addListener(AsyncListener l) {
+      listeners.add(new Entry(l, null, null));
+   }
+   
+   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
+      listeners.add(new Entry(l, req, resp));
+   }
+   
+   public void addListener(PortletAsyncListener l) {
+      listeners.add(new Entry(l, null, null));
+   }
+   
+   public void addListener(PortletAsyncListener l, ResourceRequest req, ResourceResponse resp) {
+      listeners.add(new Entry(l, req, resp));
+   }
+   
+   private void trace (String meth) {
+      if (isDebug) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Firing ").append(meth).append(" event for ");
+         txt.append(listeners.size()).append(" listeners.");
+         int hcnt=0, pcnt=0;
+         for (Entry e : listeners) {
+            if (e.hlis != null) hcnt++;
+            if (e.plis != null) pcnt++;
+         }
+         txt.append(", # AsyncListeners: ").append(hcnt);
+         txt.append(", # PortletAsyncListeners: ").append(pcnt);
+         LOG.debug(txt.toString());
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onComplete(AsyncEvent evt) throws IOException {
+
+      trace("onComplete");
+      
+      pactx.registerContext(true);
+      for (Entry l : listeners) {
+         if (l.hlis != null) {
+            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
+            l.hlis.onComplete(lisevt);
+         } else {
+            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
+            l.plis.onComplete(lisevt);
+         }
+      }
+      pactx.deregisterContext(true);
+      pactx.setComplete(true);
+      
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Completed. Execution time: ").append(delta).append(" milliseconds.");
+      txt.append(" Releasing: ");
+
+      HttpServletRequest hreq = (HttpServletRequest) evt.getSuppliedRequest();
+      if (hreq != null) {
+         ResourceRequest rreq = (ResourceRequest) hreq.getAttribute(PortletInvokerService.PORTLET_REQUEST);
+         if (rreq != null) {
+
+            // remove portlet-scoped barnacles
+
+            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();
+            }
+         } else {
+            txt.append("... no resource request stuff. Couldn't get resource request; ");
+         }
+         
+         // remove container-scoped attributes
+
+         txt.append("container-scoped attributes; ");
+         hreq.removeAttribute(PortletInvokerService.METHOD_ID);
+         hreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+         hreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+         hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+
+      } else {
+         txt.append("... no servlet request stuff. Couldn't get servlet request.");
+      }
+      
+      txt.append(" Removing contextual info.");
+      pactx.removeContext();
+
+      if (isDebug) {
+         LOG.debug(txt.toString());
+      }
+
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onError(AsyncEvent evt) throws IOException {
+      
+      trace("onError");      
+      pactx.registerContext(true);
+      for (Entry l : listeners) {
+         if (l.hlis != null) {
+            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
+            l.hlis.onError(lisevt);
+         } else {
+            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
+            l.plis.onError(lisevt);
+         }
+      }
+      pactx.deregisterContext(true);
+      
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Error after ").append(delta).append(" milliseconds.");
+
+      // attempt to complete
+
+      try {
+         AsyncContext ctx = evt.getAsyncContext();
+         ctx.complete();
+         txt.append(" Portlet container completed request processing on behalf of the application.");
+      } catch (IllegalStateException e) {
+         txt.append(" An earlier listener has already dispatched or completed request.");
+      } catch (Exception e) {
+      }
+
+      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
+      if (isDebug) {
+         LOG.debug(txt.toString());
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onStartAsync(AsyncEvent evt) throws IOException {
+
+      trace("onStartAsync");
+      
+      // copy & clear the original listener list. If a listener wants to be notified
+      // again, it will add itself again.
+      
+      ArrayList<Entry> entries = new ArrayList<Entry>(listeners);
+      listeners.clear();
+
+      pactx.registerContext(true);
+      for (Entry l : entries) {
+         if (l.hlis != null) {
+            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
+            l.hlis.onStartAsync(lisevt);
+         } else {
+            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
+            l.plis.onStartAsync(lisevt);
+         }
+      }
+      pactx.deregisterContext(true);
+      
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Async started again after ").append(delta).append(" milliseconds.");
+      if (isDebug) {
+         LOG.debug(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 {
+
+      trace("onTimeout");
+      
+      pactx.registerContext(true);
+      for (Entry l : listeners) {
+         if (l.hlis != null) {
+            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
+            l.hlis.onTimeout(lisevt);
+         } else {
+            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
+            l.plis.onTimeout(lisevt);
+         }
+      }
+      pactx.deregisterContext(true);
+      
+      long delta = System.currentTimeMillis() - start;
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Timeout after ").append(delta).append(" milliseconds.");
+      
+      // if the application has properly registered a listener and has not processed the 
+      // timeout by calling onComplete or dispatch, complete the request.
+      
+      boolean warn = false;
+      AsyncContext ctx = evt.getAsyncContext();
+      try {
+         ctx.getRequest();
+         
+         try {
+            ctx.complete();
+            txt.append(" Portlet container completed request processing on behalf of the application.");
+            warn = true;
+         } catch (IllegalStateException e) {
+            txt.append(" An earlier listener has dispatched again.");
+         } catch (Exception e) {
+            txt.append(" Exception occured while completing request: " + e.toString());
+         }
+         
+      } catch(Exception e) {
+         txt.append(" Async processing was completed by the application.");
+      }
+
+      if (warn) {
+         LOG.warn(txt.toString());
+      } else {
+         if (isDebug) {
+            LOG.debug(txt.toString());
+         }
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
index bfbfd34..c44c27f 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
@@ -19,7 +19,7 @@
 
 package org.apache.pluto.driver.services.container;
 
-import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletAsyncManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,13 +37,13 @@ public class PortletAsyncContextualRunner implements Runnable {
    private static final boolean isTrace = LOG.isTraceEnabled();
    
 
-   private PortletAsyncContext pactx;
+   private PortletAsyncManager pactx;
    private Runnable targetRunner; 
 
    public PortletAsyncContextualRunner() {
    }
    
-   public void init(PortletAsyncContext pactx, Runnable targetRunner) {
+   public void init(PortletAsyncManager pactx, Runnable targetRunner) {
       this.pactx = pactx;
       this.targetRunner = targetRunner;
    }


[05/34] portals-pluto git commit: Added unit tests for async configuration code.

Posted by ms...@apache.org.
Added unit tests for async configuration code.


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

Branch: refs/heads/V3Prototype
Commit: 914a9683516f93a97a0642cc02e557a4c08898d6
Parents: e14ab86
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Mar 15 06:44:58 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Mar 15 06:44:58 2016 +0100

----------------------------------------------------------------------
 .../container/om/portlet/PortletDefinition.java |  3 ++
 .../om/portlet/impl/ConfigurationProcessor.java | 23 ++++++++++++++
 .../impl/JSR362ConfigurationProcessor.java      |  8 ++++-
 .../om/portlet/impl/PortletDefinitionImpl.java  | 19 ++++++++++-
 .../processor/fixtures/resource/Resource1.java  |  4 +--
 .../bean/processor/tests/ResourceTest.java      | 33 +++++++++++++++++---
 .../impl/fixtures/TestAnnotatedPortlet.java     |  3 +-
 .../fixtures/TestMultiAnnotatedPortlet.java     | 22 +++++++++++--
 .../impl/jsr362/MergePortletDefinitionTest.java |  6 ++++
 .../impl/jsr362/MultiAnnotatedPortletTest.java  | 24 +++++++++++---
 .../PortletDefinition362AnnotationTest.java     | 11 ++++---
 .../jsr362/PortletDefinition362ImplTest.java    | 22 ++++++++++---
 .../om/portlet/portlet362Generated.xml          |  1 +
 .../container/om/portlet/portlet362Merge.xml    |  1 +
 14 files changed, 156 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container-api/src/main/java/org/apache/pluto/container/om/portlet/PortletDefinition.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/om/portlet/PortletDefinition.java b/pluto-container-api/src/main/java/org/apache/pluto/container/om/portlet/PortletDefinition.java
index 225844c..6d896a4 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/om/portlet/PortletDefinition.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/om/portlet/PortletDefinition.java
@@ -86,4 +86,7 @@ public interface PortletDefinition {
    List<Dependency> getDependencies();
    Dependency getDependency(String name);
 
+   boolean isAsyncSupported();
+   void setAsyncSupported(boolean asyncSupported);
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/ConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/ConfigurationProcessor.java b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/ConfigurationProcessor.java
index 40e16f4..d8250c1 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/ConfigurationProcessor.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/ConfigurationProcessor.java
@@ -25,6 +25,7 @@ import javax.enterprise.inject.spi.BeanManager;
 import javax.portlet.Portlet;
 import javax.portlet.annotations.PortletApplication;
 import javax.portlet.annotations.PortletConfiguration;
+import javax.portlet.annotations.ServeResourceMethod;
 import javax.xml.bind.JAXBElement;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
@@ -391,11 +392,31 @@ public abstract class ConfigurationProcessor {
       
       for (String pn : portletNames) {
          
+         // copy data from the method store to the portlet definition
+         
          PortletDefinition pd = pad.getPortlet(pn);
          if (pd == null) {
             pd = new PortletDefinitionImpl(pn, pad);
          }
          
+         // if one of the @serveResourceMethod annotations has its ayncSupported
+         // flag set to true, set the flag to true in the portlet definition
+         
+         Set<MethodIdentifier> mis = ams.getMethodIDsForPortlet(pn);
+         for (MethodIdentifier mi : mis) {
+            if (mi.getType() == MethodType.RESOURCE) {
+               List<AnnotatedMethod> meths = ams.getMethods(mi);
+               for (AnnotatedMethod meth : meths) {
+                  ServeResourceMethod srm = (ServeResourceMethod) meth.getAnnotation();
+                  if (srm != null && srm.asyncSupported()) {
+                     pd.setAsyncSupported(true);
+                  }
+               }
+            }
+         }
+         
+         // The processing event references
+         
          List<EventDefinitionReference> edrs = pd.getSupportedProcessingEvents();
          for (QName qn : ams.getProcessingEventRefs(pn)) {
             EventDefinition ed = pad.getEventDefinition(qn);
@@ -418,6 +439,8 @@ public abstract class ConfigurationProcessor {
             }
          }
          
+         // The publishing event references
+         
          edrs = pd.getSupportedPublishingEvents();
          for (QName qn : ams.getPublishingEventRefs(pn)) {
             EventDefinition ed = pad.getEventDefinition(qn);

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
index 321b706..eae8230 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/JSR362ConfigurationProcessor.java
@@ -867,6 +867,11 @@ public class JSR362ConfigurationProcessor extends JSR286ConfigurationProcessor {
             Dependency dep = new DependencyImpl(dt.getName().getValue(), dt.getMinVersion().getValue());
             pd.addDependency(dep);
          }
+         
+         // Async supported
+         if (portlet.isAsyncSupported() != null) {
+            pd.setAsyncSupported(portlet.isAsyncSupported());
+         }
 
          pad.addPortlet(pd);
 
@@ -1286,11 +1291,12 @@ public class JSR362ConfigurationProcessor extends JSR286ConfigurationProcessor {
             pd.addInitParam(plutoInitParam);
          }
 
-         // cache scope, expiration time, resource bundle
+         // cache scope, expiration time, resource bundle, async flag
 
          pd.setCacheScope(pc.cacheScopePublic() ? "public" : "private");
          pd.setExpirationCache(pc.cacheExpirationTime());
          pd.setResourceBundle(pc.resourceBundle());
+         pd.setAsyncSupported(pc.asyncSupported());
 
          // handle portlet info - title, short title, keywords
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/PortletDefinitionImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/PortletDefinitionImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/PortletDefinitionImpl.java
index c69f48f..e2fd37d 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/PortletDefinitionImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/om/portlet/impl/PortletDefinitionImpl.java
@@ -73,8 +73,8 @@ public class PortletDefinitionImpl implements PortletDefinition {
    private final List<InitParam> iparms = new ArrayList<InitParam>(); 
    private final List<SecurityRoleRef> secRefs = new ArrayList<SecurityRoleRef>(); 
    private final List<Supports> supps = new ArrayList<Supports>();
-   
    private final List<Dependency> dependencies = new ArrayList<Dependency>(); 
+   private boolean asyncSupported = false;
 
    /**
     * Copy constructor
@@ -126,6 +126,7 @@ public class PortletDefinitionImpl implements PortletDefinition {
       for (Dependency dep : pd.getDependencies()) {
          this.dependencies.add(dep);
       }
+      this.asyncSupported = pd.isAsyncSupported();
    }
    
    /**
@@ -596,6 +597,22 @@ public class PortletDefinitionImpl implements PortletDefinition {
       crtOptions.add(new ContainerRuntimeOptionImpl(cro));
    }
 
+   /**
+    * @return the asyncSupported
+    */
+   @Override
+   public boolean isAsyncSupported() {
+      return asyncSupported;
+   }
+
+   /**
+    * @param asyncSupported the asyncSupported to set
+    */
+   @Override
+   public void setAsyncSupported(boolean asyncSupported) {
+      this.asyncSupported = asyncSupported;
+   }
+
    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/resource/Resource1.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/resource/Resource1.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/resource/Resource1.java
index 69486d6..4d44be3 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/resource/Resource1.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/fixtures/resource/Resource1.java
@@ -56,7 +56,7 @@ public class Resource1 {
       meths.addMethod(this.getClass().getSimpleName() + "#resource2a");
    }
    
-   @ServeResourceMethod(portletNames="portlet2", resourceID="edit")
+   @ServeResourceMethod(portletNames="portlet2", resourceID="edit", asyncSupported=false)
    public void resource2b(ResourceRequest req, ResourceResponse resp) {
       meths.addMethod(this.getClass().getSimpleName() + "#resource2b");
    }
@@ -71,7 +71,7 @@ public class Resource1 {
       meths.addMethod(this.getClass().getSimpleName() + "#resource3a");
    }
    
-   @ServeResourceMethod(portletNames="portlet3", ordinal=300)
+   @ServeResourceMethod(portletNames="portlet3", ordinal=300, asyncSupported=true)
    public void resource3b() {
       meths.addMethod(this.getClass().getSimpleName() + "#resource3b");
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/tests/ResourceTest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/tests/ResourceTest.java b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/tests/ResourceTest.java
index e5724e1..8ff1be4 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/tests/ResourceTest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/bean/processor/tests/ResourceTest.java
@@ -19,10 +19,7 @@
 package org.apache.pluto.container.bean.processor.tests;
 
 import static org.apache.pluto.container.bean.processor.MethodType.RESOURCE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -41,6 +38,9 @@ import org.apache.pluto.container.bean.processor.MethodIdentifier;
 import org.apache.pluto.container.bean.processor.PortletCDIExtension;
 import org.apache.pluto.container.bean.processor.fixtures.resource.Resource1;
 import org.apache.pluto.container.bean.processor.fixtures.resource.Resource2;
+import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.apache.pluto.container.om.portlet.impl.ConfigurationHolder;
 import org.jglue.cdiunit.AdditionalClasses;
 import org.jglue.cdiunit.AdditionalPackages;
 import org.jglue.cdiunit.CdiRunner;
@@ -64,6 +64,7 @@ public class ResourceTest {
 
    private AnnotatedMethodStore ams     = null;
    private ConfigSummary        summary = null;
+   private PortletApplicationDefinition pad = null;
 
    @Before
    public void setUp() {
@@ -73,6 +74,11 @@ public class ResourceTest {
 
       assertNotNull(ams);
       assertNotNull(summary);
+      
+      ConfigurationHolder ch = new ConfigurationHolder();
+      ch.reconcileBeanConfig(ams);
+      pad = ch.getPad();
+      assertNotNull(pad);
    }
 
    @Test
@@ -372,4 +378,23 @@ public class ResourceTest {
       assertEquals(0, qns.size());
    }
 
+   @Test
+   public void testAsyncSupported() throws Exception {
+      PortletDefinition pd;
+      
+      // asyncSupported default value
+      pd = pad.getPortlet("portlet1");
+      assertNotNull(pd);
+      assertFalse(pd.isAsyncSupported());
+      
+      // set to false
+      pd = pad.getPortlet("portlet2");
+      assertNotNull(pd);
+      assertFalse(pd.isAsyncSupported());
+      
+      // set to true
+      pd = pad.getPortlet("portlet3");
+      assertNotNull(pd);
+      assertTrue(pd.isAsyncSupported());
+   }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestAnnotatedPortlet.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestAnnotatedPortlet.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestAnnotatedPortlet.java
index bed73a4..8e7cc29 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestAnnotatedPortlet.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestAnnotatedPortlet.java
@@ -74,7 +74,8 @@ import javax.portlet.annotations.Supports;
    }, dependencies = {
       @Dependency(name="Dojo", minVersion="3.1.4"),
       @Dependency(name="AngularJS", minVersion="1.4.8")
-   }
+   },
+   asyncSupported = true
    
 )
 public class TestAnnotatedPortlet {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestMultiAnnotatedPortlet.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestMultiAnnotatedPortlet.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestMultiAnnotatedPortlet.java
index c8e47fe..6b17008 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestMultiAnnotatedPortlet.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/fixtures/TestMultiAnnotatedPortlet.java
@@ -66,8 +66,26 @@ import javax.portlet.annotations.PortletConfigurations;
          @LocaleString(locale="DE", value="Ein Portlet")
       }, keywords={
          @LocaleString(locale="DE", value="Eins, Zwei, Drei")
-      }
-   )
+      },
+      asyncSupported=true
+   ),
+   @PortletConfiguration(portletName="Portlet3", 
+   initParams = {
+         @InitParameter(name="color", value="#def"),
+      },
+      description={
+         @LocaleString(locale="de", value="Dieses Portlet zeigt die Zeit in verschiedenen Zeitzonen an")
+      }, displayName={
+         @LocaleString(locale="de", value="ZeitzonenPortlet")
+      }, title={
+         @LocaleString(locale="DE", value="Annotiertes Portlet")
+      }, shortTitle={
+         @LocaleString(locale="DE", value="Ein Portlet")
+      }, keywords={
+         @LocaleString(locale="DE", value="Eins, Zwei, Drei")
+      },
+      asyncSupported=false
+   ),
 })
 public class TestMultiAnnotatedPortlet extends GenericPortlet {
    // add portlet methods

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MergePortletDefinitionTest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MergePortletDefinitionTest.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MergePortletDefinitionTest.java
index dcb8d99..c8b5d69 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MergePortletDefinitionTest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MergePortletDefinitionTest.java
@@ -21,6 +21,7 @@ package org.apache.pluto.container.om.portlet.impl.jsr362;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -879,4 +880,9 @@ public class MergePortletDefinitionTest {
       assertTrue(deps.contains(dep));
    }
 
+   @Test
+   public void testAsyncSupported() throws Exception {
+      assertFalse(cut.isAsyncSupported());
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MultiAnnotatedPortletTest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MultiAnnotatedPortletTest.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MultiAnnotatedPortletTest.java
index 762af95..2561f3b 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MultiAnnotatedPortletTest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/MultiAnnotatedPortletTest.java
@@ -19,9 +19,7 @@
 
 package org.apache.pluto.container.om.portlet.impl.jsr362;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.util.HashSet;
 import java.util.List;
@@ -60,6 +58,7 @@ public class MultiAnnotatedPortletTest {
    // Class under test
    private PortletDefinition portlet1;
    private PortletDefinition portlet2;
+   private PortletDefinition portlet3;
 
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
@@ -79,12 +78,14 @@ public class MultiAnnotatedPortletTest {
 
    @Before
    public void setUpBefore() throws Exception {
-      assertEquals(2, pad.getPortlets().size());
+      assertEquals(3, pad.getPortlets().size());
       assertNotNull(pad.getPortlet("Portlet1"));
       assertNotNull(pad.getPortlet("Portlet2"));
+      assertNotNull(pad.getPortlet("Portlet3"));
       app = new PortletApplicationDefinitionImpl(pad);
       portlet1 = new PortletDefinitionImpl(pad.getPortlet("Portlet1"));
       portlet2 = new PortletDefinitionImpl(pad.getPortlet("Portlet2"));
+      portlet3 = new PortletDefinitionImpl(pad.getPortlet("Portlet3"));
    }
 
    // Begin portlet app tests ==================================
@@ -342,5 +343,20 @@ public class MultiAnnotatedPortletTest {
       assertEquals(text, info.getKeywords(Locale.FRENCH).getText());
       assertEquals(txt2, info.getKeywords(Locale.GERMAN).getText());
    }
+   
+   @Test
+   public void testAsyncSupportedDefault() throws Exception {
+      assertFalse(portlet1.isAsyncSupported());
+   }
+   
+   @Test
+   public void testAsyncSupportedTrue() throws Exception {
+      assertTrue(portlet2.isAsyncSupported());
+   }
+   
+   @Test
+   public void testAsyncSupportedFalse() throws Exception {
+      assertFalse(portlet3.isAsyncSupported());
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362AnnotationTest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362AnnotationTest.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362AnnotationTest.java
index 4d206c0..0f94248 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362AnnotationTest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362AnnotationTest.java
@@ -19,11 +19,7 @@
 
 package org.apache.pluto.container.om.portlet.impl.jsr362;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -811,5 +807,10 @@ public class PortletDefinition362AnnotationTest {
       assertEquals(2, deps.size());
       assertTrue(deps.contains(dep));
    }
+   
+   @Test
+   public void testAsyncSupported() throws Exception {
+      assertTrue(cut.isAsyncSupported());
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362ImplTest.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362ImplTest.java b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362ImplTest.java
index 401036a..abd89da 100644
--- a/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362ImplTest.java
+++ b/pluto-container/src/test/java/org/apache/pluto/container/om/portlet/impl/jsr362/PortletDefinition362ImplTest.java
@@ -19,10 +19,7 @@
 
 package org.apache.pluto.container.om.portlet.impl.jsr362;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.io.InputStream;
 import java.util.Arrays;
@@ -874,5 +871,22 @@ public class PortletDefinition362ImplTest {
       assertEquals(2, deps.size());
       assertTrue(deps.contains(dep));
    }
+   
+   @Test
+   public void testAsyncSupported() throws Exception {
+      assertTrue(cut.isAsyncSupported());
+   }
+   
+   @Test
+   public void testSetAsyncSupportedTrue() throws Exception {
+      cut.setAsyncSupported(true);
+      assertTrue(cut.isAsyncSupported());
+   }
+   
+   @Test
+   public void testSetAsyncSupportedFalse() throws Exception {
+      cut.setAsyncSupported(false);
+      assertFalse(cut.isAsyncSupported());
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Generated.xml
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Generated.xml b/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Generated.xml
index bc2d3d4..2c0a6bd 100644
--- a/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Generated.xml
+++ b/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Generated.xml
@@ -91,6 +91,7 @@
          <name>AngularJS</name>
          <min-version>1.4.8</min-version>
       </dependency>
+      <async-supported>true</async-supported>
    </portlet>
    <custom-portlet-mode id="mode1">
       <description xml:lang="de">description</description>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/914a9683/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Merge.xml
----------------------------------------------------------------------
diff --git a/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Merge.xml b/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Merge.xml
index b078403..8ad2e91 100644
--- a/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Merge.xml
+++ b/pluto-container/src/test/resources/org/apache/pluto/container/om/portlet/portlet362Merge.xml
@@ -93,6 +93,7 @@
          <name>AngularJS</name>
          <min-version>1.4.8</min-version>
       </dependency>
+      <async-supported>false</async-supported>
    </portlet>
    <custom-portlet-mode id="mode1">
       <description xml:lang="de">description</description>


[11/34] portals-pluto git commit: worked on startAsync implementaion

Posted by ms...@apache.org.
worked on startAsync implementaion


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

Branch: refs/heads/V3Prototype
Commit: ba9ee3bea3026ab99e3ec7e182d3a9cfebd9ffa0
Parents: 51caad7
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 24 06:34:43 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 24 06:34:43 2016 +0100

----------------------------------------------------------------------
 .../container/impl/ResourceRequestImpl.java     | 43 +++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ba9ee3be/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 aafbbee..b73a29b 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
@@ -20,13 +20,20 @@ import java.util.Enumeration;
 import java.util.Map;
 
 import javax.portlet.CacheControl;
+import javax.portlet.PortletConfig;
 import javax.portlet.PortletRequest;
 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.PortletInvokerService;
+import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResourceResponseContext;
 import org.slf4j.Logger;
@@ -126,7 +133,23 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
 
    @Override
    public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
-      return null;
+      
+      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;
    }
 
    @Override
@@ -148,4 +171,22 @@ public class ResourceRequestImpl extends ClientDataRequestImpl implements Resour
    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;
+   }
 }


[16/34] portals-pluto git commit: more work on async portlet

Posted by ms...@apache.org.
more work on async portlet


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

Branch: refs/heads/V3Prototype
Commit: 870277c87101e668b4cf384ad94e800e847ed958
Parents: f0e0b11
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Mar 29 12:53:05 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Mar 29 12:53:05 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java |   4 +
 .../portals/samples/AsyncPortletResource.java   | 162 ++++++++++++++-----
 2 files changed, 126 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/870277c8/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index 5f824a2..08389b2 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -213,6 +213,10 @@ public class AsyncDialogBean implements PortletSerializable {
       String auto = req.getActionParameters().getValue(PARAM_AUTO);
       if (auto != null) {
          autoDispatch = true;
+         if (reps > 1) {
+            msg = "Repetitions cannot be > 1 for non-recursive use.";
+            reps = 1;
+         }
       } else {
          autoDispatch = false;
       }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/870277c8/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 221de53..a61550d 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -23,6 +23,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.portlet.annotations.ServeResourceMethod;
@@ -37,19 +39,21 @@ import org.apache.portals.samples.AsyncDialogBean.OutputType;
  * Implements the async resource method for the async portlet.
  * 
  * @author Scott Nicklous
- *
+ * 
  */
 public class AsyncPortletResource {
-   private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
-   
-   private final static String JSP = "/WEB-INF/jsp/asyncOutput.jsp";
+   private static final Logger LOGGER      = Logger.getLogger(AsyncPortletResource.class.getName());
+
+   private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
+   private final static String ATTRIB_REPS = "reps";
+   private final static String ATTRIB_AUTO = "auto";
 
    private class AsyncRunnable implements Runnable {
-      
+
       private final AsyncContext ctx;
-      private final int delay;
-      private final OutputType type;
-      private final boolean done;
+      private final int          delay;
+      private final OutputType   type;
+      private final boolean      done;
 
       public AsyncRunnable(AsyncContext ctx, int delay, OutputType type, boolean done) {
          this.ctx = ctx;
@@ -68,36 +72,42 @@ public class AsyncPortletResource {
             RequestDispatcher rd;
 
             switch (type) {
-               case TEXT:
-                  StringBuilder txt = new StringBuilder(128);
-                  txt.append("<p>AsyncRunnable:");
-                  txt.append(" dispatcher type: ").append(hreq.getDispatcherType().toString());
-                  txt.append("</p>");
-                  hresp.getWriter().write(txt.toString());
-                  if (done) {
-                     ctx.complete();
-                  }
-                  break;
-               case AUTO:
-                  ctx.dispatch();
-                  break;
-               case DISPATCH:
-                  ctx.dispatch(JSP);
-                  break;
-               case FWD:
-                  rd = hreq.getRequestDispatcher(JSP);
-                  rd.forward(hreq, hresp);
-                  if (done) {
-                     ctx.complete();
-                  }
-                  break;
-               case INC:
-                  rd = hreq.getRequestDispatcher(JSP);
-                  rd.include(hreq, hresp);
-                  if (done) {
-                     ctx.complete();
-                  }
-                  break;
+            case TEXT:
+               LOGGER.fine("Producing text output.");
+               StringBuilder txt = new StringBuilder(128);
+               txt.append("<p>AsyncRunnable.");
+               txt.append(" dispatcher type: ").append(hreq.getDispatcherType().toString());
+               txt.append("</p>");
+               hresp.getWriter().write(txt.toString());
+               if (done) {
+                  ctx.complete();
+               }
+               break;
+            case AUTO:
+               LOGGER.fine("Dispatching to resource method.");
+               hreq.setAttribute(ATTRIB_AUTO, new Boolean(true));
+               ctx.dispatch();
+               break;
+            case DISPATCH:
+               LOGGER.fine("Dispatching to JSP.");
+               ctx.dispatch(JSP);
+               break;
+            case FWD:
+               LOGGER.fine("Doing request dispatcher forward to JSP.");
+               rd = hreq.getRequestDispatcher(JSP);
+               rd.forward(hreq, hresp);
+               if (done) {
+                  ctx.complete();
+               }
+               break;
+            case INC:
+               LOGGER.fine("Doing request dispatcher include of JSP.");
+               rd = hreq.getRequestDispatcher(JSP);
+               rd.include(hreq, hresp);
+               if (done) {
+                  ctx.complete();
+               }
+               break;
             }
 
          } catch (Exception e) {
@@ -111,7 +121,79 @@ public class AsyncPortletResource {
    private AsyncDialogBean adb;
 
    @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
-   public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException {
-      resp.getWriter().write("<p>Hello from the resource method!</p>");
+   public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
+
+      Integer reps = (Integer) req.getAttribute(ATTRIB_REPS);
+      if (reps == null) {
+         reps = adb.getReps();
+      }
+
+      boolean done = false;
+      if (--reps <= 0 || !adb.isAutoDispatch()) {
+         done = true;
+      }
+      req.setAttribute(ATTRIB_REPS, reps);
+
+      Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
+      req.removeAttribute(ATTRIB_AUTO);
+
+      if ((adb.getDelay() <= 0) || (auto != null)) {
+         
+         PortletRequestDispatcher rd;
+         AsyncContext ctx = null;
+         try {
+            ctx = req.getAsyncContext();
+         } catch (Exception e) {}
+
+         switch (adb.getType()) {
+         case TEXT:
+            LOGGER.fine("Producing text output.");
+            StringBuilder txt = new StringBuilder(128);
+            txt.append("<p>AsyncRunnable.");
+            txt.append(" dispatcher type: ").append(req.getDispatcherType().toString());
+            txt.append("</p>");
+            resp.getWriter().write(txt.toString());
+            if (done && ctx != null) {
+               ctx.complete();
+            }
+            break;
+         case DISPATCH:
+            LOGGER.fine("Dispatching to JSP.");
+            if (ctx != null) {
+               ctx.dispatch(JSP);
+            }
+            break;
+         case FWD:
+            LOGGER.fine("Doing request dispatcher forward to JSP.");
+            rd = req.getPortletContext().getRequestDispatcher(JSP);
+            rd.forward(req, resp);
+            if (done && ctx != null) {
+               ctx.complete();
+            }
+            break;
+         case INC:
+            LOGGER.fine("Doing request dispatcher include of JSP.");
+            rd = req.getPortletContext().getRequestDispatcher(JSP);
+            rd.include(req, resp);
+            if (done && ctx != null) {
+               ctx.complete();
+            }
+            break;
+         default:
+            break;
+         }
+      }
+      
+      if (adb.getDelay() > 0 && (!done || auto == null)) {
+         AsyncContext ctx = req.startAsync();
+         ctx.setTimeout(4000);
+         OutputType type = adb.getType();
+         if (adb.isAutoDispatch()) {
+            type = OutputType.AUTO;
+         }
+         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type, done);
+         ctx.start(ar);
+      }
+
    }
 }


[33/34] portals-pluto git commit: Added new classes for asynchronous processing and improved async documentation. New classes: PortletAsyncListener, PortletAsyncContext, and PortletAsyncEvent. Modified the Pluto implmentation to use the new interfaces. M

Posted by ms...@apache.org.
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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
deleted file mode 100644
index 11069ac..0000000
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*  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.util.ArrayList;
-import java.util.List;
-
-import javax.portlet.ResourceRequest;
-import javax.servlet.AsyncContext;
-import javax.servlet.AsyncEvent;
-import javax.servlet.AsyncListener;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.pluto.container.PortletAsyncContext;
-import org.apache.pluto.container.PortletInvokerService;
-import org.apache.pluto.container.PortletResourceResponseContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Manages the listeners registered by the application. Releases portal resources when 
- * the async request completes and provides contextual services for the listeners. 
- * 
- * @author Scott Nicklous
- */
-public class PortletAsyncListener implements AsyncListener {
-   
-   /** Logger. */
-   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncListener.class);
-   private static final boolean isDebug = LOG.isDebugEnabled();
-   @SuppressWarnings("unused")
-   private static final boolean isTrace = LOG.isTraceEnabled();
-   
-   
-   // Data for one listener
-   private class Entry {
-      public Entry(AsyncListener lis, ServletRequest req, ServletResponse resp) {
-         this.lis = lis;
-         this.req = req;
-         this.resp = resp;
-      }
-      public AsyncListener   lis;
-      public ServletRequest  req;
-      public ServletResponse resp;
-   }
-   
-   // The registered listeners
-   List<Entry> listeners = new ArrayList<Entry>();
-   
-   private long start  = System.currentTimeMillis();
-   private final PortletAsyncContext pactx;
-   
- 
-   public PortletAsyncListener(PortletAsyncContext pactx) {
-      this.pactx = pactx;
-   }
-   
-   public void addListener(AsyncListener l) {
-      listeners.add(new Entry(l, null, null));
-   }
-   
-   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
-      listeners.add(new Entry(l, req, resp));
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
-    */
-   @Override
-   public void onComplete(AsyncEvent evt) throws IOException {
-      
-      if (isDebug) {
-         StringBuilder txt = new StringBuilder();
-         txt.append("Firing onComplete event for ");
-         txt.append(listeners.size()).append(" listeners.");
-         LOG.debug(txt.toString());
-      }
-      
-      pactx.registerContext(true);
-      for (Entry listener : listeners) {
-         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
-         listener.lis.onComplete(lisevt);
-      }
-      pactx.deregisterContext(true);
-      pactx.setComplete(true);
-      
-      long delta = System.currentTimeMillis() - start;
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Completed. Execution time: ").append(delta).append(" milliseconds.");
-      txt.append(" Releasing: ");
-
-      HttpServletRequest hreq = (HttpServletRequest) evt.getSuppliedRequest();
-      if (hreq != null) {
-         ResourceRequest rreq = (ResourceRequest) hreq.getAttribute(PortletInvokerService.PORTLET_REQUEST);
-         if (rreq != null) {
-
-            // remove portlet-scoped barnacles
-
-            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();
-            }
-         } else {
-            txt.append("... no resource request stuff. Couldn't get resource request; ");
-         }
-         
-         // remove container-scoped attributes
-
-         txt.append("container-scoped attributes; ");
-         hreq.removeAttribute(PortletInvokerService.METHOD_ID);
-         hreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
-         hreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
-         hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);
-
-      } else {
-         txt.append("... no servlet request stuff. Couldn't get servlet request.");
-      }
-      
-      txt.append(" Removing contextual info.");
-      pactx.removeContext();
-
-      if (isDebug) {
-         LOG.debug(txt.toString());
-      }
-
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
-    */
-   @Override
-   public void onError(AsyncEvent evt) throws IOException {
-      
-      if (isDebug) {
-         StringBuilder txt = new StringBuilder();
-         txt.append("Firing onError event for ");
-         txt.append(listeners.size()).append(" listeners.");
-         LOG.debug(txt.toString());
-      }
-      
-      pactx.registerContext(true);
-      for (Entry listener : listeners) {
-         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp, evt.getThrowable());
-         listener.lis.onError(lisevt);
-      }
-      pactx.deregisterContext(true);
-      
-      long delta = System.currentTimeMillis() - start;
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Error after ").append(delta).append(" milliseconds.");
-
-      // attempt to complete
-
-      try {
-         AsyncContext ctx = evt.getAsyncContext();
-         ctx.complete();
-         txt.append(" Portlet container completed request processing on behalf of the application.");
-      } catch (IllegalStateException e) {
-         txt.append(" An earlier listener has already dispatched or completed request.");
-      } catch (Exception e) {
-      }
-
-      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
-      if (isDebug) {
-         LOG.debug(txt.toString());
-      }
-   }
-
-   /*
-    * (non-Javadoc)
-    * 
-    * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
-    */
-   @Override
-   public void onStartAsync(AsyncEvent evt) throws IOException {
-      
-      if (isDebug) {
-         StringBuilder txt = new StringBuilder();
-         txt.append("Firing onStartAsync event for ");
-         txt.append(listeners.size()).append(" listeners.");
-         LOG.debug(txt.toString());
-      }
-      
-      // copy & clear the original listener list. If a listener wants to be notified
-      // again, it will add itself again.
-      
-      ArrayList<Entry> entries = new ArrayList<Entry>(listeners);
-      listeners.clear();
-
-      pactx.registerContext(true);
-      for (Entry listener : entries) {
-         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
-         listener.lis.onStartAsync(lisevt);
-      }
-      pactx.deregisterContext(true);
-      
-      long delta = System.currentTimeMillis() - start;
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Async started again after ").append(delta).append(" milliseconds.");
-      if (isDebug) {
-         LOG.debug(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 {
-      
-      if (isDebug) {
-         StringBuilder txt = new StringBuilder();
-         txt.append("Firing onTimeout event for ");
-         txt.append(listeners.size()).append(" listeners.");
-         LOG.debug(txt.toString());
-      }
-      
-      pactx.registerContext(true);
-      for (Entry listener : listeners) {
-         AsyncEvent lisevt = new AsyncEvent(pactx, listener.req, listener.resp);
-         listener.lis.onTimeout(lisevt);
-      }
-      pactx.deregisterContext(true);
-      
-      long delta = System.currentTimeMillis() - start;
-      StringBuilder txt = new StringBuilder(128);
-      txt.append("Timeout after ").append(delta).append(" milliseconds.");
-      
-      // if the application has properly registered a listener and has not processed the 
-      // timeout by calling onComplete or dispatch, complete the request.
-      
-      boolean warn = false;
-      AsyncContext ctx = evt.getAsyncContext();
-      try {
-         ctx.getRequest();
-         
-         try {
-            ctx.complete();
-            txt.append(" Portlet container completed request processing on behalf of the application.");
-            warn = true;
-         } catch (IllegalStateException e) {
-            txt.append(" An earlier listener has dispatched again.");
-         } catch (Exception e) {
-            txt.append(" Exception occured while completing request: " + e.toString());
-         }
-         
-      } catch(Exception e) {
-         txt.append(" Async processing was completed by the application.");
-      }
-
-      if (warn) {
-         LOG.warn(txt.toString());
-      } else {
-         if (isDebug) {
-            LOG.debug(txt.toString());
-         }
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/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 c1e8332..ec34127 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
@@ -32,7 +32,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletAsyncManager;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceRequestContext;
@@ -72,7 +72,7 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    }
    
    @Override
-   public PortletAsyncContext getPortletAsyncContext() {
+   public PortletAsyncManager getPortletAsyncContext() {
       return actx;
    }
 
@@ -146,6 +146,10 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
 
    @Override
    public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+      if (actx != null && actx.isComplete()) {
+         return null;
+      }
+
 
       HttpServletRequest hreq = getServletRequest();
       HttpServletResponse hresp = getServletResponse();
@@ -254,6 +258,9 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    // For wrapper use
    @Override
    public AsyncContext startAsync() {
+      if (actx != null && actx.isComplete()) {
+         return null;
+      }
       AsyncContext ac = getServletRequest().startAsync();
       if (actx == null) {
          // this should not happen, the wrapper is created during the resource request
@@ -267,6 +274,9 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    // for wrapper use
    @Override
    public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
+      if (actx != null && actx.isComplete()) {
+         return null;
+      }
       AsyncContext ac = getServletRequest().startAsync(request, response);
       if (actx == null) {
          // this should not happen, the wrapper is created during the resource request
@@ -290,6 +300,9 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    @Override
    public AsyncContext getAsyncContext() {
       if (actx != null) {
+         if (actx.isComplete()) {
+            return null;
+         }
          return actx;
       }
       return getServletRequest().getAsyncContext();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
index af3ef1f..8469c45 100644
--- a/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
@@ -31,19 +31,24 @@ import javax.servlet.ServletContext;
  * general, the portlet async methods behave in the same manner as their 
  * <code>AsyncContext</code> analog. 
  * <p>
- * A PortletAsyncContext is created and initialized by a call to
- * ResourceRequest#startAsync() or ResourceRequest#startAsync(ServletRequest,
- * ServletResponse). Repeated invocations of these methods will return the same
- * AsyncContext instance, reinitialized as appropriate.
+ * A <code>PortletAsyncContext</code> is created and initialized by a call to
+ * <code>ResourceRequest#startAsync()</code> or 
+ * <code>ResourceRequest#startAsync(ServletRequest, ServletResponse)</code>. 
+ * Repeated invocations of these methods will return the same
+ * <code>PortletAsyncContext</code> instance, reinitialized as appropriate.
  * <p>
- * In the event that an asynchronous operation has timed out, the container must
- * invoke, at their onTimeout method, all PortletAsyncListener instances registered
- * with the ResourceRequest on which the asynchronous operation was initiated.
- * If none of the listeners called complete() or any of the dispatch() methods,
- * complete the request on behalf of the application. * 
+ * In the event that an asynchronous operation times out, the container will
+ * invoke the onTimeout method of all <code>PortletAsyncListener</code> instances registered
+ * with the <code>PortletAsyncContext</code> on which the asynchronous operation was initiated.
+ * If none of the listeners call <code>complete()</code> or any of the 
+ * <code>dispatch()</code> methods, the portlet container will
+ * complete the request on behalf of the application and may respond with error information.
  * </div>
  * 
  * @see     javax.servlet.AsyncContext
+ * @see     PortletAsyncListener
+ * @see     PortletAsyncEvent
+ * 
  * @since   3.0
  */
 public interface PortletAsyncContext {
@@ -63,12 +68,15 @@ public interface PortletAsyncContext {
     * <code>PortletAsyncListener</code> instances will be notified in the order in 
     * which they were added. 
     * <p>
-    * If <code>ResourceRequest.startAsync(ResourceRequest, ResourceResponse)</code> or
-    * <code>ResourceRequest.startAsync()</code> is called, the exact same request and response
-    * objects are available from the <code>PortletAsyncEvent</code> when the 
-    * <code>PortletAsyncListener</code> is notified.
+    * When one of the listener methods is invoked, the 
+    * <code>PortletAsyncListener</code> <code>getSuppliedRequest()</code> and
+    * <code>getSuppliedResponse()</code> methods of the 
+    * <code>PortletAsyncEvent</code> object will return <code>null</code>.
     * </div>
     * 
+    * @see PortletAsyncListener
+    * @see PortletAsyncEvent
+    * 
     * @since   3.0
     * 
     * @param listener   the listener to be added
@@ -100,14 +108,16 @@ public interface PortletAsyncContext {
     * <code>getSuppliedRequest</code> and
     * <code>getSuppliedResponse</code> methods, respectively, of the 
     * <code>PortletAsyncEvent</code> delivered to
-    * it. These objects should not be read from or written to, respectively, at the
+    * it. These objects should not be read from or written to at the
     * time the <code>PortletAsyncEvent</code> is delivered, because additional wrapping 
     * may have
-    * occurred since the given <code>PortletAsyncListener</code> was registered, but may 
-    * be used in
-    * order to release any resources associated with them.
+    * occurred since the given <code>PortletAsyncListener</code> was registered. 
+    * However, they may be used to release any resources associated with them.
     * </div>
     * 
+    * @see PortletAsyncListener
+    * @see PortletAsyncEvent
+    * 
     * @since   3.0
     * 
     * @param listener   the listener to be added
@@ -123,6 +133,23 @@ public interface PortletAsyncContext {
 
    /**
     * <div class="changed_added_3_0">
+    * Completes the <code>PortletAsynchronous</code> operation
+    * and closes the response associated with this <code>PortletAsyncContext</code> object.
+    * <p>
+    * The <code>onComplete</code> method of any registered listeners that were registered 
+    * with the <code>PortletAsyncContext</code> object for this asynchronous cycle 
+    * will be invoked.
+    * <p>
+    * It is legal to call this method any time after a call to
+    * <code>ResourceRequest#startAsync()</code> or 
+    * <code>ResourceRequest#startAsync(ResourceRequest, ResourceResponse)</code>, 
+    * and before a call to one of the dispatch methods of this
+    * class. If this method is called before the container-initiated dispatch that
+    * called <code>startAsync</code> has returned to the container, then the call will 
+    * not take effect (and any invocations of 
+    * <code>PortletAsyncListener#onComplete(PortletAsyncEvent)</code> will
+    * be delayed) until after the container-initiated dispatch has returned to the
+    * container.
     * </div>
     * 
     * @since   3.0
@@ -137,15 +164,16 @@ public interface PortletAsyncContext {
 
    /**
     * <div class="changed_added_3_0">
-    * Instantiates the given AsyncListener class.
+    * Instantiates the given <code>PortletAsyncListener</code> class.
     * <p>
-    * The returned AsyncListener instance may be further customized before it is
-    * registered with this AsyncContext via a call to one of the addListener methods.
+    * The returned <code>PortletAsyncListener</code> instance may be further customized before it is
+    * registered with this <code>PortletAsyncContext</code> via a call to one of the addListener methods.
     * <p>
-    * The given AsyncListener class must define a zero argument constructor, which is
+    * The given <code>PortletAsyncListener</code> class must define a zero argument constructor, which is
     * used to instantiate it.
     * <p>
-    * This method supports resource injection if the given class represents a Managed
+    * This method supports resource injection if contextual support is available, and if 
+    * the given class represents a Managed
     * Bean. See the Java EE platform and JSR 299 specifications for additional details
     * about Managed Beans and resource injection.
     * </div>
@@ -154,49 +182,138 @@ public interface PortletAsyncContext {
     * 
     * @param cls     the class to be instantiated
     * @return        the instantiated class
-    * @throws PortletException if the given class cannot be instantiated
+    * @throws        PortletException if the given class cannot be instantiated
     */
-   public <T extends PortletAsyncListener> T createListener(Class<T> cls) throws PortletException;
+   public <T extends PortletAsyncListener> T createPortletAsyncListener(Class<T> cls) throws PortletException;
 
    /**
     * <div class="changed_added_3_0">
+    * Dispatches the request and response objects of this <code>PortletAsyncContext</code> to
+    * the portlet container.
+    * <p>
+    * The portlet container will dispatch the the request and response to the
+    * portlet resource method in which the first asynchronous processing cycle was
+    * initiated.
+    * <p>
+    * This method returns immediately after passing the request and response
+    * objects to a container managed thread which will perform the dispatch
+    * operation. If this method is called before the container-initiated dispatch
+    * that called startAsync has returned to the container, the dispatch operation
+    * will be delayed until after the container-initiated dispatch has returned to
+    * the container.
+    * <p>
+    * The dispatcher type of the request is set to <code>DispatcherType.ASYNC</code>. Unlike
+    * forward dispatches, the response buffer and headers will not be reset, and
+    * it is legal to dispatch even if the response has already been committed.
+    * <p>
+    * Control over the request and response is delegated to the dispatch target,
+    * and the response will be closed when the dispatch target has completed
+    * execution, unless <code>ResourceRequest#startAsync()</code> or
+    * <code>ResourceRequest#startAsync(ResourceRequest, ResourceResponse)</code> are called.
+    * <p>
+    * Any errors or exceptions that may occur during the execution of this method
+    * must be caught and handled by the container as follows:
+    * <ul>
+    * <li>
+    * Invoke the <code>onError</code> method of all <code>PortletAsyncListener</code> 
+    * instances registered with this <code>PortletAsyncContext</code> and
+    * make the caught <code>Throwable</code> available via 
+    * <code>PortletAsyncEvent#getThrowable</code>.
+    * </li>
+    * <li>
+    * If none of the listeners called <code>complete()</code> or any of the <code>dispatch()</code>
+    * methods, set the status code equal to
+    * <code>HttpResourceResponse.SC_INTERNAL_SERVER_ERROR</code>, make the 
+    * <code>Throwable</code> leading to the error available as the value of the
+    * <code>RequestDispatcher.ERROR_EXCEPTION</code> request attribute, and perform 
+    * an error dispatch to generate a platform-specific error message. 
+    * </li>
+    * <li>
+    * Complete the asynchronous processing cycle by calling <code>complete()</code>.
+    * </li>
+    * </ul>
+    * <p>
+    * There can be at most one asynchronous dispatch operation per asynchronous
+    * cycle, which is started by a call to one of the <code>ResourceRequest#startAsync</code>
+    * methods. Any attempt to perform an additional asynchronous dispatch
+    * operation within the same asynchronous cycle will result in an
+    * <code>IllegalStateException</code>. When the container performs the dispatch operation,
+    * <code>startAsync()</code> may be invoked on the dispatched request to initiate a new
+    * asynchronous processing cycle, after which any of the dispatch methods or the
+    * <code>complete()</code> method may be called.
     * </div>
     * 
     * @since   3.0
     * 
     * @throws IllegalStateException 
     * if called before an asynchronous processing cycle has been started, 
-    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
-    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    * if one of the dispatch methods has been called but the <code>startAsync</code> method has not
+    * been called during the resulting dispatch, or if <code>complete()</code> was called
     */
    public void dispatch() throws IllegalStateException;
 
    /**
     * <div class="changed_added_3_0">
+    * Dispatches the request and response objects of this <code>PortletAsyncContext</code> to
+    * the given path within the <code>PortletContext</code>.
+    * <p>
+    * The path parameter is interpreted in the same way as in
+    * <code>PortletContext#getRequestDispatcher(String)</code> scoped to
+    * the current portlet context.
+    * <p>
+    * There can be at most one asynchronous dispatch operation per asynchronous
+    * cycle, which is started by a call to one of the <code>ResourceRequest#startAsync</code>
+    * methods. Any attempt to perform an additional asynchronous dispatch
+    * operation within the same asynchronous cycle will result in an
+    * <code>IllegalStateException</code>. When the container performs the dispatch operation,
+    * <code>startAsync()</code> may be invoked on the dispatched request to initiate a new
+    * asynchronous processing cycle, after which any of the dispatch methods or the
+    * <code>complete()</code> method may be called.
+    * <p>
+    * See {@link #dispatch()} for additional details, including error handling.
     * </div>
     * 
     * @since   3.0
     * 
-    * @param path
+    * @param path the path of the dispatch target, scoped to the PortletContext from which 
+    * this PortletAsyncContext was initialized 
     * @throws IllegalStateException
     * if called before an asynchronous processing cycle has been started, 
-    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
-    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    * if one of the dispatch methods has been called but the <code>startAsync</code> method has not
+    * been called during the resulting dispatch, or if <code>complete()</code> was called
     */
    public void dispatch(String path) throws IllegalStateException;
 
    /**
     * <div class="changed_added_3_0">
+    * Dispatches the request and response objects of this <code>PortletAsyncContext</code> to
+    * the given path scoped to the given context.
+    * <p>
+    * The path parameter is interpreted in the same way as in
+    * <code>PortletContext#getRequestDispatcher(String)</code>, except that it is scoped to
+    * the given context.
+    * <p>
+    * There can be at most one asynchronous dispatch operation per asynchronous
+    * cycle, which is started by a call to one of the <code>ResourceRequest#startAsync</code>
+    * methods. Any attempt to perform an additional asynchronous dispatch
+    * operation within the same asynchronous cycle will result in an
+    * <code>IllegalStateException</code>. When the container performs the dispatch operation,
+    * <code>startAsync()</code> may be invoked on the dispatched request to initiate a new
+    * asynchronous processing cycle, after which any of the dispatch methods or the
+    * <code>complete()</code> method may be called.
+    * <p>
+    * See {@link #dispatch()} for additional details, including error handling.
     * </div>
     * 
     * @since   3.0
     * 
-    * @param context
-    * @param path
+    * @param context    the ServletContext of the dispatch target
+    * @param path       the path of the dispatch target, scoped to the given 
+    * <code>ServletContext</code>
     * @throws IllegalStateException
     * if called before an asynchronous processing cycle has been started, 
-    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
-    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    * if one of the dispatch methods has been called but the <code>startAsync</code> method has not
+    * been called during the resulting dispatch, or if <code>complete()</code> was called
     */
    public void dispatch(ServletContext context, String path) throws IllegalStateException;
 
@@ -210,10 +327,10 @@ public interface PortletAsyncContext {
     * 
     * @return
     * @throws IllegalStateException
-    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
-    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    * if one of the dispatch methods has been called but the <code>startAsync</code> method has not
+    * been called during the resulting dispatch, or if <code>complete()</code> was called
     */
-   public ResourceRequest getRequest() throws IllegalStateException;
+   public ResourceRequest getResourceRequest() throws IllegalStateException;
 
    /**
     * <div class="changed_added_3_0">
@@ -225,10 +342,10 @@ public interface PortletAsyncContext {
     * 
     * @return
     * @throws IllegalStateException
-    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
-    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    * if one of the dispatch methods has been called but the <code>startAsync</code> method has not
+    * been called during the resulting dispatch, or if <code>complete()</code> was called
     */
-   public ResourceResponse getResponse() throws IllegalStateException;
+   public ResourceResponse getResourceResponse() throws IllegalStateException;
 
    /**
     * <div class="changed_added_3_0">
@@ -298,11 +415,14 @@ public interface PortletAsyncContext {
 
    /**
     * <div class="changed_added_3_0">
+    * Causes the container to dispatch a thread, possibly from a managed thread pool,
+    * to run the specified <code>Runnable</code>. The container may propagate appropriate
+    * contextual information to the <code>Runnable</code>.
     * </div>
     * 
     * @since   3.0
     * 
-    * @param run
+    * @param run     the asynchronous handler
     * @throws IllegalStateException
     * if this method is called before an asynchronous processing cycle was started, 
     * after it has already been completed, or after a call to 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
index 66182dd..7829890 100644
--- a/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncEvent.java
@@ -23,11 +23,14 @@ package javax.portlet;
 /**
  * <div class="changed_added_3_0">
  * Event that gets fired when the asynchronous operation initiated on a
- * ResourceRequest (via a call to ResourceRequest#startAsync or
- * ResourceRequest#startAsync(ResourceRequest, ResouceResponse)) has completed, timed
+ * <code>ResourceRequest</code> (via a call to <code>ResourceRequest#startAsync</code> or
+ * <code>ResourceRequest#startAsync(ResourceRequest, ResouceResponse))</code> has completed, timed
  * out, or produced an error.
  * </div>
  * 
+ * @see     PortletAsyncContext
+ * @see     PortletAsyncEvent
+ * @see     ResourceRequest
  * @since   3.0
  */
 public class PortletAsyncEvent {
@@ -39,8 +42,9 @@ public class PortletAsyncEvent {
    
    /**
     * <div class="changed_added_3_0">
-    * Constructs a PortletAsyncEvent from the given 
-    * PortletAsyncContext, ResourceRequest, ResourceResponse, and Throwable.
+    * Constructs a <code>PortletAsyncEvent</code> from the given 
+    * <code>PortletAsyncContext</code>, <code>ResourceRequest</code>, <code>ResourceResponse</code>, 
+    * and <code>Throwable</code>.
     * </div>
     * 
     * @since   3.0
@@ -59,8 +63,8 @@ public class PortletAsyncEvent {
 
    /**
     * <div class="changed_added_3_0">
-    * Constructs a PortletAsyncEvent from the given 
-    * PortletAsyncContext, ResourceRequest, and ResourceResponse.
+    * Constructs a <code>PortletAsyncEvent</code> from the given 
+    * <code>PortletAsyncContext</code>, <code>ResourceRequest</code>, and <code>ResourceResponse</code>.
     * </div>
     * 
     * @since   3.0
@@ -77,8 +81,8 @@ public class PortletAsyncEvent {
 
    /**
     * <div class="changed_added_3_0">
-    * Constructs a PortletAsyncEvent from the given 
-    * PortletAsyncContext and Throwable.
+    * Constructs a <code>PortletAsyncEvent</code> from the given 
+    * <code>PortletAsyncContext</code> and <code>Throwable</code>.
     * </div>
     * 
     * @since   3.0
@@ -95,8 +99,8 @@ public class PortletAsyncEvent {
 
    /**
     * <div class="changed_added_3_0">
-    * Constructs a PortletAsyncEvent from the given 
-    * PortletAsyncContext.
+    * Constructs a <code>PortletAsyncEvent</code> from the given 
+    * <code>PortletAsyncContext</code>.
     * </div>
     * 
     * @since   3.0
@@ -125,7 +129,13 @@ public class PortletAsyncEvent {
 
    /**
     * <div class="changed_added_3_0">
-    * Gets the resource request associated with the event.
+    * Gets the resource request associated with the listener when it was added through the 
+    * <code>PortletAsyncContext#addListener(PortletAsyncListener, ResourceRequest, ResourceResponse)</code>
+    * method. 
+    * <p>
+    * If the listener was added through the 
+    * <code>PortletAsyncContext#addListener(PortletAsyncListener)</code> method,
+    * the returned resource request will be <code>null</code>.
     * </div>
     * 
     * @since   3.0
@@ -139,7 +149,13 @@ public class PortletAsyncEvent {
 
    /**
     * <div class="changed_added_3_0">
-    * Gets the resource response associated with the event.
+    * Gets the resource response associated with the listener when it was added through the 
+    * <code>PortletAsyncContext#addListener(PortletAsyncListener, ResourceRequest, ResourceResponse)</code>
+    * method. 
+    * <p>
+    * If the listener was added through the 
+    * <code>PortletAsyncContext#addListener(PortletAsyncListener)</code> method,
+    * the returned resource response will be <code>null</code>.
     * </div>
     * 
     * @since   3.0

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
index 0865365..0b825da 100644
--- a/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncListener.java
@@ -24,10 +24,12 @@ import java.io.IOException;
 /**
  * <div class="changed_added_3_0">
  * Listener that will be notified in the event that an asynchronous operation
- * initiated on a ResourceRequest to which the listener had been added has
+ * initiated on a <code>ResourceRequest</code> to which the listener had been added has
  * completed, timed out, or resulted in an error.
  * </div>
  * 
+ * @see     PortletAsyncContext
+ * @see     PortletAsyncEvent
  * @since   3.0
  */
 public interface PortletAsyncListener {
@@ -47,12 +49,14 @@ public interface PortletAsyncListener {
     * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
     * be retrieved by calling <code>getSuppliedRequest</code> and
     * <code>getSuppliedResponse</code>, respectively, on the given event.
-    *
+    * <p>
+    * The <code>PortletAsyncContext</code> dispatch and complete methods may not be invoked
+    * within this method.
     * </div>
     * 
     * @since   3.0
     * 
-    * @param evt  the PortletAsyncEvent indicating that an asynchronous operation has been completed 
+    * @param evt  the <code>PortletAsyncEvent</code> indicating that an asynchronous operation has been completed 
     * @throws IOException  if an I/O related error has occurred during the processing
     */
    public void onComplete(PortletAsyncEvent evt) throws IOException;
@@ -72,6 +76,9 @@ public interface PortletAsyncListener {
     * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
     * be retrieved by calling <code>getSuppliedRequest</code> and
     * <code>getSuppliedResponse</code>, respectively, on the given event.
+    * <p>
+    * The <code>PortletAsyncContext</code> dispatch and complete methods may be invoked
+    * within this method.
     * </div>
     * 
     * @since   3.0
@@ -129,6 +136,9 @@ public interface PortletAsyncListener {
     * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects may
     * be retrieved by calling <code>getSuppliedRequest</code> and
     * <code>getSuppliedResponse</code>, respectively, on the given event.
+    * <p>
+    * The <code>PortletAsyncContext</code> dispatch and complete methods may be invoked
+    * within this method.
     * 
     * </div>
     * 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/ResourceRequest.java b/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
index 24177a8..10edfc3 100644
--- a/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
+++ b/portlet-api/src/main/java/javax/portlet/ResourceRequest.java
@@ -24,7 +24,6 @@
 
 package javax.portlet;
 
-import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
 
 /**
@@ -296,7 +295,7 @@ public interface ResourceRequest extends ClientDataRequest {
     * @see     javax.portlet.filter.ResourceFilter
     */
 
-   public AsyncContext startAsync() throws IllegalStateException;
+   public PortletAsyncContext startAsync() throws IllegalStateException;
 
 
    /**
@@ -363,7 +362,7 @@ public interface ResourceRequest extends ClientDataRequest {
     * @see     javax.portlet.filter.ResourceFilter
     */
 
-   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException;
+   public PortletAsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException;
 
 
    /**
@@ -417,7 +416,7 @@ public interface ResourceRequest extends ClientDataRequest {
     * @see      javax.servlet.AsyncContext 
     */
    
-   public AsyncContext getAsyncContext();
+   public PortletAsyncContext getAsyncContext();
 
 
    /**

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
index fe4ec74..43b2ef2 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
@@ -24,7 +24,6 @@ import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
 import javax.portlet.ClientDataRequest;
-import javax.portlet.PortletContext;
 
 /**
  * <div class="changed_added_3_0"> The <code>ClientDataRequestWrapper</code>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java b/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
index 94ae61d..d58db8c 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ResourceFilter.java
@@ -55,10 +55,15 @@ import javax.portlet.PortletException;
  * if asynchronous mode has been started.
  * <p>
  * If resources must be allocated in this way during inbound processing, the portlet should
+ * use a {@link javax.portlet.PortletAsyncListener} to release the resources upon request 
+ * completion even when error conditions or timeouts occur. 
+ * <p>
+ * Alternatively, the portlet may
  * use the <code>AsyncContext#dispatch()</code> method at the end of asynchronous processing
  * in order to cause the portlet resource method to be invoked again with the same
  * <code>ResourceRequest</code> and <code>ResourceResponse</code> objects.
- * The resources can be released during asynchronous dispatch outbound processing.
+ * The resources can be released during asynchronous dispatch outbound processing if
+ * asynchronous mode is not active.
  * <p>
  * The <code>ResourceRequest#isAsyncStarted()</code> method will return <code>true</code>
  * if the portlet is currently in asynchronous mode.

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
index 406a8c7..cc31ca5 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ResourceRequestWrapper.java
@@ -26,10 +26,10 @@ package javax.portlet.filter;
 
 import java.util.Map;
 
+import javax.portlet.PortletAsyncContext;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
-import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
 
 /**
@@ -119,12 +119,12 @@ public class ResourceRequestWrapper extends ClientDataRequestWrapper implements
    }
 
    @Override
-   public AsyncContext startAsync() throws IllegalStateException {
+   public PortletAsyncContext startAsync() throws IllegalStateException {
       return ((ResourceRequest)wrapped).startAsync();
    }
 
    @Override
-   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+   public PortletAsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
       return ((ResourceRequest)wrapped).startAsync(request, response);
    }
 
@@ -139,7 +139,7 @@ public class ResourceRequestWrapper extends ClientDataRequestWrapper implements
    }
 
    @Override
-   public AsyncContext getAsyncContext() {
+   public PortletAsyncContext getAsyncContext() {
       return ((ResourceRequest)wrapped).getAsyncContext();
    }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/overview.html b/portlet-api/src/main/javadoc/overview.html
index ade4007..4e6f55b 100644
--- a/portlet-api/src/main/javadoc/overview.html
+++ b/portlet-api/src/main/javadoc/overview.html
@@ -21,6 +21,19 @@
     <div class="indexContainer-not">
     <ul>
     <li>
+    20160406:
+    Added new classes to implement 
+    <a href="https://java.net/jira/browse/PORTLETSPEC3-68">PORTLETSPEC3-68 Add Async Support</a>:
+    {@link javax.portlet.PortletAsyncContext PortletAsyncContext}, 
+    {@link javax.portlet.PortletAsyncListener PortletAsyncListener}, and
+    {@link javax.portlet.PortletAsyncEvent PortletAsyncEvent}.
+    Modified 
+    {@link javax.portlet.ResourceRequest#startAsync() ResourceRequest#startAsync()}, 
+    {@link javax.portlet.ResourceRequest#startAsync(ResourceRequest, ResourceResponse) ResourceRequest#startAsync(ResourceRequest, ResourceResponse)}, and 
+    {@link javax.portlet.ResourceRequest#getAsyncContext() ResourceRequest#getAsyncContext()}
+    along with the corresponding wrapper class accordingly.
+    </li>
+    <li>
     20160316:
     Added new methods, configuration elements, and documentation to implement 
     <a href="https://java.net/jira/browse/PORTLETSPEC3-68">PORTLETSPEC3-68 Add Async Support</a>:

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/0e71c8ab/portlet-api/src/main/javadoc/portlet-api.css
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/javadoc/portlet-api.css b/portlet-api/src/main/javadoc/portlet-api.css
index 14cc9ea..7f6b832 100644
--- a/portlet-api/src/main/javadoc/portlet-api.css
+++ b/portlet-api/src/main/javadoc/portlet-api.css
@@ -8,7 +8,7 @@ body {
     background-color:#ffffff;
     color:#353833;
     font-family:Arial, Helvetica, sans-serif;
-    font-size:76%;
+    font-size:100%;
     margin:0;
 }
 a:link, a:visited {
@@ -631,6 +631,10 @@ h1.hidden {
 .indexContainer a[href*="ResourceParametersWrapper.html"],
 .indexContainer a[href*="ResourceURLWrapper.html"],
 
+.indexContainer a[href*="PortletAsyncContext.html"],
+.indexContainer a[href*="PortletAsyncListener.html"],
+.indexContainer a[href*="PortletAsyncEvent.html"],
+
 .indexContainer a[href*="ActionURL.html"],
 .indexContainer a[href*="RenderURL.html"],
 .indexContainer a[href*="MimeResponse.Copy.html"],


[20/34] portals-pluto git commit: async support debugging

Posted by ms...@apache.org.
async support debugging


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

Branch: refs/heads/V3Prototype
Commit: 3a6b398c9f85cef721d2fcb438087b8d30eba771
Parents: 79160b5
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Mar 30 21:26:02 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Mar 30 21:26:02 2016 +0200

----------------------------------------------------------------------
 .../pluto/container/impl/PortletAsyncRequestWrapper.java  | 10 +++++++++-
 .../container/impl/PortletRequestDispatcherImpl.java      |  9 +++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/3a6b398c/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
index 57bdee6..f2f6c2b 100644
--- 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
@@ -24,6 +24,7 @@ import java.util.Enumeration;
 import javax.portlet.PortletRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -66,7 +67,14 @@ public class PortletAsyncRequestWrapper extends HttpServletRequestWrapper {
       preq.removeAttribute(name);
    }
    
-   
+   @Override
+   public RequestDispatcher getRequestDispatcher(String path) {
+      RequestDispatcher rd = super.getRequestDispatcher(path);
+      if (rd != null) {
+         return new PortletRequestDispatcherImpl(rd, false);
+      }
+      return null;
+   }
    
    
    

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/3a6b398c/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
index 2ef980c..90c6904 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletRequestDispatcherImpl.java
@@ -243,6 +243,15 @@ public class PortletRequestDispatcherImpl implements PortletRequestDispatcher, R
     {
         HttpServletPortletRequestWrapper req = getWrappedRequest(request);
         HttpServletPortletResponseWrapper res = getWrappedResponse(response);
+        
+        if (isDebug) {
+           StringBuilder txt = new StringBuilder();
+           txt.append("Forwarding ... ");
+           txt.append(" hreq: ").append((req == null) ? "null" : "not null");
+           txt.append(" hresp: ").append((res == null) ? "null" : "not null");
+           LOG.debug(txt.toString());
+        }
+        
         res.resetBuffer();
         
         // cache the current dispatch state


[07/34] portals-pluto git commit: worked on portlet async support

Posted by ms...@apache.org.
worked on portlet 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/49ca2dd0
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/49ca2dd0
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/49ca2dd0

Branch: refs/heads/V3Prototype
Commit: 49ca2dd09c7b85eda9959ee2cf478145c3813dc8
Parents: 45fb2a6
Author: Scott Nicklous <ms...@apache.org>
Authored: Mon Mar 21 17:47:52 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Mon Mar 21 17:47:52 2016 +0100

----------------------------------------------------------------------
 .../samples/AsyncHackIncludedServlet.java       |  49 ++++++
 .../portals/samples/AsyncHackPortlet.java       | 148 +++++++++++++++++++
 .../apache/portals/samples/PathInfoPortlet.java |  44 +-----
 .../src/main/resources/logging.properties       |   2 +-
 .../container/impl/PortletContainerImpl.java    |  27 ++--
 .../pluto/driver/PortalDriverServlet.java       |  48 ++++++
 .../container/DefaultPortletInvokerService.java |  21 ++-
 7 files changed, 280 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackIncludedServlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackIncludedServlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackIncludedServlet.java
new file mode 100644
index 0000000..9c752c2
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackIncludedServlet.java
@@ -0,0 +1,49 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author Scott Nicklous
+ *
+ */
+@WebServlet(urlPatterns="/ais")
+public class AsyncHackIncludedServlet extends HttpServlet {
+   private static final long serialVersionUID = 1L;
+
+   public AsyncHackIncludedServlet() {
+   }
+
+   @Override
+   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+      
+      PrintWriter writer = resp.getWriter();
+      writer.append("<p>Hello from dispatched servlet!</p>");
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
new file mode 100644
index 0000000..9e2c243
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncHackPortlet.java
@@ -0,0 +1,148 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.portlet.PortletException;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+import javax.portlet.annotations.Namespace;
+import javax.portlet.annotations.RenderMethod;
+import javax.portlet.annotations.ServeResourceMethod;
+import javax.portlet.annotations.URLFactory;
+import javax.servlet.AsyncContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Resource portlet for viewing path information.
+ */
+public class AsyncHackPortlet {
+   private static final Logger LOGGER = Logger.getLogger(AsyncHackPortlet.class.getName());
+
+   public static final String RESPARAM_DISPLAY = "display";
+
+   // Injecting the namespace & URLFactory
+   @Inject
+   @Namespace
+   private String             pid;
+   @Inject
+   private URLFactory         uf;
+
+   @RenderMethod(portletNames = { "AsyncHackPortlet" }, ordinal = 100)
+   public String getImageInclude() {
+      LOGGER.fine("Rendering async hack portlet");
+
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("<h3>Async Hack Portlet</h3>");
+
+      ResourceURL resurl = uf.createResourceURL();
+
+      txt.append("<div class='infobox' id='").append(pid).append("-putResourceHere'></div>\n");
+      txt.append("<script>\n");
+      txt.append("(function () {\n");
+      txt.append("   var xhr = new XMLHttpRequest();\n");
+      txt.append("   xhr.onreadystatechange=function() {\n");
+      txt.append("      if (xhr.readyState==4 && xhr.status==200) {\n");
+      txt.append("         document.getElementById('").append(pid)
+            .append("-putResourceHere').innerHTML=xhr.responseText;\n");
+      txt.append("      }\n");
+      txt.append("   };\n");
+      txt.append("   xhr.open(\"GET\",\"").append(resurl.toString()).append("\",true);\n");
+      txt.append("   xhr.send();\n");
+      txt.append("})();\n");
+      txt.append("</script>\n");
+
+      return txt.toString();
+   }
+
+   /**
+    * This resource method generates some output directly, then includes output from a JSP as specified in the
+    * annotation.
+    * 
+    * @return The string for inclusion in the output.
+    * @throws IOException
+    * @throws PortletException 
+    */
+   @ServeResourceMethod(portletNames = { "AsyncHackPortlet" }, asyncSupported = true)
+   public void getPathInfo(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
+      LOGGER.fine("Doing async hack resource request");
+
+      @SuppressWarnings("unchecked")
+      ArrayList<String> pathInfo = (ArrayList<String>) req.getAttribute("pathInfo");
+      if (pathInfo == null) {
+         pathInfo = new ArrayList<String>();
+      }
+
+      HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
+      HttpServletResponse hresp = (HttpServletResponse) req.getAttribute("javax.portlet.debug.ServletResponse");
+      PathDisplay pd;
+      if (hreq != null) {
+         pd = new PathDisplay(hreq, "Resource Method (Servlet)");
+         hreq.setAttribute("pathInfo", pathInfo);
+      } else {
+         pd = new PathDisplay(req, "Resource Method (Resource)");
+         req.setAttribute("pathInfo", pathInfo);
+      }
+      pathInfo.add(pd.toMarkup());
+
+      PrintWriter writer = resp.getWriter();
+      writer.append("<h5>Async Hack Resource Request</h5>");
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Trying to start async. Servlet context: ").append(hreq.getServletContext().getContextPath());
+
+      String jsp = "/WEB-INF/jsp/pathinfo.jsp";
+//      String jsp = "/ais";
+//      RequestDispatcher rd = null;
+//      rd = hreq.getRequestDispatcher(jsp);
+//      txt.append("Request dispatcher: ").append(rd);
+      LOGGER.fine(txt.toString());
+      txt.setLength(0);
+      
+      if (hreq != null && hresp != null) {
+         try {
+            
+            AsyncContext context = hreq.startAsync(hreq, hresp);
+            context.setTimeout(1000);
+            
+            txt.append("Async context: ").append((context == null) ? "null." : "not null.");
+            txt.append(" Now dispatching ... ");
+
+//            context.dispatch(hreq.getServletContext(), jsp);
+            context.dispatch(jsp);
+            
+            txt.append(" done. ");
+         } catch (Exception e) {
+            txt.append(" ... didn't work. Exception: ").append(e.toString());
+         }
+         
+         LOGGER.fine(txt.toString());
+         txt.setLength(0);
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
index aa87980..8eb2594 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PathInfoPortlet.java
@@ -19,7 +19,6 @@
 package org.apache.portals.samples;
 
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
@@ -30,11 +29,7 @@ import javax.portlet.annotations.Namespace;
 import javax.portlet.annotations.RenderMethod;
 import javax.portlet.annotations.ServeResourceMethod;
 import javax.portlet.annotations.URLFactory;
-import javax.servlet.AsyncContext;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * Resource portlet for viewing path information.
@@ -83,7 +78,7 @@ public class PathInfoPortlet {
     * @return The string for inclusion in the output.
     * @throws IOException
     */
-   @ServeResourceMethod(portletNames = { "PathInfoPortlet" }, asyncSupported = true)
+   @ServeResourceMethod(portletNames = { "PathInfoPortlet" }, include="/WEB-INF/jsp/pathinfo.jsp")
    public void getPathInfo(ResourceRequest req, ResourceResponse resp) throws IOException {
 
       @SuppressWarnings("unchecked")
@@ -93,7 +88,6 @@ public class PathInfoPortlet {
       }
 
       HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
-      HttpServletResponse hresp = (HttpServletResponse) req.getAttribute("javax.portlet.debug.ServletResponse");
       PathDisplay pd;
       if (hreq != null) {
          pd = new PathDisplay(hreq, "Resource Method (Servlet)");
@@ -104,42 +98,6 @@ public class PathInfoPortlet {
 
       req.setAttribute("pathInfo", pathInfo);
 
-      PrintWriter writer = resp.getWriter();
-      writer.append("<h5>Async Hack Resource Request</h5>");
-      writer.append("<p>");
-      writer.append("Trying to start async. Servlet context = ").append(hreq.getServletContext().getContextPath())
-            .append(". ");
-      resp.flushBuffer();
-
-      RequestDispatcher rd = null;
-      String jsp = "/WEB-INF/jsp/pathinfo.jsp";
-      rd = hreq.getRequestDispatcher(jsp);
-      if (hreq != null && hresp != null) {
-         try {
-            AsyncContext context = hreq.startAsync(hreq, hresp);
-            context.setTimeout(3000);
-            writer = context.getResponse().getWriter();
-            writer.append("worked. Async context: ").append((context == null) ? "null." : "not null.");
-            writer.append(" Now dispatching ... ");
-            resp.flushBuffer();
-            context.dispatch(jsp);
-            writer.append(" done. ");
-         } catch (Exception e) {
-            writer.append(" ... didn't work. Exception: ").append(e.toString());
-            resp.flushBuffer();
-         }
-      }
-
-      writer.append("</p><hr>");
-      resp.flushBuffer();
-      try {
-         writer.append("<p>Now doing request dispatcher include.</p>");
-         rd.include(hreq, hresp);
-      } catch (ServletException e) {
-         writer.append("<p>Exception including jsp. ").append(e.toString());
-         writer.append("</p>");
-      }
-
    }
 
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/PortletV3AnnotatedDemo/src/main/resources/logging.properties
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/resources/logging.properties b/PortletV3AnnotatedDemo/src/main/resources/logging.properties
index 09bae36..9a479f9 100644
--- a/PortletV3AnnotatedDemo/src/main/resources/logging.properties
+++ b/PortletV3AnnotatedDemo/src/main/resources/logging.properties
@@ -34,4 +34,4 @@ org.apache.juli.FileHandler.directory = ${catalina.base}/logs
 org.apache.juli.FileHandler.prefix = PortletV3AnnotatedDemo.
 
 org.apache.pluto.level=FINE
-basic.portlet.level=FINEST
+org.apache.portals.samples.level=FINEST

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
index c1be463..dc17d7f 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletContainerImpl.java
@@ -267,16 +267,23 @@ public class PortletContainerImpl implements PortletContainer
         ResourceResponse portletResponse = envService.createResourceResponse(responseContext, requestContext.getCacheability());
 
         FilterManager filterManager = filterInitialisation(portletWindow,PortletRequest.RESOURCE_PHASE);
-
-        try
-        {
-            invoker.serveResource(requestContext, portletRequest, portletResponse, filterManager);
-            // Mark portlet interaction is completed: backend implementation can flush response state now
-            responseContext.close();
-        }
-        finally
-        {
-            responseContext.release();
+        
+        if (portletWindow.getPortletDefinition().isAsyncSupported()) {
+           LOG.debug("invoking for async ... no resource release");
+           invoker.serveResource(requestContext, portletRequest, portletResponse, filterManager);
+           
+        } else {
+           LOG.debug("invocation through request dispatcher.");
+           try
+           {
+              invoker.serveResource(requestContext, portletRequest, portletResponse, filterManager);
+              // Mark portlet interaction is completed: backend implementation can flush response state now
+              responseContext.close();
+           }
+           finally
+           {
+              responseContext.release();
+           }
         }
 
         debugWithName("Portlet resource done for: " + portletWindow.getPortletDefinition().getPortletName());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
index 21326ae..722b037 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
@@ -17,6 +17,7 @@
 package org.apache.pluto.driver;
 
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.List;
@@ -24,6 +25,7 @@ import java.util.Map;
 
 import javax.portlet.PortletException;
 import javax.portlet.PortletRequest;
+import javax.servlet.AsyncContext;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -35,6 +37,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.pluto.container.HeaderData;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletContainerException;
+import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.om.portlet.ContainerRuntimeOption;
 import org.apache.pluto.container.om.portlet.PortletDefinition;
 import org.apache.pluto.driver.config.DriverConfiguration;
@@ -142,6 +145,51 @@ public class PortalDriverServlet extends HttpServlet {
             LOG.debug("Processing " + reqType + " request for window: " + portletWindow.getId().getStringId());
          }
 
+         
+//          String portletName = portletWindow.getPortletName();
+//          if (portletName.equals("AsyncHackPortlet")
+//                && portalURL.getType() == URLType.Resource) {
+// 
+//             String uri =  PortletInvokerService.URIPREFIX + portletWindow.getPortletDefinition().getPortletName();
+//             String ctxpath =  "/PortletV3AnnotatedDemo";
+//             String jsp = "/WEB-INF/jsp/pathinfo.jsp";
+//             
+// //            LOG.debug("Directly doing async dispatch to JSP. uri: " + uri + ", jsp: " + jsp);
+//             LOG.debug("Directly dispatching to portlet servlet. uri: " + uri);
+//             
+//             ServletContext ctx = request.getServletContext().getContext(ctxpath);
+//             RequestDispatcher rd = ctx.getRequestDispatcher(uri);
+//             rd.forward(request, response);
+//             LOG.debug("Completed the dispatch.");
+//             return;
+//             
+// //             ServletContext ctx = request.getServletContext().getContext(ctxpath);
+// //             if (ctx == null) {
+// //                LOG.debug("couldn't get context for uri.");
+// //             } else {
+// //                LOG.debug("Got context, path: >>>" + ctx.getContextPath() + "<<<");
+// // 
+// //                AsyncContext context = request.startAsync();
+// //                context.dispatch(ctx, jsp);
+// //                
+// //                LOG.debug("Completed the dispatch.");
+// //                return;
+// // 
+// //                
+// //               RequestDispatcher rd = ctx.getRequestDispatcher(jsp);
+// //               if (rd == null) {
+// //                  LOG.debug("couldn't get request dispatcher for context.");
+// //               } else {
+// //                  LOG.debug("Got the request dispatcher.");
+// // //                  PrintWriter writer = response.getWriter();
+// // //                  writer.append("<h5>Greetings from portal driver servlet!</h5>");
+// //                  rd.include(request, response);
+// //                  LOG.debug("Dispatch seemed to go OK.");
+// //                  return;
+// //               }
+// //             }
+//          }
+
          try {
             PageState ps;
             String jsondata;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/49ca2dd0/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 a46a4e5..3d1e4ea 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
@@ -31,6 +31,7 @@ import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
+import javax.servlet.AsyncContext;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -239,7 +240,15 @@ public class DefaultPortletInvokerService implements PortletInvokerService {
 
                 if (methodID.equals(PortletInvokerService.METHOD_RESOURCE))
                 {
-                    dispatcher.forward(containerRequest, containerResponse);
+                    if (portletWindow.getPortletDefinition().isAsyncSupported()) {
+                       LOG.debug("Async dispatching resource request to portlet servlet.");
+                       AsyncContext actx = containerRequest.startAsync(containerRequest, containerResponse);
+                       actx.dispatch(servletContext, uri);
+                    } else {
+                       LOG.debug("Request dispatcher forward resource request to portlet servlet.");
+                       dispatcher.forward(containerRequest, containerResponse);
+                    }
+                    LOG.debug("Dispatch complete.");
                 }
                 else
                 {
@@ -275,10 +284,12 @@ public class DefaultPortletInvokerService implements PortletInvokerService {
                 }
 
             } finally {
-                containerRequest.removeAttribute(PortletInvokerService.METHOD_ID);
-                containerRequest.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
-                containerRequest.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
-                containerRequest.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+                if (!portletWindow.getPortletDefinition().isAsyncSupported()) {
+                   containerRequest.removeAttribute(PortletInvokerService.METHOD_ID);
+                   containerRequest.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+                   containerRequest.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+                   containerRequest.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+                }
             }
         } else {
             String msg = EXCEPTIONS.getString(


[29/34] portals-pluto git commit: Completed contextual support for thread executed with AsyncContext#start()

Posted by ms...@apache.org.
Completed contextual support for thread executed with AsyncContext#start()


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

Branch: refs/heads/V3Prototype
Commit: 74d5f10be327e165686edc46f72da50b5a60feda
Parents: 27e17ae
Author: Scott Nicklous <ms...@apache.org>
Authored: Mon Apr 4 22:07:08 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Mon Apr 4 22:07:08 2016 +0200

----------------------------------------------------------------------
 .../java/org/apache/portals/samples/AsyncPortletFilter.java  | 2 +-
 .../services/container/PortletAsyncContextualRunner.java     | 5 ++++-
 .../container/PortletResourceRequestContextImpl.java         | 8 ++++++--
 3 files changed, 11 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/74d5f10b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
index be096c5..f7c430e 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletFilter.java
@@ -65,7 +65,7 @@ public class AsyncPortletFilter implements ResourceFilter {
       txt.append(", request #: ").append(reqnum.getRandomNumber());
       LOGGER.fine(txt.toString());
       
-      if (type != DispatcherType.ASYNC && adb.isUseFilter()) {
+      if (adb.isUseFilter()) {
          txt.setLength(0);
          txt.append("<div class='msgbox'>");
          txt.append("Filter: Request number: ").append(reqnum.getRandomNumber());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/74d5f10b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
index 6dcac04..8535a7e 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
@@ -54,9 +54,12 @@ public class PortletAsyncContextualRunner implements Runnable {
          LOG.debug("Initializing contextual environment and launching runner in thread: " + Thread.currentThread().getId());
       }
 
-      pactx.registerContext();
       try {
+         pactx.registerContext();
          targetRunner.run();
+      } catch (Exception e) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Exception running thread: ").append(e.toString());
       } finally {
          if (isDebug) {
             LOG.debug("Shutting down contextual environment for thread: " + Thread.currentThread().getId());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/74d5f10b/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 f607449..6906a57 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
@@ -184,9 +184,13 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request, this);
       HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
 
-      // Start async, add listener to release resources upon async complete only once.
+      // Start async, create portlet async context first time only.
 
-      actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), wreq);
+      if (actx != null) {
+         actx.setWrapped(hreq.startAsync(wreq, wresp));
+      } else {
+         actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), wreq);
+      }
 
       if (isTrace) {
          List<String> attrNames = Collections.list(hreq.getAttributeNames());


[19/34] portals-pluto git commit: Added bug fixes and debugging code for async support

Posted by ms...@apache.org.
Added bug fixes and debugging code for 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/79160b5d
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/79160b5d
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/79160b5d

Branch: refs/heads/V3Prototype
Commit: 79160b5d6ce8dbbfd2c764f54a25f0ec9b0eca00
Parents: 1d62807
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Mar 30 18:18:58 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Mar 30 18:18:58 2016 +0200

----------------------------------------------------------------------
 .../apache/portals/samples/AsyncDialogBean.java |  22 ++-
 .../portals/samples/AsyncPortletResource.java   | 183 +++++++++++++++----
 .../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp |   4 +-
 .../pluto/container/driver/PortletServlet3.java |  14 +-
 .../bean/processor/PortletInvoker.java          |   7 +-
 .../impl/PortletAsyncRequestWrapper.java        |  96 +++++++---
 .../container/PortletAsyncListener.java         |  94 +++++-----
 .../PortletResourceRequestContextImpl.java      |  86 ++++++++-
 8 files changed, 377 insertions(+), 129 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index f0d76f9..a74af06 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -180,15 +180,6 @@ public class AsyncDialogBean implements PortletSerializable {
       
       msg = null;
       
-      String strType = req.getActionParameters().getValue(PARAM_TYPE);
-      if (strType != null) {
-         try {
-            type = OutputType.valueOf(strType);
-         } catch (Exception e) {
-            msg = "try again. bad type: " + strType;
-         }
-      }
-      
       String strReps = req.getActionParameters().getValue(PARAM_REPS);
       if (strReps != null) {
          try {
@@ -208,6 +199,19 @@ public class AsyncDialogBean implements PortletSerializable {
             msg = "try again. bad delay.";
          }
       }
+      
+      String strType = req.getActionParameters().getValue(PARAM_TYPE);
+      if (strType != null) {
+         try {
+            type = OutputType.valueOf(strType);
+            if (type == OutputType.FWD && reps > 1) {
+               msg = "Repetitions cannot be > 1 for forwards.";
+               reps = 1;
+            }
+         } catch (Exception e) {
+            msg = "try again. bad type: " + strType;
+         }
+      }
 
       String auto = req.getActionParameters().getValue(PARAM_AUTO);
       if (auto != null) {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 792601f..65fea26 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -19,9 +19,12 @@
 package org.apache.portals.samples;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
+import javax.portlet.PortletConfig;
 import javax.portlet.PortletException;
 import javax.portlet.PortletRequestDispatcher;
 import javax.portlet.ResourceRequest;
@@ -77,28 +80,69 @@ public class AsyncPortletResource {
             HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
             HttpServletResponse hresp = (HttpServletResponse) ctx.getResponse();
             RequestDispatcher rd;
+            
+            {
+               List<String> attrNames = Collections.list(hreq.getAttributeNames());
+               StringBuilder txt = new StringBuilder(128);
+               txt.append("Runnable:");
+               txt.append("\nAttribute names: ").append(attrNames);
+               txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+               txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
+               txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+               txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+               txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
+               txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+               txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
+               txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+               txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+               txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
+               txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
+               txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
+               txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+               txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+               txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
+               txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+               txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+               txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+               txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+               txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+               LOGGER.fine(txt.toString());
+            }
+
+            
+            PortletConfig config = (PortletConfig) hreq.getAttribute("javax.portlet.config");
+            String portletName = "Could not get PortletConfig";
+            if (config != null) {
+               portletName = config.getPortletName();
+            }
 
             switch (type) {
             case TEXT:
                LOGGER.fine("Producing text output.");
                StringBuilder txt = new StringBuilder(128);
-               txt.append("<h5>Thread producing text output</h5>");
+               txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
                txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
                txt.append("</p>");
                hresp.getWriter().write(txt.toString());
                if (done) {
                   ctx.complete();
+               } else {
+                  hresp.flushBuffer();
                }
                break;
             case AUTO:
-               LOGGER.fine("Dispatching to resource method.");
+               StringBuilder str = new StringBuilder(128);
+               str.append("Dispatching to resource method.");
+               str.append(" context path: ").append(hreq.getServletContext().getContextPath());
+               str.append(", Servlet patch: ").append(hreq.getServletPath());
+               LOGGER.fine(str.toString());
                hreq.setAttribute(ATTRIB_AUTO, new Boolean(true));
-               ctx.dispatch();
+               ctx.dispatch(hreq.getServletContext(), hreq.getServletPath());
                break;
             case DISPATCH:
                LOGGER.fine("Dispatching to JSP.");
                hreq.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
-               ctx.dispatch(JSP);
+               ctx.dispatch(hreq.getServletContext(), JSP);
                break;
             case FWD:
                LOGGER.fine("Doing request dispatcher forward to JSP.");
@@ -107,6 +151,8 @@ public class AsyncPortletResource {
                rd.forward(hreq, hresp);
                if (done) {
                   ctx.complete();
+               } else {
+                  hresp.flushBuffer();
                }
                break;
             case INC:
@@ -116,6 +162,8 @@ public class AsyncPortletResource {
                rd.include(hreq, hresp);
                if (done) {
                   ctx.complete();
+               } else {
+                  hresp.flushBuffer();
                }
                break;
             }
@@ -133,52 +181,111 @@ public class AsyncPortletResource {
    @ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
    public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
 
+      Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
+      if (auto == null) {
+         auto = false;
+      }
+      req.removeAttribute(ATTRIB_AUTO);
+
       Integer reps = (Integer) req.getAttribute(ATTRIB_REPS);
+      boolean done = false;
       if (reps == null) {
          reps = adb.getReps();
       }
-
-      boolean done = false;
-      if (--reps <= 0 || !adb.isAutoDispatch()) {
+      if (reps <= 0) {
          done = true;
       }
-      req.setAttribute(ATTRIB_REPS, reps);
+      
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Resource method.");
+      txt.append(" delay: ").append(adb.getDelay());
+      txt.append(", type: ").append(adb.getType());
+      txt.append(", reps: ").append(reps);
+      txt.append(", total reps: ").append(adb.getReps());
+      txt.append(", auto: ").append(adb.isAutoDispatch());
+      txt.append(", auto-dispatch: ").append(auto);
+      txt.append(", done: ").append(done);
+      LOGGER.fine(txt.toString());
+      
+      AsyncContext ctx = null;
 
-      Boolean auto = (Boolean) req.getAttribute(ATTRIB_AUTO);
-      req.removeAttribute(ATTRIB_AUTO);
+      if (!done) {
+         reps--;
+         req.setAttribute(ATTRIB_REPS, reps);
+         
+         ctx = req.startAsync();
+         ctx.setTimeout(4000);
+      }
 
-      if ((adb.getDelay() <= 0) || (auto != null)) {
+      if (auto || (adb.getDelay() <= 0)) {
+         
+         // produce output if dispatched from work thread or if there is no delay requested
          
          PortletRequestDispatcher rd;
-         AsyncContext ctx = null;
-         try {
-            ctx = req.getAsyncContext();
-         } catch (Exception e) {}
          
-         StringBuilder txt = new StringBuilder(128);
-         txt.append("Producing output.");
-         txt.append(" delay: ").append(adb.getDelay());
-         txt.append(", type: ").append(adb.getType());
-         txt.append(", reps: ").append(reps);
-         txt.append(", total reps: ").append(adb.getReps());
-         txt.append(", recursive: ").append(adb.isAutoDispatch());
-         txt.append(", dispatched from work thread: ").append(auto);
-         txt.append(", asyncContext: ").append((ctx == null) ? "null" : "not null");
-         LOGGER.fine(txt.toString());
+         if (ctx == null) {
+            // last iteration of auto-dispatch
+            try {
+               ctx = req.getAsyncContext();
+            } catch (Exception e) {
+               txt.setLength(0);
+               txt.append("Could not get AsyncContext. Exception: ").append(e.toString());
+               LOGGER.warning(txt.toString());
+               resp.getWriter().write(txt.toString());
+               return;
+            }
+         }
+
+         HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
+         
+         {
+            List<String> attrNames = Collections.list(hreq.getAttributeNames());
+            StringBuilder txt2 = new StringBuilder(128);
+            txt2.append("During content generation:");
+            txt2.append("\nAttribute names: ").append(attrNames);
+            txt2.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+            txt2.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
+            txt2.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+            txt2.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+            txt2.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
+            txt2.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+            txt2.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
+            txt2.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+            txt2.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+            txt2.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
+            txt2.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
+            txt2.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
+            txt2.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+            txt2.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+            txt2.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
+            txt2.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+            txt2.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+            txt2.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+            txt2.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+            txt2.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+            LOGGER.fine(txt2.toString());
+         }
+
+         
+         // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
+         PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
+         String portletName = "Could not get PortletConfig";
+         if (config != null) {
+            portletName = config.getPortletName();
+         }
 
          switch (adb.getType()) {
          case DISPATCH:
             LOGGER.fine("Dispatching to JSP.");
-            if (ctx != null) {
-               ctx.dispatch(JSP);
-            }
+            ctx.dispatch(JSP);
             break;
          case FWD:
             LOGGER.fine("Doing request dispatcher forward to JSP.");
             req.setAttribute(ATTRIB_TITLE, "Resource Method forwarding to JSP");
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.forward(req, resp);
-            if (done && ctx != null) {
+            resp.flushBuffer();
+            if (!auto) {
                ctx.complete();
             }
             break;
@@ -187,32 +294,36 @@ public class AsyncPortletResource {
             req.setAttribute(ATTRIB_TITLE, "Resource Method including JSP");
             rd = req.getPortletContext().getRequestDispatcher(JSP);
             rd.include(req, resp);
-            if (done && ctx != null) {
+            resp.flushBuffer();
+            if (!auto) {
                ctx.complete();
             }
             break;
          default:
             LOGGER.fine("Producing text output.");
             txt.setLength(0);
-            txt.append("<h5>Async portlet resource method producing text output</h5>");
+            txt.append("<h5>Async portlet resource method producing text output for portlet: " + portletName + "</h5>");
             txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
             txt.append("</p>");
             resp.getWriter().write(txt.toString());
-            if (done && ctx != null) {
+            resp.flushBuffer();
+            if (!auto) {
                ctx.complete();
             }
             break;
          }
       }
       
-      if (adb.getDelay() > 0 && (!done || auto == null)) {
-         AsyncContext ctx = req.startAsync();
-         ctx.setTimeout(4000);
+      if (adb.getDelay() > 0 && req.isAsyncStarted()) {
+         
+         // now start the executor thread 
+         
          OutputType type = adb.getType();
          if (adb.isAutoDispatch()) {
             type = OutputType.AUTO;
          }
-         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type, done);
+
+         AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type, (reps<=0));
          ctx.start(ar);
       }
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
index a939991..9297b6b 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -1,9 +1,11 @@
 <%@ page session="false" %>
 <%@ page isELIgnored ="false" %> 
+<%@ taglib uri="http://xmlns.jcp.org/portlet_3_0"  prefix="portlet" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
 
+<portlet:defineObjects />
 
-<h5><%=request.getAttribute("title") %></h5>
+<h5><%=request.getAttribute("title") %> for portlet: <%=portletConfig.getPortletName() %></h5>
 <p>Dispatch type: <%=request.getDispatcherType() %></p>
 <hr>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/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 d835746..7aed69d 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
@@ -244,6 +244,13 @@ public class PortletServlet3 extends HttpServlet {
     * @throws IOException
     */
    private void dispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+      if (LOG.isDebugEnabled()) {
+         StringBuilder txt = new StringBuilder();
+         txt.append("Processing request.");
+         txt.append(" Dispatcher type: ").append(request.getDispatcherType());
+         txt.append(", request URI: ").append(request.getRequestURI());
+         LOG.debug(txt.toString());
+      }
       if (invoker == null) {
          throw new javax.servlet.UnavailableException("Portlet " + portletName + " unavailable");
       }
@@ -265,8 +272,11 @@ public class PortletServlet3 extends HttpServlet {
       final FilterManager filterManager = 
             (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
 
-      requestContext.init(portletConfig, getServletContext(), request, response);
-      responseContext.init(request, response);
+      if (request.getDispatcherType() != DispatcherType.ASYNC) {
+         // the contexts are already initialized if this is part of a resource request async sequence
+         requestContext.init(portletConfig, getServletContext(), request, response);
+         responseContext.init(request, response);
+      }
 
       PortletWindow window = requestContext.getPortletWindow();
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/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 f9a592b..fd090da 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
@@ -268,15 +268,10 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
          
          // Handle AsyncContest#dispatch() case
          
-         MethodIdentifier ami = (MethodIdentifier) req.getAttribute(PortletInvokerService.ASYNC_METHOD);
-         AnnotatedMethod meth = null;
-         if (ami != null) {
-            meth = acb.getMethodStore().getMethod(mi);
-         }
+         AnnotatedMethod meth = (AnnotatedMethod) req.getAttribute(PortletInvokerService.ASYNC_METHOD);;
          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;
          }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/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
index dd259c9..57bdee6 100644
--- 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
@@ -19,6 +19,8 @@
 
 package org.apache.pluto.container.impl;
 
+import java.util.Enumeration;
+
 import javax.portlet.PortletRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
@@ -26,50 +28,90 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpSession;
 
 /**
  * @author Scott Nicklous
  *
  */
-public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper {
+public class PortletAsyncRequestWrapper extends HttpServletRequestWrapper {
+   
+   private final PortletRequest preq;
 
-   /**
-    * 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);
-      
+   public PortletAsyncRequestWrapper(HttpServletRequest hreq, PortletRequest preq) {
+      super(hreq);
+      this.preq = preq;
    }
    
-
-
+   
+   
    @Override
-   public AsyncContext startAsync() throws IllegalStateException {
-      return getRequest().startAsync();
+   public Object getAttribute(String name) {
+      return preq.getAttribute(name);
    }
-
+   
    @Override
-   public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws IllegalStateException {
-      return getRequest().startAsync(request, response);
+   public Enumeration<String> getAttributeNames() {
+      return preq.getAttributeNames();
    }
-
+   
    @Override
-   public boolean isAsyncStarted() {
-      return getRequest().isAsyncStarted();
+   public void setAttribute(String name, Object o) {
+      preq.setAttribute(name, o);
    }
-
+   
    @Override
-   public boolean isAsyncSupported() {
-      return getRequest().isAsyncSupported();
+   public void removeAttribute(String name) {
+      preq.removeAttribute(name);
    }
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   // saved methods below.
 
+//    /**
+//     * 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/79160b5d/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
index 9474a10..d645aae 100644
--- 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
@@ -16,35 +16,33 @@
  *  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)
+   private long                start  = System.currentTimeMillis();
+
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
     */
    @Override
@@ -53,44 +51,50 @@ public class PortletAsyncListener implements AsyncListener {
       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();
+
+      HttpServletRequest hreq = (HttpServletRequest) evt.getSuppliedRequest();
+      if (hreq != null) {
+         ResourceRequest rreq = (ResourceRequest) hreq.getAttribute(PortletInvokerService.PORTLET_REQUEST);
+         if (rreq != null) {
+
+            // remove portlet-scoped barnacles
+
+            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();
+            }
+         } else {
+            txt.append("... no resource request stuff. Couldn't get resource request; ");
          }
-      }
-      
-      // Release and remove container request attributes
-      
-      HttpServletRequest containerRequest = (HttpServletRequest) evt.getSuppliedRequest();
-      if (containerRequest != null) {
+         
+         // remove container-scoped attributes
+
          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);
+         hreq.removeAttribute(PortletInvokerService.METHOD_ID);
+         hreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+         hreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+         hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+
+      } else {
+         txt.append("... nothing. Couldn't get servlet request.");
       }
-      
+
       LOGGER.fine(txt.toString());
 
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
     */
    @Override
@@ -102,7 +106,9 @@ public class PortletAsyncListener implements AsyncListener {
       LOGGER.fine(txt.toString());
    }
 
-   /* (non-Javadoc)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
     */
    @Override
@@ -111,14 +117,16 @@ public class PortletAsyncListener implements AsyncListener {
       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)
+   /*
+    * (non-Javadoc)
+    * 
     * @see javax.servlet.AsyncListener#onTimeout(javax.servlet.AsyncEvent)
     */
    @Override

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/79160b5d/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 c361dcd..a441c29 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
@@ -16,6 +16,8 @@
  */
 package org.apache.pluto.driver.services.container;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import javax.portlet.PortletConfig;
@@ -38,6 +40,8 @@ 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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @version $Id$
@@ -46,8 +50,16 @@ import org.apache.pluto.container.impl.ServletPortletSessionProxy;
 public class PortletResourceRequestContextImpl extends PortletRequestContextImpl implements
                 PortletResourceRequestContext
 {
+   
+   /** Logger. */
+   private static final Logger LOG = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
+   private static final boolean isDebug = LOG.isDebugEnabled();
+   private static final boolean isTrace = LOG.isTraceEnabled();
+   
+   
    private String pageState;
    private ResourceResponse response;
+   private AsyncContext actx = null;
    
    
     public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
@@ -121,6 +133,35 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
        ServletContext ctx = getServletContext();
        HttpSession sess = getSession();
        PortletConfig cfg = getPortletConfig(); 
+       
+       if (isDebug) {
+          List<String> attrNames = Collections.list(hreq.getAttributeNames());
+          StringBuilder txt = new StringBuilder(128);
+          txt.append("Start async before:");
+          txt.append("\nAttribute names: ").append(attrNames);
+          txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+          txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
+          txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+          txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+          txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
+          txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+          txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
+          txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+          txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+          txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
+          txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
+          txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
+          txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+          txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+          txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
+          txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+          txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+          txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+          txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+          txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+          LOG.debug(txt.toString());
+       }
+
 
        // Set portlet-scoped attributes directly on resource request
        
@@ -130,7 +171,7 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
 
        // Wrap http req & response. 
        
-       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, ctx, sess, request);
+       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request);
        HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
 
        // get the original container req & resp to pass to listener for resource releasing
@@ -138,11 +179,46 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
        HttpServletRequest creq = getContainerRequest();     
        HttpServletResponse cresp = getContainerResponse();
 
-       // Attach listener to release resources upon async complete.
+       // Start async, add listener to release resources upon async complete only once.
        
-       AsyncContext actx = hreq.startAsync(wreq, wresp);
-       PortletAsyncListener pal = new PortletAsyncListener();
-       actx.addListener(pal, creq, cresp);
+       if (actx == null) {
+          actx = hreq.startAsync(wreq, wresp);
+//          actx = hreq.startAsync(hreq, hresp);
+          PortletAsyncListener pal = new PortletAsyncListener();
+          actx.addListener(pal, creq, cresp);
+       } else {
+//          actx = hreq.startAsync(hreq, hresp);
+          actx = hreq.startAsync(wreq, wresp);
+       }
+
+       
+       if (isDebug) {
+          List<String> attrNames = Collections.list(hreq.getAttributeNames());
+          StringBuilder txt = new StringBuilder(128);
+          txt.append("Start async after:");
+          txt.append("\nAttribute names: ").append(attrNames);
+          txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+          txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
+          txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+          txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+          txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
+          txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+          txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
+          txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+          txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+          txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
+          txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
+          txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
+          txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+          txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+          txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
+          txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+          txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+          txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+          txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+          txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+          LOG.debug(txt.toString());
+       }
 
        return actx;
     }


[02/34] portals-pluto git commit: Bug fix in ClientDataRequestWrapper

Posted by ms...@apache.org.
Bug fix in ClientDataRequestWrapper


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

Branch: refs/heads/V3Prototype
Commit: 16cb7b3f64fc62d1dd5dfa74d47a43395b1540b2
Parents: 7e04857
Author: Scott Nicklous <ms...@apache.org>
Authored: Thu Mar 10 16:15:32 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Thu Mar 10 16:15:32 2016 +0100

----------------------------------------------------------------------
 .../java/javax/portlet/filter/ClientDataRequestWrapper.java     | 5 -----
 1 file changed, 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/16cb7b3f/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
index cddd18e..fe4ec74 100644
--- a/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
+++ b/portlet-api/src/main/java/javax/portlet/filter/ClientDataRequestWrapper.java
@@ -132,9 +132,4 @@ public class ClientDataRequestWrapper extends PortletRequestWrapper implements C
       return ((ClientDataRequest)wrapped).getMethod();
    }
 
-   @Override
-   public PortletContext getPortletContext() {
-      return null;
-   }
-
 }


[32/34] portals-pluto git commit: Continued work to add portlet-specific async interfaces

Posted by ms...@apache.org.
Continued work to add portlet-specific async interfaces


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

Branch: refs/heads/V3Prototype
Commit: 1cbbbc3ded36b052eabb869aac30938fe62c9e38
Parents: 593f7ce
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Apr 6 04:30:03 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Apr 6 04:30:03 2016 +0200

----------------------------------------------------------------------
 .../java/javax/portlet/PortletAsyncContext.java | 253 ++++++++++++++++++-
 1 file changed, 243 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/1cbbbc3d/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
index d77f5c4..af3ef1f 100644
--- a/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
+++ b/portlet-api/src/main/java/javax/portlet/PortletAsyncContext.java
@@ -27,6 +27,10 @@ import javax.servlet.ServletContext;
  * Class representing the execution context for an asynchronous operation that was
  * initiated on a ResourceRequest.
  * <p>
+ * Portlet asynchronous support is modeled after servlet asynchronous support, and in 
+ * general, the portlet async methods behave in the same manner as their 
+ * <code>AsyncContext</code> analog. 
+ * <p>
  * A PortletAsyncContext is created and initialized by a call to
  * ResourceRequest#startAsync() or ResourceRequest#startAsync(ServletRequest,
  * ServletResponse). Repeated invocations of these methods will return the same
@@ -44,28 +48,252 @@ import javax.servlet.ServletContext;
  */
 public interface PortletAsyncContext {
 
-   public void addListener(PortletAsyncListener listener);
+   /**
+    * <div class="changed_added_3_0">
+    * Registers the given <code>PortletAsyncListener</code> with the most recent 
+    * asynchronous cycle that was started by a call to one of the 
+    * <code>ResourceRequest.startAsync()</code> methods.
+    * <p>
+    * The given <code>PortletAsyncListener</code> will receive an 
+    * <code>PortletAsyncEvent</code> when the
+    * asynchronous cycle completes successfully, times out, results in an error, or a
+    * new asynchronous cycle is being initiated via one of the
+    * <code>ResourceRequest.startAsync()</code> methods.
+    * <p>
+    * <code>PortletAsyncListener</code> instances will be notified in the order in 
+    * which they were added. 
+    * <p>
+    * If <code>ResourceRequest.startAsync(ResourceRequest, ResourceResponse)</code> or
+    * <code>ResourceRequest.startAsync()</code> is called, the exact same request and response
+    * objects are available from the <code>PortletAsyncEvent</code> when the 
+    * <code>PortletAsyncListener</code> is notified.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param listener   the listener to be added
+    * @throws IllegalStateException
+    * if this method is called after the container-initiated dispatch, during which
+    * one of the <code>ServletRequest.startAsync()</code> methods was called, has
+    * returned to the container
+    * 
+    */
+   public void addListener(PortletAsyncListener listener) throws IllegalStateException;
 
-   public void addListener(PortletAsyncListener listener, ResourceRequest request, ResourceResponse response);
+   /**
+    * <div class="changed_added_3_0">
+    * Registers the given <code>PortletAsyncListener</code> with the most recent 
+    * asynchronous cycle that was started by a call to one of the 
+    * <code>ResourceRequest.startAsync()</code> methods.
+    * <p>
+    * The given <code>PortletAsyncListener</code> will receive an 
+    * <code>PortletAsyncEvent</code> when the
+    * asynchronous cycle completes successfully, times out, results in an error, or a
+    * new asynchronous cycle is being initiated via one of the
+    * <code>ResourceRequest.startAsync()</code> methods.
+    * <p>
+    * <code>PortletAsyncListener</code> instances will be notified in the order in 
+    * which they were added. 
+    * <p>
+    * The given <code>ResourceRequest</code> and <code>ResourceResponse</code> objects will be made
+    * available to the given <code>PortletAsyncListener</code> via the 
+    * <code>getSuppliedRequest</code> and
+    * <code>getSuppliedResponse</code> methods, respectively, of the 
+    * <code>PortletAsyncEvent</code> delivered to
+    * it. These objects should not be read from or written to, respectively, at the
+    * time the <code>PortletAsyncEvent</code> is delivered, because additional wrapping 
+    * may have
+    * occurred since the given <code>PortletAsyncListener</code> was registered, but may 
+    * be used in
+    * order to release any resources associated with them.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param listener   the listener to be added
+    * @param request    the request object to be included in the <code>PortletAsyncEvent</code>
+    * @param response   the response object to be included in the <code>PortletAsyncEvent</code>
+    * @throws IllegalStateException
+    * if this method is called after the container-initiated dispatch, during which
+    * one of the <code>ServletRequest.startAsync()</code> methods was called, has
+    * returned to the container
+    * 
+    */
+   public void addListener(PortletAsyncListener listener, ResourceRequest request, ResourceResponse response) throws IllegalStateException;
 
-   public void complete();
+   /**
+    * <div class="changed_added_3_0">
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @throws IllegalStateException
+    * if this method is called before an asynchronous processing cycle was started, 
+    * after it has already been completed, or after a call to 
+    * one of the <code>ServletRequest.dispatch()</code> methods
+    * 
+    */
+   public void complete() throws IllegalStateException;
 
+   /**
+    * <div class="changed_added_3_0">
+    * Instantiates the given AsyncListener class.
+    * <p>
+    * The returned AsyncListener instance may be further customized before it is
+    * registered with this AsyncContext via a call to one of the addListener methods.
+    * <p>
+    * The given AsyncListener class must define a zero argument constructor, which is
+    * used to instantiate it.
+    * <p>
+    * This method supports resource injection if the given class represents a Managed
+    * Bean. See the Java EE platform and JSR 299 specifications for additional details
+    * about Managed Beans and resource injection.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param cls     the class to be instantiated
+    * @return        the instantiated class
+    * @throws PortletException if the given class cannot be instantiated
+    */
    public <T extends PortletAsyncListener> T createListener(Class<T> cls) throws PortletException;
 
-   public void dispatch();
+   /**
+    * <div class="changed_added_3_0">
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @throws IllegalStateException 
+    * if called before an asynchronous processing cycle has been started, 
+    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
+    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    */
+   public void dispatch() throws IllegalStateException;
 
-   public void dispatch(String path);
+   /**
+    * <div class="changed_added_3_0">
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param path
+    * @throws IllegalStateException
+    * if called before an asynchronous processing cycle has been started, 
+    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
+    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    */
+   public void dispatch(String path) throws IllegalStateException;
 
-   public void dispatch(ServletContext context, String path);
+   /**
+    * <div class="changed_added_3_0">
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param context
+    * @param path
+    * @throws IllegalStateException
+    * if called before an asynchronous processing cycle has been started, 
+    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
+    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    */
+   public void dispatch(ServletContext context, String path) throws IllegalStateException;
 
-   public ResourceRequest getRequest();
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the request that was used to initialize this <code>PortletAsyncContext</code> by calling
+    * <code>ResourceRequest.startAsync()</code> or <code>ResourceRequest.startAsync(ServletRequest, ServletResponse)</code>.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return
+    * @throws IllegalStateException
+    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
+    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    */
+   public ResourceRequest getRequest() throws IllegalStateException;
 
-   public ResourceResponse getResponse();
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the response that was used to initialize this <code>PortletAsyncContext</code> by calling
+    * <code>ResourceRequest.startAsync()</code> or <code>ResourceRequest.startAsync(ServletRequest, ServletResponse)</code>.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return
+    * @throws IllegalStateException
+    * if one of the dispatch methods has been called but the <code>startAsync<code/> method has not
+    * been called during the resulting dispatch, or if <code>complete()<code/> was called
+    */
+   public ResourceResponse getResponse() throws IllegalStateException;
 
+   /**
+    * <div class="changed_added_3_0">
+    * Gets the timeout (in milliseconds) for this PortletAsyncContext.
+    * <p>
+    * This method returns the container's default timeout for asynchronous operations,
+    * or the timeout value passed to the most recent invocation of 
+    * <code>setTimeout(long)</code>.
+    * <p>
+    * A timeout value of zero or less indicates no timeout.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return     the timeout in milliseconds
+    */
    public long getTimeout();
 
+   /**
+    * <div class="changed_added_3_0">
+    * Checks if this <code>PortletAsyncContext</code> was initialized with the original or
+    * application-wrapped request and response objects.
+    * <p>
+    * This information may be used by filters invoked in the outbound direction, after
+    * a request was put into asynchronous mode, to determine whether any request
+    * and/or response wrappers that they added during their inbound invocation need to
+    * be preserved for the duration of the asynchronous operation, or may be released.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @return
+    * <code>true</code> if this <code>PortletAsyncContext</code> was initialized with the original 
+    * request and response objects by calling <code>ResourceRequest.startAsync()</code>, 
+    * or if it was initialized by calling 
+    * <code>ResourceRequest.startAsync(ResourceRequest, ResourceResponse)</code>, and neither
+    * the <code>ResourceRequest</code> nor <code>ResourceResponse</code> arguments carried any
+    * application-provided wrappers; <code>false</code> otherwise
+
+    */
    public boolean hasOriginalRequestAndResponse();
 
+   /**
+    * <div class="changed_added_3_0">
+    * Sets the timeout (in milliseconds) for this <code>PortletAsyncContext</code>.
+    * <p>
+    * The timeout applies to this <code>PortletAsyncContext</code> once the 
+    * container-initiated dispatch
+    * during which one of the <code>ResourceRequest.startAsync()</code> methods was 
+    * called has returned to the container.
+    * <p>
+    * The timeout will expire if neither the <code>complete()</code> method nor any of 
+    * the dispatch
+    * methods are called. A timeout value of zero or less indicates no timeout.
+    * <p>
+    * If <code>setTimeout(long)</code> is not called, then the container's default timeout, 
+    * which is available via a call to <code>getTimeout()</code>, will apply.
+    * <p>
+    * The default value is 30000 ms.
+    * </div>
+    * 
+    * @since   3.0
+    * 
+    * @param time    the timeout in milliseconds
+    */
    public void setTimeout(long time);
 
    /**
@@ -75,7 +303,12 @@ public interface PortletAsyncContext {
     * @since   3.0
     * 
     * @param run
-    */
-   public void start(Runnable run);
+    * @throws IllegalStateException
+    * if this method is called before an asynchronous processing cycle was started, 
+    * after it has already been completed, or after a call to 
+    * one of the <code>ServletRequest.dispatch()</code> methods
+    * 
+    **/
+   public void start(Runnable run) throws IllegalStateException;
 
 }


[27/34] portals-pluto git commit: Completed async listener. Added listener to demo async portlet.

Posted by ms...@apache.org.
Completed async listener. Added listener to demo async portlet.


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

Branch: refs/heads/V3Prototype
Commit: aae89a3472117160620d253df2776850d9599834
Parents: 5c26ec4
Author: Scott Nicklous <ms...@apache.org>
Authored: Sun Apr 3 23:09:03 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sun Apr 3 23:09:03 2016 +0200

----------------------------------------------------------------------
 .../portals/samples/AsyncPortletListener.java   | 118 +++++++++++++++++++
 .../portals/samples/AsyncPortletResource.java   |   4 +
 .../container/PortletAsyncListener.java         |  31 ++++-
 3 files changed, 152 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/aae89a34/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
new file mode 100644
index 0000000..ce2086c
--- /dev/null
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletListener.java
@@ -0,0 +1,118 @@
+/*  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.portals.samples;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.logging.Logger;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletResponse;
+
+/**
+ * @author Scott Nicklous
+ *
+ */
+public class AsyncPortletListener implements AsyncListener {
+   private static final Logger LOGGER = Logger.getLogger(AsyncPortletListener.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("Listener: Completed. Execution time: ").append(delta).append(" milliseconds.");
+
+      LOGGER.fine(txt.toString());
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
+    */
+   @Override
+   public void onError(AsyncEvent evt) throws IOException {
+
+      // this doesn't seem to get called when an error occurs in the executor
+      // thread.
+
+      long delta = System.currentTimeMillis() - start;
+
+      StringBuilder txt = new StringBuilder(128);
+      txt.append("Listener: Error after ").append(delta).append(" milliseconds.");
+      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
+
+      LOGGER.fine(txt.toString());
+      evt.getAsyncContext().complete();
+   }
+
+   /*
+    * (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("Listener: Timeout after ").append(delta).append(" milliseconds.");
+
+      try {
+         PrintWriter writer = evt.getAsyncContext().getResponse().getWriter();
+         writer.println("<p>");
+         writer.println(txt.toString());
+         writer.println("</p>");
+         evt.getAsyncContext().complete();
+      } catch (Exception e) {
+         txt.append(" Couldn't get response and complete. Exception: " + e.toString());
+      }
+      LOGGER.fine(txt.toString());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/aae89a34/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 59cc599..6cad2fb 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -129,6 +129,8 @@ public class AsyncPortletResource {
                break;
             }
 
+         } catch (IllegalStateException e) {
+            LOGGER.warning("Request may have timed out before it could complete. Exception: " + e.toString());
          } catch (Exception e) {
             LOGGER.warning("Exception during async processing: " + e.toString());
          }
@@ -170,6 +172,8 @@ public class AsyncPortletResource {
       
       AsyncContext ctx = req.startAsync();
       ctx.setTimeout(4000);
+      AsyncPortletListener apl = new AsyncPortletListener();
+      ctx.addListener(apl);
 
       if (auto || (adb.getDelay() <= 0)) {
          

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/aae89a34/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
index d645aae..97b77c6 100644
--- 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
@@ -25,7 +25,9 @@ import javax.portlet.ResourceRequest;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncEvent;
 import javax.servlet.AsyncListener;
+import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceResponseContext;
@@ -134,7 +136,34 @@ public class PortletAsyncListener implements AsyncListener {
       long delta = System.currentTimeMillis() - start;
       StringBuilder txt = new StringBuilder(128);
       txt.append("Timeout after ").append(delta).append(" milliseconds.");
-      LOGGER.fine(txt.toString());
+      
+      // if the application has properly registered a listener and has not processed the 
+      // timeout by calling onComplete or dispatch, complete the request.
+      
+      boolean warn = false;
+      AsyncContext ctx = evt.getAsyncContext();
+      try {
+         ctx.getRequest();
+         
+         try {
+            ctx.complete();
+            txt.append(" Portlet container completed request processing on behalf of the application.");
+            warn = true;
+         } catch (IllegalStateException e) {
+            txt.append(" An earlier listener has dispatched again.");
+         } catch (Exception e) {
+            txt.append(" Exception occured while completing request: " + e.toString());
+         }
+         
+      } catch(Exception e) {
+         txt.append(" Async processing was completed by the application.");
+      }
+
+      if (warn) {
+         LOGGER.warning(txt.toString());
+      } else {
+         LOGGER.fine(txt.toString());
+      }
    }
 
 }


[18/34] portals-pluto git commit: Fixed bug in PortalURLParserImpl that was preventing Pluto from working on Tomcat 8.0.32. Replaced blanks in the path portion with %20.

Posted by ms...@apache.org.
Fixed bug in PortalURLParserImpl that was preventing Pluto from working on
Tomcat 8.0.32. Replaced blanks in the path portion with %20.


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

Branch: refs/heads/V3Prototype
Commit: 1d628077541dcf5a644cef562d8d00376c4d0931
Parents: 46a03a1
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Mar 29 18:09:03 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Mar 29 18:09:03 2016 +0200

----------------------------------------------------------------------
 .../org/apache/pluto/driver/url/impl/PortalURLParserImpl.java     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/1d628077/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java
index ef9492c..ca10756 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java
@@ -436,7 +436,8 @@ public class PortalURLParserImpl implements PortalURLParser {
 
       // Start the pathInfo with the path to the render URL (page).
       if (portalURL.getRenderPath() != null) {
-         buffer.append(portalURL.getRenderPath());
+         String p = portalURL.getRenderPath().replaceAll(" ", "%20");
+         buffer.append(p);
       }
 
       // Add the portletIds with references


[13/34] portals-pluto git commit: fixed bug that was preventing the resource ID rfrom being stored on the URL

Posted by ms...@apache.org.
fixed bug that was preventing the resource ID rfrom being stored on the URL


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

Branch: refs/heads/V3Prototype
Commit: ae766fdfb3a89fa34025839196419593509b1e14
Parents: 70f9642
Author: Scott Nicklous <ms...@apache.org>
Authored: Fri Mar 25 06:14:21 2016 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Fri Mar 25 06:14:21 2016 +0100

----------------------------------------------------------------------
 .../pluto/driver/services/container/PortletURLProviderImpl.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/ae766fdf/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletURLProviderImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletURLProviderImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletURLProviderImpl.java
index 761c33e..074f467 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletURLProviderImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletURLProviderImpl.java
@@ -252,7 +252,7 @@ public class PortletURLProviderImpl implements PortletURLProvider {
    }
 
    public void setResourceID(String resourceID) {
-      url.setCacheability(resourceID);
+      url.setResourceID(resourceID);
    }
 
    public String toURL() {