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.lar.backgroundtask;
016    
017    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.lar.MissingReferences;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.staging.StagingUtil;
024    import com.liferay.portal.kernel.transaction.Propagation;
025    import com.liferay.portal.kernel.util.FileUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.MapUtil;
028    import com.liferay.portal.kernel.util.UnicodeProperties;
029    import com.liferay.portal.model.BackgroundTask;
030    import com.liferay.portal.model.Group;
031    import com.liferay.portal.service.GroupLocalServiceUtil;
032    import com.liferay.portal.service.LayoutLocalServiceUtil;
033    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.service.StagingLocalServiceUtil;
036    import com.liferay.portal.spring.transaction.TransactionAttributeBuilder;
037    import com.liferay.portal.spring.transaction.TransactionalCallableUtil;
038    
039    import java.io.File;
040    import java.io.Serializable;
041    
042    import java.util.Date;
043    import java.util.Map;
044    import java.util.concurrent.Callable;
045    
046    import org.springframework.transaction.interceptor.TransactionAttribute;
047    
048    /**
049     * @author Julio Camarero
050     */
051    public class LayoutStagingBackgroundTaskExecutor
052            extends BaseStagingBackgroundTaskExecutor {
053    
054            public LayoutStagingBackgroundTaskExecutor() {
055                    setBackgroundTaskStatusMessageTranslator(
056                            new LayoutStagingBackgroundTaskStatusMessageTranslator());
057            }
058    
059            @Override
060            public BackgroundTaskResult execute(BackgroundTask backgroundTask)
061                    throws Exception {
062    
063                    Map<String, Serializable> taskContextMap =
064                            backgroundTask.getTaskContextMap();
065    
066                    long userId = MapUtil.getLong(taskContextMap, "userId");
067                    long targetGroupId = MapUtil.getLong(taskContextMap, "targetGroupId");
068    
069                    StagingUtil.lockGroup(userId, targetGroupId);
070    
071                    long sourceGroupId = MapUtil.getLong(taskContextMap, "sourceGroupId");
072    
073                    clearBackgroundTaskStatus(backgroundTask);
074    
075                    MissingReferences missingReferences = null;
076    
077                    try {
078                            Callable<MissingReferences> layoutStagingCallable =
079                                    new LayoutStagingCallable(
080                                            backgroundTask, sourceGroupId, targetGroupId,
081                                            taskContextMap, userId);
082    
083                            missingReferences = TransactionalCallableUtil.call(
084                                            _transactionAttribute, layoutStagingCallable);
085                    }
086                    catch (Throwable t) {
087                            if (_log.isDebugEnabled()) {
088                                    _log.debug(t, t);
089                            }
090                            else if (_log.isWarnEnabled()) {
091                                    _log.warn("Unable to publish layout: " + t.getMessage());
092                            }
093    
094                            Group sourceGroup = GroupLocalServiceUtil.getGroup(sourceGroupId);
095    
096                            if (sourceGroup.hasStagingGroup()) {
097                                    ServiceContext serviceContext = new ServiceContext();
098    
099                                    serviceContext.setUserId(userId);
100    
101                                    StagingLocalServiceUtil.disableStaging(
102                                            sourceGroup, serviceContext);
103                            }
104    
105                            if (t instanceof Exception) {
106                                    throw (Exception)t;
107                            }
108                            else {
109                                    throw new SystemException(t);
110                            }
111                    }
112                    finally {
113                            StagingUtil.unlockGroup(targetGroupId);
114                    }
115    
116                    return processMissingReferences(backgroundTask, missingReferences);
117            }
118    
119            protected void initLayoutSetBranches(
120                            long userId, long sourceGroupId, long targetGroupId)
121                    throws Exception {
122    
123                    Group sourceGroup = GroupLocalServiceUtil.getGroup(sourceGroupId);
124    
125                    if (!sourceGroup.hasStagingGroup()) {
126                            return;
127                    }
128    
129                    LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
130                            targetGroupId, false, true);
131                    LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
132                            targetGroupId, true, true);
133    
134                    UnicodeProperties typeSettingsProperties =
135                            sourceGroup.getTypeSettingsProperties();
136    
137                    boolean branchingPrivate = GetterUtil.getBoolean(
138                            typeSettingsProperties.getProperty("branchingPrivate"));
139                    boolean branchingPublic = GetterUtil.getBoolean(
140                            typeSettingsProperties.getProperty("branchingPublic"));
141    
142                    ServiceContext serviceContext = new ServiceContext();
143    
144                    serviceContext.setUserId(userId);
145    
146                    StagingLocalServiceUtil.checkDefaultLayoutSetBranches(
147                            userId, sourceGroup, branchingPublic, branchingPrivate, false,
148                            serviceContext);
149            }
150    
151            private static Log _log = LogFactoryUtil.getLog(
152                    LayoutStagingBackgroundTaskExecutor.class);
153    
154            private TransactionAttribute _transactionAttribute =
155                    TransactionAttributeBuilder.build(
156                            Propagation.REQUIRED, new Class<?>[] {Exception.class});
157    
158            private class LayoutStagingCallable implements Callable<MissingReferences> {
159    
160                    private LayoutStagingCallable(
161                            BackgroundTask backgroundTask, long sourceGroupId,
162                            long targetGroupId, Map<String, Serializable> taskContextMap,
163                            long userId) {
164    
165                            _backgroundTask = backgroundTask;
166                            _sourceGroupId = sourceGroupId;
167                            _targetGroupId = targetGroupId;
168                            _taskContextMap = taskContextMap;
169                            _userId = userId;
170                    }
171    
172                    @Override
173                    public MissingReferences call() throws Exception {
174                            File file = null;
175                            MissingReferences missingReferences = null;
176    
177                            try {
178                                    boolean privateLayout = MapUtil.getBoolean(
179                                            _taskContextMap, "privateLayout");
180                                    long[] layoutIds = GetterUtil.getLongValues(
181                                            _taskContextMap.get("layoutIds"));
182                                    Map<String, String[]> parameterMap =
183                                            (Map<String, String[]>)_taskContextMap.get("parameterMap");
184                                    Date startDate = (Date)_taskContextMap.get("startDate");
185                                    Date endDate = (Date)_taskContextMap.get("endDate");
186    
187                                    file = LayoutLocalServiceUtil.exportLayoutsAsFile(
188                                            _sourceGroupId, privateLayout, layoutIds, parameterMap,
189                                            startDate, endDate);
190    
191                                    _backgroundTask = markBackgroundTask(
192                                            _backgroundTask, "exported");
193    
194                                    missingReferences =
195                                            LayoutLocalServiceUtil.validateImportLayoutsFile(
196                                                    _userId, _targetGroupId, privateLayout, parameterMap,
197                                                    file);
198    
199                                    _backgroundTask = markBackgroundTask(
200                                            _backgroundTask, "validated");
201    
202                                    LayoutLocalServiceUtil.importLayouts(
203                                            _userId, _targetGroupId, privateLayout, parameterMap, file);
204    
205                                    initLayoutSetBranches(_userId, _sourceGroupId, _targetGroupId);
206    
207                                    boolean updateLastPublishDate = MapUtil.getBoolean(
208                                            parameterMap,
209                                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);
210    
211                                    if (updateLastPublishDate) {
212                                            Group sourceGroup = GroupLocalServiceUtil.getGroup(
213                                                    _sourceGroupId);
214    
215                                            if (!sourceGroup.hasStagingGroup()) {
216                                                    StagingUtil.updateLastPublishDate(
217                                                            _sourceGroupId, privateLayout, endDate);
218                                            }
219                                            else {
220                                                    StagingUtil.updateLastPublishDate(
221                                                            _targetGroupId, privateLayout, endDate);
222                                            }
223                                    }
224                            }
225                            finally {
226                                    FileUtil.delete(file);
227                            }
228    
229                            return missingReferences;
230                    }
231    
232                    private BackgroundTask _backgroundTask;
233                    private long _sourceGroupId;
234                    private long _targetGroupId;
235                    private Map<String, Serializable> _taskContextMap;
236                    private long _userId;
237    
238            }
239    
240    }