/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.background.task.internal.messaging;
import com.liferay.portal.kernel.backgroundtask.BackgroundTask;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskConstants;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskExecutor;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskExecutorRegistry;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskManager;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskStatusMessageTranslator;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskStatusRegistry;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocal;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocalManager;
import com.liferay.portal.kernel.backgroundtask.ClassLoaderAwareBackgroundTaskExecutor;
import com.liferay.portal.kernel.backgroundtask.SerialBackgroundTaskExecutor;
import com.liferay.portal.kernel.backgroundtask.ThreadLocalAwareBackgroundTaskExecutor;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.lock.DuplicateLockException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.BaseMessageListener;
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageBus;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.util.ClassLoaderUtil;
import com.liferay.portal.kernel.util.InstanceFactory;
import com.liferay.portal.kernel.util.StackTraceUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
/**
* @author Michael C. Han
*/
public class BackgroundTaskMessageListener extends BaseMessageListener {
public BackgroundTaskMessageListener(
BackgroundTaskExecutorRegistry backgroundTaskExecutorRegistry,
BackgroundTaskManager backgroundTaskManager,
BackgroundTaskStatusRegistry backgroundTaskStatusRegistry,
BackgroundTaskThreadLocalManager backgroundTaskThreadLocalManager,
MessageBus messageBus) {
_backgroundTaskExecutorRegistry = backgroundTaskExecutorRegistry;
_backgroundTaskManager = backgroundTaskManager;
_backgroundTaskStatusRegistry = backgroundTaskStatusRegistry;
_backgroundTaskThreadLocalManager = backgroundTaskThreadLocalManager;
_messageBus = messageBus;
}
@Override
protected void doReceive(Message message) throws Exception {
long backgroundTaskId = (Long)message.get(
BackgroundTaskConstants.BACKGROUND_TASK_ID);
BackgroundTaskThreadLocal.setBackgroundTaskId(backgroundTaskId);
ServiceContext serviceContext = new ServiceContext();
BackgroundTask backgroundTask =
_backgroundTaskManager.amendBackgroundTask(
backgroundTaskId, null,
BackgroundTaskConstants.STATUS_IN_PROGRESS, serviceContext);
if (backgroundTask == null) {
if (_log.isDebugEnabled()) {
_log.debug(
"Unable to find background task " + backgroundTaskId);
}
return;
}
BackgroundTaskExecutor backgroundTaskExecutor = null;
BackgroundTaskStatusMessageListener
backgroundTaskStatusMessageListener = null;
int status = backgroundTask.getStatus();
String statusMessage = null;
try {
ClassLoader classLoader = getBackgroundTaskExecutorClassLoader(
backgroundTask);
backgroundTaskExecutor = wrapBackgroundTaskExecutor(
backgroundTask, classLoader);
_backgroundTaskStatusRegistry.registerBackgroundTaskStatus(
backgroundTaskId);
BackgroundTaskStatusMessageTranslator
backgroundTaskStatusMessageTranslator =
backgroundTaskExecutor.
getBackgroundTaskStatusMessageTranslator();
if (backgroundTaskStatusMessageTranslator != null) {
backgroundTaskStatusMessageListener =
new BackgroundTaskStatusMessageListener(
backgroundTaskId, backgroundTaskStatusMessageTranslator,
_backgroundTaskStatusRegistry);
_messageBus.registerMessageListener(
DestinationNames.BACKGROUND_TASK_STATUS,
backgroundTaskStatusMessageListener);
}
backgroundTask = _backgroundTaskManager.fetchBackgroundTask(
backgroundTask.getBackgroundTaskId());
BackgroundTaskResult backgroundTaskResult =
backgroundTaskExecutor.execute(backgroundTask);
status = backgroundTaskResult.getStatus();
statusMessage = backgroundTaskResult.getStatusMessage();
}
catch (DuplicateLockException dle) {
status = BackgroundTaskConstants.STATUS_QUEUED;
if (_log.isDebugEnabled()) {
_log.debug(
"Unable to acquire lock, queuing background task " +
backgroundTaskId,
dle);
}
}
catch (Exception e) {
status = BackgroundTaskConstants.STATUS_FAILED;
if (e instanceof SystemException) {
Throwable cause = e.getCause();
if (cause instanceof Exception) {
e = (Exception)cause;
}
}
if (backgroundTaskExecutor != null) {
statusMessage = backgroundTaskExecutor.handleException(
backgroundTask, e);
}
if (_log.isInfoEnabled()) {
if (statusMessage != null) {
statusMessage = statusMessage.concat(
StackTraceUtil.getStackTrace(e));
}
else {
statusMessage = StackTraceUtil.getStackTrace(e);
}
}
_log.error("Unable to execute background task", e);
}
finally {
if (_log.isDebugEnabled()) {
_log.debug(
"Completing background task " + backgroundTaskId +
" with status: " + status);
}
_backgroundTaskManager.amendBackgroundTask(
backgroundTaskId, null, status, statusMessage, serviceContext);
_backgroundTaskStatusRegistry.unregisterBackgroundTaskStatus(
backgroundTaskId);
if (backgroundTaskStatusMessageListener != null) {
_messageBus.unregisterMessageListener(
DestinationNames.BACKGROUND_TASK_STATUS,
backgroundTaskStatusMessageListener);
}
Message responseMessage = new Message();
responseMessage.put(
BackgroundTaskConstants.BACKGROUND_TASK_ID,
backgroundTask.getBackgroundTaskId());
responseMessage.put("name", backgroundTask.getName());
responseMessage.put("status", status);
responseMessage.put(
"taskExecutorClassName",
backgroundTask.getTaskExecutorClassName());
_messageBus.sendMessage(
DestinationNames.BACKGROUND_TASK_STATUS, responseMessage);
}
}
protected BackgroundTaskExecutor getBackgroundTaskExecutor(
BackgroundTask backgroundTask) {
BackgroundTaskExecutor backgroundTaskExecutor = null;
String servletContextNames = backgroundTask.getServletContextNames();
if (Validator.isNull(servletContextNames)) {
backgroundTaskExecutor =
_backgroundTaskExecutorRegistry.getBackgroundTaskExecutor(
backgroundTask.getTaskExecutorClassName());
if (backgroundTaskExecutor == null) {
throw new IllegalStateException(
"Unknown background task executor " +
backgroundTask.getTaskExecutorClassName());
}
backgroundTaskExecutor = backgroundTaskExecutor.clone();
}
else {
ClassLoader classLoader = ClassLoaderUtil.getPortalClassLoader();
if (Validator.isNotNull(servletContextNames)) {
classLoader = ClassLoaderUtil.getAggregatePluginsClassLoader(
StringUtil.split(servletContextNames), false);
}
try {
backgroundTaskExecutor =
(BackgroundTaskExecutor)InstanceFactory.newInstance(
classLoader, backgroundTask.getTaskExecutorClassName());
}
catch (Exception e) {
throw new IllegalStateException(
"Cannot instantiate BackgroundTaskExecutor: " +
backgroundTask.getTaskExecutorClassName(),
e);
}
}
return backgroundTaskExecutor;
}
protected ClassLoader getBackgroundTaskExecutorClassLoader(
BackgroundTask backgroundTask) {
if (Validator.isNull(backgroundTask.getServletContextNames())) {
return null;
}
ClassLoader classLoader = ClassLoaderUtil.getPortalClassLoader();
String servletContextNames = backgroundTask.getServletContextNames();
if (Validator.isNotNull(servletContextNames)) {
classLoader = ClassLoaderUtil.getAggregatePluginsClassLoader(
StringUtil.split(servletContextNames), false);
}
return classLoader;
}
protected BackgroundTaskExecutor wrapBackgroundTaskExecutor(
BackgroundTask backgroundTask, ClassLoader classLoader) {
BackgroundTaskExecutor backgroundTaskExecutor =
getBackgroundTaskExecutor(backgroundTask);
if (classLoader != null) {
backgroundTaskExecutor = new ClassLoaderAwareBackgroundTaskExecutor(
backgroundTaskExecutor, classLoader);
}
if (backgroundTaskExecutor.isSerial()) {
backgroundTaskExecutor = new SerialBackgroundTaskExecutor(
backgroundTaskExecutor);
}
backgroundTaskExecutor = new ThreadLocalAwareBackgroundTaskExecutor(
backgroundTaskExecutor, _backgroundTaskThreadLocalManager);
return backgroundTaskExecutor;
}
private static final Log _log = LogFactoryUtil.getLog(
BackgroundTaskMessageListener.class);
private final BackgroundTaskExecutorRegistry
_backgroundTaskExecutorRegistry;
private final BackgroundTaskManager _backgroundTaskManager;
private final BackgroundTaskStatusRegistry _backgroundTaskStatusRegistry;
private final BackgroundTaskThreadLocalManager
_backgroundTaskThreadLocalManager;
private final MessageBus _messageBus;
}