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                            if (_log.isDebugEnabled()) {
134                                    _log.debug("Unable to execute background task", e);
135                            }
136                    }
137                    finally {
138                            BackgroundTaskLocalServiceUtil.amendBackgroundTask(
139                                    backgroundTaskId, null, status, statusMessage, serviceContext);
140    
141                            BackgroundTaskStatusRegistryUtil.unregisterBackgroundTaskStatus(
142                                    backgroundTaskId);
143    
144                            if (backgroundTaskStatusMessageListener != null) {
145                                    MessageBusUtil.unregisterMessageListener(
146                                            DestinationNames.BACKGROUND_TASK_STATUS,
147                                            backgroundTaskStatusMessageListener);
148                            }
149    
150                            Message responseMessage = new Message();
151    
152                            responseMessage.put(
153                                    "backgroundTaskId", backgroundTask.getBackgroundTaskId());
154                            responseMessage.put("name", backgroundTask.getName());
155                            responseMessage.put("status", status);
156                            responseMessage.put(
157                                    "taskExecutorClassName",
158                                    backgroundTask.getTaskExecutorClassName());
159    
160                            MessageBusUtil.sendMessage(
161                                    DestinationNames.BACKGROUND_TASK_STATUS, responseMessage);
162                    }
163            }
164    
165            protected BackgroundTaskExecutor wrapBackgroundTaskExecutor(
166                    BackgroundTaskExecutor backgroundTaskExecutor,
167                    ClassLoader classLoader) {
168    
169                    if (classLoader != ClassLoaderUtil.getPortalClassLoader()) {
170                            backgroundTaskExecutor =
171                                    new ClassLoaderAwareBackgroundTaskExecutor(
172                                            backgroundTaskExecutor, classLoader);
173                    }
174    
175                    if (backgroundTaskExecutor.isSerial()) {
176                            backgroundTaskExecutor = new SerialBackgroundTaskExecutor(
177                                    backgroundTaskExecutor);
178                    }
179    
180                    return backgroundTaskExecutor;
181            }
182    
183            private static Log _log = LogFactoryUtil.getLog(
184                    BackgroundTaskMessageListener.class);
185    
186    }