001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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                            PropsKeys.LOCALES,
533                            liveTypeSettingsProperties.getProperty(PropsKeys.LOCALES));
534                    stagingTypeSettingsProperties.setProperty(
535                            "inheritLocales", Boolean.FALSE.toString());
536                    stagingTypeSettingsProperties.setProperty(
537                            "languageId",
538                            liveTypeSettingsProperties.getProperty(
539                                    "languageId",
540                                    LocaleUtil.toLanguageId(LocaleUtil.getDefault())));
541    
542                    return groupLocalService.updateGroup(
543                            stagingGroup.getGroupId(),
544                            stagingTypeSettingsProperties.toString());
545            }
546    
547            protected void clearLastPublishDate(long groupId, boolean privateLayout)
548                    throws PortalException, SystemException {
549    
550                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
551                            groupId, privateLayout);
552    
553                    UnicodeProperties settingsProperties =
554                            layoutSet.getSettingsProperties();
555    
556                    settingsProperties.remove("last-publish-date");
557    
558                    layoutSetLocalService.updateSettings(
559                            groupId, privateLayout, settingsProperties.toString());
560            }
561    
562            protected void deleteLayoutSetBranches(long groupId, boolean privateLayout)
563                    throws PortalException, SystemException {
564    
565                    // Find the latest layout revision for all the published layouts
566    
567                    Map<Long, LayoutRevision> layoutRevisions =
568                            new HashMap<Long, LayoutRevision>();
569    
570                    List<LayoutSetBranch> layoutSetBranches =
571                            layoutSetBranchLocalService.getLayoutSetBranches(
572                                    groupId, privateLayout);
573    
574                    for (LayoutSetBranch layoutSetBranch : layoutSetBranches) {
575                            String lastPublishDateString = layoutSetBranch.getSettingsProperty(
576                                    "last-publish-date");
577    
578                            if (Validator.isNull(lastPublishDateString)) {
579                                    continue;
580                            }
581    
582                            Date lastPublishDate = new Date(
583                                    GetterUtil.getLong(lastPublishDateString));
584    
585                            List<LayoutRevision> headLayoutRevisions =
586                                    layoutRevisionLocalService.getLayoutRevisions(
587                                            layoutSetBranch.getLayoutSetBranchId(), true);
588    
589                            for (LayoutRevision headLayoutRevision : headLayoutRevisions) {
590                                    LayoutRevision layoutRevision = layoutRevisions.get(
591                                            headLayoutRevision.getPlid());
592    
593                                    if (layoutRevision == null) {
594                                            layoutRevisions.put(
595                                                    headLayoutRevision.getPlid(), headLayoutRevision);
596    
597                                            continue;
598                                    }
599    
600                                    Date statusDate = headLayoutRevision.getStatusDate();
601    
602                                    if (statusDate.after(layoutRevision.getStatusDate()) &&
603                                            lastPublishDate.after(statusDate)) {
604    
605                                            layoutRevisions.put(
606                                                    headLayoutRevision.getPlid(), headLayoutRevision);
607                                    }
608                            }
609                    }
610    
611                    // Update all layouts based on their latest published revision
612    
613                    for (LayoutRevision layoutRevision : layoutRevisions.values()) {
614                            updateLayoutWithLayoutRevision(layoutRevision);
615                    }
616    
617                    layoutSetBranchLocalService.deleteLayoutSetBranches(
618                            groupId, privateLayout, true);
619            }
620    
621            protected void disableRemoteStaging(String remoteURL, long remoteGroupId)
622                    throws PortalException {
623    
624                    disableRemoteStaging(remoteURL, remoteGroupId, false);
625            }
626    
627            protected void disableRemoteStaging(
628                            String remoteURL, long remoteGroupId, boolean forceDisable)
629                    throws PortalException {
630    
631                    PermissionChecker permissionChecker =
632                            PermissionThreadLocal.getPermissionChecker();
633    
634                    User user = permissionChecker.getUser();
635    
636                    HttpPrincipal httpPrincipal = new HttpPrincipal(
637                            remoteURL, user.getScreenName(), user.getPassword(),
638                            user.getPasswordEncrypted());
639    
640                    try {
641                            GroupServiceHttp.disableStaging(httpPrincipal, remoteGroupId);
642                    }
643                    catch (NoSuchGroupException nsge) {
644                            if (_log.isWarnEnabled()) {
645                                    _log.warn("Remote live group was already deleted", nsge);
646                            }
647                    }
648                    catch (PrincipalException pe) {
649                            RemoteExportException ree = new RemoteExportException(
650                                    RemoteExportException.NO_PERMISSIONS);
651    
652                            ree.setGroupId(remoteGroupId);
653    
654                            throw ree;
655                    }
656                    catch (RemoteAuthException rae) {
657                            rae.setURL(remoteURL);
658    
659                            throw rae;
660                    }
661                    catch (SystemException se) {
662                            if (!forceDisable) {
663                                    RemoteExportException ree = new RemoteExportException(
664                                            RemoteExportException.BAD_CONNECTION);
665    
666                                    ree.setURL(remoteURL);
667    
668                                    throw ree;
669                            }
670    
671                            if (_log.isWarnEnabled()) {
672                                    _log.warn("Forcibly disable remote staging");
673                            }
674                    }
675            }
676    
677            protected void enableRemoteStaging(String remoteURL, long remoteGroupId)
678                    throws PortalException {
679    
680                    PermissionChecker permissionChecker =
681                            PermissionThreadLocal.getPermissionChecker();
682    
683                    User user = permissionChecker.getUser();
684    
685                    HttpPrincipal httpPrincipal = new HttpPrincipal(
686                            remoteURL, user.getScreenName(), user.getPassword(),
687                            user.getPasswordEncrypted());
688    
689                    try {
690                            GroupServiceHttp.enableStaging(httpPrincipal, remoteGroupId);
691                    }
692                    catch (NoSuchGroupException nsge) {
693                            RemoteExportException ree = new RemoteExportException(
694                                    RemoteExportException.NO_GROUP);
695    
696                            ree.setGroupId(remoteGroupId);
697    
698                            throw ree;
699                    }
700                    catch (PrincipalException pe) {
701                            RemoteExportException ree = new RemoteExportException(
702                                    RemoteExportException.NO_PERMISSIONS);
703    
704                            ree.setGroupId(remoteGroupId);
705    
706                            throw ree;
707                    }
708                    catch (RemoteAuthException rae) {
709                            rae.setURL(remoteURL);
710    
711                            throw rae;
712                    }
713                    catch (SystemException se) {
714                            RemoteExportException ree = new RemoteExportException(
715                                    RemoteExportException.BAD_CONNECTION);
716    
717                            ree.setURL(remoteURL);
718    
719                            throw ree;
720                    }
721            }
722    
723            protected FileEntry fetchStagingRequestFileEntry(
724                            long stagingRequestId, Folder folder)
725                    throws PortalException, SystemException {
726    
727                    try {
728                            return PortletFileRepositoryUtil.getPortletFileEntry(
729                                    folder.getGroupId(), folder.getFolderId(),
730                                    getAssembledFileName(stagingRequestId));
731                    }
732                    catch (NoSuchFileEntryException nsfe) {
733                            return null;
734                    }
735            }
736    
737            protected String getAssembledFileName(long stagingRequestId) {
738                    return _ASSEMBLED_LAR_PREFIX + String.valueOf(stagingRequestId) +
739                            ".lar";
740            }
741    
742            protected FileEntry getStagingRequestFileEntry(
743                            long userId, long stagingRequestId, Folder folder)
744                    throws PortalException, SystemException {
745    
746                    FileEntry stagingRequestFileEntry = fetchStagingRequestFileEntry(
747                            stagingRequestId, folder);
748    
749                    if (stagingRequestFileEntry != null) {
750                            return stagingRequestFileEntry;
751                    }
752    
753                    FileOutputStream fileOutputStream = null;
754    
755                    File tempFile = null;
756    
757                    boolean fileMaxSizeCheckEnabled =
758                            PortletFileRepositoryThreadLocal.isFileMaxSizeCheckEnabled();
759    
760                    try {
761                            PortletFileRepositoryThreadLocal.setFileMaxSizeCheckEnabled(false);
762    
763                            tempFile = FileUtil.createTempFile("lar");
764    
765                            fileOutputStream = new FileOutputStream(tempFile);
766    
767                            List<FileEntry> fileEntries =
768                                    PortletFileRepositoryUtil.getPortletFileEntries(
769                                            folder.getGroupId(), folder.getFolderId(),
770                                            WorkflowConstants.STATUS_ANY, QueryUtil.ALL_POS,
771                                            QueryUtil.ALL_POS, new RepositoryModelNameComparator(true));
772    
773                            for (FileEntry fileEntry : fileEntries) {
774                                    InputStream inputStream = fileEntry.getContentStream();
775    
776                                    try {
777                                            StreamUtil.transfer(inputStream, fileOutputStream, false);
778                                    }
779                                    finally {
780                                            StreamUtil.cleanUp(inputStream);
781    
782                                            PortletFileRepositoryUtil.deletePortletFileEntry(
783                                                    fileEntry.getFileEntryId());
784                                    }
785                            }
786    
787                            String checksum = FileUtil.getMD5Checksum(tempFile);
788    
789                            if (!checksum.equals(folder.getName())) {
790                                    throw new SystemException("Invalid checksum for LAR file");
791                            }
792    
793                            PortletFileRepositoryUtil.addPortletFileEntry(
794                                    folder.getGroupId(), userId, Group.class.getName(),
795                                    folder.getGroupId(), PortletKeys.SITES_ADMIN,
796                                    folder.getFolderId(), tempFile,
797                                    getAssembledFileName(stagingRequestId),
798                                    ContentTypes.APPLICATION_ZIP, false);
799    
800                            stagingRequestFileEntry = fetchStagingRequestFileEntry(
801                                    stagingRequestId, folder);
802    
803                            if (stagingRequestFileEntry == null) {
804                                    throw new SystemException("Unable to assemble LAR file");
805                            }
806    
807                            return stagingRequestFileEntry;
808                    }
809                    catch (IOException ioe) {
810                            throw new SystemException("Unable to reassemble LAR file", ioe);
811                    }
812                    finally {
813                            StreamUtil.cleanUp(fileOutputStream);
814    
815                            FileUtil.delete(tempFile);
816    
817                            PortletFileRepositoryThreadLocal.setFileMaxSizeCheckEnabled(
818                                    fileMaxSizeCheckEnabled);
819                    }
820            }
821    
822            protected void setCommonStagingOptions(
823                    Group liveGroup, UnicodeProperties typeSettingsProperties,
824                    ServiceContext serviceContext) {
825    
826                    if (liveGroup.getRemoteStagingGroupCount() > 0) {
827                            return;
828                    }
829    
830                    Set<String> parameterNames = serviceContext.getAttributes().keySet();
831    
832                    for (String parameterName : parameterNames) {
833                            if (parameterName.startsWith(StagingConstants.STAGED_PORTLET) &&
834                                    !parameterName.endsWith("Checkbox")) {
835    
836                                    boolean staged = ParamUtil.getBoolean(
837                                            serviceContext, parameterName);
838    
839                                    typeSettingsProperties.setProperty(
840                                            parameterName, String.valueOf(staged));
841                            }
842                    }
843            }
844    
845            protected Layout updateLayoutWithLayoutRevision(
846                            LayoutRevision layoutRevision)
847                    throws SystemException {
848    
849                    Layout layout = layoutLocalService.fetchLayout(
850                            layoutRevision.getPlid());
851    
852                    LayoutStagingHandler layoutStagingHandler =
853                            LayoutStagingUtil.getLayoutStagingHandler(layout);
854    
855                    layout = layoutStagingHandler.getLayout();
856    
857                    layout.setUserId(layoutRevision.getUserId());
858                    layout.setUserName(layoutRevision.getUserName());
859                    layout.setCreateDate(layoutRevision.getCreateDate());
860                    layout.setModifiedDate(layoutRevision.getModifiedDate());
861                    layout.setPrivateLayout(layoutRevision.getPrivateLayout());
862                    layout.setName(layoutRevision.getName());
863                    layout.setTitle(layoutRevision.getTitle());
864                    layout.setDescription(layoutRevision.getDescription());
865                    layout.setKeywords(layoutRevision.getKeywords());
866                    layout.setRobots(layoutRevision.getRobots());
867                    layout.setTypeSettings(layoutRevision.getTypeSettings());
868                    layout.setIconImageId(layoutRevision.getIconImageId());
869                    layout.setThemeId(layoutRevision.getThemeId());
870                    layout.setColorSchemeId(layoutRevision.getColorSchemeId());
871                    layout.setWapThemeId(layoutRevision.getWapThemeId());
872                    layout.setWapColorSchemeId(layoutRevision.getWapColorSchemeId());
873                    layout.setCss(layoutRevision.getCss());
874    
875                    return layoutLocalService.updateLayout(layout);
876            }
877    
878            protected void updateStagedPortlets(
879                            String remoteURL, long remoteGroupId,
880                            UnicodeProperties typeSettingsProperties)
881                    throws PortalException {
882    
883                    PermissionChecker permissionChecker =
884                            PermissionThreadLocal.getPermissionChecker();
885    
886                    User user = permissionChecker.getUser();
887    
888                    HttpPrincipal httpPrincipal = new HttpPrincipal(
889                            remoteURL, user.getScreenName(), user.getPassword(),
890                            user.getPasswordEncrypted());
891    
892                    Map<String, String> stagedPortletIds = new HashMap<String, String>();
893    
894                    for (String key : typeSettingsProperties.keySet()) {
895                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
896                                    stagedPortletIds.put(
897                                            key, typeSettingsProperties.getProperty(key));
898                            }
899                    }
900    
901                    try {
902                            GroupServiceHttp.updateStagedPortlets(
903                                    httpPrincipal, remoteGroupId, stagedPortletIds);
904                    }
905                    catch (NoSuchGroupException nsge) {
906                            RemoteExportException ree = new RemoteExportException(
907                                    RemoteExportException.NO_GROUP);
908    
909                            ree.setGroupId(remoteGroupId);
910    
911                            throw ree;
912                    }
913                    catch (PrincipalException pe) {
914                            RemoteExportException ree = new RemoteExportException(
915                                    RemoteExportException.NO_PERMISSIONS);
916    
917                            ree.setGroupId(remoteGroupId);
918    
919                            throw ree;
920                    }
921                    catch (RemoteAuthException rae) {
922                            rae.setURL(remoteURL);
923    
924                            throw rae;
925                    }
926                    catch (SystemException se) {
927                            RemoteExportException ree = new RemoteExportException(
928                                    RemoteExportException.BAD_CONNECTION);
929    
930                            ree.setURL(remoteURL);
931    
932                            throw ree;
933                    }
934            }
935    
936            private static final String _ASSEMBLED_LAR_PREFIX = "assembled_";
937    
938            private static Log _log = LogFactoryUtil.getLog(
939                    StagingLocalServiceImpl.class);
940    
941    }