001
014
015 package com.liferay.portal.lar.backgroundtask;
016
017 import com.liferay.portal.NoSuchLayoutException;
018 import com.liferay.portal.RemoteExportException;
019 import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
020 import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
021 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
022 import com.liferay.portal.kernel.lar.MissingReferences;
023 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024 import com.liferay.portal.kernel.staging.StagingUtil;
025 import com.liferay.portal.kernel.util.DateRange;
026 import com.liferay.portal.kernel.util.FileUtil;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.MapUtil;
029 import com.liferay.portal.kernel.util.StreamUtil;
030 import com.liferay.portal.model.BackgroundTask;
031 import com.liferay.portal.model.Layout;
032 import com.liferay.portal.security.auth.HttpPrincipal;
033 import com.liferay.portal.service.LayoutLocalServiceUtil;
034 import com.liferay.portal.service.http.LayoutServiceHttp;
035 import com.liferay.portal.service.http.StagingServiceHttp;
036 import com.liferay.portal.util.PropsValues;
037
038 import java.io.File;
039 import java.io.FileInputStream;
040 import java.io.Serializable;
041
042 import java.util.ArrayList;
043 import java.util.Date;
044 import java.util.List;
045 import java.util.Map;
046
047
050 public class LayoutRemoteStagingBackgroundTaskExecutor
051 extends BaseStagingBackgroundTaskExecutor {
052
053 public LayoutRemoteStagingBackgroundTaskExecutor() {
054 setBackgroundTaskStatusMessageTranslator(
055 new LayoutStagingBackgroundTaskStatusMessageTranslator());
056 }
057
058 @Override
059 public BackgroundTaskResult execute(BackgroundTask backgroundTask)
060 throws Exception {
061
062 Map<String, Serializable> taskContextMap =
063 backgroundTask.getTaskContextMap();
064
065 long sourceGroupId = MapUtil.getLong(taskContextMap, "groupId");
066 boolean privateLayout = MapUtil.getBoolean(
067 taskContextMap, "privateLayout");
068 Map<Long, Boolean> layoutIdMap = (Map<Long, Boolean>)taskContextMap.get(
069 "layoutIdMap");
070 Map<String, String[]> parameterMap =
071 (Map<String, String[]>)taskContextMap.get("parameterMap");
072 long remoteGroupId = MapUtil.getLong(taskContextMap, "remoteGroupId");
073 Date startDate = (Date)taskContextMap.get("startDate");
074 Date endDate = (Date)taskContextMap.get("endDate");
075 HttpPrincipal httpPrincipal = (HttpPrincipal)taskContextMap.get(
076 "httpPrincipal");
077
078 clearBackgroundTaskStatus(backgroundTask);
079
080 long stagingRequestId = 0;
081
082 File file = null;
083 FileInputStream fileInputStream = null;
084 MissingReferences missingReferences = null;
085
086 try {
087 ExportImportThreadLocal.setLayoutStagingInProcess(true);
088
089 file = exportLayoutsAsFile(
090 sourceGroupId, privateLayout, layoutIdMap, parameterMap,
091 remoteGroupId, startDate, endDate, httpPrincipal);
092
093 String checksum = FileUtil.getMD5Checksum(file);
094
095 fileInputStream = new FileInputStream(file);
096
097 stagingRequestId = StagingServiceHttp.createStagingRequest(
098 httpPrincipal, remoteGroupId, checksum);
099
100 byte[] bytes =
101 new byte[PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE];
102
103 int i = 0;
104 int j = 0;
105
106 String numberFormat = String.format(
107 "%%0%dd",
108 String.valueOf(
109 (int)(file.length() / bytes.length)).length() + 1);
110
111 while ((i = fileInputStream.read(bytes)) >= 0) {
112 String fileName =
113 file.getName() + String.format(numberFormat, j++);
114
115 if (i < PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE) {
116 byte[] tempBytes = new byte[i];
117
118 System.arraycopy(bytes, 0, tempBytes, 0, i);
119
120 StagingServiceHttp.updateStagingRequest(
121 httpPrincipal, stagingRequestId, fileName, tempBytes);
122 }
123 else {
124 StagingServiceHttp.updateStagingRequest(
125 httpPrincipal, stagingRequestId, fileName, bytes);
126 }
127
128 bytes =
129 new byte[PropsValues.STAGING_REMOTE_TRANSFER_BUFFER_SIZE];
130 }
131
132 backgroundTask = markBackgroundTask(backgroundTask, "exported");
133
134 missingReferences = StagingServiceHttp.validateStagingRequest(
135 httpPrincipal, stagingRequestId, privateLayout, parameterMap);
136
137 backgroundTask = markBackgroundTask(backgroundTask, "validated");
138
139 StagingServiceHttp.publishStagingRequest(
140 httpPrincipal, stagingRequestId, privateLayout, parameterMap);
141
142 boolean updateLastPublishDate = MapUtil.getBoolean(
143 parameterMap, PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);
144
145 if (updateLastPublishDate) {
146 DateRange dateRange = new DateRange(startDate, endDate);
147
148 StagingUtil.updateLastPublishDate(
149 sourceGroupId, privateLayout, dateRange, endDate);
150 }
151 }
152 finally {
153 ExportImportThreadLocal.setLayoutStagingInProcess(false);
154
155 StreamUtil.cleanUp(fileInputStream);
156
157 FileUtil.delete(file);
158
159 if (stagingRequestId > 0) {
160 StagingServiceHttp.cleanUpStagingRequest(
161 httpPrincipal, stagingRequestId);
162 }
163 }
164
165 return processMissingReferences(backgroundTask, missingReferences);
166 }
167
168 protected File exportLayoutsAsFile(
169 long sourceGroupId, boolean privateLayout,
170 Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
171 long remoteGroupId, Date startDate, Date endDate,
172 HttpPrincipal httpPrincipal)
173 throws Exception {
174
175 if ((layoutIdMap == null) || layoutIdMap.isEmpty()) {
176 return LayoutLocalServiceUtil.exportLayoutsAsFile(
177 sourceGroupId, privateLayout, null, parameterMap, startDate,
178 endDate);
179 }
180 else {
181 List<Layout> layouts = new ArrayList<Layout>();
182
183 for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
184 long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
185 boolean includeChildren = entry.getValue();
186
187 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
188
189 if (!layouts.contains(layout)) {
190 layouts.add(layout);
191 }
192
193 List<Layout> parentLayouts = getMissingRemoteParentLayouts(
194 httpPrincipal, layout, remoteGroupId);
195
196 for (Layout parentLayout : parentLayouts) {
197 if (!layouts.contains(parentLayout)) {
198 layouts.add(parentLayout);
199 }
200 }
201
202 if (includeChildren) {
203 for (Layout childLayout : layout.getAllChildren()) {
204 if (!layouts.contains(childLayout)) {
205 layouts.add(childLayout);
206 }
207 }
208 }
209 }
210
211 long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);
212
213 if (layoutIds.length <= 0) {
214 throw new RemoteExportException(
215 RemoteExportException.NO_LAYOUTS);
216 }
217
218 return LayoutLocalServiceUtil.exportLayoutsAsFile(
219 sourceGroupId, privateLayout, layoutIds, parameterMap,
220 startDate, endDate);
221 }
222 }
223
224
228 protected List<Layout> getMissingRemoteParentLayouts(
229 HttpPrincipal httpPrincipal, Layout layout, long remoteGroupId)
230 throws Exception {
231
232 List<Layout> missingRemoteParentLayouts = new ArrayList<Layout>();
233
234 long parentLayoutId = layout.getParentLayoutId();
235
236 while (parentLayoutId > 0) {
237 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
238 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
239
240 try {
241 LayoutServiceHttp.getLayoutByUuidAndGroupId(
242 httpPrincipal, parentLayout.getUuid(), remoteGroupId,
243 parentLayout.getPrivateLayout());
244
245
246
247 break;
248 }
249 catch (NoSuchLayoutException nsle) {
250 missingRemoteParentLayouts.add(parentLayout);
251
252 parentLayoutId = parentLayout.getParentLayoutId();
253 }
254 }
255
256 return missingRemoteParentLayouts;
257 }
258
259 }