Author: taylor Date: Sat Jul 12 20:06:36 2014 New Revision: 1610038 URL: http://svn.apache.org/r1610038 Log: JS2-1283: backporting changes to 2.2.3 from trunk
Modified: portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java Modified: portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/CommonjWorkerMonitorImpl.java Sat Jul 12 20:06:36 2014 @@ -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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/RenderingJobImpl.java Sat Jul 12 20:06:36 2014 @@ -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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerImpl.java Sat Jul 12 20:06:36 2014 @@ -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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/WorkerMonitorImpl.java Sat Jul 12 20:06:36 2014 @@ -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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/RenderingJob.java Sat Jul 12 20:06:36 2014 @@ -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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/Worker.java Sat Jul 12 20:06:36 2014 @@ -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:tay...@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/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java?rev=1610038&r1=1610037&r2=1610038&view=diff ============================================================================== --- portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java (original) +++ portals/jetspeed-2/portal/branches/JETSPEED-BRANCH-2.2.2-POST-RELEASE/jetspeed-commons/src/main/java/org/apache/jetspeed/util/ServletRequestCleanupService.java Sat Jul 12 20:06:36 2014 @@ -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-unsubscr...@portals.apache.org For additional commands, e-mail: jetspeed-dev-h...@portals.apache.org