001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.NoSuchGroupException;
018 import com.liferay.portal.RemoteExportException;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
022 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
023 import com.liferay.portal.kernel.lar.MissingReferences;
024 import com.liferay.portal.kernel.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.repository.model.FileEntry;
027 import com.liferay.portal.kernel.repository.model.Folder;
028 import com.liferay.portal.kernel.staging.StagingConstants;
029 import com.liferay.portal.kernel.staging.StagingUtil;
030 import com.liferay.portal.kernel.util.ContentTypes;
031 import com.liferay.portal.kernel.util.FileUtil;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.ParamUtil;
034 import com.liferay.portal.kernel.util.StreamUtil;
035 import com.liferay.portal.kernel.util.UnicodeProperties;
036 import com.liferay.portal.model.Group;
037 import com.liferay.portal.model.GroupConstants;
038 import com.liferay.portal.model.LayoutSet;
039 import com.liferay.portal.model.Repository;
040 import com.liferay.portal.model.User;
041 import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
042 import com.liferay.portal.security.auth.HttpPrincipal;
043 import com.liferay.portal.security.auth.PrincipalException;
044 import com.liferay.portal.security.auth.RemoteAuthException;
045 import com.liferay.portal.security.permission.PermissionChecker;
046 import com.liferay.portal.security.permission.PermissionThreadLocal;
047 import com.liferay.portal.service.ServiceContext;
048 import com.liferay.portal.service.base.StagingLocalServiceBaseImpl;
049 import com.liferay.portal.service.http.GroupServiceHttp;
050 import com.liferay.portal.util.PortletKeys;
051 import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
052 import com.liferay.portlet.documentlibrary.NoSuchFolderException;
053 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
054
055 import java.io.File;
056 import java.io.FileOutputStream;
057 import java.io.IOException;
058 import java.io.InputStream;
059
060 import java.util.HashMap;
061 import java.util.HashSet;
062 import java.util.List;
063 import java.util.Map;
064 import java.util.Set;
065
066 import javax.portlet.PortletRequest;
067
068
072 public class StagingLocalServiceImpl extends StagingLocalServiceBaseImpl {
073
074 @Override
075 public void cleanUpStagingRequest(long stagingRequestId)
076 throws PortalException, SystemException {
077
078 try {
079 PortletFileRepositoryUtil.deleteFolder(stagingRequestId);
080 }
081 catch (NoSuchFolderException nsfe) {
082 if (_log.isDebugEnabled()) {
083 _log.debug(
084 "Unable to clean up staging request " + stagingRequestId,
085 nsfe);
086 }
087 }
088 }
089
090 @Override
091 public long createStagingRequest(long userId, long groupId, String checksum)
092 throws PortalException, SystemException {
093
094 ServiceContext serviceContext = new ServiceContext();
095
096 Repository repository = PortletFileRepositoryUtil.addPortletRepository(
097 groupId, PortletKeys.SITES_ADMIN, serviceContext);
098
099 Folder folder = PortletFileRepositoryUtil.addPortletFolder(
100 userId, repository.getRepositoryId(),
101 DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, checksum,
102 serviceContext);
103
104 return folder.getFolderId();
105 }
106
107 @Override
108 public void disableStaging(Group liveGroup, ServiceContext serviceContext)
109 throws PortalException, SystemException {
110
111 disableStaging((PortletRequest)null, liveGroup, serviceContext);
112 }
113
114 @Override
115 public void disableStaging(
116 PortletRequest portletRequest, Group liveGroup,
117 ServiceContext serviceContext)
118 throws PortalException, SystemException {
119
120 UnicodeProperties typeSettingsProperties =
121 liveGroup.getTypeSettingsProperties();
122
123 boolean stagedRemotely = GetterUtil.getBoolean(
124 typeSettingsProperties.getProperty("stagedRemotely"));
125
126 if (stagedRemotely) {
127 String remoteURL = StagingUtil.buildRemoteURL(
128 typeSettingsProperties);
129
130 long remoteGroupId = GetterUtil.getLong(
131 typeSettingsProperties.getProperty("remoteGroupId"));
132
133 disableRemoteStaging(remoteURL, remoteGroupId);
134 }
135
136 typeSettingsProperties.remove("branchingPrivate");
137 typeSettingsProperties.remove("branchingPublic");
138 typeSettingsProperties.remove("remoteAddress");
139 typeSettingsProperties.remove("remoteGroupId");
140 typeSettingsProperties.remove("remotePathContext");
141 typeSettingsProperties.remove("remotePort");
142 typeSettingsProperties.remove("secureConnection");
143 typeSettingsProperties.remove("staged");
144 typeSettingsProperties.remove("stagedRemotely");
145
146 Set<String> keys = new HashSet<String>();
147
148 for (String key : typeSettingsProperties.keySet()) {
149 if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
150 keys.add(key);
151 }
152 }
153
154 for (String key : keys) {
155 typeSettingsProperties.remove(key);
156 }
157
158 StagingUtil.deleteLastImportSettings(liveGroup, true);
159 StagingUtil.deleteLastImportSettings(liveGroup, false);
160
161 if (liveGroup.hasStagingGroup()) {
162 Group stagingGroup = liveGroup.getStagingGroup();
163
164 layoutSetBranchLocalService.deleteLayoutSetBranches(
165 stagingGroup.getGroupId(), true, true);
166 layoutSetBranchLocalService.deleteLayoutSetBranches(
167 stagingGroup.getGroupId(), false, true);
168
169 groupLocalService.deleteGroup(stagingGroup.getGroupId());
170
171 liveGroup.clearStagingGroup();
172 }
173 else {
174 layoutSetBranchLocalService.deleteLayoutSetBranches(
175 liveGroup.getGroupId(), true, true);
176 layoutSetBranchLocalService.deleteLayoutSetBranches(
177 liveGroup.getGroupId(), false, true);
178 }
179
180 groupLocalService.updateGroup(
181 liveGroup.getGroupId(), typeSettingsProperties.toString());
182 }
183
184 @Override
185 public void enableLocalStaging(
186 long userId, Group liveGroup, boolean branchingPublic,
187 boolean branchingPrivate, ServiceContext serviceContext)
188 throws PortalException, SystemException {
189
190 if (liveGroup.isStagedRemotely()) {
191 disableStaging(liveGroup, serviceContext);
192 }
193
194 UnicodeProperties typeSettingsProperties =
195 liveGroup.getTypeSettingsProperties();
196
197 typeSettingsProperties.setProperty(
198 "branchingPrivate", String.valueOf(branchingPrivate));
199 typeSettingsProperties.setProperty(
200 "branchingPublic", String.valueOf(branchingPublic));
201 typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
202 typeSettingsProperties.setProperty(
203 "stagedRemotely", String.valueOf(false));
204
205 setCommonStagingOptions(
206 liveGroup, typeSettingsProperties, serviceContext);
207
208 groupLocalService.updateGroup(
209 liveGroup.getGroupId(), typeSettingsProperties.toString());
210
211 if (!liveGroup.hasStagingGroup()) {
212 serviceContext.setAttribute("staging", String.valueOf(true));
213
214 Group stagingGroup = groupLocalService.addGroup(
215 userId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
216 liveGroup.getClassName(), liveGroup.getClassPK(),
217 liveGroup.getGroupId(), liveGroup.getDescriptiveName(),
218 liveGroup.getDescription(), liveGroup.getType(),
219 liveGroup.isManualMembership(),
220 liveGroup.getMembershipRestriction(),
221 liveGroup.getFriendlyURL(), false, liveGroup.isActive(),
222 serviceContext);
223
224 Map<String, String[]> parameterMap =
225 StagingUtil.getStagingParameters();
226
227 if (liveGroup.hasPrivateLayouts()) {
228 StagingUtil.publishLayouts(
229 userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
230 true, parameterMap, null, null);
231 }
232
233 if (liveGroup.hasPublicLayouts() ||
234 !liveGroup.hasPrivateLayouts()) {
235
236 StagingUtil.publishLayouts(
237 userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
238 false, parameterMap, null, null);
239 }
240 }
241
242 StagingUtil.checkDefaultLayoutSetBranches(
243 userId, liveGroup, branchingPublic, branchingPrivate, false,
244 serviceContext);
245 }
246
247 @Override
248 public void enableRemoteStaging(
249 long userId, Group liveGroup, boolean branchingPublic,
250 boolean branchingPrivate, String remoteAddress, int remotePort,
251 String remotePathContext, boolean secureConnection,
252 long remoteGroupId, ServiceContext serviceContext)
253 throws PortalException, SystemException {
254
255 StagingUtil.validateRemote(
256 remoteAddress, remotePort, remotePathContext, secureConnection,
257 remoteGroupId);
258
259 if (liveGroup.hasStagingGroup()) {
260 disableStaging(liveGroup, serviceContext);
261 }
262
263 String remoteURL = StagingUtil.buildRemoteURL(
264 remoteAddress, remotePort, remotePathContext, secureConnection,
265 GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
266
267 UnicodeProperties typeSettingsProperties =
268 liveGroup.getTypeSettingsProperties();
269
270 boolean stagedRemotely = GetterUtil.getBoolean(
271 typeSettingsProperties.getProperty("stagedRemotely"));
272
273 if (stagedRemotely) {
274 long oldRemoteGroupId = GetterUtil.getLong(
275 typeSettingsProperties.getProperty("remoteGroupId"));
276
277 String oldRemoteURL = StagingUtil.buildRemoteURL(
278 typeSettingsProperties);
279
280 if (!remoteURL.equals(oldRemoteURL) ||
281 (remoteGroupId != oldRemoteGroupId)) {
282
283 disableRemoteStaging(oldRemoteURL, oldRemoteGroupId);
284
285 stagedRemotely = false;
286 }
287 }
288
289 if (!stagedRemotely) {
290 enableRemoteStaging(remoteURL, remoteGroupId);
291 }
292
293 typeSettingsProperties.setProperty(
294 "branchingPrivate", String.valueOf(branchingPrivate));
295 typeSettingsProperties.setProperty(
296 "branchingPublic", String.valueOf(branchingPublic));
297 typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
298 typeSettingsProperties.setProperty(
299 "remoteGroupId", String.valueOf(remoteGroupId));
300 typeSettingsProperties.setProperty(
301 "remotePathContext", remotePathContext);
302 typeSettingsProperties.setProperty(
303 "remotePort", String.valueOf(remotePort));
304 typeSettingsProperties.setProperty(
305 "secureConnection", String.valueOf(secureConnection));
306 typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
307 typeSettingsProperties.setProperty(
308 "stagedRemotely", Boolean.TRUE.toString());
309
310 setCommonStagingOptions(
311 liveGroup, typeSettingsProperties, serviceContext);
312
313 groupLocalService.updateGroup(
314 liveGroup.getGroupId(), typeSettingsProperties.toString());
315
316 updateStagedPortlets(remoteURL, remoteGroupId, typeSettingsProperties);
317
318 StagingUtil.checkDefaultLayoutSetBranches(
319 userId, liveGroup, branchingPublic, branchingPrivate, true,
320 serviceContext);
321 }
322
323 @Override
324 public void publishStagingRequest(
325 long userId, long stagingRequestId, boolean privateLayout,
326 Map<String, String[]> parameterMap)
327 throws PortalException, SystemException {
328
329 try {
330 ExportImportThreadLocal.setLayoutImportInProcess(true);
331
332 Folder folder = PortletFileRepositoryUtil.getPortletFolder(
333 stagingRequestId);
334
335 FileEntry stagingRequestFileEntry = getStagingRequestFileEntry(
336 userId, stagingRequestId, folder);
337
338 layoutLocalService.importLayouts(
339 userId, folder.getGroupId(), privateLayout, parameterMap,
340 stagingRequestFileEntry.getContentStream());
341 }
342 finally {
343 ExportImportThreadLocal.setLayoutImportInProcess(false);
344 }
345 }
346
347 @Override
348 public void updateStagingRequest(
349 long userId, long stagingRequestId, String fileName, byte[] bytes)
350 throws PortalException, SystemException {
351
352 Folder folder = PortletFileRepositoryUtil.getPortletFolder(
353 stagingRequestId);
354
355 fileName += PortletFileRepositoryUtil.getPortletFileEntriesCount(
356 folder.getGroupId(), folder.getFolderId());
357
358 PortletFileRepositoryUtil.addPortletFileEntry(
359 folder.getGroupId(), userId, Group.class.getName(),
360 folder.getGroupId(), PortletKeys.SITES_ADMIN, folder.getFolderId(),
361 new UnsyncByteArrayInputStream(bytes), fileName,
362 ContentTypes.APPLICATION_ZIP, false);
363 }
364
365 @Override
366 public MissingReferences validateStagingRequest(
367 long userId, long stagingRequestId, boolean privateLayout,
368 Map<String, String[]> parameterMap)
369 throws PortalException, SystemException {
370
371 try {
372 ExportImportThreadLocal.setLayoutValidationInProcess(true);
373
374 Folder folder = PortletFileRepositoryUtil.getPortletFolder(
375 stagingRequestId);
376
377 FileEntry fileEntry = getStagingRequestFileEntry(
378 userId, stagingRequestId, folder);
379
380 return layoutLocalService.validateImportLayoutsFile(
381 userId, folder.getGroupId(), privateLayout, parameterMap,
382 fileEntry.getContentStream());
383 }
384 finally {
385 ExportImportThreadLocal.setLayoutValidationInProcess(false);
386 }
387 }
388
389 protected void clearLastPublishDate(long groupId, boolean privateLayout)
390 throws PortalException, SystemException {
391
392 LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
393 groupId, privateLayout);
394
395 UnicodeProperties settingsProperties =
396 layoutSet.getSettingsProperties();
397
398 settingsProperties.remove("last-publish-date");
399
400 layoutSetLocalService.updateSettings(
401 groupId, privateLayout, settingsProperties.toString());
402 }
403
404 protected void disableRemoteStaging(String remoteURL, long remoteGroupId)
405 throws PortalException {
406
407 PermissionChecker permissionChecker =
408 PermissionThreadLocal.getPermissionChecker();
409
410 User user = permissionChecker.getUser();
411
412 HttpPrincipal httpPrincipal = new HttpPrincipal(
413 remoteURL, user.getScreenName(), user.getPassword(),
414 user.getPasswordEncrypted());
415
416 try {
417 GroupServiceHttp.disableStaging(httpPrincipal, remoteGroupId);
418 }
419 catch (NoSuchGroupException nsge) {
420 RemoteExportException ree = new RemoteExportException(
421 RemoteExportException.NO_GROUP);
422
423 ree.setGroupId(remoteGroupId);
424
425 throw ree;
426 }
427 catch (PrincipalException pe) {
428 RemoteExportException ree = new RemoteExportException(
429 RemoteExportException.NO_PERMISSIONS);
430
431 ree.setGroupId(remoteGroupId);
432
433 throw ree;
434 }
435 catch (RemoteAuthException rae) {
436 rae.setURL(remoteURL);
437
438 throw rae;
439 }
440 catch (SystemException se) {
441 RemoteExportException ree = new RemoteExportException(
442 RemoteExportException.BAD_CONNECTION);
443
444 ree.setURL(remoteURL);
445
446 throw ree;
447 }
448 }
449
450 protected void enableRemoteStaging(String remoteURL, long remoteGroupId)
451 throws PortalException {
452
453 PermissionChecker permissionChecker =
454 PermissionThreadLocal.getPermissionChecker();
455
456 User user = permissionChecker.getUser();
457
458 HttpPrincipal httpPrincipal = new HttpPrincipal(
459 remoteURL, user.getScreenName(), user.getPassword(),
460 user.getPasswordEncrypted());
461
462 try {
463 GroupServiceHttp.enableStaging(httpPrincipal, remoteGroupId);
464 }
465 catch (NoSuchGroupException nsge) {
466 RemoteExportException ree = new RemoteExportException(
467 RemoteExportException.NO_GROUP);
468
469 ree.setGroupId(remoteGroupId);
470
471 throw ree;
472 }
473 catch (PrincipalException pe) {
474 RemoteExportException ree = new RemoteExportException(
475 RemoteExportException.NO_PERMISSIONS);
476
477 ree.setGroupId(remoteGroupId);
478
479 throw ree;
480 }
481 catch (RemoteAuthException rae) {
482 rae.setURL(remoteURL);
483
484 throw rae;
485 }
486 catch (SystemException se) {
487 RemoteExportException ree = new RemoteExportException(
488 RemoteExportException.BAD_CONNECTION);
489
490 ree.setURL(remoteURL);
491
492 throw ree;
493 }
494 }
495
496 protected FileEntry fetchStagingRequestFileEntry(
497 long stagingRequestId, Folder folder)
498 throws PortalException, SystemException {
499
500 try {
501 return PortletFileRepositoryUtil.getPortletFileEntry(
502 folder.getGroupId(), folder.getFolderId(),
503 getAssembledFileName(stagingRequestId));
504 }
505 catch (NoSuchFileEntryException nsfe) {
506 return null;
507 }
508 }
509
510 protected String getAssembledFileName(long stagingRequestId) {
511 return _ASSEMBLED_LAR_PREFIX + String.valueOf(stagingRequestId) +
512 ".lar";
513 }
514
515 protected FileEntry getStagingRequestFileEntry(
516 long userId, long stagingRequestId, Folder folder)
517 throws PortalException, SystemException {
518
519 FileEntry stagingRequestFileEntry = fetchStagingRequestFileEntry(
520 stagingRequestId, folder);
521
522 if (stagingRequestFileEntry != null) {
523 return stagingRequestFileEntry;
524 }
525
526 FileOutputStream fileOutputStream = null;
527
528 File tempFile = null;
529
530 try {
531 tempFile = FileUtil.createTempFile("lar");
532
533 fileOutputStream = new FileOutputStream(tempFile);
534
535 List<FileEntry> fileEntries =
536 PortletFileRepositoryUtil.getPortletFileEntries(
537 folder.getGroupId(), folder.getFolderId());
538
539 for (FileEntry fileEntry : fileEntries) {
540 InputStream inputStream = fileEntry.getContentStream();
541
542 try {
543 StreamUtil.transfer(inputStream, fileOutputStream, false);
544 }
545 finally {
546 StreamUtil.cleanUp(inputStream);
547
548 PortletFileRepositoryUtil.deletePortletFileEntry(
549 fileEntry.getFileEntryId());
550 }
551 }
552
553 String checksum = FileUtil.getMD5Checksum(tempFile);
554
555 if (!checksum.equals(folder.getName())) {
556 throw new SystemException("Invalid checksum for LAR file");
557 }
558
559 PortletFileRepositoryUtil.addPortletFileEntry(
560 folder.getGroupId(), userId, Group.class.getName(),
561 folder.getGroupId(), PortletKeys.SITES_ADMIN,
562 folder.getFolderId(), tempFile,
563 getAssembledFileName(stagingRequestId),
564 ContentTypes.APPLICATION_ZIP, false);
565
566 stagingRequestFileEntry = fetchStagingRequestFileEntry(
567 stagingRequestId, folder);
568
569 if (stagingRequestFileEntry == null) {
570 throw new SystemException("Unable to assemble LAR file");
571 }
572
573 return stagingRequestFileEntry;
574 }
575 catch (IOException ioe) {
576 throw new SystemException("Unable to reassemble LAR file", ioe);
577 }
578 finally {
579 StreamUtil.cleanUp(fileOutputStream);
580
581 FileUtil.delete(tempFile);
582 }
583 }
584
585 protected void setCommonStagingOptions(
586 Group liveGroup, UnicodeProperties typeSettingsProperties,
587 ServiceContext serviceContext)
588 throws PortalException, SystemException {
589
590 clearLastPublishDate(liveGroup.getGroupId(), true);
591 clearLastPublishDate(liveGroup.getGroupId(), false);
592
593 Set<String> parameterNames = serviceContext.getAttributes().keySet();
594
595 for (String parameterName : parameterNames) {
596 if (parameterName.startsWith(StagingConstants.STAGED_PORTLET) &&
597 !parameterName.endsWith("Checkbox")) {
598
599 boolean staged = ParamUtil.getBoolean(
600 serviceContext, parameterName);
601
602 typeSettingsProperties.setProperty(
603 parameterName, String.valueOf(staged));
604 }
605 }
606 }
607
608 protected void updateStagedPortlets(
609 String remoteURL, long remoteGroupId,
610 UnicodeProperties typeSettingsProperties)
611 throws PortalException {
612
613 PermissionChecker permissionChecker =
614 PermissionThreadLocal.getPermissionChecker();
615
616 User user = permissionChecker.getUser();
617
618 HttpPrincipal httpPrincipal = new HttpPrincipal(
619 remoteURL, user.getScreenName(), user.getPassword(),
620 user.getPasswordEncrypted());
621
622 Map<String, String> stagedPortletIds = new HashMap<String, String>();
623
624 for (String key : typeSettingsProperties.keySet()) {
625 if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
626 stagedPortletIds.put(
627 key, typeSettingsProperties.getProperty(key));
628 }
629 }
630
631 try {
632 GroupServiceHttp.updateStagedPortlets(
633 httpPrincipal, remoteGroupId, stagedPortletIds);
634 }
635 catch (NoSuchGroupException nsge) {
636 RemoteExportException ree = new RemoteExportException(
637 RemoteExportException.NO_GROUP);
638
639 ree.setGroupId(remoteGroupId);
640
641 throw ree;
642 }
643 catch (PrincipalException pe) {
644 RemoteExportException ree = new RemoteExportException(
645 RemoteExportException.NO_PERMISSIONS);
646
647 ree.setGroupId(remoteGroupId);
648
649 throw ree;
650 }
651 catch (RemoteAuthException rae) {
652 rae.setURL(remoteURL);
653
654 throw rae;
655 }
656 catch (SystemException se) {
657 RemoteExportException ree = new RemoteExportException(
658 RemoteExportException.BAD_CONNECTION);
659
660 ree.setURL(remoteURL);
661
662 throw ree;
663 }
664 }
665
666 private static final String _ASSEMBLED_LAR_PREFIX = "assembled_";
667
668 private static Log _log = LogFactoryUtil.getLog(
669 StagingLocalServiceImpl.class);
670
671 }