001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.backgroundtask.messaging;
016    
017    import com.liferay.portal.DuplicateLockException;
018    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskConstants;
019    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskExecutor;
020    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
021    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskStatusMessageTranslator;
022    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskStatusRegistryUtil;
023    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocal;
024    import com.liferay.portal.kernel.backgroundtask.ClassLoaderAwareBackgroundTaskExecutor;
025    import com.liferay.portal.kernel.backgroundtask.SerialBackgroundTaskExecutor;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.messaging.BaseMessageListener;
029    import com.liferay.portal.kernel.messaging.DestinationNames;
030    import com.liferay.portal.kernel.messaging.Message;
031    import com.liferay.portal.kernel.messaging.MessageBusUtil;
032    import com.liferay.portal.kernel.util.InstanceFactory;
033    import com.liferay.portal.kernel.util.StackTraceUtil;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.model.BackgroundTask;
037    import com.liferay.portal.service.BackgroundTaskLocalServiceUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.util.ClassLoaderUtil;
040    
041    /**
042     * @author Michael C. Han
043     */
044    public class BackgroundTaskMessageListener extends BaseMessageListener {
045    
046            @Override
047            protected void doReceive(Message message) throws Exception {
048                    long backgroundTaskId = (Long)message.get("backgroundTaskId");
049    
050                    BackgroundTaskThreadLocal.setBackgroundTaskId(backgroundTaskId);
051    
052                    ServiceContext serviceContext = new ServiceContext();
053    
054                    BackgroundTask backgroundTask =
055                            BackgroundTaskLocalServiceUtil.amendBackgroundTask(
056                                    backgroundTaskId, null,
057                                    BackgroundTaskConstants.STATUS_IN_PROGRESS, serviceContext);
058    
059                    if (backgroundTask == null) {
060                            return;
061                    }
062    
063                    BackgroundTaskExecutor backgroundTaskExecutor = null;
064                    BackgroundTaskStatusMessageListener
065                            backgroundTaskStatusMessageListener = null;
066    
067                    int status = backgroundTask.getStatus();
068                    String statusMessage = null;
069    
070                    try {
071                            ClassLoader classLoader = ClassLoaderUtil.getPortalClassLoader();
072    
073                            String servletContextNames =
074                                    backgroundTask.getServletContextNames();
075    
076                            if (Validator.isNotNull(servletContextNames)) {
077                                    classLoader = ClassLoaderUtil.getAggregatePluginsClassLoader(
078                                            StringUtil.split(servletContextNames), false);
079                            }
080    
081                            backgroundTaskExecutor =
082                                    (BackgroundTaskExecutor)InstanceFactory.newInstance(
083                                            classLoader, backgroundTask.getTaskExecutorClassName());
084    
085                            backgroundTaskExecutor = wrapBackgroundTaskExecutor(
086                                    backgroundTaskExecutor, classLoader);
087    
088                            BackgroundTaskStatusRegistryUtil.registerBackgroundTaskStatus(
089                                    backgroundTaskId);
090    
091                            BackgroundTaskStatusMessageTranslator
092                                    backgroundTaskStatusMessageTranslator =
093                                            backgroundTaskExecutor.
094                                                    getBackgroundTaskStatusMessageTranslator();
095    
096                            if (backgroundTaskStatusMessageTranslator != null) {
097                                    backgroundTaskStatusMessageListener =
098                                            new BackgroundTaskStatusMessageListener(
099                                                    backgroundTaskId,
100                                                    backgroundTaskStatusMessageTranslator);
101    
102                                    MessageBusUtil.registerMessageListener(
103                                            DestinationNames.BACKGROUND_TASK_STATUS,
104                                            backgroundTaskStatusMessageListener);
105                            }
106    
107                            backgroundTask = BackgroundTaskLocalServiceUtil.fetchBackgroundTask(
108                                    backgroundTask.getBackgroundTaskId());
109    
110                            BackgroundTaskResult backgroundTaskResult =
111                                    backgroundTaskExecutor.execute(backgroundTask);
112    
113                            status = backgroundTaskResult.getStatus();
114                            statusMessage = backgroundTaskResult.getStatusMessage();
115                    }
116                    catch (DuplicateLockException e) {
117                            status = BackgroundTaskConstants.STATUS_QUEUED;
118                    }
119                    catch (Exception e) {
120                            status = BackgroundTaskConstants.STATUS_FAILED;
121    
122                            if (backgroundTaskExecutor != null) {
123                                    statusMessage = backgroundTaskExecutor.handleException(
124                                            backgroundTask, e);
125                            }
126    
127                            if (_log.isInfoEnabled()) {
128                                    if (statusMessage != null) {
129                                            statusMessage = statusMessage.concat(
130                                                    StackTraceUtil.getStackTrace(e));
131                                    }
132                                    else {
133                                            statusMessage = StackTraceUtil.getStackTrace(e);
134                                    }
135                            }
136    
137                            _log.error("Unable to execute background task", e);
138                    }
139                    finally {
140                            BackgroundTaskLocalServiceUtil.amendBackgroundTask(
141                                    backgroundTaskId, null, status, statusMessage, serviceContext);
142    
143                            BackgroundTaskStatusRegistryUtil.unregisterBackgroundTaskStatus(
144                                    backgroundTaskId);
145    
146                            if (backgroundTaskStatusMessageListener != null) {
147                                    MessageBusUtil.unregisterMessageListener(
148                                            DestinationNames.BACKGROUND_TASK_STATUS,
149                                            backgroundTaskStatusMessageListener);
150                            }
151    
152                            Message responseMessage = new Message();
153    
154                            responseMessage.put(
155                                    "backgroundTaskId", backgroundTask.getBackgroundTaskId());
156                            responseMessage.put("name", backgroundTask.getName());
157                            responseMessage.put("status", status);
158                            responseMessage.put(
159                                    "taskExecutorClassName",
160                                    backgroundTask.getTaskExecutorClassName());
161    
162                            MessageBusUtil.sendMessage(
163                                    DestinationNames.BACKGROUND_TASK_STATUS, responseMessage);
164                    }
165            }
166    
167            protected BackgroundTaskExecutor wrapBackgroundTaskExecutor(
168                    BackgroundTaskExecutor backgroundTaskExecutor,
169                    ClassLoader classLoader) {
170    
171                    if (classLoader != ClassLoaderUtil.getPortalClassLoader()) {
172                            backgroundTaskExecutor = new ClassLoaderAwareBackgroundTaskExecutor(
173                                    backgroundTaskExecutor, classLoader);
174                    }
175    
176                    if (backgroundTaskExecutor.isSerial()) {
177                            backgroundTaskExecutor = new SerialBackgroundTaskExecutor(
178                                    backgroundTaskExecutor);
179                    }
180    
181                    return backgroundTaskExecutor;
182            }
183    
184            private static final Log _log = LogFactoryUtil.getLog(
185                    BackgroundTaskMessageListener.class);
186    
187    }