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