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