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:14 UTC

[33/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

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/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 868dc20..ddc6c63 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
@@ -18,8 +18,11 @@ package org.apache.pluto.driver;
 
 import java.io.IOException;
 import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -27,8 +30,12 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 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.om.portlet.ContainerRuntimeOption;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.apache.pluto.driver.config.DriverConfiguration;
 import org.apache.pluto.driver.core.PortalRequestContext;
 import org.apache.pluto.driver.core.PortletWindowImpl;
 import org.apache.pluto.driver.services.portal.PageConfig;
@@ -40,9 +47,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The controller servlet used to drive the Portal Driver. All requests mapped
- * to this servlet will be processed as Portal Requests.
- *
+ * The controller servlet used to drive the Portal Driver. All requests mapped to this servlet will be processed as
+ * Portal Requests.
+ * 
  * @version 1.0
  * @since Sep 22, 2004
  */
@@ -51,8 +58,7 @@ public class PortalDriverServlet extends HttpServlet {
    private static final long   serialVersionUID = 1L;
 
    /** Internal Logger. */
-   private static final Logger LOG              = LoggerFactory
-                                                      .getLogger(PortalDriverServlet.class);
+   private static final Logger LOG              = LoggerFactory.getLogger(PortalDriverServlet.class);
 
    /** The Portal Driver sServlet Context */
    private ServletContext      servletContext   = null;
@@ -72,15 +78,13 @@ public class PortalDriverServlet extends HttpServlet {
    }
 
    /**
-    * Initialize the Portal Driver. This method retrieves the portlet container
-    * instance from the servlet context scope.
+    * Initialize the Portal Driver. This method retrieves the portlet container instance from the servlet context scope.
     * 
     * @see PortletContainer
     */
    public void init() {
       servletContext = getServletContext();
-      container = (PortletContainer) servletContext
-            .getAttribute(AttributeKeys.PORTLET_CONTAINER);
+      container = (PortletContainer) servletContext.getAttribute(AttributeKeys.PORTLET_CONTAINER);
       String charset = getServletConfig().getInitParameter("charset");
       if (charset != null && charset.length() > 0) {
          contentType = "text/html; charset=" + charset;
@@ -100,8 +104,7 @@ public class PortalDriverServlet extends HttpServlet {
     * @throws IOException
     *            if an error occurs writing to the response.
     */
-   public void doGet(HttpServletRequest request, HttpServletResponse response)
-         throws ServletException, IOException {
+   public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       if (LOG.isDebugEnabled()) {
          LOG.debug("Start of PortalDriverServlet.doGet() to process portlet request . . .");
       }
@@ -110,16 +113,14 @@ public class PortalDriverServlet extends HttpServlet {
          response.setContentType(contentType);
       }
 
-      PortalRequestContext portalRequestContext = new PortalRequestContext(
-            getServletContext(), request, response);
+      PortalRequestContext portalRequestContext = new PortalRequestContext(getServletContext(), request, response);
 
       PortalURL portalURL = null;
 
       try {
          portalURL = portalRequestContext.getRequestedPortalURL();
       } catch (Exception ex) {
-         String msg = "Cannot handle request for portal URL. Problem: "
-               + ex.getMessage();
+         String msg = "Cannot handle request for portal URL. Problem: " + ex.getMessage();
          LOG.error(msg, ex);
          throw new ServletException(msg, ex);
       }
@@ -129,60 +130,54 @@ public class PortalDriverServlet extends HttpServlet {
       // Handle Action, Ajax Action, Partial Action, & Resource requests.
       // Render requests handled subsequently.
 
-      if (targetWindow != null && portalURL.getType() != URLType.Render
-            && portalURL.getType() != URLType.Portal) {
+      if (targetWindow != null && portalURL.getType() != URLType.Render && portalURL.getType() != URLType.Portal) {
 
          String reqType = portalURL.getType().toString();
          PortletWindowConfig windowConfig = PortletWindowConfig.fromId(targetWindow);
-         PortletWindowImpl portletWindow = new PortletWindowImpl(container,
-               windowConfig, portalURL);
+         PortletWindowImpl portletWindow = new PortletWindowImpl(container, windowConfig, portalURL);
 
          if (LOG.isDebugEnabled()) {
-            LOG.debug("Processing " + reqType + " request for window: "
-                  + portletWindow.getId().getStringId());
+            LOG.debug("Processing " + reqType + " request for window: " + portletWindow.getId().getStringId());
          }
 
          try {
             PageState ps;
             String jsondata;
             switch (portalURL.getType()) {
-               case Action:
-                  container.doAction(portletWindow, request, response, true);
-                  break;
-               case AjaxAction:
-                  container.doAction(portletWindow, request, response, false);
-                  response.setContentType("application/json");
-                  ps = new PageState(request);
-                  Writer writer = response.getWriter();
-                  jsondata = ps.toJSONString();
-                  LOG.debug("Ajax Action: returning new page state to client: "
-                        + jsondata);
-                  writer.write(jsondata);
-                  break;
-               case PartialAction:
-                  container.doAction(portletWindow, request, response, false);
-
-                  // The page state is made available to the ResourceRequest by
-                  // passing
-                  // it through all layers, which allows for special case
-                  // processing at
-                  // some points.
-
-                  ps = new PageState(request);
-                  jsondata = ps.toJSONString();
-                  if (LOG.isDebugEnabled()) {
-                     LOG.debug("Partial Action: dump page state:\n" + jsondata);
-                  }
-
-                  container.doServeResource(portletWindow, request, response,
-                        jsondata);
-                  break;
-               case Resource:
-                  container.doServeResource(portletWindow, request, response,
-                        null);
-                  break;
-               default:
-                  LOG.warn("Unknown request: " + reqType);
+            case Action:
+               container.doAction(portletWindow, request, response, true);
+               break;
+            case AjaxAction:
+               container.doAction(portletWindow, request, response, false);
+               response.setContentType("application/json");
+               ps = new PageState(request);
+               Writer writer = response.getWriter();
+               jsondata = ps.toJSONString();
+               LOG.debug("Ajax Action: returning new page state to client: " + jsondata);
+               writer.write(jsondata);
+               break;
+            case PartialAction:
+               container.doAction(portletWindow, request, response, false);
+
+               // The page state is made available to the ResourceRequest by
+               // passing
+               // it through all layers, which allows for special case
+               // processing at
+               // some points.
+
+               ps = new PageState(request);
+               jsondata = ps.toJSONString();
+               if (LOG.isDebugEnabled()) {
+                  LOG.debug("Partial Action: dump page state:\n" + jsondata);
+               }
+
+               container.doServeResource(portletWindow, request, response, jsondata);
+               break;
+            case Resource:
+               container.doServeResource(portletWindow, request, response, null);
+               break;
+            default:
+               LOG.warn("Unknown request: " + reqType);
             }
          } catch (PortletContainerException ex) {
             LOG.error(ex.getMessage(), ex);
@@ -214,23 +209,24 @@ public class PortalDriverServlet extends HttpServlet {
 
          request.setAttribute(AttributeKeys.CURRENT_PAGE, pageConfig);
          String uri = (pageConfig.getUri() != null) ? pageConfig.getUri() : DEFAULT_PAGE_URI;
-         
+
          // Execute header request for each portlet on the page
-         
+
          if (LOG.isDebugEnabled()) {
             LOG.debug("Executing header requests for target portlets.");
          }
 
-         doHeaders(request, response, portalURL);
-         
+         String markup = doHeaders(request, response, portalURL);
+         request.setAttribute(AttributeKeys.HEAD_SECTION_MARKUP, markup);
+
          if (LOG.isDebugEnabled()) {
             LOG.debug("Dispatching to: " + uri);
          }
-         
+
          // Dispatch to the JSP that aggregates the page.
          RequestDispatcher dispatcher = request.getRequestDispatcher(uri);
          dispatcher.forward(request, response);
-         
+
          if (LOG.isDebugEnabled()) {
             LOG.debug("Render request processed.\n\n");
          }
@@ -238,8 +234,7 @@ public class PortalDriverServlet extends HttpServlet {
    }
 
    /**
-    * Pass all POST requests to
-    * {@link #doGet(HttpServletRequest, HttpServletResponse)}.
+    * Pass all POST requests to {@link #doGet(HttpServletRequest, HttpServletResponse)}.
     * 
     * @param request
     *           the incoming servlet request.
@@ -250,22 +245,55 @@ public class PortalDriverServlet extends HttpServlet {
     * @throws IOException
     *            if an exception occurs writing to the response.
     */
-   public void doPost(HttpServletRequest request, HttpServletResponse response)
-         throws ServletException, IOException {
+   public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       doGet(request, response);
    }
-   
-   
-   private void doHeaders(HttpServletRequest req, HttpServletResponse resp, PortalURL purl) {
+
+   private String doHeaders(HttpServletRequest req, HttpServletResponse resp, PortalURL purl) throws ServletException,
+         IOException {
+
+      ServletContext sc = req.getServletContext();
+      DriverConfiguration dc = (DriverConfiguration) sc.getAttribute(AttributeKeys.DRIVER_CONFIG);
+      StringBuilder markup = new StringBuilder(128);
       
+
       for (String pid : purl.getPortletIds()) {
-         PortletWindowConfig wcfg = PortletWindowConfig.fromId(pid); 
+
+         PortletWindowConfig wcfg = PortletWindowConfig.fromId(pid);
          PortletWindowImpl pwin = new PortletWindowImpl(container, wcfg, purl);
+         HeaderData hd = null;
+
          try {
-            container.doHeader(pwin, req, resp);
-         } catch (Exception e) {
+            if (purl.isVersion3(pid)) {
+               hd = container.doHeader(pwin, req, resp);
+            } else if (purl.getVersion(pid).equalsIgnoreCase("2.0")) {
+
+               String appName = wcfg.getContextPath();
+               String portletName = PortletWindowConfig.parsePortletName(pid);
+               PortletDefinition pd = dc.getPortletRegistryService().getPortletApplication(appName)
+                     .getPortlet(portletName);
+               ContainerRuntimeOption crt = pd.getContainerRuntimeOption("javax.portlet.renderHeaders");
+               if (crt != null) {
+                  List<String> headers = crt.getValues();
+                  if (headers.size() == 1 && headers.get(0).equalsIgnoreCase("true")) {
+                    hd = container.doRender(pwin, req, resp, PortletRequest.RENDER_HEADERS);
+                  }
+               }
+            }
             
+            if (hd != null) {
+               markup.append(hd.getHeadSectionMarkup()).append("\n");
+            }
+            
+         } catch (PortletContainerException ex) {
+            LOG.error(ex.getMessage(), ex);
+            throw new ServletException(ex);
+         } catch (PortletException ex) {
+            LOG.error(ex.getMessage(), ex);
+            throw new ServletException(ex);
          }
       }
+      
+      return markup.toString();
    }
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletTag.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletTag.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletTag.java
index d465928..6a2d644 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletTag.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletTag.java
@@ -1,231 +1,248 @@
-/*
- * 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.tags;
-
-import java.io.StringWriter;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.portlet.WindowState;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.JspException;
-import javax.servlet.jsp.tagext.BodyTagSupport;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.pluto.container.PortletContainer;
-import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.driver.AttributeKeys;
-import org.apache.pluto.driver.core.PortalRequestContext;
-import org.apache.pluto.driver.core.PortalServletResponse;
-import org.apache.pluto.driver.core.PortletWindowImpl;
-import org.apache.pluto.driver.services.portal.PortletWindowConfig;
-import org.apache.pluto.driver.url.PortalURL;
-import org.apache.pluto.tags.el.ExpressionEvaluatorProxy;
-
-/**
- * The portlet tag is used to render a portlet specified by the portlet ID.
- *
- * @see javax.portlet.Portlet#render(javax.portlet.RenderRequest,javax.portlet.RenderResponse)
- * @see org.apache.pluto.container.PortletContainer#doRender(PortletWindow, HttpServletRequest, HttpServletResponse)
- *
- */
-public class PortletTag extends BodyTagSupport {
-	
-	/** Logger. */
-    private static final Logger LOG = LoggerFactory.getLogger(PortletTag.class);
-    
-    /** Status constant for failed rendering. */
-    public static final int FAILED = 0;
-    
-    /** Status constant for successful rendering. */
-    public static final int SUCCESS = 1;
-    
-    
-    // Private Member Variables ------------------------------------------------
-    
-    /** The portlet ID attribute passed into this tag. */
-    private String portletId;
-
-    /** The evaluated value of the portlet ID attribute. */
-    private String evaluatedPortletId;
-
-    /** The cached portal servlet response holding rendering result. */
-    private PortalServletResponse response;
-
-    /** The cached rendering status: SUCCESS or FAILED. */
-    private int status;
-    
-    /** The cached Throwable instance when fail to render the portlet. */
-    private Throwable throwable;
-
-
-    // Tag Attribute Accessors -------------------------------------------------
-    
-    /**
-     * Returns the portlet ID attribute.
-     * @return the portlet ID attribute.
-     */
-    public String getPortletId() {
-        return portletId;
-    }
-    
-    /**
-     * Sets the portlet ID attribute.
-     * @param portletId  the portlet ID attribute.
-     */
-    public void setPortletId(String portletId) {
-        this.portletId = portletId;
-    }
-    
-    
-    // BodyTagSupport Impl -----------------------------------------------------
-    
-    /**
-     * Method invoked when the start tag is encountered.
-     * @throws JspException  if an error occurs.
-     */
-    public int doStartTag() throws JspException {
-        
-    	// Evaluate portlet ID attribute.
-    	evaluatePortletId();
-        
-    	// Retrieve the portlet window config for the evaluated portlet ID.
-        ServletContext servletContext = pageContext.getServletContext();
-
-        PortletWindowConfig windowConfig =
-            PortletWindowConfig.fromId(evaluatedPortletId);
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Rendering Portlet Window: " + windowConfig);
-        }
-        
-        // Retrieve the current portal URL.
-        PortalRequestContext portalEnv = PortalRequestContext.getContext(
-                (HttpServletRequest) pageContext.getRequest());
-        PortalURL portalURL = portalEnv.getRequestedPortalURL();
-        
-        // Retrieve the portlet container from servlet context.
-        PortletContainer container = (PortletContainer)
-                servletContext.getAttribute(AttributeKeys.PORTLET_CONTAINER);
-        
-        // Create the portlet window to render.
-        PortletWindow window = null;
-
-
-        try {
-        	window = new PortletWindowImpl(container, windowConfig, portalURL);
-        } catch(RuntimeException e) // FIXME: Prose a change to anything else, handle it.
-        {
-      	  if (LOG.isDebugEnabled()) {
-              LOG.debug("The portlet " + windowConfig.getPortletName() + " is not available. Is already deployed?");
-          }
-        }
-
-    	// Create portal servlet response to wrap the original
-    	// HTTP servlet response.
-    	PortalServletResponse portalResponse = new PortalServletResponse(
-                (HttpServletResponse) pageContext.getResponse());
-    	
-    	
-        if(window!=null)
-        {
-        	// Check if someone else is maximized. If yes, don't show content.
-        	Map windowStates = portalURL.getWindowStates();
-        	for (Iterator it = windowStates.keySet().iterator(); it.hasNext(); ) {
-        		String windowId = (String) it.next();
-        		WindowState windowState = (WindowState) windowStates.get(windowId);
-        		if (WindowState.MAXIMIZED.equals(windowState)
-        				&& !window.getId().getStringId().equals(windowId)) {
-        			return SKIP_BODY;
-        		}
-        	}
-
-        
-        }
-        
-        // Render the portlet and cache the response.
-        try {
-            container.doRender(window, (HttpServletRequest)pageContext.getRequest(), portalResponse);
-            response = portalResponse;
-            status = SUCCESS;
-        } catch (Throwable th) {
-            status = FAILED;
-            throwable = th;
-        }
-        
-        // Continue to evaluate the tag body.
-        return EVAL_BODY_INCLUDE;
-    }
-    
-    
-    // Package Methods ---------------------------------------------------------
-    
-    /**
-     * Returns the rendering status.
-     * @return the rendering status.
-     */
-    int getStatus() {
-        return status;
-    }
-    
-    /**
-     * Returns the portal servlet response holding rendering result. 
-     * @return the portal servlet response holding rendering result.
-     */
-    PortalServletResponse getPortalServletResponse() {
-        return response;
-    }
-    
-    /**
-     * Returns the error that has occurred when rendering portlet.
-     * @return the error that has occurred when rendering portlet.
-     */
-    Throwable getThrowable() {
-        return throwable;
-    }
-    
-    /**
-     * Returns the evaluated portlet ID.
-     * @return the evaluated portlet ID.
-     */
-    String getEvaluatedPortletId() {
-        return evaluatedPortletId;
-    }
-
-    
-    
-    // Private Methods ---------------------------------------------------------
-    
-    /**
-     * Evaluates the portlet ID attribute passed into this tag. This method
-     * evaluates the member variable <code>portletId</code> and saves the
-     * evaluated result to <code>evaluatedPortletId</code>
-     * @throws JspException  if an error occurs.
-     */
-    private void evaluatePortletId() throws JspException {
-        ExpressionEvaluatorProxy proxy = ExpressionEvaluatorProxy.getProxy();
-        Object obj = proxy.evaluate(portletId, pageContext);
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Evaluated portletId to: " + obj);
-        }
-        evaluatedPortletId = (String) obj;
-    }
-    
-}
+/*
+ * 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.tags;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.WindowState;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.BodyTagSupport;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.om.portlet.ContainerRuntimeOption;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.apache.pluto.driver.AttributeKeys;
+import org.apache.pluto.driver.config.DriverConfiguration;
+import org.apache.pluto.driver.core.PortalRequestContext;
+import org.apache.pluto.driver.core.PortalServletResponse;
+import org.apache.pluto.driver.core.PortletWindowImpl;
+import org.apache.pluto.driver.services.portal.PortletWindowConfig;
+import org.apache.pluto.driver.url.PortalURL;
+import org.apache.pluto.tags.el.ExpressionEvaluatorProxy;
+
+/**
+ * The portlet tag is used to render a portlet specified by the portlet ID.
+ * 
+ * @see javax.portlet.Portlet#render(javax.portlet.RenderRequest,javax.portlet.RenderResponse)
+ * @see org.apache.pluto.container.PortletContainer#doRender(PortletWindow, HttpServletRequest, HttpServletResponse)
+ * 
+ */
+public class PortletTag extends BodyTagSupport {
+   private static final long     serialVersionUID = 7369029503826395301L;
+
+   /** Logger. */
+   private static final Logger   LOG              = LoggerFactory.getLogger(PortletTag.class);
+
+   /** Status constant for failed rendering. */
+   public static final int       FAILED           = 0;
+
+   /** Status constant for successful rendering. */
+   public static final int       SUCCESS          = 1;
+
+   // Private Member Variables ------------------------------------------------
+
+   /** The portlet ID attribute passed into this tag. */
+   private String                portletId;
+
+   /** The evaluated value of the portlet ID attribute. */
+   private String                evaluatedPortletId;
+
+   /** The cached portal servlet response holding rendering result. */
+   private PortalServletResponse response;
+
+   /** The cached rendering status: SUCCESS or FAILED. */
+   private int                   status;
+
+   /** The cached Throwable instance when fail to render the portlet. */
+   private Throwable             throwable;
+
+   // Tag Attribute Accessors -------------------------------------------------
+
+   /**
+    * Returns the portlet ID attribute.
+    * 
+    * @return the portlet ID attribute.
+    */
+   public String getPortletId() {
+      return portletId;
+   }
+
+   /**
+    * Sets the portlet ID attribute.
+    * 
+    * @param portletId
+    *           the portlet ID attribute.
+    */
+   public void setPortletId(String portletId) {
+      this.portletId = portletId;
+   }
+
+   // BodyTagSupport Impl -----------------------------------------------------
+
+   /**
+    * Method invoked when the start tag is encountered.
+    * 
+    * @throws JspException
+    *            if an error occurs.
+    */
+   public int doStartTag() throws JspException {
+
+      // Evaluate portlet ID attribute.
+      evaluatePortletId();
+
+      // Retrieve the portlet window config for the evaluated portlet ID.
+      ServletContext servletContext = pageContext.getServletContext();
+
+      PortletWindowConfig windowConfig = PortletWindowConfig.fromId(evaluatedPortletId);
+
+      if (LOG.isDebugEnabled()) {
+         LOG.debug("Rendering Portlet Window: " + windowConfig);
+      }
+
+      // Retrieve the current portal URL.
+      PortalRequestContext portalEnv = PortalRequestContext.getContext((HttpServletRequest) pageContext.getRequest());
+      PortalURL portalURL = portalEnv.getRequestedPortalURL();
+
+      // Retrieve the portlet container from servlet context.
+      PortletContainer container = (PortletContainer) servletContext.getAttribute(AttributeKeys.PORTLET_CONTAINER);
+
+      // Create the portlet window to render.
+      PortletWindow window = null;
+
+      try {
+         window = new PortletWindowImpl(container, windowConfig, portalURL);
+      } catch (RuntimeException e) // FIXME: Prose a change to anything else, handle it.
+      {
+         if (LOG.isDebugEnabled()) {
+            LOG.debug("The portlet " + windowConfig.getPortletName() + " is not available. Is already deployed?");
+         }
+      }
+
+      // Create portal servlet response to wrap the original
+      // HTTP servlet response.
+      PortalServletResponse portalResponse = new PortalServletResponse((HttpServletResponse) pageContext.getResponse());
+
+      if (window != null) {
+         // Check if someone else is maximized. If yes, don't show content.
+         Map<String, WindowState> windowStates = portalURL.getWindowStates();
+         for (Iterator<String> it = windowStates.keySet().iterator(); it.hasNext();) {
+            String windowId = (String) it.next();
+            WindowState windowState = (WindowState) windowStates.get(windowId);
+            if (WindowState.MAXIMIZED.equals(windowState) && !window.getId().getStringId().equals(windowId)) {
+               return SKIP_BODY;
+            }
+         }
+
+      }
+
+      // Render the portlet and cache the response.
+      try {
+         String renderHeaders = null;
+         if (portalURL.getVersion(evaluatedPortletId).equalsIgnoreCase("2.0")) {
+
+            DriverConfiguration dc = (DriverConfiguration) servletContext.getAttribute(AttributeKeys.DRIVER_CONFIG);
+            String appName = windowConfig.getContextPath();
+            String portletName = PortletWindowConfig.parsePortletName(evaluatedPortletId);
+            PortletDefinition pd = dc.getPortletRegistryService().getPortletApplication(appName)
+                  .getPortlet(portletName);
+            ContainerRuntimeOption crt = pd.getContainerRuntimeOption("javax.portlet.renderHeaders");
+            if (crt != null) {
+               List<String> headers = crt.getValues();
+               if (headers.size() == 1 && headers.get(0).equalsIgnoreCase("true")) {
+                  renderHeaders = PortletRequest.RENDER_MARKUP;
+               }
+            }
+         }
+
+         container.doRender(window, (HttpServletRequest) pageContext.getRequest(), portalResponse, renderHeaders);
+         response = portalResponse;
+         status = SUCCESS;
+      } catch (Throwable th) {
+         status = FAILED;
+         throwable = th;
+      }
+
+      // Continue to evaluate the tag body.
+      return EVAL_BODY_INCLUDE;
+   }
+
+   // Package Methods ---------------------------------------------------------
+
+   /**
+    * Returns the rendering status.
+    * 
+    * @return the rendering status.
+    */
+   int getStatus() {
+      return status;
+   }
+
+   /**
+    * Returns the portal servlet response holding rendering result.
+    * 
+    * @return the portal servlet response holding rendering result.
+    */
+   PortalServletResponse getPortalServletResponse() {
+      return response;
+   }
+
+   /**
+    * Returns the error that has occurred when rendering portlet.
+    * 
+    * @return the error that has occurred when rendering portlet.
+    */
+   Throwable getThrowable() {
+      return throwable;
+   }
+
+   /**
+    * Returns the evaluated portlet ID.
+    * 
+    * @return the evaluated portlet ID.
+    */
+   String getEvaluatedPortletId() {
+      return evaluatedPortletId;
+   }
+
+   // Private Methods ---------------------------------------------------------
+
+   /**
+    * Evaluates the portlet ID attribute passed into this tag. This method evaluates the member variable
+    * <code>portletId</code> and saves the evaluated result to <code>evaluatedPortletId</code>
+    * 
+    * @throws JspException
+    *            if an error occurs.
+    */
+   private void evaluatePortletId() throws JspException {
+      ExpressionEvaluatorProxy proxy = ExpressionEvaluatorProxy.getProxy();
+      Object obj = proxy.evaluate(portletId, pageContext);
+      if (LOG.isDebugEnabled()) {
+         LOG.debug("Evaluated portletId to: " + obj);
+      }
+      evaluatedPortletId = (String) obj;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/pluto-portal/src/main/webapp/WEB-INF/themes/pluto-default-theme.jsp
----------------------------------------------------------------------
diff --git a/pluto-portal/src/main/webapp/WEB-INF/themes/pluto-default-theme.jsp b/pluto-portal/src/main/webapp/WEB-INF/themes/pluto-default-theme.jsp
index 0c53aba..abb5e20 100644
--- a/pluto-portal/src/main/webapp/WEB-INF/themes/pluto-default-theme.jsp
+++ b/pluto-portal/src/main/webapp/WEB-INF/themes/pluto-default-theme.jsp
@@ -62,6 +62,9 @@ group (the left column) displays portlets with odd IDs, while the second group
     <script type="text/javascript" src="<c:out value="${pageContext.request.contextPath}"/>/pluto.js"></script>
     <script type="text/javascript" src="<c:out value="${pageContext.request.contextPath}"/>/portletHubImpl.js"></script>
     <script type="text/javascript" src="<c:out value="${pageContext.request.contextPath}"/>/portlet.js"></script>
+    
+    <!-- Now include the head section markup provided by the portlet header processing methods -->
+    ${headMarkup}
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/8f9bca1b/portlet-api/src/main/java/javax/portlet/GenericPortlet.java
----------------------------------------------------------------------
diff --git a/portlet-api/src/main/java/javax/portlet/GenericPortlet.java b/portlet-api/src/main/java/javax/portlet/GenericPortlet.java
index 8b9b8c4..79b7ca9 100644
--- a/portlet-api/src/main/java/javax/portlet/GenericPortlet.java
+++ b/portlet-api/src/main/java/javax/portlet/GenericPortlet.java
@@ -72,7 +72,7 @@ import javax.xml.namespace.QName;
  * or class variables and external objects such as files, database connections,
  * and network connections.
  */
-public abstract class GenericPortlet implements Portlet, PortletConfig, EventPortlet, ResourceServingPortlet {
+public abstract class GenericPortlet implements Portlet, PortletConfig, EventPortlet, ResourceServingPortlet, HeaderPortlet {
 
 	private transient PortletConfig config;
 
@@ -211,6 +211,18 @@ public abstract class GenericPortlet implements Portlet, PortletConfig, EventPor
 	}
 
 	/**
+	 * V3 method implementing the headers stage within the render phase. The default
+	 * implementation does nothing.
+	 * <p>
+	 * Version 3 portlets should override this method to set HTTP headers, cookies, and
+	 * to provide markup for the overall document <code>HEAD</code> section.
+	 */
+	@Override
+   public void renderHeaders(HeaderRequest request, HeaderResponse response) throws PortletException, java.io.IOException {
+   }
+
+
+	/**
 	 * The default implementation of this method sets the headers using the
 	 * <code>doHeaders</code> method, sets the title using the
 	 * <code>getTitle</code> method and invokes the <code>doDispatch</code>