Index: components/portal/src/java/org/apache/jetspeed/container/invoker/ServletPortletInvoker.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/container/invoker/ServletPortletInvoker.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/container/invoker/ServletPortletInvoker.java (working copy) @@ -16,6 +16,7 @@ package org.apache.jetspeed.container.invoker; import java.io.IOException; +import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; @@ -164,6 +165,24 @@ protected void invoke(PortletRequest portletRequest, PortletResponse portletResponse, Integer methodID) throws PortletException, IOException { + // In case of parallel mode, the portletDefinition member is not thread-safe. + // So, hide the member variable by the following local variable. + PortletDefinition portletDefinition = null; + + // In case of parallel mode, get portlet definition object from the worker thread. + // Otherwise, refer the member variable. + Map workerAsMap = null; + Thread ct = Thread.currentThread(); + if (ct instanceof Map) + { + workerAsMap = (Map) ct; + portletDefinition = (PortletDefinition) workerAsMap.get(PortalReservedParameters.PORTLET_DEFINITION_ATTRIBUTE); + } + else + { + portletDefinition = this.portletDefinition; + } + ClassLoader paClassLoader = portletFactory.getPortletApplicationClassLoader((PortletApplication)portletDefinition.getPortletApplicationDefinition()); MutablePortletApplication app = (MutablePortletApplication)portletDefinition.getPortletApplicationDefinition(); @@ -211,6 +230,18 @@ RequestContext requestContext = (RequestContext)servletRequest.getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE); servletRequest.setAttribute(ContainerConstants.PORTAL_CONTEXT, requestContext.getRequest().getContextPath()); + // Store same request attributes into the worker in parallel mode. + if (workerAsMap != null) + { + workerAsMap.put(ContainerConstants.PORTLET, portletInstance); + workerAsMap.put(ContainerConstants.PORTLET_CONFIG, portletInstance.getConfig()); + workerAsMap.put(ContainerConstants.PORTLET_REQUEST, portletRequest); + workerAsMap.put(ContainerConstants.PORTLET_RESPONSE, portletResponse); + workerAsMap.put(ContainerConstants.METHOD_ID, methodID); + workerAsMap.put(ContainerConstants.PORTLET_NAME, app.getName()+"::"+portletDefinition.getName()); + workerAsMap.put(ContainerConstants.PORTAL_CONTEXT, requestContext.getRequest().getContextPath()); + } + PortletRequestContext.createContext(portletDefinition, portletInstance, portletRequest, portletResponse); dispatcher.include(servletRequest, servletResponse); @@ -225,6 +256,19 @@ finally { PortletRequestContext.clearContext(); + + // In parallel mode, remove attributes of worker. + if (workerAsMap != null) + { + workerAsMap.remove(ContainerConstants.PORTLET); + workerAsMap.remove(ContainerConstants.PORTLET_CONFIG); + workerAsMap.remove(ContainerConstants.PORTLET_REQUEST); + workerAsMap.remove(ContainerConstants.PORTLET_RESPONSE); + workerAsMap.remove(ContainerConstants.METHOD_ID); + workerAsMap.remove(ContainerConstants.PORTLET_NAME); + workerAsMap.remove(ContainerConstants.PORTAL_CONTEXT); + } + servletRequest.removeAttribute(ContainerConstants.PORTLET); servletRequest.removeAttribute(ContainerConstants.PORTLET_CONFIG); servletRequest.removeAttribute(ContainerConstants.PORTLET_REQUEST); Index: components/portal/src/java/org/apache/jetspeed/aggregator/impl/AsyncPageAggregatorImpl.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/aggregator/impl/AsyncPageAggregatorImpl.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/aggregator/impl/AsyncPageAggregatorImpl.java (working copy) @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Iterator; import java.util.List; +import java.util.ArrayList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,6 +28,8 @@ import org.apache.jetspeed.aggregator.FailedToRenderFragmentException; import org.apache.jetspeed.aggregator.PageAggregator; import org.apache.jetspeed.aggregator.PortletRenderer; +import org.apache.jetspeed.aggregator.RenderingJob; +import org.apache.jetspeed.aggregator.PortletContent; import org.apache.jetspeed.container.state.NavigationalState; import org.apache.jetspeed.exception.JetspeedException; import org.apache.jetspeed.om.page.ContentFragment; @@ -93,7 +96,7 @@ } else { - aggregateAndRender(root, context, page, true); + aggregateAndRender(root, context, page, true, null, null); } //dispatcher.include(root); @@ -157,11 +160,22 @@ } } - protected void aggregateAndRender(ContentFragment f, RequestContext context, ContentPage page, boolean isRoot) + protected void aggregateAndRender(ContentFragment f, RequestContext context, ContentPage page, boolean isRoot, + List portletJobs, List layoutFragments) throws FailedToRenderFragmentException { // First Pass, kick off async render threads for all portlets on page - + // Store portlet rendering jobs in the list to wait later. + // Store layout fragment in the list to render later. + if (portletJobs == null) + { + portletJobs = new ArrayList(16); + } + if (layoutFragments == null) + { + layoutFragments = new ArrayList(4); + } + if (f.getContentFragments() != null && f.getContentFragments().size() > 0) { Iterator children = f.getContentFragments().iterator(); @@ -173,30 +187,58 @@ if (child.getType().equals(ContentFragment.PORTLET)) { // kick off render thread - renderer.render(child, context); + // and store the portlet rendering job into the portlet jobs list. + RenderingJob job = renderer.render(child, context); + portletJobs.add(job); } else { // walk thru layout - aggregateAndRender(child, context, page, false); + // and store the layout rendering job into the layout jobs list. + aggregateAndRender(child, context, page, false, portletJobs, layoutFragments); + layoutFragments.add(child); } } } } + // If the fragment is not root, skip the following. + if (!isRoot) + return; - // sync - // TODO: synchronize on completion of all jobs - // not sure where that code went, used to be in here, very odd - try + + // synchronize on completion of all jobs + Iterator it = portletJobs.iterator(); + + try { - // TODO: remove this when I get the monitor/sync in place (again) - // need to dig thru old code in cvs if its still there - Thread.sleep(4000); + while (it.hasNext()) + { + RenderingJob job = (RenderingJob) it.next(); + PortletContent portletContent = job.getPortletContent(); + + if (!portletContent.isComplete()) + { + synchronized (portletContent) + { + portletContent.wait(); + } + } + } } catch (Exception e) - {} + { + log.error("Exception during synchronizing all portlet rendering jobs.", e); + } + // render layout fragments. + it = layoutFragments.iterator(); + while (it.hasNext()) + { + ContentFragment child = (ContentFragment) it.next(); + renderer.renderNow(child, context); + } + // Start the actual rendering process String defaultPortletDecorator = page.getEffectiveDefaultDecorator(ContentFragment.PORTLET); if (log.isDebugEnabled()) @@ -207,15 +249,6 @@ renderer.renderNow(f, context); -// if (strategy == STRATEGY_SEQUENTIAL) -// { -// renderer.renderNow(f, context); -// } -// else -// { -// renderer.render(f, context); -// } - if (f.getDecorator() != null && f.getType().equals(ContentFragment.PORTLET)) { log.debug("decorator=" + f.getDecorator()); @@ -224,8 +257,10 @@ else if (f.getDecorator() == null && f.getType().equals(ContentFragment.PORTLET)) { log.debug("no decorator for defined for portlet fragement," + f.getId() + ". So using page default, " - + defaultPortletDecorator); + + defaultPortletDecorator); contentServer.addStyle(context, defaultPortletDecorator, ContentFragment.PORTLET); } } + + } Index: components/portal/src/java/org/apache/jetspeed/aggregator/impl/PortletRendererImpl.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/aggregator/impl/PortletRendererImpl.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/aggregator/impl/PortletRendererImpl.java (working copy) @@ -15,6 +15,9 @@ */ package org.apache.jetspeed.aggregator.impl; +import java.util.Map; +import java.util.HashMap; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -116,7 +119,7 @@ servletRequest = requestContext.getRequestForWindow(portletWindow); servletResponse = dispatcherCtrl.getResponseForWindow(portletWindow, requestContext); - RenderingJob rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext); + RenderingJob rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext, false); rJob.execute(); } @@ -150,7 +153,7 @@ HttpServletRequest servletRequest = requestContext.getRequestForWindow(portletWindow); HttpServletResponse servletResponse = dispatcherCtrl.getResponseForWindow(portletWindow, requestContext); - RenderingJob rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext); + RenderingJob rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext, false); rJob.execute(); } catch (Exception e) @@ -169,8 +172,9 @@ * @throws UnknownPortletDefinitionException * @throws FailedToRetrievePortletWindow */ - public void render( ContentFragment fragment, RequestContext requestContext ) + public RenderingJob render( ContentFragment fragment, RequestContext requestContext ) { + RenderingJob rJob = null; PortletWindow portletWindow; ContentDispatcherCtrl dispatcherCtrl = getDispatcherCtrl(requestContext, true); @@ -184,7 +188,7 @@ portletWindow = getPortletWindow(fragment); servletRequest = requestContext.getRequestForWindow(portletWindow); servletResponse = dispatcherCtrl.getResponseForWindow(portletWindow, requestContext); - RenderingJob rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext); + rJob = buildRenderingJob(fragment, servletRequest, servletResponse, requestContext, true); workMonitor.process(rJob); } catch (Exception e1) @@ -197,6 +201,7 @@ // ((ContentDispatcherImpl) dispatcherCtrl).notify(oid); } + return rJob; } /** @@ -238,9 +243,10 @@ } protected RenderingJob buildRenderingJob( ContentFragment fragment, HttpServletRequest request, - HttpServletResponse response, RequestContext requestContext ) throws FailedToRetrievePortletWindow, - FailedToRenderFragmentException, PortletEntityNotStoredException + HttpServletResponse response, RequestContext requestContext, boolean isParallel ) + throws FailedToRetrievePortletWindow, FailedToRenderFragmentException, PortletEntityNotStoredException { + RenderingJob rJob = null; ContentDispatcher dispatcher = null; PortletWindow portletWindow = getPortletWindow(fragment); @@ -254,12 +260,35 @@ request.setAttribute(PortalReservedParameters.FRAGMENT_ATTRIBUTE, fragment); request.setAttribute(PortalReservedParameters.CONTENT_DISPATCHER_ATTRIBUTE, dispatcher); request.setAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE, requestContext); - request.setAttribute(PortalReservedParameters.FRAGMENT_ATTRIBUTE, fragment); request.setAttribute(PortalReservedParameters.PATH_ATTRIBUTE, requestContext.getAttribute(PortalReservedParameters.PATH_ATTRIBUTE)); request.setAttribute(PortalReservedParameters.PORTLET_WINDOW_ATTRIBUTE, portletWindow); PortletContent portletContent = dispatcher.getPortletContent(fragment); fragment.setPortletContent(portletContent); - return new RenderingJobImpl(container, portletContent, fragment, request, response, requestContext, portletWindow, statistics); + // In case of parallel mode, store attributes in a map to be refered by worker. + if (isParallel) + { + Map workerAttrs = new HashMap(); + workerAttrs.put(PortalReservedParameters.PAGE_ATTRIBUTE, requestContext.getPage()); + workerAttrs.put(PortalReservedParameters.FRAGMENT_ATTRIBUTE, fragment); + workerAttrs.put(PortalReservedParameters.CONTENT_DISPATCHER_ATTRIBUTE, dispatcher); + workerAttrs.put(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE, requestContext); + workerAttrs.put(PortalReservedParameters.PATH_ATTRIBUTE, requestContext.getAttribute(PortalReservedParameters.PATH_ATTRIBUTE)); + workerAttrs.put(PortalReservedParameters.PORTLET_WINDOW_ATTRIBUTE, portletWindow); + + // the portlet invoker is not thread safe; it stores current portlet definition as a member variable. + // so, store portlet definition as an attribute of worker + workerAttrs.put(PortalReservedParameters.PORTLET_DEFINITION_ATTRIBUTE, + portletWindow.getPortletEntity().getPortletDefinition()); + + rJob = new RenderingJobImpl(container, portletContent, fragment, request, response, requestContext, portletWindow, statistics, workerAttrs); + } + else + { + rJob = new RenderingJobImpl(container, portletContent, fragment, request, response, requestContext, portletWindow, statistics); + } + + + return rJob; } } Index: components/portal/src/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java (working copy) @@ -16,6 +16,8 @@ package org.apache.jetspeed.aggregator.impl; +import java.util.Map; + import javax.portlet.UnavailableException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -31,6 +33,9 @@ import org.apache.jetspeed.statistics.PortalStatistics; import org.apache.pluto.PortletContainer; import org.apache.pluto.om.window.PortletWindow; +import org.apache.pluto.om.portlet.PortletDefinition; +import org.apache.pluto.om.entity.PortletEntity; +import org.apache.jetspeed.components.portletentity.PortletEntityImpl; /** * The RenderingJob is responsible for storing all necessary objets for @@ -56,6 +61,8 @@ protected PortletContent portletContent; protected PortalStatistics statistics; + + protected Map workerAttributes; public RenderingJobImpl(PortletContainer container, PortletContent portletContent, @@ -78,6 +85,20 @@ } + public RenderingJobImpl(PortletContainer container, + PortletContent portletContent, + ContentFragment fragment, + HttpServletRequest request, + HttpServletResponse response, + RequestContext requestContext, + PortletWindow window, + PortalStatistics statistics, + Map workerAttributes) + { + this(container, portletContent, fragment, request, response, requestContext, window, statistics); + this.workerAttributes = workerAttributes; + } + /** * Checks if queue is empty, if not try to empty it by calling * the WorkerMonitor. When done, pause until next scheduled scan. @@ -110,10 +131,41 @@ */ public void execute() { - long start = System.currentTimeMillis(); + long start = System.currentTimeMillis(); + + Map workerAsMap = null; + try { - log.debug("Rendering OID "+this.window.getId()+" "+ this.request +" "+this.response); + log.debug("Rendering OID "+this.window.getId()+" "+ this.request +" "+this.response); + + // if the current thread is worker, then store attribues in that. + if (this.workerAttributes != null) + { + Thread ct = Thread.currentThread(); + if (ct instanceof Map) + { + workerAsMap = (Map) ct; + workerAsMap.putAll(this.workerAttributes); + + // Sometimes, the portlet definition of some portlet entities are replaced. + // I could not find why it happens. + // If the portlet definition of portlet entity is not same as an attribute of worker's, then + // reset the portlet definition of portlet entity. (by Woonsan Ko) + // TODO: Investigate more and find why it happens. + PortletDefinition portletDefinition = + (PortletDefinition) workerAsMap.get(PortalReservedParameters.PORTLET_DEFINITION_ATTRIBUTE); + PortletWindow window = + (PortletWindow) workerAsMap.get(PortalReservedParameters.PORTLET_WINDOW_ATTRIBUTE); + PortletEntityImpl portletEntityImpl = (PortletEntityImpl) window.getPortletEntity(); + PortletDefinition oldPortletDefinition = portletEntityImpl.getPortletDefinition(); + + if (!oldPortletDefinition.getId().equals(portletDefinition.getId())) { + portletEntityImpl.setPortletDefinition(portletDefinition); + } + } + } + this.request.setAttribute(PortalReservedParameters.FRAGMENT_ATTRIBUTE, fragment); this.request.setAttribute(PortalReservedParameters.PAGE_ATTRIBUTE, requestContext.getPage()); this.request.setAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE, requestContext); @@ -137,6 +189,11 @@ } finally { + if (workerAsMap != null) + { + workerAsMap.clear(); + } + portletContent.complete(); if (fragment.getType().equals(ContentFragment.PORTLET)) { @@ -160,4 +217,17 @@ { return window; } -} \ No newline at end of file + + /** + * + *
+ * getPortletContent + *
+ * + * @return The portlet content this job is in charge of rendering + */ + public PortletContent getPortletContent() + { + return portletContent; + } +} Index: components/portal/src/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java (working copy) @@ -16,6 +16,11 @@ package org.apache.jetspeed.aggregator.impl; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.Collection; + import java.security.AccessControlContext; import java.security.PrivilegedAction; @@ -35,7 +40,7 @@ * @author Rapha�l Luta * @version $Id$ */ -public class WorkerImpl extends Thread implements Worker +public class WorkerImpl extends Thread implements Worker, Map { /** Commons logging */ protected final static Log log = LogFactory.getLog(WorkerImpl.class); @@ -56,6 +61,9 @@ /** Monitor for this Worker */ private WorkerMonitor monitor = null; + /** Attributes for this Worker **/ + private Map attributes = null; + public WorkerImpl(WorkerMonitor monitor) { super(); @@ -200,4 +208,81 @@ monitor.release(this); } } + + // map implementations + + public int size() + { + return (null == this.attributes ? 0 : this.attributes.size()); + } + + public boolean isEmpty() + { + return (null == this.attributes ? true : this.attributes.isEmpty()); + } + + public boolean containsKey(Object key) + { + return (null == this.attributes ? false : this.attributes.containsKey(key)); + } + + public boolean containsValue(Object value) + { + return (null == this.attributes ? false : this.attributes.containsValue(value)); + } + + public Object get(Object key) + { + return (null == this.attributes ? null : this.attributes.get(key)); + } + + public Object put(Object key, Object value) + { + if (null == this.attributes) { + this.attributes = new HashMap(); + } + + return this.attributes.put(key, value); + } + + public Object remove(Object key) + { + if (null != this.attributes) { + return this.attributes.remove(key); + } else { + return null; + } + } + + public void putAll(Map t) + { + if (null == this.attributes) { + this.attributes = new HashMap(); + } + + this.attributes.putAll(t); + } + + public void clear() + { + if (null != this.attributes) { + this.attributes.clear(); + } + } + + public Set keySet() + { + return (null == this.attributes ? null : this.attributes.keySet()); + } + + public Collection values() + { + return (null == this.attributes ? null : this.attributes.values()); + } + + public Set entrySet() + { + return (null == this.attributes ? null : this.attributes.entrySet()); + } + } Index: components/portal/src/java/org/apache/jetspeed/request/JetspeedRequestContextComponent.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/request/JetspeedRequestContextComponent.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/request/JetspeedRequestContextComponent.java (working copy) @@ -16,6 +16,7 @@ package org.apache.jetspeed.request; import java.lang.reflect.Constructor; +import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; @@ -114,8 +115,19 @@ public RequestContext getRequestContext() { - RequestContext rc = (RequestContext) tlRequestContext.get(); - + RequestContext rc = null; + + Thread ct = Thread.currentThread(); + if (ct instanceof Map) + { + Map workerAsMap = (Map) ct; + rc = (RequestContext) workerAsMap.get(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE); + } + else + { + rc = (RequestContext) tlRequestContext.get(); + } + if(rc != null) { return rc; Index: components/portal/src/java/org/apache/jetspeed/engine/servlet/ServletRequestImpl.java =================================================================== --- components/portal/src/java/org/apache/jetspeed/engine/servlet/ServletRequestImpl.java (revision 440988) +++ components/portal/src/java/org/apache/jetspeed/engine/servlet/ServletRequestImpl.java (working copy) @@ -207,6 +207,29 @@ */ public Object getAttribute( String name ) { + Object value = null; + + // In parallel mode, first look up from the worker. + + Thread ct = Thread.currentThread(); + + if (ct instanceof Map) + { + Map workerAsMap = (Map) ct; + value = workerAsMap.get(name); + } + + // If no attribute found, then look up from the request + if (null == value) + { + value = getAttributeInternal(name); + } + + return value; + } + + private Object getAttributeInternal( String name ) + { Object value = super.getAttribute(name); if (name.equals(PortletRequest.USER_INFO)) { @@ -347,6 +370,31 @@ */ public void setAttribute( String name, Object value ) { + // In parallel mode, put attribute into worker. + + Thread ct = Thread.currentThread(); + + if (ct instanceof Map) + { + Map workerAsMap = (Map) ct; + + if (null == value) + { + workerAsMap.remove(name); + } + else + { + workerAsMap.put(name, value); + } + } + + // put attribute into request also. + + setAttributeInternal(name, value); + } + + private void setAttributeInternal( String name, Object value ) + { if (name == null) { throw new IllegalArgumentException("Attribute name == null"); Index: jetspeed-api/src/java/org/apache/jetspeed/aggregator/PortletRenderer.java =================================================================== --- jetspeed-api/src/java/org/apache/jetspeed/aggregator/PortletRenderer.java (revision 440988) +++ jetspeed-api/src/java/org/apache/jetspeed/aggregator/PortletRenderer.java (working copy) @@ -54,12 +54,13 @@ * Render the specified Page fragment. * The method returns before rendering is complete, rendered content can be * accessed through the ContentDispatcher + * @return the asynchronous portlet rendering job to synchronize */ - public void render(ContentFragment fragment, RequestContext request); + public RenderingJob render(ContentFragment fragment, RequestContext request); /** * Retrieve the ContentDispatcher for the specified request */ public ContentDispatcher getDispatcher(RequestContext request, boolean isParallel); -} \ No newline at end of file +} Index: jetspeed-api/src/java/org/apache/jetspeed/aggregator/RenderingJob.java =================================================================== --- jetspeed-api/src/java/org/apache/jetspeed/aggregator/RenderingJob.java (revision 440988) +++ jetspeed-api/src/java/org/apache/jetspeed/aggregator/RenderingJob.java (working copy) @@ -16,6 +16,7 @@ package org.apache.jetspeed.aggregator; import org.apache.pluto.om.window.PortletWindow; +import org.apache.jetspeed.aggregator.PortletContent; /** * Worker thread processes jobs and notify its WorkerMonitor when completed. @@ -30,6 +31,8 @@ void execute(); PortletWindow getWindow(); + + PortletContent getPortletContent(); } Index: jetspeed-api/src/java/org/apache/jetspeed/PortalReservedParameters.java =================================================================== --- jetspeed-api/src/java/org/apache/jetspeed/PortalReservedParameters.java (revision 440988) +++ jetspeed-api/src/java/org/apache/jetspeed/PortalReservedParameters.java (working copy) @@ -51,6 +51,7 @@ public static final String PATH_ATTRIBUTE = "org.apache.jetspeed.Path"; public static final String PARAMETER_ALREADY_DECODED_ATTRIBUTE = "org.apache.jetspeed.parameterAlreadyDecoded"; public static final String RESOVLER_CACHE_ATTR = "org.apache.jetspeed.resovler.cache"; + public static final String PORTLET_DEFINITION_ATTRIBUTE = "org.apache.jetspeed.portlet.definition"; public static final String PORTLET_WINDOW_ATTRIBUTE = "org.apache.jetspeed.portlet.window"; public static final String PAGE_THEME_ATTRIBUTE = "org.apache.jetspeed.theme"; /** Index: commons/src/java/org/apache/jetspeed/container/JetspeedContainerServlet.java =================================================================== --- commons/src/java/org/apache/jetspeed/container/JetspeedContainerServlet.java (revision 440988) +++ commons/src/java/org/apache/jetspeed/container/JetspeedContainerServlet.java (working copy) @@ -22,6 +22,7 @@ import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; +import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; @@ -198,18 +199,41 @@ Integer method = ContainerConstants.METHOD_NOOP; Portlet portlet = null; boolean destroyPortlet = false; + Map workerAsMap = null; try { - method = (Integer) request.getAttribute(ContainerConstants.METHOD_ID); + Thread ct = Thread.currentThread(); + if (ct instanceof Map) + { + workerAsMap = (Map) ct; + } + + if (workerAsMap != null) + { + method = (Integer) workerAsMap.get(ContainerConstants.METHOD_ID); + } + else + { + method = (Integer) request.getAttribute(ContainerConstants.METHOD_ID); + } + if (method == ContainerConstants.METHOD_NOOP) { return; } - portlet = (Portlet)request.getAttribute(ContainerConstants.PORTLET); - portletName = (String)request.getAttribute(ContainerConstants.PORTLET_NAME); - request.removeAttribute(ContainerConstants.PORTLET); + if (workerAsMap != null) + { + portlet = (Portlet) workerAsMap.get(ContainerConstants.PORTLET); + portletName = (String) workerAsMap.get(ContainerConstants.PORTLET_NAME); + } + else + { + portlet = (Portlet)request.getAttribute(ContainerConstants.PORTLET); + portletName = (String)request.getAttribute(ContainerConstants.PORTLET_NAME); + request.removeAttribute(ContainerConstants.PORTLET); + } if (method == ContainerConstants.METHOD_ACTION) { @@ -222,8 +246,20 @@ } else if (method == ContainerConstants.METHOD_RENDER) { - RenderRequest renderRequest = (RenderRequest) request.getAttribute(ContainerConstants.PORTLET_REQUEST); - RenderResponse renderResponse = (RenderResponse) request.getAttribute(ContainerConstants.PORTLET_RESPONSE); + RenderRequest renderRequest = null; + RenderResponse renderResponse = null; + + if (workerAsMap != null) + { + renderRequest = (RenderRequest) workerAsMap.get(ContainerConstants.PORTLET_REQUEST); + renderResponse = (RenderResponse) workerAsMap.get(ContainerConstants.PORTLET_RESPONSE); + } + else + { + renderRequest = (RenderRequest) request.getAttribute(ContainerConstants.PORTLET_REQUEST); + renderResponse = (RenderResponse) request.getAttribute(ContainerConstants.PORTLET_RESPONSE); + } + // inject the current request into the renderRequest handler (o.a.j.engine.servlet.ServletRequestImpl) ((HttpServletRequestWrapper)((HttpServletRequestWrapper)renderRequest).getRequest()).setRequest(request);