001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.staging;
016    
017    import com.liferay.portal.DuplicateLockException;
018    import com.liferay.portal.LayoutSetBranchNameException;
019    import com.liferay.portal.NoSuchGroupException;
020    import com.liferay.portal.NoSuchLayoutBranchException;
021    import com.liferay.portal.NoSuchLayoutException;
022    import com.liferay.portal.NoSuchLayoutRevisionException;
023    import com.liferay.portal.RemoteExportException;
024    import com.liferay.portal.RemoteOptionsException;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.language.LanguageUtil;
028    import com.liferay.portal.kernel.lar.PortletDataContext;
029    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
030    import com.liferay.portal.kernel.lar.UserIdStrategy;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.messaging.DestinationNames;
034    import com.liferay.portal.kernel.messaging.MessageBusUtil;
035    import com.liferay.portal.kernel.messaging.MessageStatus;
036    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
037    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
038    import com.liferay.portal.kernel.staging.LayoutStagingUtil;
039    import com.liferay.portal.kernel.staging.Staging;
040    import com.liferay.portal.kernel.staging.StagingConstants;
041    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
042    import com.liferay.portal.kernel.util.GetterUtil;
043    import com.liferay.portal.kernel.util.Http;
044    import com.liferay.portal.kernel.util.LocaleUtil;
045    import com.liferay.portal.kernel.util.MapUtil;
046    import com.liferay.portal.kernel.util.ParamUtil;
047    import com.liferay.portal.kernel.util.StringBundler;
048    import com.liferay.portal.kernel.util.StringPool;
049    import com.liferay.portal.kernel.util.Time;
050    import com.liferay.portal.kernel.util.TimeZoneUtil;
051    import com.liferay.portal.kernel.util.UnicodeProperties;
052    import com.liferay.portal.kernel.util.Validator;
053    import com.liferay.portal.kernel.workflow.WorkflowConstants;
054    import com.liferay.portal.kernel.workflow.WorkflowTask;
055    import com.liferay.portal.kernel.workflow.WorkflowTaskManagerUtil;
056    import com.liferay.portal.kernel.xml.Element;
057    import com.liferay.portal.lar.LayoutExporter;
058    import com.liferay.portal.messaging.LayoutsLocalPublisherRequest;
059    import com.liferay.portal.messaging.LayoutsRemotePublisherRequest;
060    import com.liferay.portal.model.Group;
061    import com.liferay.portal.model.GroupConstants;
062    import com.liferay.portal.model.Layout;
063    import com.liferay.portal.model.LayoutBranch;
064    import com.liferay.portal.model.LayoutRevision;
065    import com.liferay.portal.model.LayoutSet;
066    import com.liferay.portal.model.LayoutSetBranch;
067    import com.liferay.portal.model.LayoutSetBranchConstants;
068    import com.liferay.portal.model.Lock;
069    import com.liferay.portal.model.Portlet;
070    import com.liferay.portal.model.User;
071    import com.liferay.portal.model.WorkflowInstanceLink;
072    import com.liferay.portal.security.auth.HttpPrincipal;
073    import com.liferay.portal.security.auth.PrincipalException;
074    import com.liferay.portal.security.permission.ActionKeys;
075    import com.liferay.portal.security.permission.PermissionChecker;
076    import com.liferay.portal.security.permission.PermissionThreadLocal;
077    import com.liferay.portal.service.GroupLocalServiceUtil;
078    import com.liferay.portal.service.LayoutBranchLocalServiceUtil;
079    import com.liferay.portal.service.LayoutLocalServiceUtil;
080    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
081    import com.liferay.portal.service.LayoutServiceUtil;
082    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
083    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
084    import com.liferay.portal.service.LockLocalServiceUtil;
085    import com.liferay.portal.service.ServiceContext;
086    import com.liferay.portal.service.ServiceContextThreadLocal;
087    import com.liferay.portal.service.WorkflowInstanceLinkLocalServiceUtil;
088    import com.liferay.portal.service.http.GroupServiceHttp;
089    import com.liferay.portal.service.http.LayoutServiceHttp;
090    import com.liferay.portal.service.permission.GroupPermissionUtil;
091    import com.liferay.portal.theme.ThemeDisplay;
092    import com.liferay.portal.util.PortalUtil;
093    import com.liferay.portal.util.PropsValues;
094    import com.liferay.portal.util.SessionClicks;
095    import com.liferay.portal.util.WebKeys;
096    import com.liferay.portlet.PortalPreferences;
097    import com.liferay.portlet.PortletPreferencesFactoryUtil;
098    
099    import java.io.File;
100    
101    import java.util.ArrayList;
102    import java.util.Calendar;
103    import java.util.Date;
104    import java.util.HashSet;
105    import java.util.LinkedHashMap;
106    import java.util.List;
107    import java.util.Locale;
108    import java.util.Map;
109    import java.util.Set;
110    import java.util.TimeZone;
111    
112    import javax.portlet.PortletRequest;
113    
114    import javax.servlet.http.HttpServletRequest;
115    
116    /**
117     * @author Raymond Augé
118     * @author Bruno Farache
119     * @author Wesley Gong
120     * @author Zsolt Balogh
121     */
122    @DoPrivileged
123    public class StagingImpl implements Staging {
124    
125            public String buildRemoteURL(
126                    String remoteAddress, int remotePort, String remotePathContext,
127                    boolean secureConnection, long remoteGroupId, boolean privateLayout) {
128    
129                    StringBundler sb = new StringBundler((remoteGroupId > 0) ? 4 : 9);
130    
131                    if (secureConnection) {
132                            sb.append(Http.HTTPS_WITH_SLASH);
133                    }
134                    else {
135                            sb.append(Http.HTTP_WITH_SLASH);
136                    }
137    
138                    sb.append(remoteAddress);
139    
140                    if (remotePort > 0) {
141                            sb.append(StringPool.COLON);
142                            sb.append(remotePort);
143                    }
144    
145                    if (Validator.isNotNull(remotePathContext)) {
146                            sb.append(remotePathContext);
147                    }
148    
149                    if (remoteGroupId > 0) {
150                            sb.append("/c/my_sites/view?");
151                            sb.append("groupId=");
152                            sb.append(remoteGroupId);
153                            sb.append("&privateLayout=");
154                            sb.append(privateLayout);
155                    }
156    
157                    return sb.toString();
158            }
159    
160            public void copyFromLive(PortletRequest portletRequest) throws Exception {
161                    long stagingGroupId = ParamUtil.getLong(
162                            portletRequest, "stagingGroupId");
163    
164                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
165    
166                    long liveGroupId = stagingGroup.getLiveGroupId();
167    
168                    Map<String, String[]> parameterMap = getStagingParameters(
169                            portletRequest);
170    
171                    publishLayouts(
172                            portletRequest, liveGroupId, stagingGroupId, parameterMap, false);
173            }
174    
175            public void copyFromLive(PortletRequest portletRequest, Portlet portlet)
176                    throws Exception {
177    
178                    long plid = ParamUtil.getLong(portletRequest, "plid");
179    
180                    Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
181    
182                    Group stagingGroup = targetLayout.getGroup();
183                    Group liveGroup = stagingGroup.getLiveGroup();
184    
185                    Layout sourceLayout = LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
186                            targetLayout.getUuid(), liveGroup.getGroupId(),
187                            targetLayout.isPrivateLayout());
188    
189                    copyPortlet(
190                            portletRequest, liveGroup.getGroupId(), stagingGroup.getGroupId(),
191                            sourceLayout.getPlid(), targetLayout.getPlid(),
192                            portlet.getPortletId());
193            }
194    
195            public void copyPortlet(
196                            PortletRequest portletRequest, long sourceGroupId,
197                            long targetGroupId, long sourcePlid, long targetPlid,
198                            String portletId)
199                    throws Exception {
200    
201                    long userId = PortalUtil.getUserId(portletRequest);
202    
203                    Map<String, String[]> parameterMap = getStagingParameters(
204                            portletRequest);
205    
206                    File file = LayoutLocalServiceUtil.exportPortletInfoAsFile(
207                            sourcePlid, sourceGroupId, portletId, parameterMap, null, null);
208    
209                    try {
210                            LayoutLocalServiceUtil.importPortletInfo(
211                                    userId, targetPlid, targetGroupId, portletId, parameterMap,
212                                    file);
213                    }
214                    finally {
215                            file.delete();
216                    }
217            }
218    
219            public void copyRemoteLayouts(
220                            long sourceGroupId, boolean privateLayout,
221                            Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
222                            String remoteAddress, int remotePort, String remotePathContext,
223                            boolean secureConnection, long remoteGroupId,
224                            boolean remotePrivateLayout, Date startDate, Date endDate)
225                    throws Exception {
226    
227                    PermissionChecker permissionChecker =
228                            PermissionThreadLocal.getPermissionChecker();
229    
230                    User user = permissionChecker.getUser();
231    
232                    StringBundler sb = new StringBundler(4);
233    
234                    if (secureConnection) {
235                            sb.append(Http.HTTPS_WITH_SLASH);
236                    }
237                    else {
238                            sb.append(Http.HTTP_WITH_SLASH);
239                    }
240    
241                    sb.append(remoteAddress);
242                    sb.append(StringPool.COLON);
243                    sb.append(remotePort);
244                    sb.append(remotePathContext);
245    
246                    String url = sb.toString();
247    
248                    HttpPrincipal httpPrincipal = new HttpPrincipal(
249                            url, user.getEmailAddress(), user.getPassword(),
250                            user.getPasswordEncrypted());
251    
252                    // Ping remote host and verify that the group exists in the same company
253                    // as the remote user
254    
255                    try {
256                            GroupServiceHttp.checkRemoteStagingGroup(
257                                    httpPrincipal, remoteGroupId);
258                    }
259                    catch (NoSuchGroupException nsge) {
260                            RemoteExportException ree = new RemoteExportException(
261                                    RemoteExportException.NO_GROUP);
262    
263                            ree.setGroupId(remoteGroupId);
264    
265                            throw ree;
266                    }
267                    catch (SystemException se) {
268                            RemoteExportException ree = new RemoteExportException(
269                                    RemoteExportException.BAD_CONNECTION);
270    
271                            ree.setURL(url);
272    
273                            throw ree;
274                    }
275    
276                    byte[] bytes = null;
277    
278                    if (layoutIdMap == null) {
279                            bytes = LayoutLocalServiceUtil.exportLayouts(
280                                    sourceGroupId, privateLayout, parameterMap, startDate, endDate);
281                    }
282                    else {
283                            List<Layout> layouts = new ArrayList<Layout>();
284    
285                            for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
286                                    long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
287                                    boolean includeChildren = entry.getValue();
288    
289                                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
290    
291                                    if (!layouts.contains(layout)) {
292                                            layouts.add(layout);
293                                    }
294    
295                                    List<Layout> parentLayouts = getMissingRemoteParentLayouts(
296                                            httpPrincipal, layout, remoteGroupId);
297    
298                                    for (Layout parentLayout : parentLayouts) {
299                                            if (!layouts.contains(parentLayout)) {
300                                                    layouts.add(parentLayout);
301                                            }
302                                    }
303    
304                                    if (includeChildren) {
305                                            for (Layout childLayout : layout.getAllChildren()) {
306                                                    if (!layouts.contains(childLayout)) {
307                                                            layouts.add(childLayout);
308                                                    }
309                                            }
310                                    }
311                            }
312    
313                            long[] layoutIds = getLayoutIds(layouts);
314    
315                            if (layoutIds.length <= 0) {
316                                    throw new RemoteExportException(
317                                            RemoteExportException.NO_LAYOUTS);
318                            }
319    
320                            bytes = LayoutLocalServiceUtil.exportLayouts(
321                                    sourceGroupId, privateLayout, layoutIds, parameterMap,
322                                    startDate, endDate);
323                    }
324    
325                    LayoutServiceHttp.importLayouts(
326                            httpPrincipal, remoteGroupId, remotePrivateLayout, parameterMap,
327                            bytes);
328            }
329    
330            public void deleteLastImportSettings(Group liveGroup, boolean privateLayout)
331                    throws Exception {
332    
333                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
334                            liveGroup.getGroupId(), privateLayout);
335    
336                    for (Layout layout : layouts) {
337                            UnicodeProperties typeSettingsProperties =
338                                    layout.getTypeSettingsProperties();
339    
340                            Set<String> keys = new HashSet<String>();
341    
342                            for (String key : typeSettingsProperties.keySet()) {
343                                    if (key.startsWith("last-import-")) {
344                                            keys.add(key);
345                                    }
346                            }
347    
348                            if (keys.isEmpty()) {
349                                    continue;
350                            }
351    
352                            for (String key : keys) {
353                                    typeSettingsProperties.remove(key);
354                            }
355    
356                            LayoutLocalServiceUtil.updateLayout(
357                                    layout.getGroupId(), layout.getPrivateLayout(),
358                                    layout.getLayoutId(), typeSettingsProperties.toString());
359                    }
360            }
361    
362            public void deleteRecentLayoutRevisionId(
363                            HttpServletRequest request, long layoutSetBranchId, long plid)
364                    throws SystemException {
365    
366                    PortalPreferences portalPreferences =
367                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
368    
369                    deleteRecentLayoutRevisionId(
370                            portalPreferences, layoutSetBranchId, plid);
371            }
372    
373            public void deleteRecentLayoutRevisionId(
374                            User user, long layoutSetBranchId, long plid)
375                    throws SystemException {
376    
377                    PortalPreferences portalPreferences = getPortalPreferences(user);
378    
379                    deleteRecentLayoutRevisionId(
380                            portalPreferences, layoutSetBranchId, plid);
381            }
382    
383            @Deprecated
384            public void disableStaging(
385                            Group scopeGroup, Group liveGroup, ServiceContext serviceContext)
386                    throws Exception {
387    
388                    disableStaging((PortletRequest)null, liveGroup, serviceContext);
389            }
390    
391            public void disableStaging(Group liveGroup, ServiceContext serviceContext)
392                    throws Exception {
393    
394                    disableStaging((PortletRequest)null, liveGroup, serviceContext);
395            }
396    
397            @Deprecated
398            public void disableStaging(
399                            PortletRequest portletRequest, Group scopeGroup, Group liveGroup,
400                            ServiceContext serviceContext)
401                    throws Exception {
402    
403                    disableStaging(portletRequest, liveGroup, serviceContext);
404            }
405    
406            public void disableStaging(
407                            PortletRequest portletRequest, Group liveGroup,
408                            ServiceContext serviceContext)
409                    throws Exception {
410    
411                    UnicodeProperties typeSettingsProperties =
412                            liveGroup.getTypeSettingsProperties();
413    
414                    typeSettingsProperties.remove("branchingPrivate");
415                    typeSettingsProperties.remove("branchingPublic");
416                    typeSettingsProperties.remove("remoteAddress");
417                    typeSettingsProperties.remove("remoteGroupId");
418                    typeSettingsProperties.remove("remotePathContext");
419                    typeSettingsProperties.remove("remotePort");
420                    typeSettingsProperties.remove("secureConnection");
421                    typeSettingsProperties.remove("staged");
422                    typeSettingsProperties.remove("stagedRemotely");
423    
424                    Set<String> keys = new HashSet<String>();
425    
426                    for (String key : typeSettingsProperties.keySet()) {
427                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
428                                    keys.add(key);
429                            }
430                    }
431    
432                    for (String key : keys) {
433                            typeSettingsProperties.remove(key);
434                    }
435    
436                    deleteLastImportSettings(liveGroup, true);
437                    deleteLastImportSettings(liveGroup, false);
438    
439                    if (liveGroup.hasStagingGroup()) {
440                            Group stagingGroup = liveGroup.getStagingGroup();
441    
442                            LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
443                                    stagingGroup.getGroupId(), true, true);
444                            LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
445                                    stagingGroup.getGroupId(), false, true);
446    
447                            GroupLocalServiceUtil.deleteGroup(stagingGroup.getGroupId());
448                    }
449                    else {
450                            LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
451                                    liveGroup.getGroupId(), true, true);
452                            LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
453                                    liveGroup.getGroupId(), false, true);
454                    }
455    
456                    GroupLocalServiceUtil.updateGroup(
457                            liveGroup.getGroupId(), typeSettingsProperties.toString());
458            }
459    
460            public void enableLocalStaging(
461                            long userId, Group scopeGroup, Group liveGroup,
462                            boolean branchingPublic, boolean branchingPrivate,
463                            ServiceContext serviceContext)
464                    throws Exception {
465    
466                    if (liveGroup.isStagedRemotely()) {
467                            disableStaging(liveGroup, serviceContext);
468                    }
469    
470                    UnicodeProperties typeSettingsProperties =
471                            liveGroup.getTypeSettingsProperties();
472    
473                    typeSettingsProperties.setProperty(
474                            "branchingPrivate", String.valueOf(branchingPrivate));
475                    typeSettingsProperties.setProperty(
476                            "branchingPublic", String.valueOf(branchingPublic));
477                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
478                    typeSettingsProperties.setProperty(
479                            "stagedRemotely", String.valueOf(false));
480    
481                    setCommonStagingOptions(
482                            liveGroup, typeSettingsProperties, serviceContext);
483    
484                    if (!liveGroup.hasStagingGroup()) {
485                            serviceContext.setAttribute("staging", String.valueOf(true));
486    
487                            Group stagingGroup = GroupLocalServiceUtil.addGroup(
488                                    userId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
489                                    liveGroup.getClassName(), liveGroup.getClassPK(),
490                                    liveGroup.getGroupId(), liveGroup.getDescriptiveName(),
491                                    liveGroup.getDescription(), liveGroup.getType(),
492                                    liveGroup.getFriendlyURL(), false, liveGroup.isActive(),
493                                    serviceContext);
494    
495                            GroupLocalServiceUtil.updateGroup(
496                                    liveGroup.getGroupId(), typeSettingsProperties.toString());
497    
498                            if (liveGroup.hasPrivateLayouts()) {
499                                    Map<String, String[]> parameterMap = getStagingParameters();
500    
501                                    publishLayouts(
502                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
503                                            true, parameterMap, null, null);
504                            }
505    
506                            if (liveGroup.hasPublicLayouts()) {
507                                    Map<String, String[]> parameterMap = getStagingParameters();
508    
509                                    publishLayouts(
510                                            userId, liveGroup.getGroupId(), stagingGroup.getGroupId(),
511                                            false, parameterMap, null, null);
512                            }
513    
514                            checkDefaultLayoutSetBranches(
515                                    userId, liveGroup, branchingPublic, branchingPrivate, false,
516                                    serviceContext);
517                    }
518                    else {
519                            GroupLocalServiceUtil.updateGroup(
520                                    liveGroup.getGroupId(), typeSettingsProperties.toString());
521    
522                            checkDefaultLayoutSetBranches(
523                                    userId, liveGroup, branchingPublic, branchingPrivate, false,
524                                    serviceContext);
525    
526                            if (!branchingPublic) {
527                                    LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
528                                            liveGroup.getStagingGroup().getGroupId(), false, true);
529                            }
530    
531                            if (!branchingPrivate) {
532                                    LayoutSetBranchLocalServiceUtil.deleteLayoutSetBranches(
533                                            liveGroup.getStagingGroup().getGroupId(), true, true);
534                            }
535                    }
536            }
537    
538            public void enableRemoteStaging(
539                            long userId, Group scopeGroup, Group liveGroup,
540                            boolean branchingPublic, boolean branchingPrivate,
541                            String remoteAddress, int remotePort, String remotePathContext,
542                            boolean secureConnection, long remoteGroupId,
543                            ServiceContext serviceContext)
544                    throws Exception {
545    
546                    validate(
547                            remoteAddress, remotePort, remotePathContext, secureConnection,
548                            remoteGroupId);
549    
550                    if (liveGroup.hasStagingGroup()) {
551                            disableStaging(liveGroup, serviceContext);
552                    }
553    
554                    UnicodeProperties typeSettingsProperties =
555                            liveGroup.getTypeSettingsProperties();
556    
557                    typeSettingsProperties.setProperty(
558                            "branchingPrivate", String.valueOf(branchingPrivate));
559                    typeSettingsProperties.setProperty(
560                            "branchingPublic", String.valueOf(branchingPublic));
561                    typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
562                    typeSettingsProperties.setProperty(
563                            "remoteGroupId", String.valueOf(remoteGroupId));
564                    typeSettingsProperties.setProperty(
565                            "remotePathContext", remotePathContext);
566                    typeSettingsProperties.setProperty(
567                            "remotePort", String.valueOf(remotePort));
568                    typeSettingsProperties.setProperty(
569                            "secureConnection", String.valueOf(secureConnection));
570                    typeSettingsProperties.setProperty("staged", Boolean.TRUE.toString());
571                    typeSettingsProperties.setProperty(
572                            "stagedRemotely", Boolean.TRUE.toString());
573    
574                    setCommonStagingOptions(
575                            liveGroup, typeSettingsProperties, serviceContext);
576    
577                    GroupLocalServiceUtil.updateGroup(
578                            liveGroup.getGroupId(), typeSettingsProperties.toString());
579    
580                    checkDefaultLayoutSetBranches(
581                            userId, liveGroup, branchingPublic, branchingPrivate, true,
582                            serviceContext);
583            }
584    
585            public Group getLiveGroup(long groupId)
586                    throws PortalException, SystemException {
587    
588                    if (groupId == 0) {
589                            return null;
590                    }
591    
592                    Group group = GroupLocalServiceUtil.getGroup(groupId);
593    
594                    if (group.isLayout()) {
595                            group = group.getParentGroup();
596                    }
597    
598                    if (group.isStagingGroup()) {
599                            return group.getLiveGroup();
600                    }
601                    else {
602                            return group;
603                    }
604            }
605    
606            public long getLiveGroupId(long groupId)
607                    throws PortalException, SystemException {
608    
609                    if (groupId == 0) {
610                            return groupId;
611                    }
612    
613                    Group group = getLiveGroup(groupId);
614    
615                    return group.getGroupId();
616            }
617    
618            /**
619             * @see #getMissingRemoteParentLayouts(HttpPrincipal, Layout, long)
620             */
621            public List<Layout> getMissingParentLayouts(Layout layout, long liveGroupId)
622                    throws Exception {
623    
624                    List<Layout> missingParentLayouts = new ArrayList<Layout>();
625    
626                    long parentLayoutId = layout.getParentLayoutId();
627    
628                    Layout parentLayout = null;
629    
630                    while (parentLayoutId > 0) {
631                            parentLayout = LayoutLocalServiceUtil.getLayout(
632                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
633    
634                            try {
635                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
636                                            parentLayout.getUuid(), liveGroupId,
637                                            parentLayout.isPrivateLayout());
638    
639                                    // If one parent is found all others are assumed to exist
640    
641                                    break;
642                            }
643                            catch (NoSuchLayoutException nsle) {
644                                    missingParentLayouts.add(parentLayout);
645    
646                                    parentLayoutId = parentLayout.getParentLayoutId();
647                            }
648                    }
649    
650                    return missingParentLayouts;
651            }
652    
653            public long getRecentLayoutRevisionId(
654                            HttpServletRequest request, long layoutSetBranchId, long plid)
655                    throws PortalException, SystemException {
656    
657                    PortalPreferences portalPreferences =
658                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
659    
660                    return getRecentLayoutRevisionId(
661                            portalPreferences, layoutSetBranchId, plid);
662            }
663    
664            public long getRecentLayoutRevisionId(
665                            User user, long layoutSetBranchId, long plid)
666                    throws PortalException, SystemException {
667    
668                    PortalPreferences portalPreferences = getPortalPreferences(user);
669    
670                    return getRecentLayoutRevisionId(
671                            portalPreferences, layoutSetBranchId, plid);
672            }
673    
674            public long getRecentLayoutSetBranchId(
675                    HttpServletRequest request, long layoutSetId) {
676    
677                    return GetterUtil.getLong(
678                            SessionClicks.get(
679                                    request, Staging.class.getName(),
680                                    getRecentLayoutSetBranchIdKey(layoutSetId)));
681            }
682    
683            public long getRecentLayoutSetBranchId(User user, long layoutSetId)
684                    throws SystemException {
685    
686                    PortalPreferences portalPreferences = getPortalPreferences(user);
687    
688                    return GetterUtil.getLong(
689                            portalPreferences.getValue(
690                                    Staging.class.getName(),
691                                    getRecentLayoutSetBranchIdKey(layoutSetId)));
692            }
693    
694            public String getSchedulerGroupName(String destinationName, long groupId) {
695                    return destinationName.concat(StringPool.SLASH).concat(
696                            String.valueOf(groupId));
697            }
698    
699            public Map<String, String[]> getStagingParameters() {
700                    Map<String, String[]> parameterMap =
701                            new LinkedHashMap<String, String[]>();
702    
703                    parameterMap.put(
704                            PortletDataHandlerKeys.CATEGORIES,
705                            new String[] {Boolean.TRUE.toString()});
706                    parameterMap.put(
707                            PortletDataHandlerKeys.DATA_STRATEGY,
708                            new String[] {
709                                    PortletDataHandlerKeys.DATA_STRATEGY_MIRROR_OVERWRITE});
710                    parameterMap.put(
711                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
712                            new String[] {Boolean.TRUE.toString()});
713                    parameterMap.put(
714                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
715                            new String[] {Boolean.FALSE.toString()});
716                    parameterMap.put(
717                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
718                            new String[] {Boolean.TRUE.toString()});
719                    parameterMap.put(
720                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
721                            new String[] {Boolean.FALSE.toString()});
722                    parameterMap.put(
723                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
724                            new String[] {Boolean.FALSE.toString()});
725                    parameterMap.put(
726                            PortletDataHandlerKeys.LOGO,
727                            new String[] {Boolean.FALSE.toString()});
728                    parameterMap.put(
729                            PortletDataHandlerKeys.PERMISSIONS,
730                            new String[] {Boolean.TRUE.toString()});
731                    parameterMap.put(
732                            PortletDataHandlerKeys.PORTLET_DATA,
733                            new String[] {Boolean.TRUE.toString()});
734                    parameterMap.put(
735                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
736                            new String[] {Boolean.TRUE.toString()});
737                    parameterMap.put(
738                            PortletDataHandlerKeys.PORTLET_SETUP,
739                            new String[] {Boolean.TRUE.toString()});
740                    parameterMap.put(
741                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
742                            new String[] {Boolean.TRUE.toString()});
743                    parameterMap.put(
744                            PortletDataHandlerKeys.THEME,
745                            new String[] {Boolean.FALSE.toString()});
746                    parameterMap.put(
747                            PortletDataHandlerKeys.THEME_REFERENCE,
748                            new String[] {Boolean.TRUE.toString()});
749                    parameterMap.put(
750                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
751                            new String[] {Boolean.TRUE.toString()});
752                    parameterMap.put(
753                            PortletDataHandlerKeys.USER_ID_STRATEGY,
754                            new String[] {UserIdStrategy.CURRENT_USER_ID});
755    
756                    return parameterMap;
757            }
758    
759            public Map<String, String[]> getStagingParameters(
760                    PortletRequest portletRequest) {
761    
762                    Map<String, String[]> parameterMap =
763                            new LinkedHashMap<String, String[]>(
764                                    portletRequest.getParameterMap());
765    
766                    if (!parameterMap.containsKey(PortletDataHandlerKeys.DATA_STRATEGY)) {
767                            parameterMap.put(
768                                    PortletDataHandlerKeys.DATA_STRATEGY,
769                                    new String[] {
770                                            PortletDataHandlerKeys.DATA_STRATEGY_MIRROR_OVERWRITE});
771                    }
772    
773                    /*if (!parameterMap.containsKey(
774                                    PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS)) {
775    
776                            parameterMap.put(
777                                    PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
778                                    new String[] {Boolean.TRUE.toString()});
779                    }*/
780    
781                    if (!parameterMap.containsKey(
782                                    PortletDataHandlerKeys.DELETE_PORTLET_DATA)) {
783    
784                            parameterMap.put(
785                                    PortletDataHandlerKeys.DELETE_PORTLET_DATA,
786                                    new String[] {Boolean.FALSE.toString()});
787                    }
788    
789                    if (!parameterMap.containsKey(
790                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED)) {
791    
792                            parameterMap.put(
793                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
794                                    new String[] {Boolean.FALSE.toString()});
795                    }
796    
797                    if (!parameterMap.containsKey(
798                                    PortletDataHandlerKeys.LAYOUT_SET_SETTINGS)) {
799    
800                            parameterMap.put(
801                                    PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
802                                    new String[] {Boolean.FALSE.toString()});
803                    }
804    
805                    if (!parameterMap.containsKey(PortletDataHandlerKeys.LOGO)) {
806                            parameterMap.put(
807                                    PortletDataHandlerKeys.LOGO,
808                                    new String[] {Boolean.FALSE.toString()});
809                    }
810    
811                    if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_DATA)) {
812                            parameterMap.put(
813                                    PortletDataHandlerKeys.PORTLET_DATA,
814                                    new String[] {Boolean.FALSE.toString()});
815                    }
816    
817                    if (!parameterMap.containsKey(
818                                    PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
819    
820                            parameterMap.put(
821                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
822                                    new String[] {Boolean.FALSE.toString()});
823                    }
824    
825                    if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_SETUP)) {
826                            parameterMap.put(
827                                    PortletDataHandlerKeys.PORTLET_SETUP,
828                                    new String[] {Boolean.TRUE.toString()});
829                    }
830    
831                    if (!parameterMap.containsKey(
832                                    PortletDataHandlerKeys.PORTLET_USER_PREFERENCES)) {
833    
834                            parameterMap.put(
835                                    PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
836                                    new String[] {Boolean.TRUE.toString()});
837                    }
838    
839                    if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME)) {
840                            parameterMap.put(
841                                    PortletDataHandlerKeys.THEME,
842                                    new String[] {Boolean.FALSE.toString()});
843                    }
844    
845                    if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME_REFERENCE)) {
846                            parameterMap.put(
847                                    PortletDataHandlerKeys.THEME_REFERENCE,
848                                    new String[] {Boolean.FALSE.toString()});
849                    }
850    
851                    if (!parameterMap.containsKey(
852                                    PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE)) {
853    
854                            parameterMap.put(
855                                    PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
856                                    new String[] {Boolean.TRUE.toString()});
857                    }
858    
859                    if (!parameterMap.containsKey(
860                                    PortletDataHandlerKeys.USER_ID_STRATEGY)) {
861    
862                            parameterMap.put(
863                                    PortletDataHandlerKeys.USER_ID_STRATEGY,
864                                    new String[] {UserIdStrategy.CURRENT_USER_ID});
865                    }
866    
867                    return parameterMap;
868            }
869    
870            public WorkflowTask getWorkflowTask(
871                            long userId, LayoutRevision layoutRevision)
872                    throws PortalException, SystemException {
873    
874                    WorkflowInstanceLink workflowInstanceLink =
875                            WorkflowInstanceLinkLocalServiceUtil.fetchWorkflowInstanceLink(
876                                    layoutRevision.getCompanyId(), layoutRevision.getGroupId(),
877                                    LayoutRevision.class.getName(),
878                                    layoutRevision.getLayoutRevisionId());
879    
880                    if (workflowInstanceLink == null) {
881                            return null;
882                    }
883    
884                    List<WorkflowTask> workflowTasks =
885                            WorkflowTaskManagerUtil.getWorkflowTasksByWorkflowInstance(
886                                    layoutRevision.getCompanyId(), userId,
887                                    workflowInstanceLink.getWorkflowInstanceId(), false, 0, 1,
888                                    null);
889    
890                    if (!workflowTasks.isEmpty()) {
891                            return workflowTasks.get(0);
892                    }
893    
894                    return null;
895            }
896    
897            public boolean hasWorkflowTask(long userId, LayoutRevision layoutRevision)
898                    throws PortalException, SystemException {
899    
900                    WorkflowTask workflowTask = getWorkflowTask(userId, layoutRevision);
901    
902                    if (workflowTask != null) {
903                            return true;
904                    }
905    
906                    return false;
907            }
908    
909            public boolean isIncomplete(Layout layout, long layoutSetBranchId) {
910                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
911                            layout);
912    
913                    if (layoutRevision == null) {
914                            try {
915                                    layoutRevision =
916                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
917                                                    layoutSetBranchId, layout.getPlid(), true);
918    
919                                    return false;
920                            }
921                            catch (Exception e) {
922                            }
923                    }
924    
925                    try {
926                            layoutRevision = LayoutRevisionLocalServiceUtil.getLayoutRevision(
927                                    layoutSetBranchId, layout.getPlid(), false);
928                    }
929                    catch (Exception e) {
930                    }
931    
932                    if ((layoutRevision == null) ||
933                            (layoutRevision.getStatus() ==
934                                    WorkflowConstants.STATUS_INCOMPLETE)) {
935    
936                            return true;
937                    }
938    
939                    return false;
940            }
941    
942            public void publishLayout(
943                            long userId, long plid, long liveGroupId, boolean includeChildren)
944                    throws Exception {
945    
946                    Map<String, String[]> parameterMap = getStagingParameters();
947    
948                    parameterMap.put(
949                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
950                            new String[] {Boolean.FALSE.toString()});
951    
952                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
953    
954                    List<Layout> layouts = new ArrayList<Layout>();
955    
956                    layouts.add(layout);
957    
958                    layouts.addAll(getMissingParentLayouts(layout, liveGroupId));
959    
960                    if (includeChildren) {
961                            layouts.addAll(layout.getAllChildren());
962                    }
963    
964                    long[] layoutIds = getLayoutIds(layouts);
965    
966                    publishLayouts(
967                            userId, layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
968                            layoutIds, parameterMap, null, null);
969            }
970    
971            public void publishLayouts(
972                            long userId, long sourceGroupId, long targetGroupId,
973                            boolean privateLayout, long[] layoutIds,
974                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
975                    throws Exception {
976    
977                    lockGroup(userId, targetGroupId);
978    
979                    parameterMap.put(
980                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
981                            new String[] {Boolean.TRUE.toString()});
982    
983                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
984                            sourceGroupId, privateLayout, layoutIds, parameterMap, startDate,
985                            endDate);
986    
987                    try {
988                            LayoutLocalServiceUtil.importLayouts(
989                                    userId, targetGroupId, privateLayout, parameterMap, file);
990                    }
991                    finally {
992                            file.delete();
993    
994                            unlockGroup(targetGroupId);
995                    }
996            }
997    
998            public void publishLayouts(
999                            long userId, long sourceGroupId, long targetGroupId,
1000                            boolean privateLayout, Map<Long, Boolean> layoutIdMap,
1001                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1002                    throws Exception {
1003    
1004                    List<Layout> layouts = new ArrayList<Layout>();
1005    
1006                    for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
1007                            long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
1008                            boolean includeChildren = entry.getValue();
1009    
1010                            Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1011    
1012                            if (!layouts.contains(layout)) {
1013                                    layouts.add(layout);
1014                            }
1015    
1016                            List<Layout> parentLayouts = getMissingParentLayouts(
1017                                    layout, targetGroupId);
1018    
1019                            for (Layout parentLayout : parentLayouts) {
1020                                    if (!layouts.contains(parentLayout)) {
1021                                            layouts.add(parentLayout);
1022                                    }
1023                            }
1024    
1025                            if (includeChildren) {
1026                                    for (Layout childLayout : layout.getAllChildren()) {
1027                                            if (!layouts.contains(childLayout)) {
1028                                                    layouts.add(childLayout);
1029                                            }
1030                                    }
1031                            }
1032                    }
1033    
1034                    long[] layoutIds = getLayoutIds(layouts);
1035    
1036                    publishLayouts(
1037                            userId, sourceGroupId, targetGroupId, privateLayout, layoutIds,
1038                            parameterMap, startDate, endDate);
1039            }
1040    
1041            public void publishLayouts(
1042                            long userId, long sourceGroupId, long targetGroupId,
1043                            boolean privateLayout, Map<String, String[]> parameterMap,
1044                            Date startDate, Date endDate)
1045                    throws Exception {
1046    
1047                    publishLayouts(
1048                            userId, sourceGroupId, targetGroupId, privateLayout, (long[])null,
1049                            parameterMap, startDate, endDate);
1050            }
1051    
1052            public void publishToLive(PortletRequest portletRequest) throws Exception {
1053                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1054    
1055                    Group liveGroup = GroupLocalServiceUtil.getGroup(groupId);
1056    
1057                    Map<String, String[]> parameterMap = getStagingParameters(
1058                            portletRequest);
1059    
1060                    if (liveGroup.isStaged()) {
1061                            if (liveGroup.isStagedRemotely()) {
1062                                    publishToRemote(portletRequest);
1063                            }
1064                            else {
1065                                    Group stagingGroup = liveGroup.getStagingGroup();
1066    
1067                                    publishLayouts(
1068                                            portletRequest, stagingGroup.getGroupId(), groupId,
1069                                            parameterMap, false);
1070                            }
1071                    }
1072            }
1073    
1074            public void publishToLive(PortletRequest portletRequest, Portlet portlet)
1075                    throws Exception {
1076    
1077                    long plid = ParamUtil.getLong(portletRequest, "plid");
1078    
1079                    Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
1080    
1081                    Group stagingGroup = null;
1082                    Group liveGroup = null;
1083    
1084                    Layout targetLayout = null;
1085    
1086                    long scopeGroupId = PortalUtil.getScopeGroupId(portletRequest);
1087    
1088                    if (sourceLayout.hasScopeGroup() &&
1089                            (sourceLayout.getScopeGroup().getGroupId() == scopeGroupId)) {
1090    
1091                            stagingGroup = sourceLayout.getScopeGroup();
1092                            liveGroup = stagingGroup.getLiveGroup();
1093    
1094                            targetLayout = LayoutLocalServiceUtil.getLayout(
1095                                    liveGroup.getClassPK());
1096                    }
1097                    else {
1098                            stagingGroup = sourceLayout.getGroup();
1099                            liveGroup = stagingGroup.getLiveGroup();
1100    
1101                            targetLayout = LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1102                                    sourceLayout.getUuid(), liveGroup.getGroupId(),
1103                                    sourceLayout.isPrivateLayout());
1104                    }
1105    
1106                    copyPortlet(
1107                            portletRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
1108                            sourceLayout.getPlid(), targetLayout.getPlid(),
1109                            portlet.getPortletId());
1110            }
1111    
1112            public void publishToRemote(PortletRequest portletRequest)
1113                    throws Exception {
1114    
1115                    publishToRemote(portletRequest, false);
1116            }
1117    
1118            public void scheduleCopyFromLive(PortletRequest portletRequest)
1119                    throws Exception {
1120    
1121                    long stagingGroupId = ParamUtil.getLong(
1122                            portletRequest, "stagingGroupId");
1123    
1124                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1125    
1126                    long liveGroupId = stagingGroup.getLiveGroupId();
1127    
1128                    Map<String, String[]> parameterMap = getStagingParameters(
1129                            portletRequest);
1130    
1131                    publishLayouts(
1132                            portletRequest, liveGroupId, stagingGroupId, parameterMap, true);
1133            }
1134    
1135            public void schedulePublishToLive(PortletRequest portletRequest)
1136                    throws Exception {
1137    
1138                    long stagingGroupId = ParamUtil.getLong(
1139                            portletRequest, "stagingGroupId");
1140    
1141                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1142    
1143                    long liveGroupId = stagingGroup.getLiveGroupId();
1144    
1145                    Map<String, String[]> parameterMap = getStagingParameters(
1146                            portletRequest);
1147    
1148                    publishLayouts(
1149                            portletRequest, stagingGroupId, liveGroupId, parameterMap, true);
1150            }
1151    
1152            public void schedulePublishToRemote(PortletRequest portletRequest)
1153                    throws Exception {
1154    
1155                    publishToRemote(portletRequest, true);
1156            }
1157    
1158            public void setRecentLayoutBranchId(
1159                            HttpServletRequest request, long layoutSetBranchId, long plid,
1160                            long layoutBranchId)
1161                    throws SystemException {
1162    
1163                    PortalPreferences portalPreferences =
1164                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1165    
1166                    setRecentLayoutBranchId(
1167                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1168            }
1169    
1170            public void setRecentLayoutBranchId(
1171                            User user, long layoutSetBranchId, long plid, long layoutBranchId)
1172                    throws SystemException {
1173    
1174                    PortalPreferences portalPreferences = getPortalPreferences(user);
1175    
1176                    setRecentLayoutBranchId(
1177                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1178            }
1179    
1180            public void setRecentLayoutRevisionId(
1181                            HttpServletRequest request, long layoutSetBranchId, long plid,
1182                            long layoutRevisionId)
1183                    throws SystemException {
1184    
1185                    PortalPreferences portalPreferences =
1186                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1187    
1188                    setRecentLayoutRevisionId(
1189                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1190            }
1191    
1192            public void setRecentLayoutRevisionId(
1193                            User user, long layoutSetBranchId, long plid, long layoutRevisionId)
1194                    throws SystemException {
1195    
1196                    PortalPreferences portalPreferences = getPortalPreferences(user);
1197    
1198                    setRecentLayoutRevisionId(
1199                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1200            }
1201    
1202            public void setRecentLayoutSetBranchId(
1203                    HttpServletRequest request, long layoutSetId, long layoutSetBranchId) {
1204    
1205                    SessionClicks.put(
1206                            request, Staging.class.getName(),
1207                            getRecentLayoutSetBranchIdKey(layoutSetId),
1208                            String.valueOf(layoutSetBranchId));
1209            }
1210    
1211            public void setRecentLayoutSetBranchId(
1212                            User user, long layoutSetId, long layoutSetBranchId)
1213                    throws SystemException {
1214    
1215                    PortalPreferences portalPreferences = getPortalPreferences(user);
1216    
1217                    portalPreferences.setValue(
1218                            Staging.class.getName(), getRecentLayoutSetBranchIdKey(layoutSetId),
1219                            String.valueOf(layoutSetBranchId));
1220            }
1221    
1222            public void unscheduleCopyFromLive(PortletRequest portletRequest)
1223                    throws Exception {
1224    
1225                    long stagingGroupId = ParamUtil.getLong(
1226                            portletRequest, "stagingGroupId");
1227    
1228                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1229                    String groupName = getSchedulerGroupName(
1230                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
1231    
1232                    LayoutServiceUtil.unschedulePublishToLive(
1233                            stagingGroupId, jobName, groupName);
1234            }
1235    
1236            public void unschedulePublishToLive(PortletRequest portletRequest)
1237                    throws Exception {
1238    
1239                    long stagingGroupId = ParamUtil.getLong(
1240                            portletRequest, "stagingGroupId");
1241    
1242                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1243    
1244                    long liveGroupId = stagingGroup.getLiveGroupId();
1245    
1246                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1247                    String groupName = getSchedulerGroupName(
1248                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
1249    
1250                    LayoutServiceUtil.unschedulePublishToLive(
1251                            liveGroupId, jobName, groupName);
1252            }
1253    
1254            public void unschedulePublishToRemote(PortletRequest portletRequest)
1255                    throws Exception {
1256    
1257                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1258    
1259                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1260                    String groupName = getSchedulerGroupName(
1261                            DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1262    
1263                    LayoutServiceUtil.unschedulePublishToRemote(
1264                            groupId, jobName, groupName);
1265            }
1266    
1267            public void updateLastImportSettings(
1268                            Element layoutElement, Layout layout,
1269                            PortletDataContext portletDataContext)
1270                    throws Exception {
1271    
1272                    Map<String, String[]> parameterMap =
1273                            portletDataContext.getParameterMap();
1274    
1275                    String cmd = MapUtil.getString(parameterMap, "cmd");
1276    
1277                    if (!cmd.equals("publish_to_live")) {
1278                            return;
1279                    }
1280    
1281                    UnicodeProperties typeSettingsProperties =
1282                            layout.getTypeSettingsProperties();
1283    
1284                    typeSettingsProperties.setProperty(
1285                            "last-import-date", String.valueOf(System.currentTimeMillis()));
1286    
1287                    String layoutRevisionId = GetterUtil.getString(
1288                            layoutElement.attributeValue("layout-revision-id"));
1289    
1290                    typeSettingsProperties.setProperty(
1291                            "last-import-layout-revision-id", layoutRevisionId);
1292    
1293                    String layoutSetBranchId = MapUtil.getString(
1294                            parameterMap, "layoutSetBranchId");
1295    
1296                    typeSettingsProperties.setProperty(
1297                            "last-import-layout-set-branch-id", layoutSetBranchId);
1298    
1299                    String layoutSetBranchName = MapUtil.getString(
1300                            parameterMap, "layoutSetBranchName");
1301    
1302                    typeSettingsProperties.setProperty(
1303                            "last-import-layout-set-branch-name", layoutSetBranchName);
1304    
1305                    String lastImportUserName = MapUtil.getString(
1306                            parameterMap, "lastImportUserName");
1307    
1308                    typeSettingsProperties.setProperty(
1309                            "last-import-user-name", lastImportUserName);
1310    
1311                    String lastImportUserUuid = MapUtil.getString(
1312                            parameterMap, "lastImportUserUuid");
1313    
1314                    typeSettingsProperties.setProperty(
1315                            "last-import-user-uuid", lastImportUserUuid);
1316    
1317                    String layoutBranchId = GetterUtil.getString(
1318                            layoutElement.attributeValue("layout-branch-id"));
1319    
1320                    typeSettingsProperties.setProperty(
1321                            "last-import-layout-branch-id", layoutBranchId);
1322    
1323                    String layoutBranchName = GetterUtil.getString(
1324                            layoutElement.attributeValue("layout-branch-name"));
1325    
1326                    typeSettingsProperties.setProperty(
1327                            "last-import-layout-branch-name", layoutBranchName);
1328    
1329                    layout.setTypeSettingsProperties(typeSettingsProperties);
1330            }
1331    
1332            public void updateStaging(PortletRequest portletRequest, Group liveGroup)
1333                    throws Exception {
1334    
1335                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1336                            WebKeys.THEME_DISPLAY);
1337    
1338                    PermissionChecker permissionChecker =
1339                            themeDisplay.getPermissionChecker();
1340    
1341                    long userId = permissionChecker.getUserId();
1342    
1343                    Group scopeGroup = themeDisplay.getScopeGroup();
1344    
1345                    if (!GroupPermissionUtil.contains(
1346                                    permissionChecker, liveGroup.getGroupId(),
1347                                    ActionKeys.MANAGE_STAGING)) {
1348    
1349                            return;
1350                    }
1351    
1352                    int stagingType = getStagingType(portletRequest, liveGroup);
1353    
1354                    boolean branchingPublic = getBoolean(
1355                            portletRequest, liveGroup, "branchingPublic");
1356                    boolean branchingPrivate = getBoolean(
1357                            portletRequest, liveGroup, "branchingPrivate");
1358    
1359                    ServiceContext serviceContext =
1360                            ServiceContextThreadLocal.getServiceContext();
1361    
1362                    if (stagingType == StagingConstants.TYPE_NOT_STAGED) {
1363                            if (liveGroup.hasStagingGroup() || liveGroup.isStagedRemotely()) {
1364                                    disableStaging(portletRequest, liveGroup, serviceContext);
1365                            }
1366                    }
1367                    else if (stagingType == StagingConstants.TYPE_LOCAL_STAGING) {
1368                            enableLocalStaging(
1369                                    userId, scopeGroup, liveGroup, branchingPublic,
1370                                    branchingPrivate, serviceContext);
1371                    }
1372                    else if (stagingType == StagingConstants.TYPE_REMOTE_STAGING) {
1373                            String remoteAddress = getString(
1374                                    portletRequest, liveGroup, "remoteAddress");
1375    
1376                            remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
1377    
1378                            int remotePort = getInteger(
1379                                    portletRequest, liveGroup, "remotePort");
1380                            String remotePathContext = getString(
1381                                    portletRequest, liveGroup, "remotePathContext");
1382                            boolean secureConnection = getBoolean(
1383                                    portletRequest, liveGroup, "secureConnection");
1384                            long remoteGroupId = getLong(
1385                                    portletRequest, liveGroup, "remoteGroupId");
1386    
1387                            enableRemoteStaging(
1388                                    userId, scopeGroup, liveGroup, branchingPublic,
1389                                    branchingPrivate, remoteAddress, remotePort, remotePathContext,
1390                                    secureConnection, remoteGroupId, serviceContext);
1391                    }
1392            }
1393    
1394            protected void checkDefaultLayoutSetBranches(
1395                            long userId, Group liveGroup, boolean branchingPublic,
1396                            boolean branchingPrivate, boolean remote,
1397                            ServiceContext serviceContext)
1398                    throws Exception {
1399    
1400                    long targetGroupId = 0;
1401    
1402                    if (remote) {
1403                            targetGroupId = liveGroup.getGroupId();
1404                    }
1405                    else {
1406                            Group stagingGroup = liveGroup.getStagingGroup();
1407    
1408                            if (stagingGroup == null) {
1409                                    return;
1410                            }
1411    
1412                            targetGroupId = stagingGroup.getGroupId();
1413                    }
1414    
1415                    if (branchingPublic) {
1416                            Locale locale = LocaleUtil.getDefault();
1417    
1418                            String description = LanguageUtil.format(
1419                                    locale,
1420                                    LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PUBLIC,
1421                                    liveGroup.getDescriptiveName());
1422    
1423                            try {
1424                                    LayoutSetBranch layoutSetBranch =
1425                                            LayoutSetBranchLocalServiceUtil.addLayoutSetBranch(
1426                                                    userId, targetGroupId, false,
1427                                                    LayoutSetBranchConstants.MASTER_BRANCH_NAME,
1428                                                    description, true,
1429                                                    LayoutSetBranchConstants.ALL_BRANCHES, serviceContext);
1430    
1431                                    List<LayoutRevision> layoutRevisions =
1432                                            LayoutRevisionLocalServiceUtil.getLayoutRevisions(
1433                                                    layoutSetBranch.getLayoutSetBranchId(), false);
1434    
1435                                    for (LayoutRevision layoutRevision : layoutRevisions) {
1436                                            LayoutRevisionLocalServiceUtil.updateStatus(
1437                                                    userId, layoutRevision.getLayoutRevisionId(),
1438                                                    WorkflowConstants.STATUS_APPROVED, serviceContext);
1439                                    }
1440                            }
1441                            catch (LayoutSetBranchNameException lsbne) {
1442                                    if (_log.isWarnEnabled()) {
1443                                            _log.warn(
1444                                                    "Unable to create master branch for public layouts",
1445                                                    lsbne);
1446                                    }
1447                            }
1448                    }
1449    
1450                    if (branchingPrivate) {
1451                            Locale locale = LocaleUtil.getDefault();
1452    
1453                            String description = LanguageUtil.format(
1454                                    locale,
1455                                    LayoutSetBranchConstants.MASTER_BRANCH_DESCRIPTION_PRIVATE,
1456                                    liveGroup.getDescriptiveName());
1457    
1458                            try {
1459                                    LayoutSetBranch layoutSetBranch =
1460                                            LayoutSetBranchLocalServiceUtil.addLayoutSetBranch(
1461                                                    userId, targetGroupId, true,
1462                                                    LayoutSetBranchConstants.MASTER_BRANCH_NAME,
1463                                                    description, true,
1464                                                    LayoutSetBranchConstants.ALL_BRANCHES, serviceContext);
1465    
1466                                    List<LayoutRevision> layoutRevisions =
1467                                            LayoutRevisionLocalServiceUtil.getLayoutRevisions(
1468                                                    layoutSetBranch.getLayoutSetBranchId(), false);
1469    
1470                                    for (LayoutRevision layoutRevision : layoutRevisions) {
1471                                            LayoutRevisionLocalServiceUtil.updateStatus(
1472                                                    userId, layoutRevision.getLayoutRevisionId(),
1473                                                    WorkflowConstants.STATUS_APPROVED, serviceContext);
1474                                    }
1475                            }
1476                            catch (LayoutSetBranchNameException lsbne) {
1477                                    if (_log.isWarnEnabled()) {
1478                                            _log.warn(
1479                                                    "Unable to create master branch for private layouts",
1480                                                    lsbne);
1481                                    }
1482                            }
1483                    }
1484            }
1485    
1486            protected void deleteRecentLayoutRevisionId(
1487                    PortalPreferences portalPreferences, long layoutSetBranchId,
1488                    long plid) {
1489    
1490                    portalPreferences.setValue(
1491                            Staging.class.getName(),
1492                            getRecentLayoutRevisionIdKey(layoutSetBranchId, plid), null);
1493            }
1494    
1495            protected boolean getBoolean(
1496                    PortletRequest portletRequest, Group group, String param) {
1497    
1498                    return ParamUtil.getBoolean(
1499                            portletRequest, param,
1500                            GetterUtil.getBoolean(group.getTypeSettingsProperty(param)));
1501            }
1502    
1503            protected Calendar getDate(
1504                            PortletRequest portletRequest, String paramPrefix,
1505                            boolean timeZoneSensitive)
1506                    throws Exception {
1507    
1508                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1509                            WebKeys.THEME_DISPLAY);
1510    
1511                    int dateMonth = ParamUtil.getInteger(
1512                            portletRequest, paramPrefix + "Month");
1513                    int dateDay = ParamUtil.getInteger(portletRequest, paramPrefix + "Day");
1514                    int dateYear = ParamUtil.getInteger(
1515                            portletRequest, paramPrefix + "Year");
1516                    int dateHour = ParamUtil.getInteger(
1517                            portletRequest, paramPrefix + "Hour");
1518                    int dateMinute = ParamUtil.getInteger(
1519                            portletRequest, paramPrefix + "Minute");
1520                    int dateAmPm = ParamUtil.getInteger(
1521                            portletRequest, paramPrefix + "AmPm");
1522    
1523                    if (dateAmPm == Calendar.PM) {
1524                            dateHour += 12;
1525                    }
1526    
1527                    Locale locale = null;
1528                    TimeZone timeZone = null;
1529    
1530                    if (timeZoneSensitive) {
1531                            locale = themeDisplay.getLocale();
1532                            timeZone = themeDisplay.getTimeZone();
1533                    }
1534                    else {
1535                            locale = LocaleUtil.getDefault();
1536                            timeZone = TimeZoneUtil.getTimeZone(StringPool.UTC);
1537                    }
1538    
1539                    Calendar cal = CalendarFactoryUtil.getCalendar(timeZone, locale);
1540    
1541                    cal.set(Calendar.MONTH, dateMonth);
1542                    cal.set(Calendar.DATE, dateDay);
1543                    cal.set(Calendar.YEAR, dateYear);
1544                    cal.set(Calendar.HOUR_OF_DAY, dateHour);
1545                    cal.set(Calendar.MINUTE, dateMinute);
1546                    cal.set(Calendar.SECOND, 0);
1547                    cal.set(Calendar.MILLISECOND, 0);
1548    
1549                    return cal;
1550            }
1551    
1552            protected int getInteger(
1553                    PortletRequest portletRequest, Group group, String param) {
1554    
1555                    return ParamUtil.getInteger(
1556                            portletRequest, param,
1557                            GetterUtil.getInteger(group.getTypeSettingsProperty(param)));
1558            }
1559    
1560            protected long[] getLayoutIds(List<Layout> layouts) {
1561                    long[] layoutIds = new long[layouts.size()];
1562    
1563                    for (int i = 0; i < layouts.size(); i++) {
1564                            Layout layout = layouts.get(i);
1565    
1566                            layoutIds[i] = layout.getLayoutId();
1567                    }
1568    
1569                    return layoutIds;
1570            }
1571    
1572            protected long getLong(
1573                    PortletRequest portletRequest, Group group, String param) {
1574    
1575                    return ParamUtil.getLong(
1576                            portletRequest, param,
1577                            GetterUtil.getLong(group.getTypeSettingsProperty(param)));
1578            }
1579    
1580            /**
1581             * @see #getMissingParentLayouts(Layout, long)
1582             */
1583            protected List<Layout> getMissingRemoteParentLayouts(
1584                            HttpPrincipal httpPrincipal, Layout layout, long remoteGroupId)
1585                    throws Exception {
1586    
1587                    List<Layout> missingRemoteParentLayouts = new ArrayList<Layout>();
1588    
1589                    long parentLayoutId = layout.getParentLayoutId();
1590    
1591                    while (parentLayoutId > 0) {
1592                            Layout parentLayout = LayoutLocalServiceUtil.getLayout(
1593                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
1594    
1595                            try {
1596                                    LayoutServiceHttp.getLayoutByUuidAndGroupId(
1597                                            httpPrincipal, parentLayout.getUuid(), remoteGroupId,
1598                                            parentLayout.getPrivateLayout());
1599    
1600                                    // If one parent is found all others are assumed to exist
1601    
1602                                    break;
1603                            }
1604                            catch (NoSuchLayoutException nsle) {
1605                                    missingRemoteParentLayouts.add(parentLayout);
1606    
1607                                    parentLayoutId = parentLayout.getParentLayoutId();
1608                            }
1609                    }
1610    
1611                    return missingRemoteParentLayouts;
1612            }
1613    
1614            protected PortalPreferences getPortalPreferences(User user)
1615                    throws SystemException {
1616    
1617                    boolean signedIn = !user.isDefaultUser();
1618    
1619                    PortalPreferences portalPreferences =
1620                            PortletPreferencesFactoryUtil.getPortalPreferences(
1621                                    user.getCompanyId(), user.getUserId(), signedIn);
1622    
1623                    return portalPreferences;
1624            }
1625    
1626            protected long getRecentLayoutBranchId(
1627                    PortalPreferences portalPreferences, long layoutSetBranchId,
1628                    long plid) {
1629    
1630                    return GetterUtil.getLong(
1631                            portalPreferences.getValue(
1632                                    Staging.class.getName(),
1633                                    getRecentLayoutBranchIdKey(layoutSetBranchId, plid)));
1634            }
1635    
1636            protected String getRecentLayoutBranchIdKey(
1637                    long layoutSetBranchId, long plid) {
1638    
1639                    StringBundler sb = new StringBundler(4);
1640    
1641                    sb.append("layoutBranchId-");
1642                    sb.append(layoutSetBranchId);
1643                    sb.append(StringPool.DASH);
1644                    sb.append(plid);
1645    
1646                    return sb.toString();
1647            }
1648    
1649            protected long getRecentLayoutRevisionId(
1650                            PortalPreferences portalPreferences, long layoutSetBranchId,
1651                            long plid)
1652                    throws PortalException, SystemException {
1653    
1654                    long layoutRevisionId = GetterUtil.getLong(
1655                            portalPreferences.getValue(
1656                                    Staging.class.getName(),
1657                                    getRecentLayoutRevisionIdKey(layoutSetBranchId, plid)));
1658    
1659                    if (layoutRevisionId > 0) {
1660                            return layoutRevisionId;
1661                    }
1662    
1663                    long layoutBranchId = getRecentLayoutBranchId(
1664                            portalPreferences, layoutSetBranchId, plid);
1665    
1666                    if (layoutBranchId > 0) {
1667                            try {
1668                                    LayoutBranchLocalServiceUtil.getLayoutBranch(layoutBranchId);
1669                            }
1670                            catch (NoSuchLayoutBranchException nslbe) {
1671                                    LayoutBranch layoutBranch =
1672                                            LayoutBranchLocalServiceUtil.getMasterLayoutBranch(
1673                                                    layoutSetBranchId, plid);
1674    
1675                                    layoutBranchId = layoutBranch.getLayoutBranchId();
1676                            }
1677                    }
1678    
1679                    if (layoutBranchId > 0) {
1680                            try {
1681                                    LayoutRevision layoutRevision =
1682                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
1683                                                    layoutSetBranchId, layoutBranchId, plid);
1684    
1685                                    if (layoutRevision != null) {
1686                                            layoutRevisionId = layoutRevision.getLayoutRevisionId();
1687                                    }
1688                            }
1689                            catch (NoSuchLayoutRevisionException nslre) {
1690                            }
1691                    }
1692    
1693                    return layoutRevisionId;
1694            }
1695    
1696            protected String getRecentLayoutRevisionIdKey(
1697                    long layoutSetBranchId, long plid) {
1698    
1699                    StringBundler sb = new StringBundler(4);
1700    
1701                    sb.append("layoutRevisionId-");
1702                    sb.append(layoutSetBranchId);
1703                    sb.append(StringPool.DASH);
1704                    sb.append(plid);
1705    
1706                    return sb.toString();
1707            }
1708    
1709            protected String getRecentLayoutSetBranchIdKey(long layoutSetId) {
1710                    return "layoutSetBranchId_" + layoutSetId;
1711            }
1712    
1713            protected int getStagingType(
1714                    PortletRequest portletRequest, Group liveGroup) {
1715    
1716                    String stagingType = portletRequest.getParameter("stagingType");
1717    
1718                    if (stagingType != null) {
1719                            return GetterUtil.getInteger(stagingType);
1720                    }
1721    
1722                    if (liveGroup.isStagedRemotely()) {
1723                            return StagingConstants.TYPE_REMOTE_STAGING;
1724                    }
1725    
1726                    if (liveGroup.hasStagingGroup()) {
1727                            return StagingConstants.TYPE_LOCAL_STAGING;
1728                    }
1729    
1730                    return StagingConstants.TYPE_NOT_STAGED;
1731            }
1732    
1733            protected String getString(
1734                    PortletRequest portletRequest, Group group, String param) {
1735    
1736                    return ParamUtil.getString(
1737                            portletRequest, param,
1738                            GetterUtil.getString(group.getTypeSettingsProperty(param)));
1739            }
1740    
1741            protected void lockGroup(long userId, long groupId) throws Exception {
1742                    if (!PropsValues.STAGING_LOCK_ENABLED) {
1743                            return;
1744                    }
1745    
1746                    if (LockLocalServiceUtil.isLocked(Staging.class.getName(), groupId)) {
1747                            Lock lock = LockLocalServiceUtil.getLock(
1748                                    Staging.class.getName(), groupId);
1749    
1750                            throw new DuplicateLockException(lock);
1751                    }
1752    
1753                    LockLocalServiceUtil.lock(
1754                            userId, Staging.class.getName(), String.valueOf(groupId),
1755                            StagingImpl.class.getName(), false,
1756                            StagingConstants.LOCK_EXPIRATION_TIME);
1757            }
1758    
1759            protected void publishLayouts(
1760                            PortletRequest portletRequest, long sourceGroupId,
1761                            long targetGroupId, Map<String, String[]> parameterMap,
1762                            boolean schedule)
1763                    throws Exception {
1764    
1765                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1766                            WebKeys.THEME_DISPLAY);
1767    
1768                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
1769    
1770                    boolean privateLayout = true;
1771    
1772                    if (tabs1.equals("public-pages")) {
1773                            privateLayout = false;
1774                    }
1775    
1776                    String scope = ParamUtil.getString(portletRequest, "scope");
1777    
1778                    Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
1779    
1780                    if (scope.equals("selected-pages")) {
1781                            long[] rowIds = ParamUtil.getLongValues(portletRequest, "rowIds");
1782    
1783                            for (long selPlid : rowIds) {
1784                                    boolean delete = ParamUtil.getBoolean(
1785                                            portletRequest, "delete_" + selPlid);
1786                                    boolean includeChildren = ParamUtil.getBoolean(
1787                                            portletRequest, "includeChildren_" + selPlid);
1788    
1789                                    if (!delete && includeChildren) {
1790                                            layoutIdMap.put(selPlid, true);
1791                                    }
1792                                    else {
1793                                            layoutIdMap.put(selPlid, false);
1794                                    }
1795                            }
1796                    }
1797    
1798                    String range = ParamUtil.getString(portletRequest, "range");
1799    
1800                    Date startDate = null;
1801                    Date endDate = null;
1802    
1803                    if (range.equals("dateRange")) {
1804                            startDate = getDate(portletRequest, "startDate", true).getTime();
1805    
1806                            endDate = getDate(portletRequest, "endDate", true).getTime();
1807                    }
1808                    else if (range.equals("fromLastPublishDate")) {
1809                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
1810                                    sourceGroupId, privateLayout);
1811    
1812                            long lastPublishDate = GetterUtil.getLong(
1813                                    layoutSet.getSettingsProperty("last-publish-date"));
1814    
1815                            if (lastPublishDate > 0) {
1816                                    endDate = new Date();
1817    
1818                                    startDate = new Date(lastPublishDate);
1819                            }
1820                    }
1821                    else if (range.equals("last")) {
1822                            int rangeLast = ParamUtil.getInteger(portletRequest, "last");
1823    
1824                            Date now = new Date();
1825    
1826                            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1827    
1828                            endDate = now;
1829                    }
1830    
1831                    if (schedule) {
1832                            String groupName = getSchedulerGroupName(
1833                                    DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
1834    
1835                            int recurrenceType = ParamUtil.getInteger(
1836                                    portletRequest, "recurrenceType");
1837    
1838                            Calendar startCal = getDate(
1839                                    portletRequest, "schedulerStartDate", true);
1840    
1841                            String cronText = SchedulerEngineHelperUtil.getCronText(
1842                                    portletRequest, startCal, true, recurrenceType);
1843    
1844                            Date schedulerEndDate = null;
1845    
1846                            int endDateType = ParamUtil.getInteger(
1847                                    portletRequest, "endDateType");
1848    
1849                            if (endDateType == 1) {
1850                                    Calendar endCal = getDate(
1851                                            portletRequest, "schedulerEndDate", true);
1852    
1853                                    schedulerEndDate = endCal.getTime();
1854                            }
1855    
1856                            String description = ParamUtil.getString(
1857                                    portletRequest, "description");
1858    
1859                            LayoutServiceUtil.schedulePublishToLive(
1860                                    sourceGroupId, targetGroupId, privateLayout, layoutIdMap,
1861                                    parameterMap, scope, startDate, endDate, groupName, cronText,
1862                                    startCal.getTime(), schedulerEndDate, description);
1863                    }
1864                    else {
1865                            MessageStatus messageStatus = new MessageStatus();
1866    
1867                            messageStatus.startTimer();
1868    
1869                            String command =
1870                                    LayoutsLocalPublisherRequest.COMMAND_SELECTED_PAGES;
1871    
1872                            try {
1873                                    if (scope.equals("all-pages")) {
1874                                            command = LayoutsLocalPublisherRequest.COMMAND_ALL_PAGES;
1875    
1876                                            publishLayouts(
1877                                                    themeDisplay.getUserId(), sourceGroupId, targetGroupId,
1878                                                    privateLayout, parameterMap, startDate, endDate);
1879                                    }
1880                                    else {
1881                                            publishLayouts(
1882                                                    themeDisplay.getUserId(), sourceGroupId, targetGroupId,
1883                                                    privateLayout, layoutIdMap, parameterMap, startDate,
1884                                                    endDate);
1885                                    }
1886                            }
1887                            catch (Exception e) {
1888                                    messageStatus.setException(e);
1889    
1890                                    throw e;
1891                            }
1892                            finally {
1893                                    messageStatus.stopTimer();
1894    
1895                                    LayoutsLocalPublisherRequest publisherRequest =
1896                                            new LayoutsLocalPublisherRequest(
1897                                                    command, themeDisplay.getUserId(), sourceGroupId,
1898                                                    targetGroupId, privateLayout, layoutIdMap, parameterMap,
1899                                                    startDate, endDate);
1900    
1901                                    messageStatus.setPayload(publisherRequest);
1902    
1903                                    MessageBusUtil.sendMessage(
1904                                            DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1905                            }
1906                    }
1907            }
1908    
1909            protected void publishToRemote(
1910                            PortletRequest portletRequest, boolean schedule)
1911                    throws Exception {
1912    
1913                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1914                            WebKeys.THEME_DISPLAY);
1915    
1916                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
1917    
1918                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1919    
1920                    boolean privateLayout = true;
1921    
1922                    if (tabs1.equals("public-pages")) {
1923                            privateLayout = false;
1924                    }
1925    
1926                    String scope = ParamUtil.getString(portletRequest, "scope");
1927    
1928                    if (Validator.isNull(scope)) {
1929                            scope = "all-pages";
1930                    }
1931    
1932                    Map<Long, Boolean> layoutIdMap = null;
1933    
1934                    if (scope.equals("selected-pages")) {
1935                            layoutIdMap = new LinkedHashMap<Long, Boolean>();
1936    
1937                            long[] rowIds = ParamUtil.getLongValues(portletRequest, "rowIds");
1938    
1939                            for (long selPlid : rowIds) {
1940                                    boolean delete = ParamUtil.getBoolean(
1941                                            portletRequest, "delete_" + selPlid);
1942                                    boolean includeChildren = ParamUtil.getBoolean(
1943                                            portletRequest, "includeChildren_" + selPlid);
1944    
1945                                    if (!delete && includeChildren) {
1946                                            layoutIdMap.put(selPlid, true);
1947                                    }
1948                                    else {
1949                                            layoutIdMap.put(selPlid, false);
1950                                    }
1951                            }
1952                    }
1953    
1954                    Map<String, String[]> parameterMap = getStagingParameters(
1955                            portletRequest);
1956    
1957                    parameterMap.put(
1958                            PortletDataHandlerKeys.PUBLISH_TO_REMOTE,
1959                            new String[] {Boolean.TRUE.toString()});
1960    
1961                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1962    
1963                    UnicodeProperties groupTypeSettingsProperties =
1964                            group.getTypeSettingsProperties();
1965    
1966                    String remoteAddress = ParamUtil.getString(
1967                            portletRequest, "remoteAddress",
1968                            groupTypeSettingsProperties.getProperty("remoteAddress"));
1969    
1970                    remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
1971    
1972                    int remotePort = ParamUtil.getInteger(
1973                            portletRequest, "remotePort",
1974                            GetterUtil.getInteger(
1975                                    groupTypeSettingsProperties.getProperty("remotePort")));
1976                    String remotePathContext = ParamUtil.getString(
1977                            portletRequest, "remotePathContext",
1978                            groupTypeSettingsProperties.getProperty("remotePathContext"));
1979                    boolean secureConnection = ParamUtil.getBoolean(
1980                            portletRequest, "secureConnection",
1981                            GetterUtil.getBoolean(
1982                                    groupTypeSettingsProperties.getProperty("secureConnection")));
1983                    long remoteGroupId = ParamUtil.getLong(
1984                            portletRequest, "remoteGroupId",
1985                            GetterUtil.getLong(
1986                                    groupTypeSettingsProperties.getProperty("remoteGroupId")));
1987                    boolean remotePrivateLayout = ParamUtil.getBoolean(
1988                            portletRequest, "remotePrivateLayout");
1989    
1990                    validate(
1991                            remoteAddress, remotePort, remotePathContext, secureConnection,
1992                            remoteGroupId);
1993    
1994                    if (group.isCompany()) {
1995                            updateGroupTypeSettingsProperties(
1996                                    group, remoteAddress, remotePort, remotePathContext,
1997                                    secureConnection, remoteGroupId);
1998                    }
1999    
2000                    String range = ParamUtil.getString(portletRequest, "range");
2001    
2002                    Date startDate = null;
2003                    Date endDate = null;
2004    
2005                    if (range.equals("dateRange")) {
2006                            startDate = getDate(portletRequest, "startDate", true).getTime();
2007    
2008                            endDate = getDate(portletRequest, "endDate", true).getTime();
2009                    }
2010                    else if (range.equals("fromLastPublishDate")) {
2011                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
2012                                    groupId, privateLayout);
2013    
2014                            long lastPublishDate = GetterUtil.getLong(
2015                                    layoutSet.getSettingsProperty("last-publish-date"));
2016    
2017                            if (lastPublishDate > 0) {
2018                                    endDate = new Date();
2019    
2020                                    startDate = new Date(lastPublishDate);
2021                            }
2022                    }
2023                    else if (range.equals("last")) {
2024                            int rangeLast = ParamUtil.getInteger(portletRequest, "last");
2025    
2026                            Date now = new Date();
2027    
2028                            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
2029    
2030                            endDate = now;
2031                    }
2032    
2033                    if (schedule) {
2034                            String groupName = getSchedulerGroupName(
2035                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
2036    
2037                            int recurrenceType = ParamUtil.getInteger(
2038                                    portletRequest, "recurrenceType");
2039    
2040                            Calendar startCal = getDate(
2041                                    portletRequest, "schedulerStartDate", true);
2042    
2043                            String cronText = SchedulerEngineHelperUtil.getCronText(
2044                                    portletRequest, startCal, true, recurrenceType);
2045    
2046                            Date schedulerEndDate = null;
2047    
2048                            int endDateType = ParamUtil.getInteger(
2049                                    portletRequest, "endDateType");
2050    
2051                            if (endDateType == 1) {
2052                                    Calendar endCal = getDate(
2053                                            portletRequest, "schedulerEndDate", true);
2054    
2055                                    schedulerEndDate = endCal.getTime();
2056                            }
2057    
2058                            String description = ParamUtil.getString(
2059                                    portletRequest, "description");
2060    
2061                            LayoutServiceUtil.schedulePublishToRemote(
2062                                    groupId, privateLayout, layoutIdMap, parameterMap,
2063                                    remoteAddress, remotePort, remotePathContext, secureConnection,
2064                                    remoteGroupId, remotePrivateLayout, startDate, endDate,
2065                                    groupName, cronText, startCal.getTime(), schedulerEndDate,
2066                                    description);
2067                    }
2068                    else {
2069                            MessageStatus messageStatus = new MessageStatus();
2070    
2071                            messageStatus.startTimer();
2072    
2073                            try {
2074                                    copyRemoteLayouts(
2075                                            groupId, privateLayout, layoutIdMap, parameterMap,
2076                                            remoteAddress, remotePort, remotePathContext,
2077                                            secureConnection, remoteGroupId, remotePrivateLayout,
2078                                            startDate, endDate);
2079                            }
2080                            catch (Exception e) {
2081                                    messageStatus.setException(e);
2082    
2083                                    throw e;
2084                            }
2085                            finally {
2086                                    messageStatus.stopTimer();
2087    
2088                                    LayoutsRemotePublisherRequest publisherRequest =
2089                                            new LayoutsRemotePublisherRequest(
2090                                                    themeDisplay.getUserId(), groupId, privateLayout,
2091                                                    layoutIdMap, parameterMap, remoteAddress, remotePort,
2092                                                    remotePathContext, secureConnection, remoteGroupId,
2093                                                    remotePrivateLayout, startDate, endDate);
2094    
2095                                    messageStatus.setPayload(publisherRequest);
2096    
2097                                    MessageBusUtil.sendMessage(
2098                                            DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
2099                            }
2100                    }
2101            }
2102    
2103            protected void setCommonStagingOptions(
2104                            Group liveGroup, UnicodeProperties typeSettingsProperties,
2105                            ServiceContext serviceContext)
2106                    throws Exception {
2107    
2108                    LayoutExporter.updateLastPublishDate(
2109                            liveGroup.getPrivateLayoutSet(), 0);
2110                    LayoutExporter.updateLastPublishDate(liveGroup.getPublicLayoutSet(), 0);
2111    
2112                    Set<String> parameterNames = serviceContext.getAttributes().keySet();
2113    
2114                    for (String parameterName : parameterNames) {
2115                            if (parameterName.startsWith(StagingConstants.STAGED_PORTLET) &&
2116                                    !parameterName.endsWith("Checkbox")) {
2117    
2118                                    boolean staged = ParamUtil.getBoolean(
2119                                            serviceContext, parameterName);
2120    
2121                                    typeSettingsProperties.setProperty(
2122                                            parameterName, String.valueOf(staged));
2123                            }
2124                    }
2125            }
2126    
2127            protected void setRecentLayoutBranchId(
2128                    PortalPreferences portalPreferences, long layoutSetBranchId, long plid,
2129                    long layoutBranchId) {
2130    
2131                    portalPreferences.setValue(
2132                            Staging.class.getName(),
2133                            getRecentLayoutBranchIdKey(layoutSetBranchId, plid),
2134                            String.valueOf(layoutBranchId));
2135            }
2136    
2137            protected void setRecentLayoutRevisionId(
2138                            PortalPreferences portalPreferences, long layoutSetBranchId,
2139                            long plid, long layoutRevisionId)
2140                    throws SystemException {
2141    
2142                    long layoutBranchId = 0;
2143    
2144                    try {
2145                            LayoutRevision layoutRevision =
2146                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2147                                            layoutRevisionId);
2148    
2149                            layoutBranchId = layoutRevision.getLayoutBranchId();
2150    
2151                            LayoutRevision lastLayoutRevision =
2152                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2153                                            layoutSetBranchId, layoutBranchId, plid);
2154    
2155                            if (lastLayoutRevision.getLayoutRevisionId() == layoutRevisionId) {
2156                                    deleteRecentLayoutRevisionId(
2157                                            portalPreferences, layoutSetBranchId, plid);
2158                            }
2159                            else {
2160                                    portalPreferences.setValue(
2161                                            Staging.class.getName(),
2162                                            getRecentLayoutRevisionIdKey(layoutSetBranchId, plid),
2163                                            String.valueOf(layoutRevisionId));
2164                            }
2165                    }
2166                    catch (PortalException pe) {
2167                            if (_log.isWarnEnabled()) {
2168                                    _log.warn("Unable to set recent layout revision ID", pe);
2169                            }
2170                    }
2171    
2172                    portalPreferences.setValue(
2173                            Staging.class.getName(),
2174                            getRecentLayoutBranchIdKey(layoutSetBranchId, plid),
2175                            String.valueOf(layoutBranchId));
2176            }
2177    
2178            protected String stripProtocolFromRemoteAddress(String remoteAddress) {
2179                    if (remoteAddress.startsWith(Http.HTTP_WITH_SLASH)) {
2180                            remoteAddress = remoteAddress.substring(
2181                                    Http.HTTP_WITH_SLASH.length());
2182                    }
2183                    else if (remoteAddress.startsWith(Http.HTTPS_WITH_SLASH)) {
2184                            remoteAddress = remoteAddress.substring(
2185                                    Http.HTTPS_WITH_SLASH.length());
2186                    }
2187    
2188                    return remoteAddress;
2189            }
2190    
2191            protected void unlockGroup(long groupId) throws SystemException {
2192                    if (!PropsValues.STAGING_LOCK_ENABLED) {
2193                            return;
2194                    }
2195    
2196                    LockLocalServiceUtil.unlock(Staging.class.getName(), groupId);
2197            }
2198    
2199            protected void updateGroupTypeSettingsProperties(
2200                            Group group, String remoteAddress, int remotePort,
2201                            String remotePathContext, boolean secureConnection,
2202                            long remoteGroupId)
2203                    throws Exception {
2204    
2205                    UnicodeProperties typeSettingsProperties =
2206                            group.getTypeSettingsProperties();
2207    
2208                    typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
2209                    typeSettingsProperties.setProperty(
2210                            "remoteGroupId", String.valueOf(remoteGroupId));
2211                    typeSettingsProperties.setProperty(
2212                            "remotePathContext", remotePathContext);
2213                    typeSettingsProperties.setProperty(
2214                            "remotePort", String.valueOf(remotePort));
2215                    typeSettingsProperties.setProperty(
2216                            "secureConnection", String.valueOf(secureConnection));
2217    
2218                    group.setTypeSettingsProperties(typeSettingsProperties);
2219    
2220                    GroupLocalServiceUtil.updateGroup(group);
2221            }
2222    
2223            protected void validate(
2224                            String remoteAddress, int remotePort, String remotePathContext,
2225                            boolean secureConnection, long remoteGroupId)
2226                    throws Exception {
2227    
2228                    RemoteOptionsException roe = null;
2229    
2230                    if (!Validator.isDomain(remoteAddress) &&
2231                            !Validator.isIPAddress(remoteAddress)) {
2232    
2233                            roe = new RemoteOptionsException(
2234                                    RemoteOptionsException.REMOTE_ADDRESS);
2235    
2236                            roe.setRemoteAddress(remoteAddress);
2237    
2238                            throw roe;
2239                    }
2240    
2241                    if ((remotePort < 1) || (remotePort > 65535)) {
2242                            roe = new RemoteOptionsException(
2243                                    RemoteOptionsException.REMOTE_PORT);
2244    
2245                            roe.setRemotePort(remotePort);
2246    
2247                            throw roe;
2248                    }
2249    
2250                    if (Validator.isNotNull(remotePathContext) &&
2251                            (!remotePathContext.startsWith(StringPool.FORWARD_SLASH) ||
2252                             remotePathContext.endsWith(StringPool.FORWARD_SLASH))) {
2253    
2254                            roe = new RemoteOptionsException(
2255                                    RemoteOptionsException.REMOTE_PATH_CONTEXT);
2256    
2257                            roe.setRemotePathContext(remotePathContext);
2258    
2259                            throw roe;
2260                    }
2261    
2262                    if (remoteGroupId <= 0) {
2263                            roe = new RemoteOptionsException(
2264                                    RemoteOptionsException.REMOTE_GROUP_ID);
2265    
2266                            roe.setRemoteGroupId(remoteGroupId);
2267    
2268                            throw roe;
2269                    }
2270    
2271                    PermissionChecker permissionChecker =
2272                            PermissionThreadLocal.getPermissionChecker();
2273    
2274                    User user = permissionChecker.getUser();
2275    
2276                    String url = buildRemoteURL(
2277                            remoteAddress, remotePort, remotePathContext, secureConnection,
2278                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
2279    
2280                    HttpPrincipal httpPrincipal = new HttpPrincipal(
2281                            url, user.getEmailAddress(), user.getPassword(),
2282                            user.getPasswordEncrypted());
2283    
2284                    // Ping remote host and verify that the group exists in the same company
2285                    // as the remote user
2286    
2287                    try {
2288                            GroupServiceHttp.checkRemoteStagingGroup(
2289                                    httpPrincipal, remoteGroupId);
2290                    }
2291                    catch (NoSuchGroupException nsge) {
2292                            RemoteExportException ree = new RemoteExportException(
2293                                    RemoteExportException.NO_GROUP);
2294    
2295                            ree.setGroupId(remoteGroupId);
2296    
2297                            throw ree;
2298                    }
2299                    catch (PrincipalException pe) {
2300                            RemoteExportException ree = new RemoteExportException(
2301                                    RemoteExportException.NO_PERMISSIONS);
2302    
2303                            ree.setGroupId(remoteGroupId);
2304    
2305                            throw ree;
2306                    }
2307                    catch (SystemException se) {
2308                            RemoteExportException ree = new RemoteExportException(
2309                                    RemoteExportException.BAD_CONNECTION);
2310    
2311                            ree.setURL(url);
2312    
2313                            throw ree;
2314                    }
2315    
2316            }
2317    
2318            private static Log _log = LogFactoryUtil.getLog(StagingImpl.class);
2319    
2320    }