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.portlet.exportimport.service.impl;
016    
017    import com.liferay.portal.NoSuchGroupException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
021    import com.liferay.portal.kernel.language.LanguageUtil;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.repository.model.FileEntry;
025    import com.liferay.portal.kernel.repository.model.Folder;
026    import com.liferay.portal.kernel.util.ContentTypes;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.LocaleUtil;
030    import com.liferay.portal.kernel.util.PropertiesParamUtil;
031    import com.liferay.portal.kernel.util.PropsKeys;
032    import com.liferay.portal.kernel.util.StreamUtil;
033    import com.liferay.portal.kernel.util.UnicodeProperties;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.workflow.WorkflowConstants;
036    import com.liferay.portal.model.Group;
037    import com.liferay.portal.model.GroupConstants;
038    import com.liferay.portal.model.Layout;
039    import com.liferay.portal.model.LayoutRevision;
040    import com.liferay.portal.model.LayoutSetBranch;
041    import com.liferay.portal.model.LayoutSetBranchConstants;
042    import com.liferay.portal.model.PortletPreferences;
043    import com.liferay.portal.model.Repository;
044    import com.liferay.portal.model.User;
045    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
046    import com.liferay.portal.security.auth.HttpPrincipal;
047    import com.liferay.portal.security.auth.PrincipalException;
048    import com.liferay.portal.security.auth.RemoteAuthException;
049    import com.liferay.portal.security.permission.PermissionChecker;
050    import com.liferay.portal.security.permission.PermissionThreadLocal;
051    import com.liferay.portal.service.ServiceContext;
052    import com.liferay.portal.service.http.GroupServiceHttp;
053    import com.liferay.portal.util.PortalUtil;
054    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
055    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
056    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
057    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelTitleComparator;
058    import com.liferay.portlet.exportimport.RemoteExportException;
059    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationParameterMapFactory;
060    import com.liferay.portlet.exportimport.lar.ExportImportDateUtil;
061    import com.liferay.portlet.exportimport.lar.ExportImportThreadLocal;
062    import com.liferay.portlet.exportimport.lar.MissingReferences;
063    import com.liferay.portlet.exportimport.model.ExportImportConfiguration;
064    import com.liferay.portlet.exportimport.service.base.StagingLocalServiceBaseImpl;
065    import com.liferay.portlet.exportimport.staging.StagingAdvicesThreadLocal;
066    import com.liferay.portlet.exportimport.staging.StagingConstants;
067    import com.liferay.portlet.exportimport.staging.StagingUtil;
068    
069    import java.io.File;
070    import java.io.FileOutputStream;
071    import java.io.IOException;
072    import java.io.Serializable;
073    
074    import java.util.Date;
075    import java.util.HashMap;
076    import java.util.HashSet;
077    import java.util.List;
078    import java.util.Map;
079    import java.util.Set;
080    
081    import javax.portlet.PortletRequest;
082    
083    /**
084     * @author Michael C. Han
085     * @author Mate Thurzo
086     * @author Vilmos Papp
087     */
088    public class StagingLocalServiceImpl extends StagingLocalServiceBaseImpl {
089    
090            @Override
091            public void checkDefaultLayoutSetBranches(
092                            long userId, Group liveGroup, boolean branchingPublic,
093                            boolean branchingPrivate, boolean remote,
094                            ServiceContext serviceContext)
095                    throws PortalException {
096    
097                    long targetGroupId = 0;
098    
099                    if (remote) {
100                            targetGroupId = liveGroup.getGroupId();
101                    }
102                    else {
103                            Group stagingGroup = liveGroup.getStagingGroup();
104    
105                            if (stagingGroup == null) {
106                                    return;
107                            }
108    
109                            targetGroupId = stagingGroup.getGroupId();
110                    }
111    
112                    LayoutSetBranch layoutSetBranch =
113                            layoutSetBranchLocalService.fetchLayoutSetBranch(
114                                    targetGroupId, false,
115                                    LayoutSetBranchConstants.MASTER_BRANCH_NAME);
116    
117                    if (branchingPublic && (layoutSetBranch == null)) {
118                            addDefaultLayoutSetBranch(
119                                    userId, targetGroupId, liveGroup.getDescriptiveName(), false,
120                                    serviceContext);
121                    }
122                    else if (!branchingPublic && (layoutSetBranch != null)) {
123                            deleteLayoutSetBranches(targetGroupId, false);
124                    }
125                    else if (layoutSetBranch != null) {
126                            ExportImportDateUtil.clearLastPublishDate(targetGroupId, false);
127                    }
128    
129                    layoutSetBranch = layoutSetBranchLocalService.fetchLayoutSetBranch(
130                            targetGroupId, true, LayoutSetBranchConstants.MASTER_BRANCH_NAME);
131    
132                    if (branchingPrivate && (layoutSetBranch == null)) {
133                            addDefaultLayoutSetBranch(
134                                    userId, targetGroupId, liveGroup.getDescriptiveName(), true,
135                                    serviceContext);
136                    }
137                    else if (!branchingPrivate && (layoutSetBranch != null)) {
138                            deleteLayoutSetBranches(targetGroupId, true);
139                    }
140                    else if (layoutSetBranch != null) {
141                            ExportImportDateUtil.clearLastPublishDate(targetGroupId, true);
142                    }
143            }
144    
145            @Override
146            public void cleanUpStagingRequest(long stagingRequestId)
147                    throws PortalException {
148    
149                    try {
150                            PortletFileRepositoryUtil.deletePortletFolder(stagingRequestId);
151                    }
152                    catch (NoSuchFolderException nsfe) {
153                            if (_log.isDebugEnabled()) {
154                                    _log.debug(
155                                            "Unable to clean up staging request " + stagingRequestId,
156                                            nsfe);
157                            }
158                    }
159            }
160    
161            @Override
162            public long createStagingRequest(long userId, long groupId, String checksum)
163                    throws PortalException {
164    
165                    ServiceContext serviceContext = new ServiceContext();
166    
167                    Repository repository = PortletFileRepositoryUtil.addPortletRepository(
168                            groupId, _PORTLET_REPOSITORY_ID, serviceContext);
169    
170                    Folder folder = PortletFileRepositoryUtil.addPortletFolder(
171                            userId, repository.getRepositoryId(),
172                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, checksum,
173                            serviceContext);
174    
175                    return folder.getFolderId();
176            }
177    
178            @Override
179            public void disableStaging(Group liveGroup, ServiceContext serviceContext)
180                    throws PortalException {
181    
182                    disableStaging((PortletRequest)null, liveGroup, serviceContext);
183            }
184    
185            @Override
186            public void disableStaging(
187                            PortletRequest portletRequest, Group liveGroup,
188                            ServiceContext serviceContext)
189                    throws PortalException {
190    
191                    UnicodeProperties typeSettingsProperties =
192                            liveGroup.getTypeSettingsProperties();
193    
194                    boolean stagedLocally = GetterUtil.getBoolean(
195                            typeSettingsProperties.getProperty("staged"));
196                    boolean stagedRemotely = GetterUtil.getBoolean(
197                            typeSettingsProperties.getProperty("stagedRemotely"));
198    
199                    if (!stagedLocally && !stagedRemotely) {
200                            return;
201                    }
202    
203                    if (stagedRemotely) {
204                            String remoteURL = StagingUtil.buildRemoteURL(
205                                    typeSettingsProperties);
206    
207                            long remoteGroupId = GetterUtil.getLong(
208                                    typeSettingsProperties.getProperty("remoteGroupId"));
209                            boolean forceDisable = GetterUtil.getBoolean(
210                                    serviceContext.getAttribute("forceDisable"));
211    
212                            disableRemoteStaging(remoteURL, remoteGroupId, forceDisable);
213                    }
214    
215                    typeSettingsProperties.remove("branchingPrivate");
216                    typeSettingsProperties.remove("branchingPublic");
217                    typeSettingsProperties.remove("remoteAddress");
218                    typeSettingsProperties.remove("remoteGroupId");
219                    typeSettingsProperties.remove("remotePathContext");
220                    typeSettingsProperties.remove("remotePort");
221                    typeSettingsProperties.remove("secureConnection");
222                    typeSettingsProperties.remove("staged");
223                    typeSettingsProperties.remove("stagedRemotely");
224    
225                    Set<String> keys = new HashSet<>();
226    
227                    for (String key : typeSettingsProperties.keySet()) {
228                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
229                                    keys.add(key);
230                            }
231                    }
232    
233                    for (String key : keys) {
234                            typeSettingsProperties.remove(key);
235                    }
236    
237                    StagingUtil.deleteLastImportSettings(liveGroup, true);
238                    StagingUtil.deleteLastImportSettings(liveGroup, false);
239    
240                    checkDefaultLayoutSetBranches(
241                            serviceContext.getUserId(), liveGroup, false, false, stagedRemotely,
242                            serviceContext);
243    
244                    if (liveGroup.hasStagingGroup()) {
245                            Group stagingGroup = liveGroup.getStagingGroup();
246    
247                            groupLocalService.deleteGroup(stagingGroup.getGroupId());
248    
249                            liveGroup.clearStagingGroup();
250                    }
251    
252                    groupLocalService.updateGroup(
253                            liveGroup.getGroupId(), typeSettingsProperties.toString());
254            }
255    
256            @Override
257            public void enableLocalStaging(
258                            long userId, Group liveGroup, boolean branchingPublic,
259                            boolean branchingPrivate, ServiceContext serviceContext)
260                    throws PortalException {
261    
262                    if (liveGroup.isStagedRemotely()) {
263                            disableStaging(liveGroup, serviceContext);
264                    }
265    
266                    boolean hasStagingGroup = liveGroup.hasStagingGroup();
267    
268                    if (!hasStagingGroup) {
269                            serviceContext.setAttribute("staging", String.valueOf(true));
270    
271                            addStagingGroup(userId, liveGroup, serviceContext);
272                    }
273    
274                    checkDefaultLayoutSetBranches(
275                            userId, liveGroup, branchingPublic, branchingPrivate, false,
276                            serviceContext);
277    
278                    UnicodeProperties typeSettingsProperties =
279                            liveGroup.getTypeSettingsProperties();
280    
281                    typeSettingsProperties.setProperty(
282                            "branchingPrivate", String.valueOf(branchingPrivate));
283                    typeSettingsProperties.setProperty(
284                            "branchingPublic", String.valueOf(branchingPublic));
285                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
286                    typeSettingsProperties.setProperty(
287                            "stagedRemotely", String.valueOf(false));
288    
289                    setCommonStagingOptions(
290                            liveGroup, typeSettingsProperties, serviceContext);
291    
292                    groupLocalService.updateGroup(
293                            liveGroup.getGroupId(), typeSettingsProperties.toString());
294    
295                    if (!hasStagingGroup) {
296                            Group stagingGroup = liveGroup.getStagingGroup();
297    
298                            Map<String, String[]> parameterMap =
299                                    ExportImportConfigurationParameterMapFactory.
300                                            buildParameterMap();
301    
302                            if (liveGroup.hasPrivateLayouts()) {
303                                    StagingUtil.publishLayouts(
304                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
305                                            true, parameterMap);
306                            }
307    
308                            if (liveGroup.hasPublicLayouts() ||
309                                    !liveGroup.hasPrivateLayouts()) {
310    
311                                    StagingUtil.publishLayouts(
312                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
313                                            false, parameterMap);
314                            }
315                    }
316            }
317    
318            @Override
319            public void enableRemoteStaging(
320                            long userId, Group stagingGroup, boolean branchingPublic,
321                            boolean branchingPrivate, String remoteAddress, int remotePort,
322                            String remotePathContext, boolean secureConnection,
323                            long remoteGroupId, ServiceContext serviceContext)
324                    throws PortalException {
325    
326                    StagingUtil.validateRemote(
327                            stagingGroup.getGroupId(), remoteAddress, remotePort,
328                            remotePathContext, secureConnection, remoteGroupId);
329    
330                    if (stagingGroup.hasStagingGroup()) {
331                            disableStaging(stagingGroup, serviceContext);
332                    }
333    
334                    String remoteURL = StagingUtil.buildRemoteURL(
335                            remoteAddress, remotePort, remotePathContext, secureConnection,
336                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
337    
338                    UnicodeProperties typeSettingsProperties =
339                            stagingGroup.getTypeSettingsProperties();
340    
341                    boolean stagedRemotely = GetterUtil.getBoolean(
342                            typeSettingsProperties.getProperty("stagedRemotely"));
343    
344                    if (stagedRemotely) {
345                            long oldRemoteGroupId = GetterUtil.getLong(
346                                    typeSettingsProperties.getProperty("remoteGroupId"));
347    
348                            String oldRemoteURL = StagingUtil.buildRemoteURL(
349                                    typeSettingsProperties);
350    
351                            if (!remoteURL.equals(oldRemoteURL) ||
352                                    (remoteGroupId != oldRemoteGroupId)) {
353    
354                                    disableRemoteStaging(oldRemoteURL, oldRemoteGroupId, false);
355    
356                                    stagedRemotely = false;
357                            }
358                    }
359    
360                    if (!stagedRemotely) {
361                            enableRemoteStaging(remoteURL, remoteGroupId);
362                    }
363    
364                    checkDefaultLayoutSetBranches(
365                            userId, stagingGroup, branchingPublic, branchingPrivate, true,
366                            serviceContext);
367    
368                    typeSettingsProperties.setProperty(
369                            "branchingPrivate", String.valueOf(branchingPrivate));
370                    typeSettingsProperties.setProperty(
371                            "branchingPublic", String.valueOf(branchingPublic));
372                    typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
373                    typeSettingsProperties.setProperty(
374                            "remoteGroupId", String.valueOf(remoteGroupId));
375                    typeSettingsProperties.setProperty(
376                            "remotePathContext", remotePathContext);
377                    typeSettingsProperties.setProperty(
378                            "remotePort", String.valueOf(remotePort));
379                    typeSettingsProperties.setProperty(
380                            "secureConnection", String.valueOf(secureConnection));
381                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
382                    typeSettingsProperties.setProperty(
383                            "stagedRemotely", Boolean.TRUE.toString());
384    
385                    setCommonStagingOptions(
386                            stagingGroup, typeSettingsProperties, serviceContext);
387    
388                    groupLocalService.updateGroup(
389                            stagingGroup.getGroupId(), typeSettingsProperties.toString());
390    
391                    updateStagedPortlets(remoteURL, remoteGroupId, typeSettingsProperties);
392            }
393    
394            /**
395             * @deprecated As of 7.0.0, with no direct replacement
396             */
397            @Deprecated
398            @Override
399            @SuppressWarnings("unused")
400            public MissingReferences publishStagingRequest(
401                            long userId, long stagingRequestId, boolean privateLayout,
402                            Map<String, String[]> parameterMap)
403                    throws PortalException {
404    
405                    throw new UnsupportedOperationException();
406            }
407    
408            @Override
409            public MissingReferences publishStagingRequest(
410                            long userId, long stagingRequestId,
411                            ExportImportConfiguration exportImportConfiguration)
412                    throws PortalException {
413    
414                    File file = null;
415    
416                    try {
417                            ExportImportThreadLocal.setLayoutImportInProcess(true);
418                            ExportImportThreadLocal.setLayoutStagingInProcess(true);
419    
420                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
421                                    stagingRequestId);
422    
423                            FileEntry stagingRequestFileEntry = getStagingRequestFileEntry(
424                                    userId, stagingRequestId, folder);
425    
426                            file = FileUtil.createTempFile("lar");
427    
428                            FileUtil.write(file, stagingRequestFileEntry.getContentStream());
429    
430                            Map<String, Serializable> settingsMap =
431                                    exportImportConfiguration.getSettingsMap();
432    
433                            settingsMap.put("userId", userId);
434    
435                            exportImportLocalService.importLayoutsDataDeletions(
436                                    exportImportConfiguration, file);
437    
438                            MissingReferences missingReferences =
439                                    exportImportLocalService.validateImportLayoutsFile(
440                                            exportImportConfiguration, file);
441    
442                            exportImportLocalService.importLayouts(
443                                    exportImportConfiguration, file);
444    
445                            return missingReferences;
446                    }
447                    catch (IOException ioe) {
448                            throw new SystemException(ioe);
449                    }
450                    finally {
451                            ExportImportThreadLocal.setLayoutImportInProcess(false);
452                            ExportImportThreadLocal.setLayoutStagingInProcess(false);
453                    }
454            }
455    
456            @Override
457            public void updateStagingRequest(
458                            long userId, long stagingRequestId, String fileName, byte[] bytes)
459                    throws PortalException {
460    
461                    Folder folder = PortletFileRepositoryUtil.getPortletFolder(
462                            stagingRequestId);
463    
464                    PortletFileRepositoryUtil.addPortletFileEntry(
465                            folder.getGroupId(), userId, Group.class.getName(),
466                            folder.getGroupId(), _PORTLET_REPOSITORY_ID, folder.getFolderId(),
467                            new UnsyncByteArrayInputStream(bytes), fileName,
468                            ContentTypes.APPLICATION_ZIP, false);
469            }
470    
471            /**
472             * @deprecated As of 7.0.0, replaced by {@link #publishStagingRequest(long,
473             *             long, boolean, Map)}
474             */
475            @Deprecated
476            @Override
477            public MissingReferences validateStagingRequest(
478                    long userId, long stagingRequestId, boolean privateLayout,
479                    Map<String, String[]> parameterMap) {
480    
481                    return new MissingReferences();
482            }
483    
484            protected void addDefaultLayoutSetBranch(
485                            long userId, long groupId, String groupName, boolean privateLayout,
486                            ServiceContext serviceContext)
487                    throws PortalException {
488    
489                    String masterBranchDescription =
490                            LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PUBLIC;
491    
492                    if (privateLayout) {
493                            masterBranchDescription =
494                                    LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PRIVATE;
495                    }
496    
497                    String description = LanguageUtil.format(
498                            PortalUtil.getSiteDefaultLocale(groupId), masterBranchDescription,
499                            groupName, false);
500    
501                    try {
502                            serviceContext.setWorkflowAction(WorkflowConstants.STATUS_APPROVED);
503    
504                            LayoutSetBranch layoutSetBranch =
505                                    layoutSetBranchLocalService.addLayoutSetBranch(
506                                            userId, groupId, privateLayout,
507                                            LayoutSetBranchConstants.MASTER_BRANCH_NAME, description,
508                                            true, LayoutSetBranchConstants.ALL_BRANCHES,
509                                            serviceContext);
510    
511                            List<LayoutRevision> layoutRevisions =
512                                    layoutRevisionLocalService.getLayoutRevisions(
513                                            layoutSetBranch.getLayoutSetBranchId(), false);
514    
515                            for (LayoutRevision layoutRevision : layoutRevisions) {
516                                    layoutRevisionLocalService.updateStatus(
517                                            userId, layoutRevision.getLayoutRevisionId(),
518                                            WorkflowConstants.STATUS_APPROVED, serviceContext);
519                            }
520                    }
521                    catch (PortalException pe) {
522                            if (_log.isWarnEnabled()) {
523                                    _log.warn(
524                                            "Unable to create master branch for " +
525                                                    (privateLayout ? "private" : "public") + " layouts",
526                                            pe);
527                            }
528                    }
529            }
530    
531            protected Group addStagingGroup(
532                            long userId, Group liveGroup, ServiceContext serviceContext)
533                    throws PortalException {
534    
535                    long parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
536    
537                    if (liveGroup.getParentGroupId() !=
538                                    GroupConstants.DEFAULT_PARENT_GROUP_ID) {
539    
540                            Group parentGroup = liveGroup.getParentGroup();
541    
542                            if (parentGroup.hasStagingGroup()) {
543                                    parentGroup = parentGroup.getStagingGroup();
544                            }
545    
546                            parentGroupId = parentGroup.getGroupId();
547                    }
548    
549                    Group stagingGroup = groupLocalService.addGroup(
550                            userId, parentGroupId, liveGroup.getClassName(),
551                            liveGroup.getClassPK(), liveGroup.getGroupId(),
552                            liveGroup.getNameMap(), liveGroup.getDescriptionMap(),
553                            liveGroup.getType(), liveGroup.isManualMembership(),
554                            liveGroup.getMembershipRestriction(), liveGroup.getFriendlyURL(),
555                            false, liveGroup.isActive(), serviceContext);
556    
557                    if (LanguageUtil.isInheritLocales(liveGroup.getGroupId())) {
558                            return stagingGroup;
559                    }
560    
561                    UnicodeProperties liveTypeSettingsProperties =
562                            liveGroup.getTypeSettingsProperties();
563    
564                    UnicodeProperties stagingTypeSettingsProperties =
565                            stagingGroup.getTypeSettingsProperties();
566    
567                    stagingTypeSettingsProperties.setProperty(
568                            GroupConstants.TYPE_SETTINGS_KEY_INHERIT_LOCALES,
569                            Boolean.FALSE.toString());
570                    stagingTypeSettingsProperties.setProperty(
571                            PropsKeys.LOCALES,
572                            liveTypeSettingsProperties.getProperty(PropsKeys.LOCALES));
573                    stagingTypeSettingsProperties.setProperty(
574                            "languageId",
575                            liveTypeSettingsProperties.getProperty(
576                                    "languageId",
577                                    LocaleUtil.toLanguageId(LocaleUtil.getDefault())));
578    
579                    return groupLocalService.updateGroup(
580                            stagingGroup.getGroupId(),
581                            stagingTypeSettingsProperties.toString());
582            }
583    
584            protected void deleteLayoutSetBranches(long groupId, boolean privateLayout)
585                    throws PortalException {
586    
587                    // Find the latest layout revision for all the layouts
588    
589                    Map<Long, LayoutRevision> layoutRevisions = new HashMap<>();
590    
591                    List<LayoutSetBranch> layoutSetBranches =
592                            layoutSetBranchLocalService.getLayoutSetBranches(
593                                    groupId, privateLayout);
594    
595                    boolean publishedToLive = false;
596    
597                    for (LayoutSetBranch layoutSetBranch : layoutSetBranches) {
598                            String lastPublishDateString = layoutSetBranch.getSettingsProperty(
599                                    "last-publish-date");
600    
601                            if (Validator.isNotNull(lastPublishDateString)) {
602                                    publishedToLive = true;
603    
604                                    break;
605                            }
606                    }
607    
608                    for (LayoutSetBranch layoutSetBranch : layoutSetBranches) {
609                            String lastPublishDateString = layoutSetBranch.getSettingsProperty(
610                                    "last-publish-date");
611    
612                            if (Validator.isNull(lastPublishDateString) && publishedToLive) {
613                                    continue;
614                            }
615    
616                            Date lastPublishDate = null;
617    
618                            if (Validator.isNotNull(lastPublishDateString)) {
619                                    lastPublishDate = new Date(
620                                            GetterUtil.getLong(lastPublishDateString));
621                            }
622    
623                            List<LayoutRevision> headLayoutRevisions =
624                                    layoutRevisionLocalService.getLayoutRevisions(
625                                            layoutSetBranch.getLayoutSetBranchId(), true);
626    
627                            for (LayoutRevision headLayoutRevision : headLayoutRevisions) {
628                                    LayoutRevision layoutRevision = layoutRevisions.get(
629                                            headLayoutRevision.getPlid());
630    
631                                    if (layoutRevision == null) {
632                                            layoutRevisions.put(
633                                                    headLayoutRevision.getPlid(), headLayoutRevision);
634    
635                                            continue;
636                                    }
637    
638                                    Date statusDate = headLayoutRevision.getStatusDate();
639    
640                                    if (statusDate.after(layoutRevision.getStatusDate()) &&
641                                            ((lastPublishDate == null) ||
642                                             lastPublishDate.after(statusDate))) {
643    
644                                            layoutRevisions.put(
645                                                    headLayoutRevision.getPlid(), headLayoutRevision);
646                                    }
647                            }
648                    }
649    
650                    // Update all layouts based on their latest revision
651    
652                    for (LayoutRevision layoutRevision : layoutRevisions.values()) {
653                            updateLayoutWithLayoutRevision(layoutRevision);
654                    }
655    
656                    layoutSetBranchLocalService.deleteLayoutSetBranches(
657                            groupId, privateLayout, true);
658            }
659    
660            protected void disableRemoteStaging(
661                            String remoteURL, long remoteGroupId, boolean forceDisable)
662                    throws PortalException {
663    
664                    PermissionChecker permissionChecker =
665                            PermissionThreadLocal.getPermissionChecker();
666    
667                    User user = permissionChecker.getUser();
668    
669                    HttpPrincipal httpPrincipal = new HttpPrincipal(
670                            remoteURL, user.getLogin(), user.getPassword(),
671                            user.getPasswordEncrypted());
672    
673                    try {
674                            GroupServiceHttp.disableStaging(httpPrincipal, remoteGroupId);
675                    }
676                    catch (NoSuchGroupException nsge) {
677                            if (_log.isWarnEnabled()) {
678                                    _log.warn("Remote live group was already deleted", nsge);
679                            }
680                    }
681                    catch (PrincipalException pe) {
682                            RemoteExportException ree = new RemoteExportException(
683                                    RemoteExportException.NO_PERMISSIONS);
684    
685                            ree.setGroupId(remoteGroupId);
686    
687                            throw ree;
688                    }
689                    catch (RemoteAuthException rae) {
690                            rae.setURL(remoteURL);
691    
692                            throw rae;
693                    }
694                    catch (SystemException se) {
695                            if (!forceDisable) {
696                                    RemoteExportException ree = new RemoteExportException(
697                                            RemoteExportException.BAD_CONNECTION);
698    
699                                    ree.setURL(remoteURL);
700    
701                                    throw ree;
702                            }
703    
704                            if (_log.isWarnEnabled()) {
705                                    _log.warn("Forcibly disable remote staging");
706                            }
707                    }
708            }
709    
710            protected void enableRemoteStaging(String remoteURL, long remoteGroupId)
711                    throws PortalException {
712    
713                    PermissionChecker permissionChecker =
714                            PermissionThreadLocal.getPermissionChecker();
715    
716                    User user = permissionChecker.getUser();
717    
718                    HttpPrincipal httpPrincipal = new HttpPrincipal(
719                            remoteURL, user.getLogin(), user.getPassword(),
720                            user.getPasswordEncrypted());
721    
722                    try {
723                            GroupServiceHttp.enableStaging(httpPrincipal, remoteGroupId);
724                    }
725                    catch (NoSuchGroupException nsge) {
726                            RemoteExportException ree = new RemoteExportException(
727                                    RemoteExportException.NO_GROUP);
728    
729                            ree.setGroupId(remoteGroupId);
730    
731                            throw ree;
732                    }
733                    catch (PrincipalException pe) {
734                            RemoteExportException ree = new RemoteExportException(
735                                    RemoteExportException.NO_PERMISSIONS);
736    
737                            ree.setGroupId(remoteGroupId);
738    
739                            throw ree;
740                    }
741                    catch (RemoteAuthException rae) {
742                            rae.setURL(remoteURL);
743    
744                            throw rae;
745                    }
746                    catch (SystemException se) {
747                            RemoteExportException ree = new RemoteExportException(
748                                    RemoteExportException.BAD_CONNECTION);
749    
750                            ree.setURL(remoteURL);
751    
752                            throw ree;
753                    }
754            }
755    
756            protected FileEntry fetchStagingRequestFileEntry(
757                            long stagingRequestId, Folder folder)
758                    throws PortalException {
759    
760                    try {
761                            return PortletFileRepositoryUtil.getPortletFileEntry(
762                                    folder.getGroupId(), folder.getFolderId(),
763                                    getAssembledFileName(stagingRequestId));
764                    }
765                    catch (NoSuchFileEntryException nsfe) {
766                            return null;
767                    }
768            }
769    
770            protected String getAssembledFileName(long stagingRequestId) {
771                    return _ASSEMBLED_LAR_PREFIX + String.valueOf(stagingRequestId) +
772                            ".lar";
773            }
774    
775            protected FileEntry getStagingRequestFileEntry(
776                            long userId, long stagingRequestId, Folder folder)
777                    throws PortalException {
778    
779                    FileEntry stagingRequestFileEntry = fetchStagingRequestFileEntry(
780                            stagingRequestId, folder);
781    
782                    if (stagingRequestFileEntry != null) {
783                            return stagingRequestFileEntry;
784                    }
785    
786                    FileOutputStream fileOutputStream = null;
787    
788                    File tempFile = null;
789    
790                    try {
791                            tempFile = FileUtil.createTempFile("lar");
792    
793                            fileOutputStream = new FileOutputStream(tempFile);
794    
795                            List<FileEntry> fileEntries =
796                                    PortletFileRepositoryUtil.getPortletFileEntries(
797                                            folder.getGroupId(), folder.getFolderId(),
798                                            new RepositoryModelTitleComparator<FileEntry>(true));
799    
800                            for (FileEntry fileEntry : fileEntries) {
801                                    try {
802                                            StreamUtil.transfer(
803                                                    fileEntry.getContentStream(),
804                                                    StreamUtil.uncloseable(fileOutputStream));
805                                    }
806                                    finally {
807                                            PortletFileRepositoryUtil.deletePortletFileEntry(
808                                                    fileEntry.getFileEntryId());
809                                    }
810                            }
811    
812                            String checksum = FileUtil.getMD5Checksum(tempFile);
813    
814                            if (!checksum.equals(folder.getName())) {
815                                    throw new SystemException("Invalid checksum for LAR file");
816                            }
817    
818                            PortletFileRepositoryUtil.addPortletFileEntry(
819                                    folder.getGroupId(), userId, Group.class.getName(),
820                                    folder.getGroupId(), _PORTLET_REPOSITORY_ID,
821                                    folder.getFolderId(), tempFile,
822                                    getAssembledFileName(stagingRequestId),
823                                    ContentTypes.APPLICATION_ZIP, false);
824    
825                            stagingRequestFileEntry = fetchStagingRequestFileEntry(
826                                    stagingRequestId, folder);
827    
828                            if (stagingRequestFileEntry == null) {
829                                    throw new SystemException("Unable to assemble LAR file");
830                            }
831    
832                            return stagingRequestFileEntry;
833                    }
834                    catch (IOException ioe) {
835                            throw new SystemException("Unable to reassemble LAR file", ioe);
836                    }
837                    finally {
838                            StreamUtil.cleanUp(fileOutputStream);
839    
840                            FileUtil.delete(tempFile);
841                    }
842            }
843    
844            protected void setCommonStagingOptions(
845                    Group liveGroup, UnicodeProperties typeSettingsProperties,
846                    ServiceContext serviceContext) {
847    
848                    if (liveGroup.hasRemoteStagingGroup()) {
849                            return;
850                    }
851    
852                    typeSettingsProperties.putAll(
853                            PropertiesParamUtil.getProperties(
854                                    serviceContext, StagingConstants.STAGED_PREFIX));
855            }
856    
857            protected Layout updateLayoutWithLayoutRevision(
858                    LayoutRevision layoutRevision) {
859    
860                    // Suppress the usage of the advice to get the latest layout to prevent
861                    // a StaleObjectStateException
862    
863                    Layout layout = null;
864    
865                    boolean stagingAdvicesThreadLocalEnabled =
866                            StagingAdvicesThreadLocal.isEnabled();
867    
868                    try {
869                            StagingAdvicesThreadLocal.setEnabled(false);
870    
871                            layout = layoutLocalService.fetchLayout(layoutRevision.getPlid());
872                    }
873                    finally {
874                            StagingAdvicesThreadLocal.setEnabled(
875                                    stagingAdvicesThreadLocalEnabled);
876                    }
877    
878                    updatePortletPreferences(layoutRevision, layout);
879    
880                    layout.setUserId(layoutRevision.getUserId());
881                    layout.setUserName(layoutRevision.getUserName());
882                    layout.setCreateDate(layoutRevision.getCreateDate());
883                    layout.setModifiedDate(layoutRevision.getModifiedDate());
884                    layout.setPrivateLayout(layoutRevision.getPrivateLayout());
885                    layout.setName(layoutRevision.getName());
886                    layout.setTitle(layoutRevision.getTitle());
887                    layout.setDescription(layoutRevision.getDescription());
888                    layout.setKeywords(layoutRevision.getKeywords());
889                    layout.setRobots(layoutRevision.getRobots());
890                    layout.setTypeSettings(layoutRevision.getTypeSettings());
891                    layout.setIconImageId(layoutRevision.getIconImageId());
892                    layout.setThemeId(layoutRevision.getThemeId());
893                    layout.setColorSchemeId(layoutRevision.getColorSchemeId());
894                    layout.setWapThemeId(layoutRevision.getWapThemeId());
895                    layout.setWapColorSchemeId(layoutRevision.getWapColorSchemeId());
896                    layout.setCss(layoutRevision.getCss());
897    
898                    return layoutLocalService.updateLayout(layout);
899            }
900    
901            protected void updatePortletPreferences(
902                    LayoutRevision layoutRevision, Layout layout) {
903    
904                    portletPreferencesLocalService.deletePortletPreferencesByPlid(
905                            layout.getPlid());
906    
907                    List<PortletPreferences> portletPreferencesList =
908                            portletPreferencesLocalService.getPortletPreferencesByPlid(
909                                    layoutRevision.getLayoutRevisionId());
910    
911                    for (PortletPreferences portletPreferences : portletPreferencesList) {
912                            portletPreferencesLocalService.addPortletPreferences(
913                                    layoutRevision.getCompanyId(), portletPreferences.getOwnerId(),
914                                    portletPreferences.getOwnerType(), layout.getPlid(),
915                                    portletPreferences.getPortletId(), null,
916                                    portletPreferences.getPreferences());
917                    }
918            }
919    
920            protected void updateStagedPortlets(
921                            String remoteURL, long remoteGroupId,
922                            UnicodeProperties typeSettingsProperties)
923                    throws PortalException {
924    
925                    PermissionChecker permissionChecker =
926                            PermissionThreadLocal.getPermissionChecker();
927    
928                    User user = permissionChecker.getUser();
929    
930                    HttpPrincipal httpPrincipal = new HttpPrincipal(
931                            remoteURL, user.getLogin(), user.getPassword(),
932                            user.getPasswordEncrypted());
933    
934                    Map<String, String> stagedPortletIds = new HashMap<>();
935    
936                    for (String key : typeSettingsProperties.keySet()) {
937                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
938                                    stagedPortletIds.put(
939                                            key, typeSettingsProperties.getProperty(key));
940                            }
941                    }
942    
943                    try {
944                            GroupServiceHttp.updateStagedPortlets(
945                                    httpPrincipal, remoteGroupId, stagedPortletIds);
946                    }
947                    catch (NoSuchGroupException nsge) {
948                            RemoteExportException ree = new RemoteExportException(
949                                    RemoteExportException.NO_GROUP);
950    
951                            ree.setGroupId(remoteGroupId);
952    
953                            throw ree;
954                    }
955                    catch (PrincipalException pe) {
956                            RemoteExportException ree = new RemoteExportException(
957                                    RemoteExportException.NO_PERMISSIONS);
958    
959                            ree.setGroupId(remoteGroupId);
960    
961                            throw ree;
962                    }
963                    catch (RemoteAuthException rae) {
964                            rae.setURL(remoteURL);
965    
966                            throw rae;
967                    }
968                    catch (SystemException se) {
969                            RemoteExportException ree = new RemoteExportException(
970                                    RemoteExportException.BAD_CONNECTION);
971    
972                            ree.setURL(remoteURL);
973    
974                            throw ree;
975                    }
976            }
977    
978            private static final String _ASSEMBLED_LAR_PREFIX = "assembled_";
979    
980            private static final String _PORTLET_REPOSITORY_ID = "134";
981    
982            private static final Log _log = LogFactoryUtil.getLog(
983                    StagingLocalServiceImpl.class);
984    
985    }