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    
205                            disableRemoteStaging(remoteURL, remoteGroupId);
206                    }
207    
208                    typeSettingsProperties.remove("branchingPrivate");
209                    typeSettingsProperties.remove("branchingPublic");
210                    typeSettingsProperties.remove("remoteAddress");
211                    typeSettingsProperties.remove("remoteGroupId");
212                    typeSettingsProperties.remove("remotePathContext");
213                    typeSettingsProperties.remove("remotePort");
214                    typeSettingsProperties.remove("secureConnection");
215                    typeSettingsProperties.remove("staged");
216                    typeSettingsProperties.remove("stagedRemotely");
217    
218                    Set<String> keys = new HashSet<String>();
219    
220                    for (String key : typeSettingsProperties.keySet()) {
221                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
222                                    keys.add(key);
223                            }
224                    }
225    
226                    for (String key : keys) {
227                            typeSettingsProperties.remove(key);
228                    }
229    
230                    StagingUtil.deleteLastImportSettings(liveGroup, true);
231                    StagingUtil.deleteLastImportSettings(liveGroup, false);
232    
233                    checkDefaultLayoutSetBranches(
234                            serviceContext.getUserId(), liveGroup, false, false, stagedRemotely,
235                            serviceContext);
236    
237                    if (liveGroup.hasStagingGroup()) {
238                            Group stagingGroup = liveGroup.getStagingGroup();
239    
240                            groupLocalService.deleteGroup(stagingGroup.getGroupId());
241    
242                            liveGroup.clearStagingGroup();
243                    }
244    
245                    groupLocalService.updateGroup(
246                            liveGroup.getGroupId(), typeSettingsProperties.toString());
247            }
248    
249            @Override
250            public void enableLocalStaging(
251                            long userId, Group liveGroup, boolean branchingPublic,
252                            boolean branchingPrivate, ServiceContext serviceContext)
253                    throws PortalException, SystemException {
254    
255                    if (liveGroup.isStagedRemotely()) {
256                            disableStaging(liveGroup, serviceContext);
257                    }
258    
259                    UnicodeProperties typeSettingsProperties =
260                            liveGroup.getTypeSettingsProperties();
261    
262                    typeSettingsProperties.setProperty(
263                            "branchingPrivate", String.valueOf(branchingPrivate));
264                    typeSettingsProperties.setProperty(
265                            "branchingPublic", String.valueOf(branchingPublic));
266                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
267                    typeSettingsProperties.setProperty(
268                            "stagedRemotely", String.valueOf(false));
269    
270                    setCommonStagingOptions(
271                            liveGroup, typeSettingsProperties, serviceContext);
272    
273                    groupLocalService.updateGroup(
274                            liveGroup.getGroupId(), typeSettingsProperties.toString());
275    
276                    if (!liveGroup.hasStagingGroup()) {
277                            serviceContext.setAttribute("staging", String.valueOf(true));
278    
279                            Group stagingGroup = addStagingGroup(
280                                    userId, liveGroup, serviceContext);
281    
282                            Map<String, String[]> parameterMap =
283                                    StagingUtil.getStagingParameters();
284    
285                            if (liveGroup.hasPrivateLayouts()) {
286                                    StagingUtil.publishLayouts(
287                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
288                                            true, parameterMap, null, null);
289                            }
290    
291                            if (liveGroup.hasPublicLayouts() ||
292                                    !liveGroup.hasPrivateLayouts()) {
293    
294                                    StagingUtil.publishLayouts(
295                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
296                                            false, parameterMap, null, null);
297                            }
298                    }
299    
300                    checkDefaultLayoutSetBranches(
301                            userId, liveGroup, branchingPublic, branchingPrivate, false,
302                            serviceContext);
303            }
304    
305            @Override
306            public void enableRemoteStaging(
307                            long userId, Group liveGroup, boolean branchingPublic,
308                            boolean branchingPrivate, String remoteAddress, int remotePort,
309                            String remotePathContext, boolean secureConnection,
310                            long remoteGroupId, ServiceContext serviceContext)
311                    throws PortalException, SystemException {
312    
313                    StagingUtil.validateRemote(
314                            remoteAddress, remotePort, remotePathContext, secureConnection,
315                            remoteGroupId);
316    
317                    if (liveGroup.hasStagingGroup()) {
318                            disableStaging(liveGroup, serviceContext);
319                    }
320    
321                    String remoteURL = StagingUtil.buildRemoteURL(
322                            remoteAddress, remotePort, remotePathContext, secureConnection,
323                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
324    
325                    UnicodeProperties typeSettingsProperties =
326                            liveGroup.getTypeSettingsProperties();
327    
328                    boolean stagedRemotely = GetterUtil.getBoolean(
329                            typeSettingsProperties.getProperty("stagedRemotely"));
330    
331                    if (stagedRemotely) {
332                            long oldRemoteGroupId = GetterUtil.getLong(
333                                    typeSettingsProperties.getProperty("remoteGroupId"));
334    
335                            String oldRemoteURL = StagingUtil.buildRemoteURL(
336                                    typeSettingsProperties);
337    
338                            if (!remoteURL.equals(oldRemoteURL) ||
339                                    (remoteGroupId != oldRemoteGroupId)) {
340    
341                                    disableRemoteStaging(oldRemoteURL, oldRemoteGroupId);
342    
343                                    stagedRemotely = false;
344                            }
345                    }
346    
347                    if (!stagedRemotely) {
348                            enableRemoteStaging(remoteURL, remoteGroupId);
349                    }
350    
351                    typeSettingsProperties.setProperty(
352                            "branchingPrivate", String.valueOf(branchingPrivate));
353                    typeSettingsProperties.setProperty(
354                            "branchingPublic", String.valueOf(branchingPublic));
355                    typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
356                    typeSettingsProperties.setProperty(
357                            "remoteGroupId", String.valueOf(remoteGroupId));
358                    typeSettingsProperties.setProperty(
359                            "remotePathContext", remotePathContext);
360                    typeSettingsProperties.setProperty(
361                            "remotePort", String.valueOf(remotePort));
362                    typeSettingsProperties.setProperty(
363                            "secureConnection", String.valueOf(secureConnection));
364                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
365                    typeSettingsProperties.setProperty(
366                            "stagedRemotely", Boolean.TRUE.toString());
367    
368                    setCommonStagingOptions(
369                            liveGroup, typeSettingsProperties, serviceContext);
370    
371                    groupLocalService.updateGroup(
372                            liveGroup.getGroupId(), typeSettingsProperties.toString());
373    
374                    updateStagedPortlets(remoteURL, remoteGroupId, typeSettingsProperties);
375    
376                    checkDefaultLayoutSetBranches(
377                            userId, liveGroup, branchingPublic, branchingPrivate, true,
378                            serviceContext);
379            }
380    
381            @Override
382            public void publishStagingRequest(
383                            long userId, long stagingRequestId, boolean privateLayout,
384                            Map<String, String[]> parameterMap)
385                    throws PortalException, SystemException {
386    
387                    try {
388                            ExportImportThreadLocal.setLayoutImportInProcess(true);
389    
390                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
391                                    stagingRequestId);
392    
393                            FileEntry stagingRequestFileEntry = getStagingRequestFileEntry(
394                                    userId, stagingRequestId, folder);
395    
396                            layoutLocalService.importLayouts(
397                                    userId, folder.getGroupId(), privateLayout, parameterMap,
398                                    stagingRequestFileEntry.getContentStream());
399                    }
400                    finally {
401                            ExportImportThreadLocal.setLayoutImportInProcess(false);
402                    }
403            }
404    
405            @Override
406            public void updateStagingRequest(
407                            long userId, long stagingRequestId, String fileName, byte[] bytes)
408                    throws PortalException, SystemException {
409    
410                    Folder folder = PortletFileRepositoryUtil.getPortletFolder(
411                            stagingRequestId);
412    
413                    PortletFileRepositoryUtil.addPortletFileEntry(
414                            folder.getGroupId(), userId, Group.class.getName(),
415                            folder.getGroupId(), PortletKeys.SITES_ADMIN, folder.getFolderId(),
416                            new UnsyncByteArrayInputStream(bytes), fileName,
417                            ContentTypes.APPLICATION_ZIP, false);
418            }
419    
420            @Override
421            public MissingReferences validateStagingRequest(
422                            long userId, long stagingRequestId, boolean privateLayout,
423                            Map<String, String[]> parameterMap)
424                    throws PortalException, SystemException {
425    
426                    try {
427                            ExportImportThreadLocal.setLayoutValidationInProcess(true);
428    
429                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
430                                    stagingRequestId);
431    
432                            FileEntry fileEntry = getStagingRequestFileEntry(
433                                    userId, stagingRequestId, folder);
434    
435                            return layoutLocalService.validateImportLayoutsFile(
436                                    userId, folder.getGroupId(), privateLayout, parameterMap,
437                                    fileEntry.getContentStream());
438                    }
439                    finally {
440                            ExportImportThreadLocal.setLayoutValidationInProcess(false);
441                    }
442            }
443    
444            protected void addDefaultLayoutSetBranch(
445                            long userId, long groupId, String groupName, boolean privateLayout,
446                            ServiceContext serviceContext)
447                    throws PortalException, SystemException {
448    
449                    String masterBranchDescription =
450                            LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PUBLIC;
451    
452                    if (privateLayout) {
453                            masterBranchDescription =
454                                    LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PRIVATE;
455                    }
456    
457                    String description = LanguageUtil.format(
458                            PortalUtil.getSiteDefaultLocale(groupId), masterBranchDescription,
459                            groupName, false);
460    
461                    try {
462                            serviceContext.setWorkflowAction(WorkflowConstants.STATUS_APPROVED);
463    
464                            LayoutSetBranch layoutSetBranch =
465                                    layoutSetBranchLocalService.addLayoutSetBranch(
466                                            userId, groupId, privateLayout,
467                                            LayoutSetBranchConstants.MASTER_BRANCH_NAME, description,
468                                            true, LayoutSetBranchConstants.ALL_BRANCHES,
469                                            serviceContext);
470    
471                            List<LayoutRevision> layoutRevisions =
472                                    layoutRevisionLocalService.getLayoutRevisions(
473                                            layoutSetBranch.getLayoutSetBranchId(), false);
474    
475                            for (LayoutRevision layoutRevision : layoutRevisions) {
476                                    layoutRevisionLocalService.updateStatus(
477                                            userId, layoutRevision.getLayoutRevisionId(),
478                                            WorkflowConstants.STATUS_APPROVED, serviceContext);
479                            }
480                    }
481                    catch (PortalException pe) {
482                            if (_log.isWarnEnabled()) {
483                                    _log.warn(
484                                            "Unable to create master branch for " +
485                                                    (privateLayout ? "private" : "public") + " layouts",
486                                            pe);
487                            }
488                    }
489            }
490    
491            protected Group addStagingGroup(
492                            long userId, Group liveGroup, ServiceContext serviceContext)
493                    throws PortalException, SystemException {
494    
495                    long parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
496    
497                    if (liveGroup.getParentGroupId() !=
498                                    GroupConstants.DEFAULT_PARENT_GROUP_ID) {
499    
500                            Group parentGroup = liveGroup.getParentGroup();
501    
502                            if (parentGroup.hasStagingGroup()) {
503                                    parentGroup = parentGroup.getStagingGroup();
504                            }
505    
506                            parentGroupId = parentGroup.getGroupId();
507                    }
508    
509                    Group stagingGroup = groupLocalService.addGroup(
510                            userId, parentGroupId, liveGroup.getClassName(),
511                            liveGroup.getClassPK(), liveGroup.getGroupId(),
512                            liveGroup.getDescriptiveName(), liveGroup.getDescription(),
513                            liveGroup.getType(), liveGroup.isManualMembership(),
514                            liveGroup.getMembershipRestriction(), liveGroup.getFriendlyURL(),
515                            false, liveGroup.isActive(), serviceContext);
516    
517                    if (LanguageUtil.isInheritLocales(liveGroup.getGroupId())) {
518                            return stagingGroup;
519                    }
520    
521                    UnicodeProperties liveTypeSettingsProperties =
522                            liveGroup.getTypeSettingsProperties();
523    
524                    UnicodeProperties stagingTypeSettingsProperties =
525                            stagingGroup.getTypeSettingsProperties();
526    
527                    stagingTypeSettingsProperties.setProperty(
528                            PropsKeys.LOCALES,
529                            liveTypeSettingsProperties.getProperty(PropsKeys.LOCALES));
530                    stagingTypeSettingsProperties.setProperty(
531                            "inheritLocales", Boolean.FALSE.toString());
532                    stagingTypeSettingsProperties.setProperty(
533                            "languageId",
534                            liveTypeSettingsProperties.getProperty(
535                                    "languageId",
536                                    LocaleUtil.toLanguageId(LocaleUtil.getDefault())));
537    
538                    return groupLocalService.updateGroup(
539                            stagingGroup.getGroupId(),
540                            stagingTypeSettingsProperties.toString());
541            }
542    
543            protected void clearLastPublishDate(long groupId, boolean privateLayout)
544                    throws PortalException, SystemException {
545    
546                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
547                            groupId, privateLayout);
548    
549                    UnicodeProperties settingsProperties =
550                            layoutSet.getSettingsProperties();
551    
552                    settingsProperties.remove("last-publish-date");
553    
554                    layoutSetLocalService.updateSettings(
555                            groupId, privateLayout, settingsProperties.toString());
556            }
557    
558            protected void deleteLayoutSetBranches(long groupId, boolean privateLayout)
559                    throws PortalException, SystemException {
560    
561                    // Find the latest layout revision for all the published layouts
562    
563                    Map<Long, LayoutRevision> layoutRevisions =
564                            new HashMap<Long, LayoutRevision>();
565    
566                    List<LayoutSetBranch> layoutSetBranches =
567                            layoutSetBranchLocalService.getLayoutSetBranches(
568                                    groupId, privateLayout);
569    
570                    for (LayoutSetBranch layoutSetBranch : layoutSetBranches) {
571                            String lastPublishDateString = layoutSetBranch.getSettingsProperty(
572                                    "last-publish-date");
573    
574                            if (Validator.isNull(lastPublishDateString)) {
575                                    continue;
576                            }
577    
578                            Date lastPublishDate = new Date(
579                                    GetterUtil.getLong(lastPublishDateString));
580    
581                            List<LayoutRevision> headLayoutRevisions =
582                                    layoutRevisionLocalService.getLayoutRevisions(
583                                            layoutSetBranch.getLayoutSetBranchId(), true);
584    
585                            for (LayoutRevision headLayoutRevision : headLayoutRevisions) {
586                                    LayoutRevision layoutRevision = layoutRevisions.get(
587                                            headLayoutRevision.getPlid());
588    
589                                    if (layoutRevision == null) {
590                                            layoutRevisions.put(
591                                                    headLayoutRevision.getPlid(), headLayoutRevision);
592    
593                                            continue;
594                                    }
595    
596                                    Date statusDate = headLayoutRevision.getStatusDate();
597    
598                                    if (statusDate.after(layoutRevision.getStatusDate()) &&
599                                            lastPublishDate.after(statusDate)) {
600    
601                                            layoutRevisions.put(
602                                                    headLayoutRevision.getPlid(), headLayoutRevision);
603                                    }
604                            }
605                    }
606    
607                    // Update all layouts based on their latest published revision
608    
609                    for (LayoutRevision layoutRevision : layoutRevisions.values()) {
610                            updateLayoutWithLayoutRevision(layoutRevision);
611                    }
612    
613                    layoutSetBranchLocalService.deleteLayoutSetBranches(
614                            groupId, privateLayout, true);
615            }
616    
617            protected void disableRemoteStaging(String remoteURL, long remoteGroupId)
618                    throws PortalException {
619    
620                    PermissionChecker permissionChecker =
621                            PermissionThreadLocal.getPermissionChecker();
622    
623                    User user = permissionChecker.getUser();
624    
625                    HttpPrincipal httpPrincipal = new HttpPrincipal(
626                            remoteURL, user.getScreenName(), user.getPassword(),
627                            user.getPasswordEncrypted());
628    
629                    try {
630                            GroupServiceHttp.disableStaging(httpPrincipal, remoteGroupId);
631                    }
632                    catch (NoSuchGroupException nsge) {
633                            if (_log.isWarnEnabled()) {
634                                    _log.warn("Remote live group was already deleted", nsge);
635                            }
636                    }
637                    catch (PrincipalException pe) {
638                            RemoteExportException ree = new RemoteExportException(
639                                    RemoteExportException.NO_PERMISSIONS);
640    
641                            ree.setGroupId(remoteGroupId);
642    
643                            throw ree;
644                    }
645                    catch (RemoteAuthException rae) {
646                            rae.setURL(remoteURL);
647    
648                            throw rae;
649                    }
650                    catch (SystemException se) {
651                            RemoteExportException ree = new RemoteExportException(
652                                    RemoteExportException.BAD_CONNECTION);
653    
654                            ree.setURL(remoteURL);
655    
656                            throw ree;
657                    }
658            }
659    
660            protected void enableRemoteStaging(String remoteURL, long remoteGroupId)
661                    throws PortalException {
662    
663                    PermissionChecker permissionChecker =
664                            PermissionThreadLocal.getPermissionChecker();
665    
666                    User user = permissionChecker.getUser();
667    
668                    HttpPrincipal httpPrincipal = new HttpPrincipal(
669                            remoteURL, user.getScreenName(), user.getPassword(),
670                            user.getPasswordEncrypted());
671    
672                    try {
673                            GroupServiceHttp.enableStaging(httpPrincipal, remoteGroupId);
674                    }
675                    catch (NoSuchGroupException nsge) {
676                            RemoteExportException ree = new RemoteExportException(
677                                    RemoteExportException.NO_GROUP);
678    
679                            ree.setGroupId(remoteGroupId);
680    
681                            throw ree;
682                    }
683                    catch (PrincipalException pe) {
684                            RemoteExportException ree = new RemoteExportException(
685                                    RemoteExportException.NO_PERMISSIONS);
686    
687                            ree.setGroupId(remoteGroupId);
688    
689                            throw ree;
690                    }
691                    catch (RemoteAuthException rae) {
692                            rae.setURL(remoteURL);
693    
694                            throw rae;
695                    }
696                    catch (SystemException se) {
697                            RemoteExportException ree = new RemoteExportException(
698                                    RemoteExportException.BAD_CONNECTION);
699    
700                            ree.setURL(remoteURL);
701    
702                            throw ree;
703                    }
704            }
705    
706            protected FileEntry fetchStagingRequestFileEntry(
707                            long stagingRequestId, Folder folder)
708                    throws PortalException, SystemException {
709    
710                    try {
711                            return PortletFileRepositoryUtil.getPortletFileEntry(
712                                    folder.getGroupId(), folder.getFolderId(),
713                                    getAssembledFileName(stagingRequestId));
714                    }
715                    catch (NoSuchFileEntryException nsfe) {
716                            return null;
717                    }
718            }
719    
720            protected String getAssembledFileName(long stagingRequestId) {
721                    return _ASSEMBLED_LAR_PREFIX + String.valueOf(stagingRequestId) +
722                            ".lar";
723            }
724    
725            protected FileEntry getStagingRequestFileEntry(
726                            long userId, long stagingRequestId, Folder folder)
727                    throws PortalException, SystemException {
728    
729                    FileEntry stagingRequestFileEntry = fetchStagingRequestFileEntry(
730                            stagingRequestId, folder);
731    
732                    if (stagingRequestFileEntry != null) {
733                            return stagingRequestFileEntry;
734                    }
735    
736                    FileOutputStream fileOutputStream = null;
737    
738                    File tempFile = null;
739    
740                    boolean fileMaxSizeCheckEnabled =
741                            PortletFileRepositoryThreadLocal.isFileMaxSizeCheckEnabled();
742    
743                    try {
744                            PortletFileRepositoryThreadLocal.setFileMaxSizeCheckEnabled(false);
745    
746                            tempFile = FileUtil.createTempFile("lar");
747    
748                            fileOutputStream = new FileOutputStream(tempFile);
749    
750                            List<FileEntry> fileEntries =
751                                    PortletFileRepositoryUtil.getPortletFileEntries(
752                                            folder.getGroupId(), folder.getFolderId(),
753                                            WorkflowConstants.STATUS_ANY, QueryUtil.ALL_POS,
754                                            QueryUtil.ALL_POS, new RepositoryModelNameComparator(true));
755    
756                            for (FileEntry fileEntry : fileEntries) {
757                                    InputStream inputStream = fileEntry.getContentStream();
758    
759                                    try {
760                                            StreamUtil.transfer(inputStream, fileOutputStream, false);
761                                    }
762                                    finally {
763                                            StreamUtil.cleanUp(inputStream);
764    
765                                            PortletFileRepositoryUtil.deletePortletFileEntry(
766                                                    fileEntry.getFileEntryId());
767                                    }
768                            }
769    
770                            String checksum = FileUtil.getMD5Checksum(tempFile);
771    
772                            if (!checksum.equals(folder.getName())) {
773                                    throw new SystemException("Invalid checksum for LAR file");
774                            }
775    
776                            PortletFileRepositoryUtil.addPortletFileEntry(
777                                    folder.getGroupId(), userId, Group.class.getName(),
778                                    folder.getGroupId(), PortletKeys.SITES_ADMIN,
779                                    folder.getFolderId(), tempFile,
780                                    getAssembledFileName(stagingRequestId),
781                                    ContentTypes.APPLICATION_ZIP, false);
782    
783                            stagingRequestFileEntry = fetchStagingRequestFileEntry(
784                                    stagingRequestId, folder);
785    
786                            if (stagingRequestFileEntry == null) {
787                                    throw new SystemException("Unable to assemble LAR file");
788                            }
789    
790                            return stagingRequestFileEntry;
791                    }
792                    catch (IOException ioe) {
793                            throw new SystemException("Unable to reassemble LAR file", ioe);
794                    }
795                    finally {
796                            StreamUtil.cleanUp(fileOutputStream);
797    
798                            FileUtil.delete(tempFile);
799    
800                            PortletFileRepositoryThreadLocal.setFileMaxSizeCheckEnabled(
801                                    fileMaxSizeCheckEnabled);
802                    }
803            }
804    
805            protected void setCommonStagingOptions(
806                    Group liveGroup, UnicodeProperties typeSettingsProperties,
807                    ServiceContext serviceContext) {
808    
809                    if (liveGroup.getRemoteStagingGroupCount() > 0) {
810                            return;
811                    }
812    
813                    Set<String> parameterNames = serviceContext.getAttributes().keySet();
814    
815                    for (String parameterName : parameterNames) {
816                            if (parameterName.startsWith(StagingConstants.STAGED_PORTLET) &&
817                                    !parameterName.endsWith("Checkbox")) {
818    
819                                    boolean staged = ParamUtil.getBoolean(
820                                            serviceContext, parameterName);
821    
822                                    typeSettingsProperties.setProperty(
823                                            parameterName, String.valueOf(staged));
824                            }
825                    }
826            }
827    
828            protected Layout updateLayoutWithLayoutRevision(
829                            LayoutRevision layoutRevision)
830                    throws SystemException {
831    
832                    Layout layout = layoutLocalService.fetchLayout(
833                            layoutRevision.getPlid());
834    
835                    LayoutStagingHandler layoutStagingHandler =
836                            LayoutStagingUtil.getLayoutStagingHandler(layout);
837    
838                    layout = layoutStagingHandler.getLayout();
839    
840                    layout.setUserId(layoutRevision.getUserId());
841                    layout.setUserName(layoutRevision.getUserName());
842                    layout.setCreateDate(layoutRevision.getCreateDate());
843                    layout.setModifiedDate(layoutRevision.getModifiedDate());
844                    layout.setPrivateLayout(layoutRevision.getPrivateLayout());
845                    layout.setName(layoutRevision.getName());
846                    layout.setTitle(layoutRevision.getTitle());
847                    layout.setDescription(layoutRevision.getDescription());
848                    layout.setKeywords(layoutRevision.getKeywords());
849                    layout.setRobots(layoutRevision.getRobots());
850                    layout.setTypeSettings(layoutRevision.getTypeSettings());
851                    layout.setIconImageId(layoutRevision.getIconImageId());
852                    layout.setThemeId(layoutRevision.getThemeId());
853                    layout.setColorSchemeId(layoutRevision.getColorSchemeId());
854                    layout.setWapThemeId(layoutRevision.getWapThemeId());
855                    layout.setWapColorSchemeId(layoutRevision.getWapColorSchemeId());
856                    layout.setCss(layoutRevision.getCss());
857    
858                    return layoutLocalService.updateLayout(layout);
859            }
860    
861            protected void updateStagedPortlets(
862                            String remoteURL, long remoteGroupId,
863                            UnicodeProperties typeSettingsProperties)
864                    throws PortalException {
865    
866                    PermissionChecker permissionChecker =
867                            PermissionThreadLocal.getPermissionChecker();
868    
869                    User user = permissionChecker.getUser();
870    
871                    HttpPrincipal httpPrincipal = new HttpPrincipal(
872                            remoteURL, user.getScreenName(), user.getPassword(),
873                            user.getPasswordEncrypted());
874    
875                    Map<String, String> stagedPortletIds = new HashMap<String, String>();
876    
877                    for (String key : typeSettingsProperties.keySet()) {
878                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
879                                    stagedPortletIds.put(
880                                            key, typeSettingsProperties.getProperty(key));
881                            }
882                    }
883    
884                    try {
885                            GroupServiceHttp.updateStagedPortlets(
886                                    httpPrincipal, remoteGroupId, stagedPortletIds);
887                    }
888                    catch (NoSuchGroupException nsge) {
889                            RemoteExportException ree = new RemoteExportException(
890                                    RemoteExportException.NO_GROUP);
891    
892                            ree.setGroupId(remoteGroupId);
893    
894                            throw ree;
895                    }
896                    catch (PrincipalException pe) {
897                            RemoteExportException ree = new RemoteExportException(
898                                    RemoteExportException.NO_PERMISSIONS);
899    
900                            ree.setGroupId(remoteGroupId);
901    
902                            throw ree;
903                    }
904                    catch (RemoteAuthException rae) {
905                            rae.setURL(remoteURL);
906    
907                            throw rae;
908                    }
909                    catch (SystemException se) {
910                            RemoteExportException ree = new RemoteExportException(
911                                    RemoteExportException.BAD_CONNECTION);
912    
913                            ree.setURL(remoteURL);
914    
915                            throw ree;
916                    }
917            }
918    
919            private static final String _ASSEMBLED_LAR_PREFIX = "assembled_";
920    
921            private static Log _log = LogFactoryUtil.getLog(
922                    StagingLocalServiceImpl.class);
923    
924    }