You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by wo...@apache.org on 2013/07/16 18:34:02 UTC

svn commit: r1503788 - in /portals/jetspeed-2/portal/trunk: components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/ jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/ jetspeed-commons/src/main/java/org/apache/jetspeed/util/

Author: woonsan
Date: Tue Jul 16 16:34:02 2013
New Revision: 1503788

URL: http://svn.apache.org/r1503788
Log:
JS2-1283: Applying Ate's initial patch to avoid the problem with some additions:

(1) Moved the code retrieving AccessControlContext/Subject from Worker impl class to RenderingJob impl class because a worker thread implementation can be provided by the container (e.g, commonj worker monitor)
  By the way, JSSubject.doAsPrivileged() may involve JSSubject.setSubject() which also needs ServletRequestCleanupService. Therefore, the code calling JSSubject.doAsPrivileged() must be moved to the job implementation class as well.

(2) ServletRequestCleanupService now has #executeNestedRenderJob() method to provide proper thread context initialization/clean up like its #doFilter() method. (Thanks to Ate!)

(3) Contract extraction to be shared with worker monitor implementations (RenderingJob.ACCESS_CONTROL_CONTEXT_WORKER_ATTR)

Modified:
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java
    portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -19,27 +19,26 @@ package org.apache.jetspeed.aggregator.i
 
 import java.security.AccessControlContext;
 import java.security.AccessController;
-import java.util.List;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.Collections;
-import java.util.Map;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jetspeed.aggregator.PortletContent;
 import org.apache.jetspeed.aggregator.RenderingJob;
 import org.apache.jetspeed.aggregator.Worker;
 import org.apache.jetspeed.aggregator.WorkerMonitor;
-import org.apache.jetspeed.aggregator.PortletContent;
-
 import org.apache.jetspeed.container.PortletWindow;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import commonj.work.WorkManager;
 import commonj.work.Work;
+import commonj.work.WorkEvent;
 import commonj.work.WorkItem;
 import commonj.work.WorkListener;
-import commonj.work.WorkEvent;
+import commonj.work.WorkManager;
 
 /**
  * The CommonjWorkerMonitorImpl is responsible for dispatching jobs to workers
@@ -51,45 +50,49 @@ import commonj.work.WorkEvent;
 public class CommonjWorkerMonitorImpl implements WorkerMonitor, WorkListener
 {
 
-    public static final String ACCESS_CONTROL_CONTEXT_WORKER_ATTR = AccessControlContext.class.getName();
+    /**
+     * @deprecated Use {@link RenderingJob#ACCESS_CONTROL_CONTEXT_WORKER_ATTR} instead.
+     */
+    public static final String ACCESS_CONTROL_CONTEXT_WORKER_ATTR = RenderingJob.ACCESS_CONTROL_CONTEXT_WORKER_ATTR;
+
     public static final String COMMONJ_WORK_ITEM_ATTR = WorkItem.class.getName();
     public static final String WORKER_THREAD_ATTR = Worker.class.getName();
-    
+
     /** CommonJ Work Manamger provided by JavaEE container */
     protected WorkManager workManager;
 
     /** If true, invoke interrupt() on the worker thread when the job is timeout. */
     protected boolean interruptOnTimeout = true;
-    
+
     /** Enable rendering job works monitor thread for timeout checking */
     protected boolean jobWorksMonitorEnabled = true;
-    
+
     /** Rendering job works to be monitored for timeout checking */
     protected Map<WorkItem,RenderingJobCommonjWork> jobWorksMonitored = Collections.synchronizedMap(new HashMap<WorkItem,RenderingJobCommonjWork>());
-    
+
     public CommonjWorkerMonitorImpl(WorkManager workManager)
     {
         this(workManager, true);
     }
-    
+
     public CommonjWorkerMonitorImpl(WorkManager workManager, boolean jobWorksMonitorEnabled)
     {
         this(workManager, jobWorksMonitorEnabled, true);
     }
-    
+
     public CommonjWorkerMonitorImpl(WorkManager workManager, boolean jobWorksMonitorEnabled, boolean interruptOnTimeout)
     {
         this.workManager = workManager;
         this.jobWorksMonitorEnabled = jobWorksMonitorEnabled;
         this.interruptOnTimeout = interruptOnTimeout;
     }
-    
+
     /** Commons logging */
     protected final static Logger log = LoggerFactory.getLogger(CommonjWorkerMonitorImpl.class);
-    
+
     /** Renering Job Timeout monitor */
     protected CommonjWorkerRenderingJobTimeoutMonitor jobMonitor = null;
-    
+
     public void start()
     {
         if (this.jobWorksMonitorEnabled)
@@ -108,7 +111,7 @@ public class CommonjWorkerMonitorImpl im
 
         jobMonitor = null;
     }
-    
+
     /**
      * Assign a job to a worker and execute it or queue the job if no
      * worker is available.
@@ -118,14 +121,14 @@ public class CommonjWorkerMonitorImpl im
     public void process(RenderingJob job)
     {
         AccessControlContext context = AccessController.getContext();
-        job.setWorkerAttribute(ACCESS_CONTROL_CONTEXT_WORKER_ATTR, context);
-        
+        job.setWorkerAttribute(RenderingJob.ACCESS_CONTROL_CONTEXT_WORKER_ATTR, context);
+
         try
         {
             RenderingJobCommonjWork jobWork = new RenderingJobCommonjWork(job);
             WorkItem workItem = this.workManager.schedule(jobWork, this);
             job.setWorkerAttribute(COMMONJ_WORK_ITEM_ATTR, workItem);
-            
+
             if (this.jobWorksMonitorEnabled)
             {
                 this.jobWorksMonitored.put(workItem, jobWork);
@@ -141,24 +144,24 @@ public class CommonjWorkerMonitorImpl im
     {
         return 0;
     }
-    
+
     /**
-     * Wait for all rendering jobs in the collection to finish successfully or otherwise. 
+     * Wait for all rendering jobs in the collection to finish successfully or otherwise.
      * @param renderingJobs the Collection of rendering job objects to wait for.
      */
     public void waitForRenderingJobs(List<RenderingJob> renderingJobs)
     {
         if (this.jobWorksMonitorEnabled)
         {
-            try 
+            try
             {
                 for (RenderingJob job : renderingJobs)
                 {
                     PortletContent portletContent = job.getPortletContent();
-                    
-                    synchronized (portletContent) 
+
+                    synchronized (portletContent)
                     {
-                        if (!portletContent.isComplete()) 
+                        if (!portletContent.isComplete())
                         {
                             portletContent.wait();
                         }
@@ -174,14 +177,14 @@ public class CommonjWorkerMonitorImpl im
         {
             // We cannot use WorkingManager#waitForAll(workitems, timeout_ms) for timeout.
             // The second argument could be either WorkManager.IMMEDIATE or WorkManager.INDEFINITE.
-            
+
             try
             {
                 if (!renderingJobs.isEmpty())
                 {
                     Object lock = new Object();
                     MonitoringJobCommonjWork monitoringWork = new MonitoringJobCommonjWork(lock, renderingJobs);
-                    
+
                     synchronized (lock)
                     {
                         this.workManager.schedule(monitoringWork, this);
@@ -195,7 +198,7 @@ public class CommonjWorkerMonitorImpl im
             }
         }
     }
-    
+
     /**
      * Returns a snapshot of the available jobs
      * @return available jobs
@@ -204,14 +207,14 @@ public class CommonjWorkerMonitorImpl im
     {
         return 0;
     }
-    
+
     public int getRunningJobsCount()
     {
         return 0;
     }
-    
+
     // commonj.work.WorkListener implementations
-    
+
     public void workAccepted(WorkEvent we)
     {
         WorkItem workItem = we.getWorkItem();
@@ -228,7 +231,7 @@ public class CommonjWorkerMonitorImpl im
         {
             log.debug("[CommonjWorkMonitorImpl] workRejected: " + workItem);
         }
-        
+
         if (this.jobWorksMonitorEnabled)
         {
             removeMonitoredJobWork(workItem);
@@ -251,18 +254,18 @@ public class CommonjWorkerMonitorImpl im
         {
             log.debug("[CommonjWorkMonitorImpl] workCompleted: " + workItem);
         }
-        
+
         if (this.jobWorksMonitorEnabled)
         {
             removeMonitoredJobWork(workItem);
         }
     }
-    
+
     protected Object removeMonitoredJobWork(WorkItem workItem)
     {
         return this.jobWorksMonitored.remove(workItem);
     }
-    
+
     class RenderingJobCommonjWork implements Work
     {
 
@@ -277,21 +280,21 @@ public class CommonjWorkerMonitorImpl im
         {
             return false;
         }
-        
+
         public void run()
         {
             if (jobWorksMonitorEnabled || interruptOnTimeout)
             {
                 this.job.setWorkerAttribute(WORKER_THREAD_ATTR, Thread.currentThread());
             }
-            
+
             this.job.run();
         }
-        
+
         public void release()
         {
         }
-        
+
         public RenderingJob getRenderingJob()
         {
             return this.job;
@@ -300,7 +303,7 @@ public class CommonjWorkerMonitorImpl im
 
     class MonitoringJobCommonjWork implements Work
     {
-        
+
         protected Object lock;
         protected List<RenderingJob> renderingJobs;
 
@@ -309,12 +312,12 @@ public class CommonjWorkerMonitorImpl im
             this.lock = lock;
             this.renderingJobs = new ArrayList<RenderingJob>(jobs);
         }
-        
+
         public boolean isDaemon()
         {
             return false;
         }
-        
+
         public void run()
         {
             try
@@ -326,22 +329,22 @@ public class CommonjWorkerMonitorImpl im
                         RenderingJob job = it.next();
                         WorkItem workItem = (WorkItem) job.getWorkerAttribute(COMMONJ_WORK_ITEM_ATTR);
                         int status = WorkEvent.WORK_ACCEPTED;
-                        
+
                         if (workItem != null)
                         {
                             status = workItem.getStatus();
                         }
-                        
+
                         boolean isTimeout = job.isTimeout();
-                        
+
                         if (isTimeout)
                         {
                             PortletContent content = job.getPortletContent();
-                            
+
                             if (interruptOnTimeout)
                             {
                                 Thread worker = (Thread) job.getWorkerAttribute(WORKER_THREAD_ATTR);
-                                
+
                                 if (worker != null)
                                 {
                                     synchronized (content)
@@ -362,13 +365,13 @@ public class CommonjWorkerMonitorImpl im
                                 }
                             }
                         }
-                        
+
                         if (status == WorkEvent.WORK_COMPLETED || status == WorkEvent.WORK_REJECTED || isTimeout)
                         {
                             it.remove();
-                        }                    
+                        }
                     }
-                    
+
                     if (!this.renderingJobs.isEmpty())
                     {
                         synchronized (this)
@@ -377,7 +380,7 @@ public class CommonjWorkerMonitorImpl im
                         }
                     }
                 }
-                
+
                 synchronized (this.lock)
                 {
                     this.lock.notify();
@@ -388,31 +391,31 @@ public class CommonjWorkerMonitorImpl im
                 log.error("Exceptiong during job timeout monitoring.", e);
             }
         }
-        
+
         public void release()
         {
         }
-        
+
     }
 
     class CommonjWorkerRenderingJobTimeoutMonitor extends Thread {
 
         long interval = 1000;
         boolean shouldRun = true;
-        
-        CommonjWorkerRenderingJobTimeoutMonitor(long interval) 
+
+        CommonjWorkerRenderingJobTimeoutMonitor(long interval)
         {
             super("CommonjWorkerRenderingJobTimeoutMonitor");
             setDaemon(true);
 
-            if (interval > 0) 
+            if (interval > 0)
             {
                 this.interval = interval;
             }
         }
         /**
          * Thread.stop() is deprecated.
-         * This method achieves the same by setting the run varaible "shouldRun" to false and interrupting the Thread, 
+         * This method achieves the same by setting the run varaible "shouldRun" to false and interrupting the Thread,
          * effectively causing the thread to shutdown correctly.
          *
          */
@@ -421,25 +424,25 @@ public class CommonjWorkerMonitorImpl im
         	shouldRun = false;
         	this.interrupt();
         }
-        
+
         public void run()
         {
             while (shouldRun)
             {
-                try 
+                try
                 {
                     List<RenderingJobCommonjWork> timeoutJobWorks = new ArrayList<RenderingJobCommonjWork>();
-                    
+
                     for (RenderingJobCommonjWork jobWork : jobWorksMonitored.values() )
                     {
                         RenderingJob job = jobWork.getRenderingJob();
-                        
+
                         if (job.isTimeout())
                         {
                             timeoutJobWorks.add(jobWork);
                         }
                     }
-                    
+
                     // Now, we can kill the timeout worker(s).
                     for (RenderingJobCommonjWork jobWork : timeoutJobWorks )
                     {
@@ -451,30 +454,30 @@ public class CommonjWorkerMonitorImpl im
                             killJobWork(jobWork);
                         }
                     }
-                } 
-                catch (Exception e) 
+                }
+                catch (Exception e)
                 {
                     log.error("Exception during job monitoring.", e);
                 }
-               
-                try 
+
+                try
                 {
-                    synchronized (this) 
+                    synchronized (this)
                     {
                         wait(this.interval);
                     }
-                } 
-                catch (InterruptedException e) 
+                }
+                catch (InterruptedException e)
                 {
                     ;
                 }
             }
         }
-        
+
         public void killJobWork(RenderingJobCommonjWork jobWork)
         {
             RenderingJob job = jobWork.getRenderingJob();
-            
+
             try
             {
                 if (log.isWarnEnabled())
@@ -485,7 +488,7 @@ public class CommonjWorkerMonitorImpl im
 
                 PortletContent content = job.getPortletContent();
                 Thread worker = (Thread) job.getWorkerAttribute(WORKER_THREAD_ATTR);
-                
+
                 if (worker != null)
                 {
                     synchronized (content)
@@ -497,15 +500,15 @@ public class CommonjWorkerMonitorImpl im
                         }
                     }
                 }
-            } 
+            }
             catch (Exception e)
             {
                 log.error("Exceptiong during job killing.", e);
-            } 
-            finally 
+            }
+            finally
             {
                 WorkItem workItem = (WorkItem) job.getWorkerAttribute(COMMONJ_WORK_ITEM_ATTR);
-                
+
                 if (workItem != null)
                 {
                     removeMonitoredJobWork(workItem);

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -17,27 +17,32 @@
 
 package org.apache.jetspeed.aggregator.impl;
 
-import java.util.Map;
-import java.util.HashMap;
+import java.security.AccessControlContext;
+import java.security.PrivilegedAction;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.portlet.UnavailableException;
+import javax.security.auth.Subject;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.jetspeed.aggregator.PortletContent;
 import org.apache.jetspeed.aggregator.PortletRenderer;
 import org.apache.jetspeed.aggregator.PortletTrackingManager;
 import org.apache.jetspeed.aggregator.RenderingJob;
+import org.apache.jetspeed.container.PortletWindow;
 import org.apache.jetspeed.om.page.ContentFragment;
 import org.apache.jetspeed.om.page.Fragment;
+import org.apache.jetspeed.om.portlet.PortletDefinition;
 import org.apache.jetspeed.request.RequestContext;
+import org.apache.jetspeed.security.JSSubject;
 import org.apache.jetspeed.statistics.PortalStatistics;
+import org.apache.jetspeed.util.ServletRequestCleanupService;
 import org.apache.pluto.container.PortletContainer;
-import org.apache.jetspeed.om.portlet.PortletDefinition;
-import org.apache.jetspeed.container.PortletWindow;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The RenderingJob is responsible for storing all necessary objets for
@@ -58,7 +63,7 @@ public class RenderingJobImpl implements
     protected PortletWindow window = null;
     protected HttpServletRequest request = null;
     protected HttpServletResponse response = null;
-    
+
     protected PortletContainer container = null;
     protected PortletRenderer renderer = null;
     protected RequestContext requestContext = null;
@@ -66,38 +71,38 @@ public class RenderingJobImpl implements
 
     protected PortletDefinition portletDefinition;
     protected PortalStatistics statistics;
-    
+
     protected int expirationCache = 0;
-    
+
     protected Map<String, Object> workerAttributes;
 
     protected boolean parallel;
 
     protected long startTimeMillis = 0;
     protected long timeout;
-    
+
     public RenderingJobImpl(PortletContainer container,
                             PortletRenderer renderer,
                             PortletDefinition portletDefinition,
-                            HttpServletRequest request, 
-                            HttpServletResponse response, 
-                            RequestContext requestContext, 
+                            HttpServletRequest request,
+                            HttpServletResponse response,
+                            RequestContext requestContext,
                             PortletWindow window,
                             PortalStatistics statistics,
                             int expirationCache)
     {
         this.container = container;
         this.renderer = renderer;
-        this.portletTracking = renderer.getPortletTrackingManager();        
+        this.portletTracking = renderer.getPortletTrackingManager();
         this.statistics = statistics;
         this.portletDefinition = portletDefinition;
         this.request = request;
         this.response = response;
-        this.requestContext = requestContext; 
+        this.requestContext = requestContext;
         this.window = window;
         this.expirationCache = expirationCache;
     }
-    
+
     public PortletRenderer getRenderer()
     {
         return renderer;
@@ -132,20 +137,21 @@ public class RenderingJobImpl implements
     }
 
     /**
-     * Checks if queue is empty, if not try to empty it by calling
-     * the WorkerMonitor. When done, pause until next scheduled scan.
+     * Job execution entry point method.
      */
     public void run()
-    {      
+    {
         parallel = true;
         boolean clearContext = requestContext.ensureThreadContext();
+
         try
         {
-            if (this.timeout > 0) 
+            if (this.timeout > 0)
             {
                 this.startTimeMillis = System.currentTimeMillis();
             }
-            execute();                     
+
+            ServletRequestCleanupService.executeNestedRenderJob(this);
         }
         finally
         {
@@ -153,34 +159,90 @@ public class RenderingJobImpl implements
             {
                 requestContext.clearThreadContext();
             }
+
             parallel = false;
+
             synchronized (window.getFragment().getPortletContent())
             {
-               if (log.isDebugEnabled()) log.debug("Notifying completion of rendering job for portlet window " + this.window.getId());                
+               if (log.isDebugEnabled())
+               {
+                   log.debug("Notifying completion of rendering job for portlet window " + this.window.getId());
+               }
+
                window.getFragment().getPortletContent().notifyAll();
             }
         }
     }
-    
+
     /**
-     * <p>
-     * execute
-     * </p>
-     *
-     * 
+     * The rendering job execution method.
+     * This method tries to find the underlying access control context, and execute it as a privileged action if found.
+     * This method is invoked back by {@link ServletRequestCleanupService} which is called in the {@link #run()} call.
      */
     public void execute()
     {
+        // We should try to retrieve the subject in context when this job is executed in a worker thread.
+        // If it is being executed in the normal http request processing thread, not in a separate worker thread,
+        // then we don't have to find the subject in context and run it with the context.
+        Subject subject = null;
+
+        // The ACCESS_CONTROL_CONTEXT_WORKER_ATTR attribute is available only when this job is executed in a worker thread.
+        AccessControlContext context = (AccessControlContext) getWorkerAttribute(ACCESS_CONTROL_CONTEXT_WORKER_ATTR);
+
+        if (context != null)
+        {
+            subject = JSSubject.getSubject(context);
+        }
+
+        // If a subject found from the the ACCESS_CONTROL_CONTEXT_WORKER_ATTR attribute from the worker executing job.
+        if (subject != null)
+        {
+            JSSubject.doAsPrivileged(subject, new PrivilegedAction<Object>()
+                {
+                    public Object run()
+                    {
+                        try
+                        {
+                            executeInternal();
+                        }
+                        catch (Throwable t)
+                        {
+                            log.error("Job execution error", t);
+                        }
+                        return null;
+                    }
+                }, context);
+        }
+        // Otherwise, just execute it without doing a privileged action.
+        else
+        {
+            try
+            {
+                executeInternal();
+            }
+            catch (Throwable t)
+            {
+                log.error("Job execution error", t);
+            }
+        }
+
+    }
+
+    /**
+     * The internal rendering job execution method called by {@link #execute()}.
+     */
+    private void executeInternal()
+    {
         long start = System.currentTimeMillis();
         ContentFragment fragment = this.window.getFragment();
-        
+
         try
         {
             if (log.isDebugEnabled())
             {
                 log.debug("Rendering OID "+this.window.getId()+" "+ this.request +" "+this.response);
             }
-            container.doRender(this.window, this.request, this.response);               
+            container.doRender(this.window, this.request, this.response);
         }
         catch (Throwable t)
         {
@@ -203,7 +265,7 @@ public class RenderingJobImpl implements
                 {
                     long end = System.currentTimeMillis();
                     boolean exceededTimeout = portletTracking.exceededTimeout(end - start, window);
-                    
+
                     if (statistics != null)
                     {
                         statistics.logPortletAccess(requestContext, fragment.getName(), PortalStatistics.HTTP_OK, end - start);
@@ -233,9 +295,9 @@ public class RenderingJobImpl implements
             }
         }
     }
- 
+
     /**
-     * 
+     *
      * <p>
      * getWindow
      * </p>
@@ -248,7 +310,7 @@ public class RenderingJobImpl implements
     }
 
     /**
-     * 
+     *
      * <p>
      * getPortletContent
      * </p>
@@ -296,7 +358,7 @@ public class RenderingJobImpl implements
         {
             this.workerAttributes = Collections.synchronizedMap(new HashMap<String, Object>());
         }
-        
+
         if (value != null)
         {
             this.workerAttributes.put(name, value);
@@ -306,19 +368,19 @@ public class RenderingJobImpl implements
             this.workerAttributes.remove(name);
         }
     }
-    
+
     public Object getWorkerAttribute(String name)
     {
         Object value = null;
-        
+
         if (this.workerAttributes != null)
         {
             value = this.workerAttributes.get(name);
         }
-        
+
         return value;
     }
-    
+
     public void removeWorkerAttribute(String name)
     {
         if (this.workerAttributes != null)

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -18,16 +18,12 @@
 package org.apache.jetspeed.aggregator.impl;
 
 import java.security.AccessControlContext;
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.jetspeed.aggregator.RenderingJob;
 import org.apache.jetspeed.aggregator.Worker;
 import org.apache.jetspeed.aggregator.WorkerMonitor;
-import org.apache.jetspeed.security.JSSubject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Worker thread processes jobs and notify its WorkerMonitor when completed.
@@ -53,7 +49,11 @@ public class WorkerImpl extends Thread i
     /** Job to process */
     Runnable job = null;
 
-    /** Context to process job within */
+    /**
+     * Context to process job within
+     *
+     * @deprecated AccessControlContext must not be directly accessed by a worker thread.
+     */
     private AccessControlContext context = null;
 
     /** Monitor for this Worker */
@@ -109,6 +109,11 @@ public class WorkerImpl extends Thread i
 
     /**
      * Sets the job to execute in security context
+     *
+     * @deprecated Use only {@link #setJob(Runnable)} because AccessControlContext must not be directly accessed by
+     * a worker thread. Instead AccessControlContext must be accessed directly by the job implementation in order
+     * to use the AccessControlContext instance safely regardless of the physical worker thread implementation
+     * (e.g, WorkerImpl or container managed thread by commonj worker monitor).
      */
     public void setJob(Runnable job, AccessControlContext context)
     {
@@ -162,39 +167,14 @@ public class WorkerImpl extends Thread i
             if (this.job != null)
             {
                 log.debug("Processing job for window :" + ((RenderingJob)job).getWindow().getId());
-                Subject subject = null;
-                if (this.context != null)
+
+                try
                 {
-                    subject = JSSubject.getSubject(this.context);
+                    this.job.run();
                 }
-                if (subject != null)
+                catch (Throwable t)
                 {
-                    JSSubject.doAsPrivileged(subject, new PrivilegedAction<Object>()
-                        {
-                            public Object run()
-                            {
-                                try 
-                                {
-                                    WorkerImpl.this.job.run();
-                                }
-                                catch (Throwable t)
-                                {                        
-                                    log.error("Thread error", t);
-                                }
-                                return null;                    
-                            }
-                        }, this.context);
-                }
-                else
-                {
-                    try
-                    {
-                        this.job.run();
-                    }
-                    catch (Throwable t)
-                    {
-                        log.error("Thread error", t);
-                    }
+                    log.error("Thread error", t);
                 }
             }
 
@@ -210,5 +190,5 @@ public class WorkerImpl extends Thread i
     	this.running = false;
     	super.interrupt();
     }
-    
+
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -20,21 +20,20 @@ package org.apache.jetspeed.aggregator.i
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Stack;
-import java.util.LinkedList;
-import java.util.Collections;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jetspeed.aggregator.PortletContent;
 import org.apache.jetspeed.aggregator.RenderingJob;
 import org.apache.jetspeed.aggregator.WorkerMonitor;
-import org.apache.jetspeed.aggregator.PortletContent;
-import org.apache.jetspeed.util.Queue;
-import org.apache.jetspeed.util.FIFOQueue;
-
 import org.apache.jetspeed.container.PortletWindow;
 import org.apache.jetspeed.container.PortletWindowID;
+import org.apache.jetspeed.util.FIFOQueue;
+import org.apache.jetspeed.util.Queue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The WorkerMonitor is responsible for dispatching jobs to workers
@@ -49,7 +48,10 @@ import org.apache.jetspeed.container.Por
  */
 public class WorkerMonitorImpl implements WorkerMonitor
 {
-    public static final String ACCESS_CONTROL_CONTEXT_WORKER_ATTR = AccessControlContext.class.getName();
+    /**
+     * @deprecated Use {@link RenderingJob#ACCESS_CONTROL_CONTEXT_WORKER_ATTR} instead.
+     */
+    public static final String ACCESS_CONTROL_CONTEXT_WORKER_ATTR = RenderingJob.ACCESS_CONTROL_CONTEXT_WORKER_ATTR;
 
     public WorkerMonitorImpl(int minWorkers, int maxWorkers, int spareWorkers, int maxJobsPerWorker)
     {
@@ -58,7 +60,7 @@ public class WorkerMonitorImpl implement
         this.spareWorkers = spareWorkers;
         this.maxJobsPerWorker = maxJobsPerWorker;
     }
-    
+
     /** Commons logging */
     protected final static Logger log = LoggerFactory.getLogger(WorkerMonitorImpl.class);
 
@@ -67,7 +69,7 @@ public class WorkerMonitorImpl implement
 
     /** Count of running jobs **/
     protected int runningJobs = 0;
-    
+
     /** Minimum number of wokers to create */
     protected int minWorkers = 5;
 
@@ -107,14 +109,14 @@ public class WorkerMonitorImpl implement
     public void stop()
     {
         synchronized (workers)
-        {        
+        {
             for (WorkerImpl worker : new ArrayList<WorkerImpl>(workers))
             {
                 worker.interrupt();
             }
         }
         synchronized (workersMonitored)
-        {        
+        {
             for (WorkerImpl worker : new ArrayList<WorkerImpl>(workersMonitored))
             {
                 worker.interrupt();
@@ -189,8 +191,8 @@ public class WorkerMonitorImpl implement
         WorkerImpl worker = this.getWorker();
 
         AccessControlContext context = AccessController.getContext();
-        job.setWorkerAttribute(ACCESS_CONTROL_CONTEXT_WORKER_ATTR, context);
-        
+        job.setWorkerAttribute(RenderingJob.ACCESS_CONTROL_CONTEXT_WORKER_ATTR, context);
+
         if (worker==null)
         {
             queue.push(job);
@@ -201,7 +203,7 @@ public class WorkerMonitorImpl implement
             {
                 synchronized (worker)
                 {
-                    worker.setJob(job, context);
+                    worker.setJob(job);
 
                     if (job.getTimeout() > 0)
                     {
@@ -218,22 +220,22 @@ public class WorkerMonitorImpl implement
             }
         }
     }
-    
+
     /**
-     * Wait for all rendering jobs in the collection to finish successfully or otherwise. 
+     * Wait for all rendering jobs in the collection to finish successfully or otherwise.
      * @param renderingJobs the Collection of rendering job objects to wait for.
      */
     public void waitForRenderingJobs(List<RenderingJob> renderingJobs)
     {
-        try 
+        try
         {
             for (RenderingJob job : renderingJobs)
             {
                 PortletContent portletContent = job.getPortletContent();
-                
-                synchronized (portletContent) 
+
+                synchronized (portletContent)
                 {
-                    if (!portletContent.isComplete()) 
+                    if (!portletContent.isComplete())
                     {
                         portletContent.wait();
                     }
@@ -267,20 +269,19 @@ public class WorkerMonitorImpl implement
         synchronized (worker)
         {
             RenderingJob job = null;
-            
+
             if (worker.getJobCount() < this.maxJobsPerWorker)
             {
                 job = (RenderingJob) queue.pop();
-                
+
                 if (job != null)
                 {
-                    AccessControlContext context = (AccessControlContext) job.getWorkerAttribute(ACCESS_CONTROL_CONTEXT_WORKER_ATTR);
-                    worker.setJob(job, context);
+                    worker.setJob(job);
                     runningJobs--;
                     return;
                 }
             }
-            
+
             worker.setJob(null);
             worker.resetJobCount();
             runningJobs--;
@@ -301,7 +302,7 @@ public class WorkerMonitorImpl implement
     {
         return queue.size();
     }
-    
+
     /**
      * Returns a snapshot of the available jobs
      * @return available jobs
@@ -310,17 +311,17 @@ public class WorkerMonitorImpl implement
     {
         return workers.size();
     }
-    
+
     public int getRunningJobsCount()
     {
         return this.tg.activeCount();
     }
-    
+
     class RenderingJobTimeoutMonitor extends Thread
     {
         long interval = 1000;
         boolean shouldRun = true;
-        
+
         RenderingJobTimeoutMonitor(long interval)
         {
             super("RenderingJobTimeoutMonitor");
@@ -333,7 +334,7 @@ public class WorkerMonitorImpl implement
         }
         /**
          * Thread.stop() is deprecated.
-         * This method achieves the same by setting the run varaible "shouldRun" to false and interrupting the Thread, 
+         * This method achieves the same by setting the run varaible "shouldRun" to false and interrupting the Thread,
          * effectively causing the thread to shutdown correctly.
          *
          */
@@ -342,25 +343,25 @@ public class WorkerMonitorImpl implement
         	shouldRun = false;
         	this.interrupt();
         }
-        
+
         public void run()
         {
             while (shouldRun)
             {
-                try 
+                try
                 {
-                    // Because a timeout worker can be removed 
+                    // Because a timeout worker can be removed
                     // in the workersMonitored collection during iterating,
                     // copy timeout workers in the following collection to kill later.
 
                     List<WorkerImpl> timeoutWorkers = new ArrayList<WorkerImpl>();
 
-                    synchronized (workersMonitored) 
+                    synchronized (workersMonitored)
                     {
                         for (WorkerImpl worker : workersMonitored)
                         {
                             RenderingJob job = (RenderingJob) worker.getJob();
-                            
+
                             if ((null != job) && (job.isTimeout()))
                             {
                                 timeoutWorkers.add(worker);
@@ -379,21 +380,21 @@ public class WorkerMonitorImpl implement
                             killJob(worker, job);
                         }
                     }
-                } 
-                catch (Exception e) 
+                }
+                catch (Exception e)
                 {
                     log.error("Exception during job monitoring.", e);
                 }
-               
-                try 
+
+                try
                 {
-                    synchronized (this) 
+                    synchronized (this)
                     {
                         wait(this.interval);
                     }
-                }   
-                catch (InterruptedException e) 
-                {   
+                }
+                catch (InterruptedException e)
+                {
                 }
             }
         }
@@ -410,7 +411,7 @@ public class WorkerMonitorImpl implement
                 }
 
                 PortletContent content = job.getPortletContent();
-                
+
                 synchronized (content)
                 {
                     if (!content.isComplete())
@@ -419,7 +420,7 @@ public class WorkerMonitorImpl implement
                         content.wait();
                     }
                 }
-                
+
             } catch (Exception e)
             {
                 log.error("Exceptiong during job killing.", e);

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -16,13 +16,15 @@
  */
 package org.apache.jetspeed.aggregator;
 
+import java.security.AccessControlContext;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.jetspeed.container.PortletWindow;
 import org.apache.jetspeed.om.page.ContentFragment;
-import org.apache.jetspeed.request.RequestContext;
 import org.apache.jetspeed.om.portlet.PortletDefinition;
-import org.apache.jetspeed.container.PortletWindow;
+import org.apache.jetspeed.request.RequestContext;
 
 /**
  * Worker thread processes jobs and notify its WorkerMonitor when completed.
@@ -34,11 +36,17 @@ import org.apache.jetspeed.container.Por
  */
 public interface RenderingJob extends Runnable
 {
+
+    /**
+     * Worker attribute name of AccessControlContext object in the current request processing context.
+     */
+    String ACCESS_CONTROL_CONTEXT_WORKER_ATTR = AccessControlContext.class.getName();
+
     void execute();
-    
+
     PortletRenderer getRenderer();
-    
-    PortletWindow getWindow(); 
+
+    PortletWindow getWindow();
 
     PortletContent getPortletContent();
 
@@ -47,7 +55,7 @@ public interface RenderingJob extends Ru
     long getTimeout();
 
     boolean isTimeout();
-    
+
     PortletDefinition getPortletDefinition();
 
     HttpServletRequest getRequest();
@@ -61,9 +69,9 @@ public interface RenderingJob extends Ru
     int getExpirationCache();
 
     void setWorkerAttribute(String name, Object value);
-    
+
     Object getWorkerAttribute(String name);
-    
+
     void removeWorkerAttribute(String name);
 }
 

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java Tue Jul 16 16:34:02 2013
@@ -5,9 +5,9 @@
  * 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.
@@ -26,7 +26,7 @@ import java.security.AccessControlContex
  * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
  * @version $Id: $
  */
-public interface Worker 
+public interface Worker
 {
      int getJobCount();
 
@@ -40,14 +40,19 @@ public interface Worker 
      * stop after processing its current job.
      */
      void setRunning(boolean status);
-     
+
     /**
      * Sets the moitor of this worker
      */
      void setMonitor(WorkerMonitor monitor);
-     
+
     /**
      * Sets the job to execute in security context
+     *
+     * @deprecated Use only {@link #setJob(Runnable)} because AccessControlContext must not be directly accessed by
+     * a worker thread. Instead AccessControlContext must be accessed directly by the job implementation in order
+     * to use the AccessControlContext instance safely regardless of the physical worker thread implementation
+     * (e.g, WorkerImpl or container managed thread by commonj worker monitor).
      */
      void setJob(Runnable job, AccessControlContext context);
 
@@ -60,6 +65,6 @@ public interface Worker 
      * Retrieves the job to execute
      */
      Runnable getJob();
-     
+
      void start();
 }

Modified: portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java?rev=1503788&r1=1503787&r2=1503788&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java Tue Jul 16 16:34:02 2013
@@ -26,6 +26,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.jetspeed.aggregator.RenderingJob;
+
 /**
  * @version $Id$
  *
@@ -44,12 +46,12 @@ public class ServletRequestCleanupServic
         }
         return list;
     }
-    
+
     public static void addCleanupCallback(ServletRequestCleanupCallback callback)
     {
         List<ServletRequestCleanupCallback> callbacks = getCallbacks(false);
         if (callbacks == null)
-        {            
+        {
             callbacks = getCallbacks(true);
             try
             {
@@ -64,7 +66,61 @@ public class ServletRequestCleanupServic
         }
         callbacks.add(callback);
     }
-    
+
+    public static void executeNestedRenderJob(RenderingJob job)
+    {
+        if (getCallbacks(false) == null)
+        {
+            List<ServletRequestCleanupCallback> callbacks = getCallbacks(true);
+            Throwable jobException = null;
+
+            try
+            {
+                job.execute();
+            }
+            catch (Throwable t)
+            {
+                jobException = t;
+                t.fillInStackTrace();
+            }
+
+            for (ServletRequestCleanupCallback callback : callbacks)
+            {
+                try
+                {
+                    callback.cleanup(job.getWindow().getPortletRequestContext().getServletContext(), job.getRequest(), job.getResponse());
+                }
+                catch (Throwable tc)
+                {
+                    try
+                    {
+                        JetspeedLoggerUtil.getSharedLogger(ServletRequestCleanupService.class).error("Cleanup callback execution failed", tc);
+                    }
+                    catch (Throwable tl)
+                    {
+                        // ignore
+                    }
+                }
+            }
+
+            ServletRequestCleanupService.callbacks.remove();
+
+            if (jobException != null)
+            {
+                if (jobException instanceof RuntimeException)
+                {
+                    throw (RuntimeException) jobException;
+                }
+
+                throw new RuntimeException(jobException);
+            }
+        }
+        else
+        {
+            job.execute();
+        }
+    }
+
     /**
      * Servlet Filter doFilter delegate method which will execute registered ServletRequestCleanupCallbacks
      * after the filterChain, if any.
@@ -94,7 +150,7 @@ public class ServletRequestCleanupServic
         {
             filterException = tf;
             tf.fillInStackTrace();
-        }        
+        }
         for (ServletRequestCleanupCallback callback : callbacks)
         {
             try



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org