001
014
015 package com.liferay.portlet.exportimport.backgroundtask;
016
017 import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PUBLICATION_LAYOUT_REMOTE_FAILED;
018 import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PUBLICATION_LAYOUT_REMOTE_STARTED;
019 import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PUBLICATION_LAYOUT_REMOTE_SUCCEEDED;
020 import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS;
021
022 import com.liferay.portal.NoSuchLayoutException;
023 import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
024 import com.liferay.portal.kernel.exception.PortalException;
025 import com.liferay.portal.kernel.exception.SystemException;
026 import com.liferay.portal.kernel.log.Log;
027 import com.liferay.portal.kernel.log.LogFactoryUtil;
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.StreamUtil;
032 import com.liferay.portal.model.BackgroundTask;
033 import com.liferay.portal.model.Layout;
034 import com.liferay.portal.security.auth.HttpPrincipal;
035 import com.liferay.portal.service.LayoutLocalServiceUtil;
036 import com.liferay.portal.service.http.LayoutServiceHttp;
037 import com.liferay.portal.util.PropsValues;
038 import com.liferay.portlet.exportimport.lar.ExportImportHelperUtil;
039 import com.liferay.portlet.exportimport.lar.ExportImportThreadLocal;
040 import com.liferay.portlet.exportimport.lar.MissingReferences;
041 import com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleManager;
042 import com.liferay.portlet.exportimport.model.ExportImportConfiguration;
043 import com.liferay.portlet.exportimport.service.ExportImportLocalServiceUtil;
044 import com.liferay.portlet.exportimport.service.http.StagingServiceHttp;
045
046 import java.io.File;
047 import java.io.FileInputStream;
048 import java.io.Serializable;
049
050 import java.util.ArrayList;
051 import java.util.List;
052 import java.util.Map;
053
054
057 public class LayoutRemoteStagingBackgroundTaskExecutor
058 extends BaseStagingBackgroundTaskExecutor {
059
060 public LayoutRemoteStagingBackgroundTaskExecutor() {
061 setBackgroundTaskStatusMessageTranslator(
062 new LayoutStagingBackgroundTaskStatusMessageTranslator());
063 }
064
065 @Override
066 public BackgroundTaskResult execute(BackgroundTask backgroundTask) {
067 ExportImportConfiguration exportImportConfiguration =
068 getExportImportConfiguration(backgroundTask);
069
070 clearBackgroundTaskStatus(backgroundTask);
071
072 File file = null;
073 HttpPrincipal httpPrincipal = null;
074 MissingReferences missingReferences = null;
075 long stagingRequestId = 0L;
076
077 try {
078 ExportImportThreadLocal.setLayoutStagingInProcess(true);
079
080 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
081 EVENT_PUBLICATION_LAYOUT_REMOTE_STARTED,
082 PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
083 exportImportConfiguration);
084
085 Map<String, Serializable> settingsMap =
086 exportImportConfiguration.getSettingsMap();
087
088 long sourceGroupId = MapUtil.getLong(settingsMap, "sourceGroupId");
089 boolean privateLayout = MapUtil.getBoolean(
090 settingsMap, "privateLayout");
091
092 initThreadLocals(sourceGroupId, privateLayout);
093
094 Map<Long, Boolean> layoutIdMap =
095 (Map<Long, Boolean>)settingsMap.get("layoutIdMap");
096 long remoteGroupId = MapUtil.getLong(settingsMap, "remoteGroupId");
097
098 Map<String, Serializable> taskContextMap =
099 backgroundTask.getTaskContextMap();
100
101 httpPrincipal = (HttpPrincipal)taskContextMap.get("httpPrincipal");
102
103 file = exportLayoutsAsFile(
104 exportImportConfiguration, layoutIdMap, remoteGroupId,
105 httpPrincipal);
106
107 String checksum = FileUtil.getMD5Checksum(file);
108
109 stagingRequestId = StagingServiceHttp.createStagingRequest(
110 httpPrincipal, remoteGroupId, checksum);
111
112 transferFileToRemoteLive(file, stagingRequestId, httpPrincipal);
113
114 markBackgroundTask(
115 backgroundTask.getBackgroundTaskId(), "exported");
116
117 missingReferences = StagingServiceHttp.publishStagingRequest(
118 httpPrincipal, stagingRequestId, exportImportConfiguration);
119
120 ExportImportThreadLocal.setLayoutStagingInProcess(false);
121
122 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
123 EVENT_PUBLICATION_LAYOUT_REMOTE_SUCCEEDED,
124 PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
125 exportImportConfiguration);
126 }
127 catch (Throwable t) {
128 ExportImportThreadLocal.setLayoutStagingInProcess(false);
129
130 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
131 EVENT_PUBLICATION_LAYOUT_REMOTE_FAILED,
132 PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
133 exportImportConfiguration);
134
135 if (_log.isDebugEnabled()) {
136 _log.debug(t, t);
137 }
138 else if (_log.isWarnEnabled()) {
139 _log.warn("Unable to publish layout: " + t.getMessage());
140 }
141
142 deleteTempLarOnFailure(file);
143
144 throw new SystemException(t);
145 }
146 finally {
147 if ((stagingRequestId > 0) && (httpPrincipal != null)) {
148 try {
149 StagingServiceHttp.cleanUpStagingRequest(
150 httpPrincipal, stagingRequestId);
151 }
152 catch (PortalException pe) {
153 _log.warn("Unable to clean up the remote live site");
154 }
155 }
156 }
157
158 deleteTempLarOnSuccess(file);
159
160 return processMissingReferences(
161 backgroundTask.getBackgroundTaskId(), missingReferences);
162 }
163
164 protected File exportLayoutsAsFile(
165 ExportImportConfiguration exportImportConfiguration,
166 Map<Long, Boolean> layoutIdMap, long remoteGroupId,
167 HttpPrincipal httpPrincipal)
168 throws PortalException {
169
170 List<Layout> layouts = new ArrayList<>();
171
172 if (layoutIdMap != null) {
173 for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
174 long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
175 boolean includeChildren = entry.getValue();
176
177 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
178
179 if (!layouts.contains(layout)) {
180 layouts.add(layout);
181 }
182
183 List<Layout> parentLayouts = getMissingRemoteParentLayouts(
184 httpPrincipal, layout, remoteGroupId);
185
186 for (Layout parentLayout : parentLayouts) {
187 if (!layouts.contains(parentLayout)) {
188 layouts.add(parentLayout);
189 }
190 }
191
192 if (includeChildren) {
193 for (Layout childLayout : layout.getAllChildren()) {
194 if (!layouts.contains(childLayout)) {
195 layouts.add(childLayout);
196 }
197 }
198 }
199 }
200 }
201
202 long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);
203
204 Map<String, Serializable> settingsMap =
205 exportImportConfiguration.getSettingsMap();
206
207 settingsMap.remove("layoutIdMap");
208
209 settingsMap.put("layoutIds", layoutIds);
210
211 return ExportImportLocalServiceUtil.exportLayoutsAsFile(
212 exportImportConfiguration);
213 }
214
215
219 protected List<Layout> getMissingRemoteParentLayouts(
220 HttpPrincipal httpPrincipal, Layout layout, long remoteGroupId)
221 throws PortalException {
222
223 List<Layout> missingRemoteParentLayouts = new ArrayList<>();
224
225 long parentLayoutId = layout.getParentLayoutId();
226
227 while (parentLayoutId > 0) {
228 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
229 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
230
231 try {
232 LayoutServiceHttp.getLayoutByUuidAndGroupId(
233 httpPrincipal, parentLayout.getUuid(), remoteGroupId,
234 parentLayout.getPrivateLayout());
235
236
237
238 break;
239 }
240 catch (NoSuchLayoutException nsle) {
241 missingRemoteParentLayouts.add(parentLayout);
242
243 parentLayoutId = parentLayout.getParentLayoutId();
244 }
245 }
246
247 return missingRemoteParentLayouts;
248 }
249
250 protected void transferFileToRemoteLive(
251 File file, long stagingRequestId, HttpPrincipal httpPrincipal)
252 throws Exception {
253
254 byte[] bytes =
255 new byte[PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE];
256
257 int i = 0;
258 int j = 0;
259
260 String numberFormat = String.format(
261 "%%0%dd",
262 String.valueOf((int) (file.length() / bytes.length)).length() + 1);
263
264 FileInputStream fileInputStream = null;
265
266 try {
267 fileInputStream = new FileInputStream(file);
268
269 while ((i = fileInputStream.read(bytes)) >= 0) {
270 String fileName =
271 file.getName() + String.format(numberFormat, j++);
272
273 if (i < PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE) {
274 byte[] tempBytes = new byte[i];
275
276 System.arraycopy(bytes, 0, tempBytes, 0, i);
277
278 StagingServiceHttp.updateStagingRequest(
279 httpPrincipal, stagingRequestId, fileName, tempBytes);
280 }
281 else {
282 StagingServiceHttp.updateStagingRequest(
283 httpPrincipal, stagingRequestId, fileName, bytes);
284 }
285
286 bytes =
287 new byte[PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE];
288 }
289 }
290 finally {
291 StreamUtil.cleanUp(fileInputStream);
292 }
293 }
294
295 private static final Log _log = LogFactoryUtil.getLog(
296 LayoutRemoteStagingBackgroundTaskExecutor.class);
297
298 }