Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/StandaloneChannelRenderer.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/StandaloneChannelRenderer.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/StandaloneChannelRenderer.java	(working copy)
@@ -120,7 +120,7 @@
         }
 
         // start rendering
-        IChannelRenderer cr = cChannelRendererFactory.newInstance( this, rd );
+        IChannelRenderer cr = cChannelRendererFactory.newInstance( this, rd, pcs );
         cr.setTimeout (timeOut);
         cr.startRendering ();
 
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/servlet/AttributeScopingRequestWrapper.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/servlet/AttributeScopingRequestWrapper.java	(revision 0)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/servlet/AttributeScopingRequestWrapper.java	(revision 0)
@@ -0,0 +1,484 @@
+/* Copyright 2007 The JA-SIG Collaborative.  All rights reserved.
+*  See license distributed with this file and
+*  available online at http://www.uportal.org/license.html
+*/
+
+package org.jasig.portal.servlet;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.collections.iterators.IteratorEnumeration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * HttpServletRequest wrapper that tracks a set of request attributes that are local to
+ * this request wrapper.
+ * 
+ * @author Eric Dalquist
+ * @version $Id: AttributeScopingRequestWrapper.java,v 1.1 2006/04/25 22:15:26 dalquist Exp $
+ */
+public class AttributeScopingRequestWrapper implements HttpServletRequest {
+    private static final Log LOG = LogFactory.getLog(AttributeScopingRequestWrapper.class);
+
+    private final Map scopedAttributes = new Hashtable();
+    private final HttpServletRequest delegate;
+
+    public AttributeScopingRequestWrapper(HttpServletRequest request) {
+        if (request == null) {
+            throw new IllegalArgumentException("Wrapped request can no be null.");
+        }
+
+        this.delegate = request;
+    }
+
+    /**
+     * Provides access to the attributes stored in this wrapper.
+     * @return A READ-ONLY Map of the attributes stored in this wrapper.
+     */
+    public Map getScopedAttributeMap() {
+        return Collections.unmodifiableMap(this.scopedAttributes);
+    }
+
+    //*********************************************
+    // Over-ridden methods to scope attributes.
+    //*********************************************
+
+    /**
+     * If the attribute isn't in the Map for this wrapper the wrapped request is
+     * consulted.
+     * 
+     * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
+     */
+    public Object getAttribute(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Attribute name cannot be null");
+        }
+
+        Object value = this.scopedAttributes.get(name);
+        if (value != null) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("getAttribute(" + name + ") - from scoped Map with value='" + value + "'");
+            }
+        }
+        else {
+            value = this.delegate.getAttribute(name);
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("getAttribute(" + name + ") - from parent request with value='" + value + "'");
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * The set of attribute names is merged from the attributes stored in this request and the
+     * attributes from the parent requests.
+     * 
+     * @see javax.servlet.ServletRequest#getAttributeNames()
+     */
+    public Enumeration getAttributeNames() {
+        final Set namesSet = new HashSet();
+
+        for (final Enumeration parentNames = this.delegate.getAttributeNames(); parentNames.hasMoreElements();) {
+            namesSet.add(parentNames.nextElement());
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("getAttributeNames() - parent request attribute names=" + namesSet + "");
+        }
+
+        namesSet.addAll(this.scopedAttributes.keySet());
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("getAttributeNames() - all attribute names=" + namesSet + "");
+        }
+
+        return new IteratorEnumeration(namesSet.iterator());
+    }
+
+    /**
+     * Removes the attribute from this request and the wrapped request.
+     * 
+     * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
+     */
+    public void removeAttribute(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Attribute name cannot be null");
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("removeAttribute(" + name + ")");
+        }
+
+        this.scopedAttributes.remove(name);
+        this.delegate.removeAttribute(name);
+    }
+
+    /**
+     * Stores the attribute in the request wrapper.
+     * 
+     * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
+     */
+    public void setAttribute(String name, Object value) {
+        if (name == null) {
+            throw new IllegalArgumentException("Attribute name cannot be null");
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("setAttribute(" + name + ", " + value + ")");
+        }
+
+        if (value == null) {
+            this.scopedAttributes.remove(name);
+        }
+        else {
+            this.scopedAttributes.put(name, value);
+        }
+    }
+
+    //*********************************************
+    // Delegating methods
+    //*********************************************
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getAuthType()
+     */
+    public String getAuthType() {
+        return this.delegate.getAuthType();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getCharacterEncoding()
+     */
+    public String getCharacterEncoding() {
+        return this.delegate.getCharacterEncoding();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getContentLength()
+     */
+    public int getContentLength() {
+        return this.delegate.getContentLength();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getContentType()
+     */
+    public String getContentType() {
+        return this.delegate.getContentType();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getContextPath()
+     */
+    public String getContextPath() {
+        return this.delegate.getContextPath();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getCookies()
+     */
+    public Cookie[] getCookies() {
+        return this.delegate.getCookies();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
+     */
+    public long getDateHeader(String arg0) {
+        return this.delegate.getDateHeader(arg0);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
+     */
+    public String getHeader(String arg0) {
+        return this.delegate.getHeader(arg0);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
+     */
+    public Enumeration getHeaderNames() {
+        return this.delegate.getHeaderNames();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
+     */
+    public Enumeration getHeaders(String arg0) {
+        return this.delegate.getHeaders(arg0);
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getInputStream()
+     */
+    public ServletInputStream getInputStream() throws IOException {
+        return this.delegate.getInputStream();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
+     */
+    public int getIntHeader(String arg0) {
+        return this.delegate.getIntHeader(arg0);
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getLocale()
+     */
+    public Locale getLocale() {
+        return this.delegate.getLocale();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getLocales()
+     */
+    public Enumeration getLocales() {
+        return this.delegate.getLocales();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getMethod()
+     */
+    public String getMethod() {
+        return this.delegate.getMethod();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
+     */
+    public String getParameter(String arg0) {
+        return this.delegate.getParameter(arg0);
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getParameterMap()
+     */
+    public Map getParameterMap() {
+        return this.delegate.getParameterMap();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getParameterNames()
+     */
+    public Enumeration getParameterNames() {
+        return this.delegate.getParameterNames();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
+     */
+    public String[] getParameterValues(String arg0) {
+        return this.delegate.getParameterValues(arg0);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getPathInfo()
+     */
+    public String getPathInfo() {
+        return this.delegate.getPathInfo();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
+     */
+    public String getPathTranslated() {
+        return this.delegate.getPathTranslated();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getProtocol()
+     */
+    public String getProtocol() {
+        return this.delegate.getProtocol();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getQueryString()
+     */
+    public String getQueryString() {
+        return this.delegate.getQueryString();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getReader()
+     */
+    public BufferedReader getReader() throws IOException {
+        return this.delegate.getReader();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
+     * @deprecated
+     */
+    public String getRealPath(String arg0) {
+        return this.delegate.getRealPath(arg0);
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getRemoteAddr()
+     */
+    public String getRemoteAddr() {
+        return this.delegate.getRemoteAddr();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getRemoteHost()
+     */
+    public String getRemoteHost() {
+        return this.delegate.getRemoteHost();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
+     */
+    public String getRemoteUser() {
+        return this.delegate.getRemoteUser();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
+     */
+    public RequestDispatcher getRequestDispatcher(String arg0) {
+        return this.delegate.getRequestDispatcher(arg0);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
+     */
+    public String getRequestedSessionId() {
+        return this.delegate.getRequestedSessionId();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getRequestURI()
+     */
+    public String getRequestURI() {
+        return this.delegate.getRequestURI();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getRequestURL()
+     */
+    public StringBuffer getRequestURL() {
+        return this.delegate.getRequestURL();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getScheme()
+     */
+    public String getScheme() {
+        return this.delegate.getScheme();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getServerName()
+     */
+    public String getServerName() {
+        return this.delegate.getServerName();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#getServerPort()
+     */
+    public int getServerPort() {
+        return this.delegate.getServerPort();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getServletPath()
+     */
+    public String getServletPath() {
+        return this.delegate.getServletPath();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getSession()
+     */
+    public HttpSession getSession() {
+        return this.delegate.getSession();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
+     */
+    public HttpSession getSession(boolean arg0) {
+        return this.delegate.getSession(arg0);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
+     */
+    public Principal getUserPrincipal() {
+        return this.delegate.getUserPrincipal();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
+     */
+    public boolean isRequestedSessionIdFromCookie() {
+        return this.delegate.isRequestedSessionIdFromCookie();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
+     * @deprecated
+     */
+    public boolean isRequestedSessionIdFromUrl() {
+        return this.delegate.isRequestedSessionIdFromUrl();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
+     */
+    public boolean isRequestedSessionIdFromURL() {
+        return this.delegate.isRequestedSessionIdFromURL();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
+     */
+    public boolean isRequestedSessionIdValid() {
+        return this.delegate.isRequestedSessionIdValid();
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#isSecure()
+     */
+    public boolean isSecure() {
+        return this.delegate.isSecure();
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
+     */
+    public boolean isUserInRole(String arg0) {
+        return this.delegate.isUserInRole(arg0);
+    }
+
+    /**
+     * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
+     */
+    public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
+        this.delegate.setCharacterEncoding(arg0);
+    }
+}
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRendererFactoryImpl.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRendererFactoryImpl.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRendererFactoryImpl.java	(working copy)
@@ -119,12 +119,14 @@
      **/
     public IChannelRenderer newInstance(
         IChannel channel,
-        ChannelRuntimeData channelRuntimeData
+        ChannelRuntimeData channelRuntimeData,
+        PortalControlStructures pcs
         )
     {
         return new ChannelRenderer(
             channel,
             channelRuntimeData,
+            pcs,
             (null == this.mThreadPool) ? cSharedThreadPool : this.mThreadPool
             );
     }
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/IChannelRendererFactory.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/IChannelRendererFactory.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/IChannelRendererFactory.java	(working copy)
@@ -38,6 +38,7 @@
      **/
     IChannelRenderer newInstance(
         IChannel channel,
-        ChannelRuntimeData channelRuntimeData
+        ChannelRuntimeData channelRuntimeData,
+        PortalControlStructures pcs
         );
 }
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/UserInstance.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/UserInstance.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/UserInstance.java	(working copy)
@@ -285,7 +285,7 @@
                     // (examples of such events are "remove channel", "minimize channel", etc.
                     //  basically things that directly affect the userLayout structure)
                     try {
-                        processUserLayoutParameters(req,channelManager);
+                        processUserLayoutParameters(req,res,channelManager);
                     } catch (PortalException pe) {
                         log.error("UserInstance.renderState(): processUserLayoutParameters() threw an exception - ", pe);
                     }
@@ -714,7 +714,7 @@
      * @param channelManager a <code>ChannelManager</code> value
      * @exception PortalException if an error occurs
      */
-    private synchronized void processUserLayoutParameters (HttpServletRequest req, ChannelManager channelManager) throws PortalException {
+    private synchronized void processUserLayoutParameters (HttpServletRequest req, HttpServletResponse res, ChannelManager channelManager) throws PortalException {
      try {
 
        IUserLayoutManager ulm = uPreferencesManager.getUserLayoutManager();
@@ -743,21 +743,21 @@
         String[] values;
         if ((values = req.getParameterValues("uP_help_target")) != null) {
             for (int i = 0; i < values.length; i++) {
-                channelManager.passPortalEvent(values[i], PortalEvent.HELP_BUTTON);
+                channelManager.passPortalEvent(req, res, values[i], PortalEvent.HELP_BUTTON);
             }
         }
         if ((values = req.getParameterValues("uP_about_target")) != null) {
             for (int i = 0; i < values.length; i++) {
-                channelManager.passPortalEvent(values[i], PortalEvent.ABOUT_BUTTON);
+                channelManager.passPortalEvent(req, res, values[i], PortalEvent.ABOUT_BUTTON);
             }
         }
         if ((values = req.getParameterValues("uP_edit_target")) != null) {
             for (int i = 0; i < values.length; i++) {
-                channelManager.passPortalEvent(values[i], PortalEvent.EDIT_BUTTON);
+                channelManager.passPortalEvent(req, res, values[i], PortalEvent.EDIT_BUTTON);
             }
         }
         if ((values = req.getParameterValues("uP_detach_target")) != null) {
-            channelManager.passPortalEvent(values[0], PortalEvent.DETACH_BUTTON);
+            channelManager.passPortalEvent(req, res, values[0], PortalEvent.DETACH_BUTTON);
         }
 
         if ((values = req.getParameterValues("uP_request_move_targets")) != null) {
@@ -903,7 +903,7 @@
                                 e = PortalEvent.MAXIMIZE;
                             }
 
-                            channelManager.passPortalEvent(aNode[j], e);
+                            channelManager.passPortalEvent(req, res, aNode[j], e);
 
                             if (log.isDebugEnabled())
                                 log.debug("Sending window state event to '" + aName + "' of '" + aNode[j] + "' to '" + aValue + "'.");
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelManager.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelManager.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelManager.java	(working copy)
@@ -75,7 +75,10 @@
     private Map channelCacheTable;
 
     private String channelTarget;
-    private Hashtable targetParams;
+    //Using a ThreadLocal to store the target parameters to allow
+    //multiple threads to be accessing this class in parallel without
+    //overwriting the others parameters.
+    private static ThreadLocal targetParamsLocal = new ThreadLocal();
     private BrowserInfo binfo;
     private LocaleManager lm;
 
@@ -132,11 +135,8 @@
      * @param uPElement an <code>UPFileSpec</code> that includes a tag number.
      */
     public ChannelManager(HttpServletRequest request, HttpServletResponse response, IUserPreferencesManager manager,UPFileSpec uPElement) {
-        this();
-        this.upm=manager;
-        pcs=new PortalControlStructures();
-        pcs.setUserPreferencesManager(upm);
-        pcs.setChannelManager(this);
+        this(manager);
+        
         this.startRenderingCycle(request,response,uPElement);
     }
 
@@ -254,7 +254,11 @@
         }
         rendererTable.clear();
         clearRepeatedRenderings();
-        targetParams=null;
+        targetParamsLocal.set(null);
+        //To ensure the old request and response objects are not used by the next
+        //request clear them at the end of the processing cycle.
+        this.pcs.setHttpServletRequest(null);
+        this.pcs.setHttpServletResponse(null);
         pendingChannels=new HashSet();
         groupedRendering=false;
     }
@@ -751,17 +755,33 @@
      * @param channelSubscribeId the channel subscribe id
      * @param le the portal event
      */
-    public void passPortalEvent(String channelSubscribeId, PortalEvent le) {
+    public void passPortalEvent(HttpServletRequest req, HttpServletResponse res, String channelSubscribeId, PortalEvent le) {
+        //The latest portlet req/res are required in the portal control structures
+        //for events because of portlet adapter requirements regarding
+        //stats collection.
+        pcs.setHttpServletRequest(req);
+        pcs.setHttpServletResponse(res);
+        
         IChannel ch= (IChannel) channelTable.get(channelSubscribeId);
 
         if (ch != null) {
+            //Ensure the channel (if IPrivileged) has the latest control
+            //structures object before recieving the event.
+            if ((ch instanceof IPrivileged)) {
+                try {
+                    ((IPrivileged) ch).setPortalControlStructures(pcs);
+                } catch (Exception e) {
+                    log.warn("ChannelManager::passPortalEvent() :  ChannelManager threw exception while trying to set portalControlStructures", e);
+                }
+            }
+            
             try {
                 ch.receiveEvent(le);
             } catch (Exception e) {
                 log.error("Error sending layout event " + le + " to channel " + ch, e);
             }
         } else {
-            log.error("ChannelManager::passPortalEvent() : trying to pass an event to a channel that is not in cache. (cahnel=\"" + channelSubscribeId + "\")");
+            log.error("ChannelManager::passPortalEvent() : trying to pass an event to a channel that is not in cache. (channel=\"" + channelSubscribeId + "\")");
         }
     }
 
@@ -774,7 +794,7 @@
     private void processRequestChannelParameters(HttpServletRequest req) {
         // clear the previous settings
         channelTarget = null;
-        targetParams = new Hashtable();
+        targetParamsLocal.set(new Hashtable());
 
         // see if this is targeted at an fname channel. if so then it takes
         // precedence. This is done so that a baseActionURL can be used for
@@ -828,6 +848,7 @@
                     // detect if channel target talks to other channels
                     groupedRendering=hasListeningChannels(channelTarget);
                 }
+                Map targetParams = (Map)targetParamsLocal.get();
                 while (en.hasMoreElements()) {
                     String pName= (String) en.nextElement();
                     if (!pName.equals ("uP_channelTarget")&& !pName.equals ("uP_fname")) {
@@ -895,7 +916,7 @@
     private IChannel feedRuntimeDataToChannel(IChannel chObj, HttpServletRequest req) {
         try {
             ChannelRuntimeData rd = new ChannelRuntimeData();
-            rd.setParameters(targetParams);
+            rd.setParameters((Map)targetParamsLocal.get());
             String qs = pcs.getHttpServletRequest().getQueryString();
             if (qs != null && qs.indexOf("=") == -1)
               rd.setKeywords(qs);
@@ -1134,7 +1155,7 @@
             if(!(ch instanceof IPrivileged)) {
                 rd = new ChannelRuntimeData();
                 rd.setTargeted(true);
-                rd.setParameters(targetParams);
+                rd.setParameters((Map)targetParamsLocal.get());
                 String qs = pcs.getHttpServletRequest().getQueryString();
                 if (qs != null && qs.indexOf("=") == -1)
                   rd.setKeywords(qs);
@@ -1163,7 +1184,8 @@
         // Build a new channel renderer instance.
         IChannelRenderer cr = cChannelRendererFactory.newInstance(
             ch,
-            rd
+            rd,
+            pcs
             );
 
         cr.setCharacterCacheable(this.isCharacterCaching());
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/PortalControlStructures.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/PortalControlStructures.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/PortalControlStructures.java	(working copy)
@@ -16,29 +16,46 @@
  * @version $Revision$
  */
 public class PortalControlStructures {
+    //Track the current request and response in a thread local as well
+    //as the member variables. This ensures that the case of multiple
+    //request from a single user rendering at the same time is possible.
+    //The class member variables are still used as a fallback if needed.
+    protected static final ThreadLocal reqLocal = new ThreadLocal();
+    protected static final ThreadLocal resLocal = new ThreadLocal();
+
     protected IUserPreferencesManager ulm;
     protected HttpServletRequest req;
     protected HttpServletResponse res;
     protected ChannelManager cm;
 
     public PortalControlStructures(HttpServletRequest req,HttpServletResponse res, ChannelManager cm, IUserPreferencesManager ulm) {
-        this.req=req;
-        this.res=res;
-        this.cm=cm;
-        this.ulm=ulm;
+        this.setHttpServletRequest(req);
+        this.setHttpServletResponse(res);
+        this.setChannelManager(cm);
+        this.setUserPreferencesManager(ulm);
     }
     
     public PortalControlStructures() {
-        this.req=null;
-        this.res=null;
-        this.cm=null;
-        this.ulm=null;
+        this(null, null, null, null);
     }
         
 
     public IUserPreferencesManager getUserPreferencesManager() { return ulm; }
-    public HttpServletRequest getHttpServletRequest() { return req;}
-    public HttpServletResponse getHttpServletResponse() { return res; }
+    public HttpServletRequest getHttpServletRequest() {
+        final HttpServletRequest localReq = (HttpServletRequest)reqLocal.get();
+        if (localReq != null) {
+            return localReq;
+        }
+        return req;
+    }
+
+    public HttpServletResponse getHttpServletResponse() {
+        final HttpServletResponse localRes = (HttpServletResponse)resLocal.get();
+        if (localRes != null) {
+            return localRes;
+        }
+        return res;
+    }
     public ChannelManager getChannelManager() {return cm; }
 
     /**
@@ -47,13 +64,20 @@
      */
     public HttpSession getHttpSession() {
       HttpSession session = null;
-      if (req != null)
-         session = req.getSession(false);
+      if (this.getHttpServletRequest() != null)
+         session = this.getHttpServletRequest().getSession(false);
       return session;
     }
 
     public void setUserPreferencesManager(IUserPreferencesManager lm) { ulm=lm; }
-    public void setHttpServletRequest(HttpServletRequest r) { req=r; }
-    public void setHttpServletResponse(HttpServletResponse r) { res=r; }
+    public void setHttpServletRequest(HttpServletRequest r) {
+        req = r;
+        reqLocal.set(req);
+    }
+
+    public void setHttpServletResponse(HttpServletResponse r) {
+        res = r;
+        resLocal.set(res);
+    }
     public void setChannelManager(ChannelManager m) { cm=m; }
 }
Index: /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRenderer.java
===================================================================
--- /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRenderer.java	(revision 42434)
+++ /home/edalquist/JavaClasses/workspace_33/uPortal_2.5-patches/source/org/jasig/portal/ChannelRenderer.java	(working copy)
@@ -9,11 +9,15 @@
 import java.io.StringWriter;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.jasig.portal.channels.support.IChannelTitle;
 import org.jasig.portal.channels.support.IDynamicChannelTitleRenderer;
 import org.jasig.portal.properties.PropertiesManager;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.jasig.portal.servlet.AttributeScopingRequestWrapper;
 import org.jasig.portal.utils.SAX2BufferImpl;
 import org.jasig.portal.utils.SetCheckInSemaphore;
 import org.jasig.portal.utils.SoftHashMap;
@@ -53,6 +57,7 @@
     protected ChannelRuntimeData rd;
     protected Map channelCache;
     protected Map cacheTables;
+    protected PortalControlStructures pcs;
 
     protected boolean rendering;
     protected boolean donerendering;
@@ -80,9 +85,10 @@
      * @param runtimeData a <code>ChannelRuntimeData</code> value
      * @param threadPool a <code>ThreadPool</code> value
      */
-    public ChannelRenderer (IChannel chan,ChannelRuntimeData runtimeData, ExecutorService threadPool) {
+    public ChannelRenderer (IChannel chan,ChannelRuntimeData runtimeData, PortalControlStructures pcs, ExecutorService threadPool) {
         this.channel=chan;
         this.rd=runtimeData;
+        this.pcs = pcs;
         this.rendering = false;
         this.ccacheable=false;
         tp = threadPool;
@@ -105,8 +111,8 @@
      * @param groupSemaphore a <code>SetCheckInSemaphore</code> for the current rendering group
      * @param groupRenderingKey an <code>Object</code> to be used for check ins with the group semaphore
      */
-    public ChannelRenderer (IChannel chan,ChannelRuntimeData runtimeData, ExecutorService threadPool, SetCheckInSemaphore groupSemaphore, Object groupRenderingKey) {
-        this(chan,runtimeData,threadPool);
+    public ChannelRenderer (IChannel chan,ChannelRuntimeData runtimeData, PortalControlStructures pcs, ExecutorService threadPool, SetCheckInSemaphore groupSemaphore, Object groupRenderingKey) {
+        this(chan,runtimeData,pcs,threadPool);
         this.groupSemaphore=groupSemaphore;
         this.groupRenderingKey=groupRenderingKey;
     }
@@ -177,7 +183,8 @@
   {
     // start the rendering thread
 
-    this.worker = new Worker (this.channel,this.rd);
+    //Pass the Request/Response for this thread into the worker so it can use them in the pool thread
+    this.worker = new Worker (this.channel,this.rd, this.pcs.getHttpServletRequest(), this.pcs.getHttpServletResponse());
 
     this.workTracker = tp.submit(this.worker); // XXX is execute okay?
     this.rendering = true;
@@ -434,16 +441,23 @@
         private ChannelRuntimeData rd;
         private SAX2BufferImpl buffer;
         private String cbuffer;
+        private HttpServletRequest req;
+        private HttpServletResponse res;
         
         /**
          * The dynamic title of the channel, if any.  Null otherwise.
          */
         private String channelTitle = null;
 
-        public Worker (IChannel ch, ChannelRuntimeData runtimeData) {
+        //Pass the request/response into the worker, this will allow the objects
+        //to be passed into the ThreadLocalized PortalControlStructures when execute()
+        //is called by the worker thread.
+        public Worker (IChannel ch, ChannelRuntimeData runtimeData, HttpServletRequest req, HttpServletResponse res) {
             this.channel=ch;  this.rd=runtimeData;
             successful = false; done = false; setRuntimeDataComplete=false;
             buffer=null; cbuffer=null;
+            this.req = new AttributeScopingRequestWrapper(req);
+            this.res = res;
         }
 
         public void setChannel(IChannel ch) {
@@ -456,6 +470,16 @@
 
         public void execute () throws Exception {
             try {
+                if (pcs != null) {
+                    //Set the request/response for this thread.
+                    pcs.setHttpServletRequest(this.req);
+                    pcs.setHttpServletResponse(this.res);
+
+                    if (channel instanceof IPrivileged) {
+                        ((IPrivileged)channel).setPortalControlStructures(pcs);
+                    }
+                }
+                
                 if(rd!=null) {
                     channel.setRuntimeData(rd);
                 }
@@ -604,6 +628,13 @@
                 }
                 this.setException(e);
             }
+            finally {
+                if (pcs != null) {
+                    //Clear the request/response for this thread
+                    pcs.setHttpServletRequest(null);
+                    pcs.setHttpServletResponse(null);
+                }
+            }
             
             /*
              * Get the channel's ChannelRuntimeProperties, and handle them.
