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