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 2015/11/27 13:38:15 UTC

[34/38] portals-pluto git commit: Continued work on header phase implementation. Implemented PortletResponse#addProperty(String, Element) for both V2 and V3 portlets. Completed execution path that allows the header information to be integrated into the o

Continued work on header phase implementation. Implemented
PortletResponse#addProperty(String, Element) for both V2 and V3 portlets.
Completed execution path that allows the header information to be integrated
into the overall portal response.


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

Branch: refs/heads/V3Prototype
Commit: 8f9bca1bc1d1dad3f817821d19b1f1e244873fbb
Parents: 65c0050
Author: Scott Nicklous <ms...@apache.org>
Authored: Tue Nov 24 10:48:39 2015 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Tue Nov 24 10:51:58 2015 +0100

----------------------------------------------------------------------
 .../main/java/basic/portlet/HeaderPortlet.java  | 113 +++++
 .../src/main/webapp/WEB-INF/jsp/view-hdp.jsp    |  32 ++
 .../src/main/webapp/WEB-INF/portlet.xml         |  18 +
 .../src/main/webapp/resources/css/styles.css    |  15 +-
 .../org/apache/pluto/container/HeaderData.java  |  42 ++
 .../pluto/container/PortletContainer.java       |  10 +-
 .../pluto/container/PortletRequestContext.java  |   4 +
 .../pluto/container/PortletResponseContext.java |   8 +
 .../pluto/container/driver/PortletServlet3.java |   4 +
 .../container/impl/PortletContainerImpl.java    |  27 +-
 .../services/container/PortalContextImpl.java   | 338 ++++++-------
 .../PortletActionResponseContextImpl.java       | 202 ++++----
 .../PortletEventResponseContextImpl.java        |  80 ++--
 .../PortletHeaderResponseContextImpl.java       |   2 +
 .../PortletRenderResponseContextImpl.java       | 112 ++---
 .../container/PortletRequestContextImpl.java    |  13 +-
 .../PortletResourceResponseContextImpl.java     |   2 +
 .../container/PortletResponseContextImpl.java   | 371 ++++++++------
 .../org/apache/pluto/driver/AttributeKeys.java  | 134 +++---
 .../pluto/driver/PortalDriverServlet.java       | 176 ++++---
 .../apache/pluto/driver/tags/PortletTag.java    | 479 ++++++++++---------
 .../WEB-INF/themes/pluto-default-theme.jsp      |   3 +
 .../main/java/javax/portlet/GenericPortlet.java |  14 +-
 23 files changed, 1308 insertions(+), 891 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/PortletV3Demo/src/main/java/basic/portlet/HeaderPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/HeaderPortlet.java b/PortletV3Demo/src/main/java/basic/portlet/HeaderPortlet.java
new file mode 100644
index 0000000..3270287
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/HeaderPortlet.java
@@ -0,0 +1,113 @@
+/*  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 basic.portlet;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionParameters;
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.ActionURL;
+import javax.portlet.GenericPortlet;
+import javax.portlet.HeaderRequest;
+import javax.portlet.HeaderResponse;
+import javax.portlet.MimeResponse;
+import javax.portlet.PortalContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.RenderParameters;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.RenderURL;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.w3c.dom.Element;
+
+import static javax.portlet.MimeResponse.Copy.*;
+import static basic.portlet.Constants.*;
+
+/**
+ * Portlet for testing the redirect funtionality, including the new getRedirectURL API.
+ */
+public class HeaderPortlet extends GenericPortlet {
+
+   private static final Logger  LOGGER  = Logger.getLogger(HeaderPortlet.class.getName());
+   private static final boolean isDebug = LOGGER.isLoggable(Level.FINE);
+   
+   @Override
+   public void renderHeaders(HeaderRequest req, HeaderResponse resp) throws PortletException, IOException {
+      
+      if (LOGGER.isLoggable(Level.FINE)) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Doing the headers. ");
+         txt.append("portal ctx prop names: ");
+         txt.append(Collections.list(req.getPortalContext().getPropertyNames()).toString());
+         txt.append(", markup head prop: ");
+         txt.append(req.getPortalContext().getProperty(PortalContext.MARKUP_HEAD_ELEMENT_SUPPORT));
+         txt.append(", RENDER_PART: ");
+         txt.append((String)req.getAttribute(PortletRequest.RENDER_PART));
+         LOGGER.fine(txt.toString());
+      }
+
+      // Add link tag to head section to include the style sheet
+      Element link = resp.createElement("link");
+      link.setAttribute("rel", "stylesheet");
+      link.setAttribute("type", "text/css");
+      String contextRoot = req.getContextPath();
+      link.setAttribute("href", contextRoot + "/resources/css/styles.css");
+      resp.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, link);
+
+   }
+
+   @Override
+   protected void doView(RenderRequest req, RenderResponse resp) throws PortletException, IOException {
+      
+      if (LOGGER.isLoggable(Level.FINE)) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Rendering. ");
+         txt.append("RENDER_PART: ");
+         txt.append((String)req.getAttribute(PortletRequest.RENDER_PART));
+         LOGGER.fine(txt.toString());
+      }
+
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/view-hdp.jsp");
+      rd.include(req, resp);
+
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp) throws PortletException, IOException {
+   }
+
+   public void processAction(ActionRequest req, ActionResponse resp) throws PortletException, IOException {
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-hdp.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-hdp.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-hdp.jsp
new file mode 100644
index 0000000..95d4e44
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-hdp.jsp
@@ -0,0 +1,32 @@
+<%--
+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 basic.portlet.Constants.*" %>
+
+<portlet:defineObjects />
+
+<div class='headerPortlet'>
+<h3>V3 Header Portlet</h3><hr/>
+<p>
+Portlet to demo the V3 header request functionality. The portlet uses a CSS class that sets a border and
+background color.
+</p>
+</div>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml b/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
index d1217a2..a7aba59 100644
--- a/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
@@ -112,6 +112,24 @@
    </portlet>
 
    <portlet>
+      <portlet-name>V3HeaderPortlet</portlet-name>
+      <display-name>Header Phase Test Portlet</display-name>
+      
+      <portlet-class>basic.portlet.HeaderPortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>Header Phase Test Portlet</title>
+      </portlet-info>
+   </portlet>
+
+   <portlet>
       <portlet-name>PortletConfigPortlet1</portlet-name>
       <display-name>Portlet Config Portlet #1</display-name>
       

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/PortletV3Demo/src/main/webapp/resources/css/styles.css
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/css/styles.css b/PortletV3Demo/src/main/webapp/resources/css/styles.css
index 9029874..cecb135 100644
--- a/PortletV3Demo/src/main/webapp/resources/css/styles.css
+++ b/PortletV3Demo/src/main/webapp/resources/css/styles.css
@@ -1,16 +1,5 @@
-.emphasis {
-   font-style: italic;
-   font-size: 1.3em;
-}
-
-.basicJSFApp {
-   padding: 5px;
-   background-color: #DDFFDD;
-   border: thin solid #66DD66;
-}
-
-.infoBox {
+.headerPortlet {
    padding: 5px;
    background-color: #DDDDFF;
-   border: thin solid #6666DD;
+   border: thick solid #2288EE;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-container-api/src/main/java/org/apache/pluto/container/HeaderData.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/HeaderData.java b/pluto-container-api/src/main/java/org/apache/pluto/container/HeaderData.java
new file mode 100644
index 0000000..8283739
--- /dev/null
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/HeaderData.java
@@ -0,0 +1,42 @@
+/*  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;
+
+/**
+ * This class is a holder for the HTTP header data, cookies, and header section markup 
+ * provided by the portlet during header phase execution. 
+ * 
+ * @author Scott Nicklous
+ *
+ */
+public class HeaderData {
+
+   private String headSectionMarkup = "";
+
+   public String getHeadSectionMarkup() {
+      return headSectionMarkup;
+   }
+
+   public void setHeadSectionMarkup(String headSectionMarkup) {
+      this.headSectionMarkup = headSectionMarkup;
+   }
+   
+   
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletContainer.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletContainer.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletContainer.java
index 8529654..f986c9f 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletContainer.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletContainer.java
@@ -72,8 +72,9 @@ public interface PortletContainer {
      * @throws IOException               if the streaming causes an I/O problem
      * @throws PortletContainerException if the portlet container implementation
      *                                   has trouble fulfilling the request
+     * @return The header data 
      */
-    void doHeader(PortletWindow portletWindow,
+    HeaderData doHeader(PortletWindow portletWindow,
             HttpServletRequest request,
             HttpServletResponse response)
     throws PortletException, IOException, PortletContainerException;
@@ -83,15 +84,18 @@ public interface PortletContainer {
      * @param portletWindow the portlet Window
      * @param request               the servlet request
      * @param response              the servlet response
+     * @param renderHeaders         marks if doHeaders or render
      * @throws PortletException          if one portlet has trouble fulfilling
      *                                   the request
      * @throws IOException               if the streaming causes an I/O problem
      * @throws PortletContainerException if the portlet container implementation
      *                                   has trouble fulfilling the request
+     * @return The header data if it's a RENDER_HEADERS call, otherwise <code>null</code>                                   
      */
-    void doRender(PortletWindow portletWindow,
+    HeaderData doRender(PortletWindow portletWindow,
             HttpServletRequest request,
-            HttpServletResponse response)
+            HttpServletResponse response,
+            String renderHeaders)
     throws PortletException, IOException, PortletContainerException;
 
     /**

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/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 26b3860..322e427 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
@@ -76,4 +76,8 @@ public interface PortletRequestContext
      * @return
      */
     ActionParameters getActionParameters();
+    
+    // for render headers support
+    void setRenderHeaders(String renderHeaders);
+    String getRenderHeaders();
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResponseContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResponseContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResponseContext.java
index 8d48f14..ef541ef 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResponseContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResponseContext.java
@@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.PortletURLProvider.TYPE;
 import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
 /**
@@ -38,6 +39,13 @@ public interface PortletResponseContext
     HttpServletResponse getServletResponse();
     PortletWindow getPortletWindow();
     
+    // needed for header processing
+    void setLifecycle(String lifecycle);
+    String getLifecycle();
+    void setPropsAllowed(boolean isSetPropsAllowed);
+    boolean isSetPropsAllowed();
+    HeaderData getHeaderData();
+    
     ResourceURLProvider getResourceURLProvider();
     PortletURLProvider getPortletURLProvider(TYPE type);
     void addProperty(Cookie cookie);

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/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 e8aaf53..d939d24 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
@@ -320,6 +320,10 @@ public class PortletServlet3 extends HttpServlet {
          // The requested method is RENDER: call Portlet.render(..)
          if (methodId == PortletInvokerService.METHOD_RENDER) {
             RenderRequest renderRequest = (RenderRequest) portletRequest;
+            String rh = requestContext.getRenderHeaders();
+            if (rh != null) {
+               renderRequest.setAttribute(PortletRequest.RENDER_PART, rh);
+            }
             RenderResponse renderResponse = (RenderResponse) portletResponse;
             filterManager.processFilter(renderRequest, renderResponse, portlet, portletContext);
          }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/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 84b5146..c1be463 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
@@ -37,6 +37,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.pluto.container.ContainerServices;
 import org.apache.pluto.container.FilterManager;
+import org.apache.pluto.container.HeaderData;
 import org.apache.pluto.container.PortletActionResponseContext;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletContainerException;
@@ -135,7 +136,7 @@ public class PortletContainerImpl implements PortletContainer
      * @see javax.portlet.Portlet#header(HeaderRequest, HeaderResponse)
      */
     @Override
-    public void doHeader(PortletWindow portletWindow,
+    public HeaderData doHeader(PortletWindow portletWindow,
             HttpServletRequest request,
             HttpServletResponse response)
     throws PortletException, IOException, PortletContainerException
@@ -151,15 +152,17 @@ public class PortletContainerImpl implements PortletContainer
 
         PortletRequestContext requestContext = rcService.getPortletHeaderRequestContext(this, request, response, portletWindow);
         PortletHeaderResponseContext responseContext = rcService.getPortletHeaderResponseContext(this, request, response, portletWindow);
+        responseContext.setPropsAllowed(true);
         HeaderRequest portletRequest = envService.createHeaderRequest(requestContext, responseContext);
         HeaderResponse portletResponse = envService.createHeaderResponse(responseContext);
+        HeaderData headerData = new HeaderData();
 
         FilterManager filterManager = filterInitialisation(portletWindow,PortletRequest.HEADER_PHASE);
 
         try
         {
             invoker.header(requestContext, portletRequest, portletResponse, filterManager);
-            // Mark portlet interaction is completed: backend implementation can flush response state now
+            headerData = responseContext.getHeaderData();
             responseContext.close();
         }
         finally
@@ -168,6 +171,7 @@ public class PortletContainerImpl implements PortletContainer
         }
 
         debugWithName("Portlet header done for: " + portletWindow.getPortletDefinition().getPortletName());
+        return headerData;
     }
 
 
@@ -184,9 +188,10 @@ public class PortletContainerImpl implements PortletContainer
      * @see javax.portlet.Portlet#render(RenderRequest, RenderResponse)
      */
     @Override
-    public void doRender(PortletWindow portletWindow,
+    public HeaderData doRender(PortletWindow portletWindow,
             HttpServletRequest request,
-            HttpServletResponse response)
+            HttpServletResponse response,
+            String renderHeaders)
     throws PortletException, IOException, PortletContainerException
     {
         ensureInitialized();
@@ -200,6 +205,15 @@ public class PortletContainerImpl implements PortletContainer
 
         PortletRequestContext requestContext = rcService.getPortletRenderRequestContext(this, request, response, portletWindow);
         PortletRenderResponseContext responseContext = rcService.getPortletRenderResponseContext(this, request, response, portletWindow);
+
+        if (renderHeaders != null && renderHeaders.equals(PortletRequest.RENDER_HEADERS)) {
+           responseContext.setPropsAllowed(true);
+        } else {
+           responseContext.setPropsAllowed(false);
+        }
+        requestContext.setRenderHeaders(renderHeaders);
+        HeaderData headerData = new HeaderData();
+
         RenderRequest portletRequest = envService.createRenderRequest(requestContext, responseContext);
         RenderResponse portletResponse = envService.createRenderResponse(responseContext);
 
@@ -208,7 +222,7 @@ public class PortletContainerImpl implements PortletContainer
         try
         {
             invoker.render(requestContext, portletRequest, portletResponse, filterManager);
-            // Mark portlet interaction is completed: backend implementation can flush response state now
+            headerData = responseContext.getHeaderData();
             responseContext.close();
         }
         finally
@@ -217,6 +231,7 @@ public class PortletContainerImpl implements PortletContainer
         }
 
         debugWithName("Portlet render done for: " + portletWindow.getPortletDefinition().getPortletName());
+        return headerData;
     }
 
     /**
@@ -247,6 +262,7 @@ public class PortletContainerImpl implements PortletContainer
 
         PortletResourceRequestContext requestContext = rcService.getPortletResourceRequestContext(this, request, response, portletWindow, pageState);
         PortletResourceResponseContext responseContext = rcService.getPortletResourceResponseContext(this, request, response, portletWindow);
+        responseContext.setPropsAllowed(true);
         ResourceRequest portletRequest = envService.createResourceRequest(requestContext, responseContext);
         ResourceResponse portletResponse = envService.createResourceResponse(responseContext, requestContext.getCacheability());
 
@@ -297,6 +313,7 @@ public class PortletContainerImpl implements PortletContainer
 
         PortletRequestContext requestContext = rcService.getPortletActionRequestContext(this, request, response, portletWindow);
         PortletActionResponseContext responseContext = rcService.getPortletActionResponseContext(this, request, response, portletWindow);
+        responseContext.setPropsAllowed(true);
         ActionRequest portletRequest = envService.createActionRequest(requestContext, responseContext);
         ActionResponse portletResponse = envService.createActionResponse(responseContext);
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortalContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortalContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortalContextImpl.java
index 9f1eeac..faec892 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortalContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortalContextImpl.java
@@ -1,166 +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.pluto.driver.services.container;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Vector;
-
-import javax.portlet.PortalContext;
-import javax.portlet.PortletMode;
-import javax.portlet.WindowState;
-
-import org.apache.pluto.driver.config.DriverConfiguration;
-
-/**
- * <code>PortalContext</code> implementation for the Pluto Portal Driver.
- */
-public class PortalContextImpl implements PortalContext {
-
-    /**
-     * The <code>DriverConfigurationImpl</code> from which this
-     * <code>PortalContext</code> recieves it's configuration information.
-     */
-    private DriverConfiguration config;
-
-    /**
-     * Portal information.
-     */
-    private String info = null;
-
-    /**
-     * Portal Properties
-     */
-    private HashMap properties = new HashMap();
-
-    /**
-     * Supported PortletModes.
-     */
-    private Vector portletModes;
-
-    /**
-     * Supported WindowStates.
-     */
-    private Vector windowStates;
-
-
-    /**
-     * Default Constructor.
-     * @param config
-     */
-    public PortalContextImpl(DriverConfiguration config) {
-        this.config = config;
-        reset();
-    }
-
-    /**
-     * Get a dynamic portal property.
-     * @param name
-     * @return the property value associated with the given key.
-     * @throws IllegalArgumentException if the specified name is null.
-     */
-    public String getProperty(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Property name == null");
-        }
-
-        return (String) properties.get(name);
-    }
-
-
-    /**
-     * Get an enumeration containing all names of the portal properties.
-     * @return an enumeration of all keys to which properties are bound.
-     */
-    public Enumeration getPropertyNames() {
-        Vector names = new Vector(properties.keySet());
-        return names.elements();
-    }
-
-
-    /**
-     * Get an enumeration of all <code>PortletMode</code>s supported by this
-     * portal.
-     * @return enumeration of all supported portlet modes.
-     */
-    public Enumeration getSupportedPortletModes() {
-        if (portletModes == null) {
-            portletModes = new Vector();
-            Enumeration enumeration = new Vector(config.getSupportedPortletModes()).elements();
-            while (enumeration.hasMoreElements()) {
-                portletModes.add(
-                    new PortletMode(enumeration.nextElement().toString()));
-            }
-        }
-        return portletModes.elements();
-    }
-
-    /**
-     * Get an enumeration of all <code>WindowState</code>s supported by this
-     * portal.
-     * @return an enumeration of all supported window states.
-     */
-    public Enumeration getSupportedWindowStates() {
-        if (windowStates == null) {
-            windowStates = new Vector();
-            Enumeration enumeration = new Vector(config.getSupportedWindowStates()).elements();
-            while (enumeration.hasMoreElements()) {
-                windowStates.add(
-                    new WindowState(enumeration.nextElement().toString()));
-            }
-        }
-        return windowStates.elements();
-    }
-
-    /**
-     * Get the portal info for this portal.
-     * @return the portal information for this context.
-     */
-    public String getPortalInfo() {
-        if(info == null) {
-            info = config.getPortalName() + "/" + config.getPortalVersion();
-        }
-        return info;
-    }
-
-
-    // additional methods.
-    // methods used container internally to set
-
-    public void setProperty(String name, String value) {
-        if (name == null) {
-            throw new IllegalArgumentException("Property name == null");
-        }
-
-        properties.put(name, value);
-    }
-
-
-    /**
-     * reset all values to default portlet modes and window states; delete all
-     * properties and set the given portlet information as portlet info string.
-     */
-    public void reset() {
-        info = null;
-        properties.clear();
-    }
-
-    public DriverConfiguration getDriverConfiguration() {
-        return config;
-    }
-
-}
+/*
+ * 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.util.Enumeration;
+import java.util.HashMap;
+import java.util.Vector;
+
+import javax.portlet.PortalContext;
+import javax.portlet.PortletMode;
+import javax.portlet.WindowState;
+
+import org.apache.pluto.driver.config.DriverConfiguration;
+
+/**
+ * <code>PortalContext</code> implementation for the Pluto Portal Driver.
+ */
+public class PortalContextImpl implements PortalContext {
+   
+
+    /**
+     * The <code>DriverConfigurationImpl</code> from which this
+     * <code>PortalContext</code> recieves it's configuration information.
+     */
+    private DriverConfiguration config;
+
+    /**
+     * Portal information.
+     */
+    private String info = null;
+
+    /**
+     * Portal Properties
+     */
+    private HashMap<String, String> properties = new HashMap<String, String>();
+
+    /**
+     * Supported PortletModes.
+     */
+    private Vector<PortletMode> portletModes;
+
+    /**
+     * Supported WindowStates.
+     */
+    private Vector<WindowState> windowStates;
+
+
+    /**
+     * Default Constructor.
+     * @param config
+     */
+    public PortalContextImpl(DriverConfiguration config) {
+        this.config = config;
+        reset();
+
+        // we now support render headers
+        properties.put(PortalContext.MARKUP_HEAD_ELEMENT_SUPPORT, "true");
+    }
+
+    /**
+     * Get a dynamic portal property.
+     * @param name
+     * @return the property value associated with the given key.
+     * @throws IllegalArgumentException if the specified name is null.
+     */
+    public String getProperty(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Property name == null");
+        }
+
+        return (String) properties.get(name);
+    }
+
+
+    /**
+     * Get an enumeration containing all names of the portal properties.
+     * @return an enumeration of all keys to which properties are bound.
+     */
+    public Enumeration<String> getPropertyNames() {
+        Vector<String> names = new Vector<String>(properties.keySet());
+        return names.elements();
+    }
+
+
+    /**
+     * Get an enumeration of all <code>PortletMode</code>s supported by this
+     * portal.
+     * @return enumeration of all supported portlet modes.
+     */
+    public Enumeration<PortletMode> getSupportedPortletModes() {
+        if (portletModes == null) {
+            portletModes = new Vector<PortletMode>();
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            Enumeration enumeration = new Vector(config.getSupportedPortletModes()).elements();
+            while (enumeration.hasMoreElements()) {
+                portletModes.add(
+                    new PortletMode(enumeration.nextElement().toString()));
+            }
+        }
+        return portletModes.elements();
+    }
+
+    /**
+     * Get an enumeration of all <code>WindowState</code>s supported by this
+     * portal.
+     * @return an enumeration of all supported window states.
+     */
+    public Enumeration<WindowState> getSupportedWindowStates() {
+        if (windowStates == null) {
+            windowStates = new Vector<WindowState>();
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            Enumeration enumeration = new Vector(config.getSupportedWindowStates()).elements();
+            while (enumeration.hasMoreElements()) {
+                windowStates.add(
+                    new WindowState(enumeration.nextElement().toString()));
+            }
+        }
+        return windowStates.elements();
+    }
+
+    /**
+     * Get the portal info for this portal.
+     * @return the portal information for this context.
+     */
+    public String getPortalInfo() {
+        if(info == null) {
+            info = config.getPortalName() + "/" + config.getPortalVersion();
+        }
+        return info;
+    }
+
+
+    // additional methods.
+    // methods used container internally to set
+
+    public void setProperty(String name, String value) {
+        if (name == null) {
+            throw new IllegalArgumentException("Property name == null");
+        }
+
+        properties.put(name, value);
+    }
+
+
+    /**
+     * reset all values to default portlet modes and window states; delete all
+     * properties and set the given portlet information as portlet info string.
+     */
+    public void reset() {
+        info = null;
+        properties.clear();
+    }
+
+    public DriverConfiguration getDriverConfiguration() {
+        return config;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletActionResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletActionResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletActionResponseContextImpl.java
index a8b545a..51773f5 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletActionResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletActionResponseContextImpl.java
@@ -1,100 +1,102 @@
-/*
- * 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.UnsupportedEncodingException;
-import java.net.URLEncoder;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.pluto.container.PortletActionResponseContext;
-import org.apache.pluto.container.PortletContainer;
-import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.driver.core.PortalRequestContext;
-import org.apache.pluto.driver.url.PortalURL;
-
-/**
- * @version $Id$
- *
- */
-public class PortletActionResponseContextImpl extends PortletStateAwareResponseContextImpl implements
-                PortletActionResponseContext
-{
-    private boolean redirect;
-    private String redirectLocation;
-    private String renderURLParamName;
-    
-    public PortletActionResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                            HttpServletResponse containerResponse, PortletWindow window)
-    {
-        super(container, containerRequest, containerResponse, window);
-    }
-
-    public String getResponseURL()
-    {
-        if (!isReleased())
-        {
-            close();
-            if (!redirect || renderURLParamName != null)
-            {
-                PortalURL url = PortalRequestContext.getContext(getServletRequest()).createPortalURL();
-                if (redirect)
-                {
-                    try
-                    {
-                        return redirectLocation + "?" + URLEncoder.encode(renderURLParamName, "UTF-8") + "=" + URLEncoder.encode(url.toURL(true), "UTF-8");
-                    }
-                    catch (UnsupportedEncodingException e)
-                    {
-                        // Cannot happen: UTF-8 is a buildin/required encoder
-                        return null;
-                    }
-                }
-                else
-                {
-                    return url.toURL(false);
-                }
-            }
-            else
-            {
-                return redirectLocation;
-            }
-        }
-        return null;
-    }
-
-    public boolean isRedirect()
-    {
-        return redirect;
-    }
-
-    public void setRedirect(String location)
-    {
-        setRedirect(location, null);
-    }
-
-    public void setRedirect(String location, String renderURLParamName)
-    {
-        if (!isClosed())
-        {
-            this.redirectLocation = location;
-            this.renderURLParamName = renderURLParamName;
-            this.redirect = true;
-        }
-    }
-}
+/*
+ * 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.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import javax.portlet.PortletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.container.PortletActionResponseContext;
+import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.driver.core.PortalRequestContext;
+import org.apache.pluto.driver.url.PortalURL;
+
+/**
+ * @version $Id$
+ *
+ */
+public class PortletActionResponseContextImpl extends PortletStateAwareResponseContextImpl implements
+                PortletActionResponseContext
+{
+    private boolean redirect;
+    private String redirectLocation;
+    private String renderURLParamName;
+    
+    public PortletActionResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+                                            HttpServletResponse containerResponse, PortletWindow window)
+    {
+        super(container, containerRequest, containerResponse, window);
+        setLifecycle(PortletRequest.ACTION_PHASE);
+    }
+
+    public String getResponseURL()
+    {
+        if (!isReleased())
+        {
+            close();
+            if (!redirect || renderURLParamName != null)
+            {
+                PortalURL url = PortalRequestContext.getContext(getServletRequest()).createPortalURL();
+                if (redirect)
+                {
+                    try
+                    {
+                        return redirectLocation + "?" + URLEncoder.encode(renderURLParamName, "UTF-8") + "=" + URLEncoder.encode(url.toURL(true), "UTF-8");
+                    }
+                    catch (UnsupportedEncodingException e)
+                    {
+                        // Cannot happen: UTF-8 is a buildin/required encoder
+                        return null;
+                    }
+                }
+                else
+                {
+                    return url.toURL(false);
+                }
+            }
+            else
+            {
+                return redirectLocation;
+            }
+        }
+        return null;
+    }
+
+    public boolean isRedirect()
+    {
+        return redirect;
+    }
+
+    public void setRedirect(String location)
+    {
+        setRedirect(location, null);
+    }
+
+    public void setRedirect(String location, String renderURLParamName)
+    {
+        if (!isClosed())
+        {
+            this.redirectLocation = location;
+            this.renderURLParamName = renderURLParamName;
+            this.redirect = true;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletEventResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletEventResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletEventResponseContextImpl.java
index 9546578..d717aa8 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletEventResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletEventResponseContextImpl.java
@@ -1,39 +1,41 @@
-/*
- * 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.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.pluto.container.PortletContainer;
-import org.apache.pluto.container.PortletEventResponseContext;
-import org.apache.pluto.container.PortletWindow;
-
-/**
- * @version $Id$
- *
- */
-public class PortletEventResponseContextImpl extends PortletStateAwareResponseContextImpl implements
-                PortletEventResponseContext
-{
-
-    public PortletEventResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                           HttpServletResponse containerResponse, PortletWindow window)
-    {
-        super(container, containerRequest, containerResponse, window);
-    }
-}
+/*
+ * 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.portlet.PortletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletEventResponseContext;
+import org.apache.pluto.container.PortletWindow;
+
+/**
+ * @version $Id$
+ *
+ */
+public class PortletEventResponseContextImpl extends PortletStateAwareResponseContextImpl implements
+                PortletEventResponseContext
+{
+
+    public PortletEventResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+                                           HttpServletResponse containerResponse, PortletWindow window)
+    {
+        super(container, containerRequest, containerResponse, window);
+        setLifecycle(PortletRequest.EVENT_PHASE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletHeaderResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletHeaderResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletHeaderResponseContextImpl.java
index 5825be5..e74b824 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletHeaderResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletHeaderResponseContextImpl.java
@@ -19,6 +19,7 @@ package org.apache.pluto.driver.services.container;
 import java.util.Collection;
 
 import javax.portlet.PortletMode;
+import javax.portlet.PortletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -38,6 +39,7 @@ public class PortletHeaderResponseContextImpl extends PortletMimeResponseContext
                                             HttpServletResponse containerResponse, PortletWindow window)
     {
         super(container, containerRequest, containerResponse, window);
+        setLifecycle(PortletRequest.HEADER_PHASE);
     }
 
     public void setNextPossiblePortletModes(Collection<PortletMode> portletModes)

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRenderResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRenderResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRenderResponseContextImpl.java
index 5191783..02bfd20 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRenderResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletRenderResponseContextImpl.java
@@ -1,55 +1,57 @@
-/*
- * 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.util.Collection;
-
-import javax.portlet.PortletMode;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.pluto.container.PortletContainer;
-import org.apache.pluto.container.PortletRenderResponseContext;
-import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.driver.AttributeKeys;
-
-/**
- * @version $Id$
- *
- */
-public class PortletRenderResponseContextImpl extends PortletMimeResponseContextImpl implements
-                PortletRenderResponseContext
-{
-    public PortletRenderResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                            HttpServletResponse containerResponse, PortletWindow window)
-    {
-        super(container, containerRequest, containerResponse, window);
-    }
-
-    public void setNextPossiblePortletModes(Collection<PortletMode> portletModes)
-    {
-        // not supported
-    }
-
-    public void setTitle(String title)
-    {
-        if (!isClosed())
-        {
-            getServletRequest().setAttribute(AttributeKeys.PORTLET_TITLE, title);
-        }
-    }
-}
+/*
+ * 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.util.Collection;
+
+import javax.portlet.PortletMode;
+import javax.portlet.PortletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletRenderResponseContext;
+import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.driver.AttributeKeys;
+
+/**
+ * @version $Id$
+ *
+ */
+public class PortletRenderResponseContextImpl extends PortletMimeResponseContextImpl implements
+                PortletRenderResponseContext
+{
+    public PortletRenderResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+                                            HttpServletResponse containerResponse, PortletWindow window)
+    {
+        super(container, containerRequest, containerResponse, window);
+        setLifecycle(PortletRequest.RENDER_PHASE);
+    }
+
+    public void setNextPossiblePortletModes(Collection<PortletMode> portletModes)
+    {
+        // not supported
+    }
+
+    public void setTitle(String title)
+    {
+        if (!isClosed())
+        {
+            getServletRequest().setAttribute(AttributeKeys.PORTLET_TITLE, title);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/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 2d2eb23..694b955 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
@@ -62,8 +62,9 @@ public class PortletRequestContextImpl implements PortletRequestContext {
    private PortletConfig       portletConfig;
    private ServletContext      servletContext;
    private Cookie              cookies[];
+   private String              renderHeaders = null;      
    
-   // make sure thethese classes are loaded first by the container classloader
+   // make sure these classes are loaded first by the container classloader
    // so that the logs from these classes land in the Pluto log file.
    static {
       PortletURLProviderImpl.load();
@@ -95,6 +96,16 @@ public class PortletRequestContextImpl implements PortletRequestContext {
       this.paramFactory = url.getPortletParameterFactory();
    }
 
+   @Override
+   public String getRenderHeaders() {
+      return renderHeaders;
+   }
+
+   @Override
+   public void setRenderHeaders(String renderHeaders) {
+      this.renderHeaders = renderHeaders;
+   }
+
    protected boolean isReservedAttributeName(String name) {
       return name.startsWith("javax.servlet.");
    }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceResponseContextImpl.java
index e098316..94818ed 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceResponseContextImpl.java
@@ -18,6 +18,7 @@ package org.apache.pluto.driver.services.container;
 
 import java.util.Locale;
 
+import javax.portlet.PortletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -42,6 +43,7 @@ public class PortletResourceResponseContextImpl extends PortletMimeResponseConte
                                               HttpServletResponse containerResponse, PortletWindow window)
     {        
         super(container, containerRequest, containerResponse, window);
+        setLifecycle(PortletRequest.RESOURCE_PHASE);
     }
 
     public void setCharacterEncoding(String charset)

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResponseContextImpl.java
index 7093bcf..491a539 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResponseContextImpl.java
@@ -16,164 +16,257 @@
  */
 package org.apache.pluto.driver.services.container;
 
+import static javax.portlet.PortletRequest.HEADER_PHASE;
+import static javax.portlet.PortletRequest.RENDER_PHASE;
+
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Set;
+
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 
+import org.apache.pluto.container.HeaderData;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.PortletURLProvider;
+import org.apache.pluto.container.PortletURLProvider.TYPE;
 import org.apache.pluto.container.PortletWindow;
 import org.apache.pluto.container.ResourceURLProvider;
-import org.apache.pluto.container.PortletURLProvider.TYPE;
 import org.apache.pluto.driver.core.PortalRequestContext;
 import org.apache.pluto.driver.url.PortalURL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
 /**
  * @version $Id$
- *
+ * 
  */
-public abstract class PortletResponseContextImpl implements PortletResponseContext
-{
-    private PortletContainer container;
-    private HttpServletRequest containerRequest;
-    private HttpServletResponse containerResponse;
-    private HttpServletRequest servletRequest;
-    private HttpServletResponse servletResponse;
-    private PortletWindow window;
-    private PortalURL portalURL;
-    private boolean closed;
-    private boolean released;
-    
-    public PortletResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                      HttpServletResponse containerResponse, PortletWindow window)
-    {
-        this.container = container;
-        this.containerRequest = containerRequest;
-        this.containerResponse = containerResponse;
-        this.window = window;
-        this.portalURL = PortalRequestContext.getContext(containerRequest).createPortalURL();
-    }
-    
-    protected PortalURL getPortalURL()
-    {
-        return portalURL;
-    }
-
-    protected boolean isClosed()
-    {
-        return closed;
-    }
-    
-    protected boolean isReleased()
-    {
-        return released;
-    }
-
-    public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
-    {
-        this.servletRequest = servletRequest;
-        this.servletResponse = servletResponse;
-    }
-    
-    public void addProperty(Cookie cookie)
-    {
-        if (!isClosed())
-        {
-            servletResponse.addCookie(cookie);
-        }
-    }
-
-    public void addProperty(String key, Element element)
-    {
-        // not supported 
-    }
-
-    public void addProperty(String key, String value)
-    {
-        // not supported
-    }
-    
-    public Element createElement(String tagName) throws DOMException
-    {
-        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
-        DocumentBuilder docBuilder;
-        
-        try
-        {
-            docBuilder = dbfac.newDocumentBuilder();
-            Document doc = docBuilder.newDocument();
-            return doc.createElement(tagName);
-        }
-        catch (ParserConfigurationException e)
-        {
-            throw new DOMException((short) 0, "Initialization failure");
-        }
-    }
-
-    public void close()
-    {
-        closed = true;
-    }
-
-    public PortletContainer getContainer()
-    {
-        return container;
-    }
-
-    public PortletWindow getPortletWindow()
-    {
-        return window;
-    }
-
-    public HttpServletRequest getContainerRequest()
-    {
-        return containerRequest;
-    }
-
-    public HttpServletResponse getContainerResponse()
-    {
-        return containerResponse;
-    }
-
-    public HttpServletRequest getServletRequest()
-    {
-        return servletRequest;
-    }
-
-    public HttpServletResponse getServletResponse()
-    {
-        return servletResponse;
-    }
-
-    public void release()
-    {
-        closed = true;
-        released = true;
-        container = null;
-        servletRequest = null;
-        servletResponse = null;
-        window = null;
-    }
-
-    public void setProperty(String key, String value)
-    {
-        // not supported
-    }
-
-    public ResourceURLProvider getResourceURLProvider()
-    {
-        return isReleased() ? null : new ResourceURLProviderImpl(servletRequest,window);
-    }
-
-    public PortletURLProvider getPortletURLProvider(TYPE type)
-    {
-        return isClosed() ? null : new PortletURLProviderImpl(getPortalURL(), type, getPortletWindow());
-    }
+public abstract class PortletResponseContextImpl implements PortletResponseContext {
+
+   /** Logger. */
+   private static final Logger      LOG               = LoggerFactory.getLogger(PortletResponseContextImpl.class);
+   private static final boolean     isDebug           = LOG.isDebugEnabled();
+
+   private PortletContainer         container;
+   private HttpServletRequest       containerRequest;
+   private HttpServletResponse      containerResponse;
+   private HttpServletRequest       servletRequest;
+   private HttpServletResponse      servletResponse;
+   private PortletWindow            window;
+   private PortalURL                portalURL;
+   private boolean                  closed;
+   private boolean                  released;
+
+   // needed for processing of properties based on request type
+   private String                   lifecycle;
+   private boolean                  isSetPropsAllowed = false;
+
+   private Document                 doc               = null;
+   private Element                  root              = null;
+   private static final String      ROOT_ELEMENT      = "rootElement";
+   private static final Set<String> allowedTags       = new HashSet<String>();
+   static {
+      allowedTags.add("META");
+      allowedTags.add("LINK");
+      allowedTags.add("STYLE");
+      allowedTags.add("SCRIPT");
+      allowedTags.add("NOSCRIPT");
+   }
+   
+   // holder for the header data
+   protected HeaderData headerData = new HeaderData();
+
+   public PortletResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+         HttpServletResponse containerResponse, PortletWindow window) {
+      this.container = container;
+      this.containerRequest = containerRequest;
+      this.containerResponse = containerResponse;
+      this.window = window;
+      this.portalURL = PortalRequestContext.getContext(containerRequest).createPortalURL();
+   }
+
+   public String getLifecycle() {
+      return lifecycle;
+   }
+
+   public void setLifecycle(String lifecycle) {
+      this.lifecycle = lifecycle;
+   }
+
+   public boolean isSetPropsAllowed() {
+      return isSetPropsAllowed;
+   }
+
+   public void setPropsAllowed(boolean isSetPropsAllowed) {
+      this.isSetPropsAllowed = isSetPropsAllowed;
+   }
+   
+   /**
+    * returns the header data provided by the portlet during header phase execution.
+    */
+   @Override
+   public HeaderData getHeaderData() {
+      headerData.setHeadSectionMarkup(getTags());
+      return headerData;
+   }
+
+   /**
+    * returns a string containing any tags that should go into the document head section.
+    * 
+    * @return String containing the tags, or the empty string if no tags are available.
+    */
+   private String getTags() {
+      String tags = "";
+      if (doc != null) {
+         DOMSource src = new DOMSource(doc);
+         StringWriter sw = new StringWriter();
+         StreamResult res = new StreamResult(sw);
+         try {
+
+            Transformer trans = TransformerFactory.newInstance().newTransformer();
+            trans.setOutputProperty(OutputKeys.INDENT, "yes");
+            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            trans.setOutputProperty(OutputKeys.METHOD, "html");
+
+            trans.transform(src, res);
+
+            String regex = "(?:\\s*)</{0,1}" + ROOT_ELEMENT + ">(?:\\s*)";
+            tags = sw.toString().replaceAll(regex, "");
+
+         } catch (Exception e) {
+            StringBuilder txt = new StringBuilder();
+            txt.append("Error converting tags to string. Exception: ");
+            txt.append(e.toString());
+            LOG.warn(txt.toString());
+         }
+      }
+
+      if (isDebug) {
+         StringBuilder sb = new StringBuilder();
+         sb.append("returning tags: ");
+         sb.append((tags.length()>0) ? "\n" + tags : "");
+         LOG.debug(sb.toString());
+      }
+
+      return tags;
+   }
+
+   protected PortalURL getPortalURL() {
+      return portalURL;
+   }
+
+   protected boolean isClosed() {
+      return closed;
+   }
+
+   protected boolean isReleased() {
+      return released;
+   }
+
+   public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
+      this.servletRequest = servletRequest;
+      this.servletResponse = servletResponse;
+   }
+
+   public void addProperty(Cookie cookie) {
+      if (!isClosed()) {
+         servletResponse.addCookie(cookie);
+      }
+   }
+
+   /**
+    * saves elements for adding to the head section markup if header request or render request
+    */
+   public void addProperty(String key, Element element) {
+      if (!isClosed() && isSetPropsAllowed && element != null && root != null) {
+         if (lifecycle.equals(RENDER_PHASE) || lifecycle.equals(HEADER_PHASE)) {
+            String tag = element.getTagName().toUpperCase();
+            if (allowedTags.contains(tag)) {
+               root.appendChild(element);
+            }
+         }
+      }
+   }
+
+   public void addProperty(String key, String value) {
+      // not supported
+   }
+
+   public Element createElement(String tagName) throws DOMException {
+
+      try {
+         if (doc == null) {
+            DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
+            DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
+            doc = docBuilder.newDocument();
+            root = doc.createElement(ROOT_ELEMENT);
+            doc.appendChild(root);
+         }
+         return doc.createElement(tagName);
+      } catch (ParserConfigurationException e) {
+         throw new DOMException((short) 0, "Initialization failure");
+      }
+   }
+
+   public void close() {
+      closed = true;
+   }
+
+   public PortletContainer getContainer() {
+      return container;
+   }
+
+   public PortletWindow getPortletWindow() {
+      return window;
+   }
+
+   public HttpServletRequest getContainerRequest() {
+      return containerRequest;
+   }
+
+   public HttpServletResponse getContainerResponse() {
+      return containerResponse;
+   }
+
+   public HttpServletRequest getServletRequest() {
+      return servletRequest;
+   }
+
+   public HttpServletResponse getServletResponse() {
+      return servletResponse;
+   }
+
+   public void release() {
+      closed = true;
+      released = true;
+      container = null;
+      servletRequest = null;
+      servletResponse = null;
+      window = null;
+   }
+
+   public void setProperty(String key, String value) {
+      // not supported
+   }
+
+   public ResourceURLProvider getResourceURLProvider() {
+      return isReleased() ? null : new ResourceURLProviderImpl(servletRequest, window);
+   }
+
+   public PortletURLProvider getPortletURLProvider(TYPE type) {
+      return isClosed() ? null : new PortletURLProviderImpl(getPortalURL(), type, getPortletWindow());
+   }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/AttributeKeys.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/AttributeKeys.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/AttributeKeys.java
index bf3c4f7..bf11239 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/AttributeKeys.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/AttributeKeys.java
@@ -1,64 +1,70 @@
-/*
- * 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;
-
-/**
- * Constants used as attribute keys to bind values to servlet context or servlet
- * request.
- *
- * @version 1.0
- * @since Sep 25, 2004
- */
-public class AttributeKeys {
-
-    /**
-     * Attribute Key used to bind the application's driver config to the
-     * ServletContext.
-     */
-    public static final String DRIVER_CONFIG = "driverConfig";
-
-    /**
-     * Attribute Key used to bind the application's driver admin config
-     * to the ServletContext.
-     */
-    public static final String DRIVER_ADMIN_CONFIG = "driverAdminConfig";
-
-    /**
-     * Attribute Key used to bind the application's portlet container to the
-     * ServletContext.
-     */
-    public static final String PORTLET_CONTAINER = "portletContainer";
-
-    /** Attribute key used to bind the current page to servlet request. */
-    public static final String CURRENT_PAGE = "currentPage";
-
-    /** Attribute key used to bind the portlet title to servlet request. */
-    public static final String PORTLET_TITLE =
-    		"org.apache.pluto.driver.DynamicPortletTitle";
-
-    public static final String PORTAL_URL_PARSER = "PORTAL_URL_PARSER";
-
-    // Constructor -------------------------------------------------------------
-
-    /**
-     * Private constructor that prevents external instantiation.
-     */
-    private AttributeKeys() {
-
-    }
-}
-
+/*
+ * 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;
+
+/**
+ * Constants used as attribute keys to bind values to servlet context or servlet
+ * request.
+ *
+ * @version 1.0
+ * @since Sep 25, 2004
+ */
+public class AttributeKeys {
+
+    /**
+     * Attribute Key used to bind the application's driver config to the
+     * ServletContext.
+     */
+    public static final String DRIVER_CONFIG = "driverConfig";
+
+    /**
+     * Attribute Key used to bind the application's driver admin config
+     * to the ServletContext.
+     */
+    public static final String DRIVER_ADMIN_CONFIG = "driverAdminConfig";
+
+    /**
+     * Attribute Key used to bind the application's portlet container to the
+     * ServletContext.
+     */
+    public static final String PORTLET_CONTAINER = "portletContainer";
+
+    /** Attribute key used to bind the current page to servlet request. */
+    public static final String CURRENT_PAGE = "currentPage";
+
+    /** Attribute key used to bind the portlet title to servlet request. */
+    public static final String PORTLET_TITLE =
+    		"org.apache.pluto.driver.DynamicPortletTitle";
+
+    public static final String PORTAL_URL_PARSER = "PORTAL_URL_PARSER";
+    
+    /**
+     * For passing the head section markup collected from the portlets 
+     * to the aggregation JSP.
+     */
+    public static final String HEAD_SECTION_MARKUP = "headMarkup";
+
+    // Constructor -------------------------------------------------------------
+
+    /**
+     * Private constructor that prevents external instantiation.
+     */
+    private AttributeKeys() {
+
+    }
+}
+