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