001    /**
002     * Copyright (c) 2000-2013 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                            BackgroundTaskResult backgroundTaskResult =
108                                    backgroundTaskExecutor.execute(backgroundTask);
109    
110                            status = backgroundTaskResult.getStatus();
111                            statusMessage = backgroundTaskResult.getStatusMessage();
112                    }
113                    catch (DuplicateLockException e) {
114                            status = BackgroundTaskConstants.STATUS_QUEUED;
115                    }
116                    catch (Exception e) {
117                            status = BackgroundTaskConstants.STATUS_FAILED;
118    
119                            if (backgroundTaskExecutor != null) {
120                                    statusMessage = backgroundTaskExecutor.handleException(
121                                            backgroundTask, e);
122                            }
123    
124                            if (_log.isInfoEnabled()) {
125                                    if (statusMessage != null) {
126                                            statusMessage.concat(StackTraceUtil.getStackTrace(e));
127                                    }
128                                    else {
129                                            statusMessage = StackTraceUtil.getStackTrace(e);
130                                    }
131                            }
132    
133                            _log.error("Unable to execute background task", e);
134                    }
135                    finally {
136                            BackgroundTaskLocalServiceUtil.amendBackgroundTask(
137                                    backgroundTaskId, null, status, statusMessage, serviceContext);
138    
139                            BackgroundTaskStatusRegistryUtil.unregisterBackgroundTaskStatus(
140                                    backgroundTaskId);
141    
142                            if (backgroundTaskStatusMessageListener != null) {
143                                    MessageBusUtil.unregisterMessageListener(
144                                            DestinationNames.BACKGROUND_TASK_STATUS,
145                                            backgroundTaskStatusMessageListener);
146                            }
147    
148                            Message responseMessage = new Message();
149    
150                            responseMessage.put(
151                                    "backgroundTaskId", backgroundTask.getBackgroundTaskId());
152                            responseMessage.put("name", backgroundTask.getName());
153                            responseMessage.put("status", status);
154                            responseMessage.put(
155                                    "taskExecutorClassName",
156                                    backgroundTask.getTaskExecutorClassName());
157    
158                            MessageBusUtil.sendMessage(
159                                    DestinationNames.BACKGROUND_TASK_STATUS, responseMessage);
160                    }
161            }
162    
163            protected BackgroundTaskExecutor wrapBackgroundTaskExecutor(
164                    BackgroundTaskExecutor backgroundTaskExecutor,
165                    ClassLoader classLoader) {
166    
167                    if (classLoader != ClassLoaderUtil.getPortalClassLoader()) {
168                            backgroundTaskExecutor =
169                                    new ClassLoaderAwareBackgroundTaskExecutor(
170                                            backgroundTaskExecutor, classLoader);
171                    }
172    
173                    if (backgroundTaskExecutor.isSerial()) {
174                            backgroundTaskExecutor = new SerialBackgroundTaskExecutor(
175                                    backgroundTaskExecutor);
176                    }
177    
178                    return backgroundTaskExecutor;
179            }
180    
181            private static Log _log = LogFactoryUtil.getLog(
182                    BackgroundTaskMessageListener.class);
183    
184    }