1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.communities.util;
24  
25  import com.liferay.portal.NoSuchGroupException;
26  import com.liferay.portal.NoSuchLayoutException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.RemoteExportException;
29  import com.liferay.portal.SystemException;
30  import com.liferay.portal.kernel.cal.DayAndPosition;
31  import com.liferay.portal.kernel.cal.Duration;
32  import com.liferay.portal.kernel.cal.Recurrence;
33  import com.liferay.portal.kernel.cal.RecurrenceSerializer;
34  import com.liferay.portal.kernel.io.FileCacheOutputStream;
35  import com.liferay.portal.kernel.messaging.DestinationNames;
36  import com.liferay.portal.kernel.messaging.MessageBusUtil;
37  import com.liferay.portal.kernel.messaging.MessageStatus;
38  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
39  import com.liferay.portal.kernel.util.GetterUtil;
40  import com.liferay.portal.kernel.util.Http;
41  import com.liferay.portal.kernel.util.LocaleUtil;
42  import com.liferay.portal.kernel.util.MapUtil;
43  import com.liferay.portal.kernel.util.ParamUtil;
44  import com.liferay.portal.kernel.util.StringPool;
45  import com.liferay.portal.kernel.util.Time;
46  import com.liferay.portal.kernel.util.TimeZoneUtil;
47  import com.liferay.portal.kernel.util.Validator;
48  import com.liferay.portal.lar.PortletDataHandlerKeys;
49  import com.liferay.portal.lar.UserIdStrategy;
50  import com.liferay.portal.model.Group;
51  import com.liferay.portal.model.GroupConstants;
52  import com.liferay.portal.model.Layout;
53  import com.liferay.portal.model.Portlet;
54  import com.liferay.portal.model.User;
55  import com.liferay.portal.security.auth.HttpPrincipal;
56  import com.liferay.portal.security.auth.PrincipalException;
57  import com.liferay.portal.security.permission.ActionKeys;
58  import com.liferay.portal.security.permission.PermissionChecker;
59  import com.liferay.portal.security.permission.PermissionThreadLocal;
60  import com.liferay.portal.service.GroupLocalServiceUtil;
61  import com.liferay.portal.service.GroupServiceUtil;
62  import com.liferay.portal.service.LayoutLocalServiceUtil;
63  import com.liferay.portal.service.LayoutServiceUtil;
64  import com.liferay.portal.service.UserLocalServiceUtil;
65  import com.liferay.portal.service.http.GroupServiceHttp;
66  import com.liferay.portal.service.http.LayoutServiceHttp;
67  import com.liferay.portal.service.permission.GroupPermissionUtil;
68  import com.liferay.portal.theme.ThemeDisplay;
69  import com.liferay.portal.util.WebKeys;
70  import com.liferay.portlet.communities.messaging.LayoutsLocalPublisherRequest;
71  import com.liferay.portlet.communities.messaging.LayoutsRemotePublisherRequest;
72  
73  import java.util.ArrayList;
74  import java.util.Calendar;
75  import java.util.Date;
76  import java.util.Iterator;
77  import java.util.LinkedHashMap;
78  import java.util.List;
79  import java.util.Locale;
80  import java.util.Map.Entry;
81  import java.util.Map;
82  import java.util.TimeZone;
83  
84  import javax.portlet.ActionRequest;
85  
86  /**
87   * <a href="StagingUtil.java.html"><b><i>View Source</i></b></a>
88   *
89   * @author Raymond Augé
90   * @author Bruno Farache
91   *
92   */
93  public class StagingUtil {
94  
95      public static void copyFromLive(ActionRequest actionRequest)
96          throws Exception {
97  
98          long stagingGroupId = ParamUtil.getLong(
99              actionRequest, "stagingGroupId");
100 
101         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
102 
103         long liveGroupId = stagingGroup.getLiveGroupId();
104 
105         Map<String, String[]> parameterMap = getStagingParameters(
106             actionRequest);
107 
108         _publishLayouts(
109             actionRequest, liveGroupId, stagingGroupId, parameterMap, false);
110     }
111 
112     public static void copyFromLive(
113             ActionRequest actionRequest, Portlet portlet)
114         throws Exception {
115 
116         long plid = ParamUtil.getLong(actionRequest, "plid");
117 
118         Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
119 
120         Group stagingGroup = targetLayout.getGroup();
121         Group liveGroup = stagingGroup.getLiveGroup();
122 
123         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(
124             liveGroup.getGroupId(), targetLayout.isPrivateLayout(),
125             targetLayout.getLayoutId());
126 
127         copyPortlet(
128             actionRequest, liveGroup.getGroupId(), stagingGroup.getGroupId(),
129             sourceLayout.getPlid(), targetLayout.getPlid(),
130             portlet.getPortletId());
131     }
132 
133     public static void copyPortlet(
134             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
135             long sourcePlid, long targetPlid, String portletId)
136         throws Exception {
137 
138         Map<String, String[]> parameterMap = getStagingParameters(
139             actionRequest);
140 
141         FileCacheOutputStream fileCacheOutputStream =
142             LayoutLocalServiceUtil.exportPortletInfoAsStream(
143                 sourcePlid, sourceGroupId, portletId, parameterMap, null, null);
144 
145         try {
146             LayoutServiceUtil.importPortletInfo(
147                 targetPlid, targetGroupId, portletId, parameterMap,
148                 fileCacheOutputStream.getFileInputStream());
149         }
150         finally {
151             fileCacheOutputStream.close();
152         }
153     }
154 
155     public static void copyRemoteLayouts(
156             long sourceGroupId, boolean privateLayout,
157             Map<Long, Boolean> layoutIdMap,
158             Map<String, String[]> exportParameterMap, String remoteAddress,
159             int remotePort, boolean secureConnection, long remoteGroupId,
160             boolean remotePrivateLayout,
161             Map<String, String[]> importParameterMap, Date startDate,
162             Date endDate)
163         throws Exception {
164 
165         PermissionChecker permissionChecker =
166             PermissionThreadLocal.getPermissionChecker();
167 
168         User user = UserLocalServiceUtil.getUser(permissionChecker.getUserId());
169 
170         StringBuilder sb = new StringBuilder();
171 
172         if (secureConnection) {
173             sb.append(Http.HTTPS_WITH_SLASH);
174         }
175         else {
176             sb.append(Http.HTTP_WITH_SLASH);
177         }
178 
179         sb.append(remoteAddress);
180         sb.append(StringPool.COLON);
181         sb.append(remotePort);
182 
183         String url = sb.toString();
184 
185         HttpPrincipal httpPrincipal = new HttpPrincipal(
186             url, user.getEmailAddress(), user.getPassword(),
187             user.getPasswordEncrypted());
188 
189         // Ping remote host and verify that the group exists
190 
191         try {
192             GroupServiceHttp.getGroup(httpPrincipal, remoteGroupId);
193         }
194         catch (NoSuchGroupException nsge) {
195             RemoteExportException ree = new RemoteExportException(
196                 RemoteExportException.NO_GROUP);
197 
198             ree.setGroupId(remoteGroupId);
199 
200             throw ree;
201         }
202         catch (SystemException se) {
203             RemoteExportException ree = new RemoteExportException(
204                 RemoteExportException.BAD_CONNECTION);
205 
206             ree.setURL(url);
207 
208             throw ree;
209         }
210 
211         byte[] bytes = null;
212 
213         if (layoutIdMap == null) {
214             bytes = LayoutServiceUtil.exportLayouts(
215                 sourceGroupId, privateLayout, exportParameterMap, startDate,
216                 endDate);
217         }
218         else {
219             List<Layout> layouts = new ArrayList<Layout>();
220 
221             Iterator<Map.Entry<Long, Boolean>> itr1 =
222                 layoutIdMap.entrySet().iterator();
223 
224             while (itr1.hasNext()) {
225                 Entry<Long, Boolean> entry = itr1.next();
226 
227                 long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
228                 boolean includeChildren = entry.getValue();
229 
230                 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
231 
232                 if (!layouts.contains(layout)) {
233                     layouts.add(layout);
234                 }
235 
236                 Iterator<Layout> itr2 = getMissingParents(
237                     layout, sourceGroupId).iterator();
238 
239                 while (itr2.hasNext()) {
240                     Layout parentLayout = itr2.next();
241 
242                     if (!layouts.contains(parentLayout)) {
243                         layouts.add(parentLayout);
244                     }
245                 }
246 
247                 if (includeChildren) {
248                     itr2 = layout.getAllChildren().iterator();
249 
250                     while (itr2.hasNext()) {
251                         Layout childLayout = itr2.next();
252 
253                         if (!layouts.contains(childLayout)) {
254                             layouts.add(childLayout);
255                         }
256                     }
257                 }
258             }
259 
260             long[] layoutIds = new long[layouts.size()];
261 
262             for (int i = 0; i < layouts.size(); i++) {
263                 Layout curLayout = layouts.get(i);
264 
265                 layoutIds[i] = curLayout.getLayoutId();
266             }
267 
268             if (layoutIds.length <= 0) {
269                 throw new RemoteExportException(
270                     RemoteExportException.NO_LAYOUTS);
271             }
272 
273             bytes = LayoutServiceUtil.exportLayouts(
274                 sourceGroupId, privateLayout, layoutIds, exportParameterMap,
275                 startDate, endDate);
276         }
277 
278         LayoutServiceHttp.importLayouts(
279             httpPrincipal, remoteGroupId, remotePrivateLayout,
280             importParameterMap, bytes);
281     }
282 
283     public static List<Layout> getMissingParents(
284             Layout layout, long liveGroupId)
285         throws PortalException, SystemException {
286 
287         List<Layout> missingParents = new ArrayList<Layout>();
288 
289         long parentLayoutId = layout.getParentLayoutId();
290 
291         while (parentLayoutId > 0) {
292             try {
293                 LayoutLocalServiceUtil.getLayout(
294                     liveGroupId, layout.isPrivateLayout(), parentLayoutId);
295 
296                 // If one parent is found all others are assumed to exist
297 
298                 break;
299             }
300             catch (NoSuchLayoutException nsle) {
301                 Layout parent = LayoutLocalServiceUtil.getLayout(
302                     layout.getGroupId(), layout.isPrivateLayout(),
303                     parentLayoutId);
304 
305                 missingParents.add(parent);
306 
307                 parentLayoutId = parent.getParentLayoutId();
308             }
309         }
310 
311         return missingParents;
312     }
313 
314     public static String getSchedulerGroupName(
315         String destinationName, long groupId) {
316 
317         StringBuilder sb = new StringBuilder();
318 
319         sb.append(destinationName);
320         sb.append(StringPool.SLASH);
321         sb.append(groupId);
322 
323         return sb.toString();
324     }
325 
326     public static Map<String, String[]> getStagingParameters() {
327         Map<String, String[]> parameterMap =
328             new LinkedHashMap<String, String[]>();
329 
330         parameterMap.put(
331             PortletDataHandlerKeys.CATEGORIES,
332             new String[] {Boolean.TRUE.toString()});
333         parameterMap.put(
334             PortletDataHandlerKeys.DATA_STRATEGY,
335             new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
336         parameterMap.put(
337             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
338             new String[] {Boolean.TRUE.toString()});
339         parameterMap.put(
340             PortletDataHandlerKeys.DELETE_PORTLET_DATA,
341             new String[] {Boolean.FALSE.toString()});
342         parameterMap.put(
343             PortletDataHandlerKeys.PERMISSIONS,
344             new String[] {Boolean.TRUE.toString()});
345         parameterMap.put(
346             PortletDataHandlerKeys.PORTLET_DATA,
347             new String[] {Boolean.TRUE.toString()});
348         parameterMap.put(
349             PortletDataHandlerKeys.PORTLET_DATA_ALL,
350             new String[] {Boolean.TRUE.toString()});
351         parameterMap.put(
352             PortletDataHandlerKeys.PORTLET_SETUP,
353             new String[] {Boolean.TRUE.toString()});
354         parameterMap.put(
355             PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
356             new String[] {Boolean.TRUE.toString()});
357         parameterMap.put(
358             PortletDataHandlerKeys.THEME,
359             new String[] {Boolean.FALSE.toString()});
360         parameterMap.put(
361             PortletDataHandlerKeys.USER_ID_STRATEGY,
362             new String[] {UserIdStrategy.CURRENT_USER_ID});
363         parameterMap.put(
364             PortletDataHandlerKeys.USER_PERMISSIONS,
365             new String[] {Boolean.FALSE.toString()});
366 
367         return parameterMap;
368     }
369 
370     public static Map<String, String[]> getStagingParameters(
371         ActionRequest actionRequest) {
372 
373         Map<String, String[]> parameterMap =
374             new LinkedHashMap<String, String[]>(
375                 actionRequest.getParameterMap());
376 
377         if (!parameterMap.containsKey(PortletDataHandlerKeys.DATA_STRATEGY)) {
378             parameterMap.put(
379                 PortletDataHandlerKeys.DATA_STRATEGY,
380                 new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
381         }
382 
383         if (!parameterMap.containsKey(
384                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS)) {
385 
386             parameterMap.put(
387                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
388                 new String[] {Boolean.TRUE.toString()});
389         }
390 
391         if (!parameterMap.containsKey(
392                 PortletDataHandlerKeys.DELETE_PORTLET_DATA)) {
393 
394             parameterMap.put(
395                 PortletDataHandlerKeys.DELETE_PORTLET_DATA,
396                 new String[] {Boolean.FALSE.toString()});
397         }
398 
399         if (!parameterMap.containsKey(
400                 PortletDataHandlerKeys.PORTLET_DATA)) {
401 
402             parameterMap.put(
403                 PortletDataHandlerKeys.PORTLET_DATA,
404                 new String[] {Boolean.FALSE.toString()});
405         }
406 
407         if (!parameterMap.containsKey(
408                 PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
409 
410             Boolean portletDataAll = Boolean.FALSE;
411 
412             if (MapUtil.getBoolean(
413                     parameterMap, PortletDataHandlerKeys.PORTLET_DATA)) {
414 
415                 portletDataAll = Boolean.TRUE;
416             }
417 
418             parameterMap.put(
419                 PortletDataHandlerKeys.PORTLET_DATA_ALL,
420                 new String[] {portletDataAll.toString()});
421         }
422 
423         if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_SETUP)) {
424             parameterMap.put(
425                 PortletDataHandlerKeys.PORTLET_SETUP,
426                 new String[] {Boolean.TRUE.toString()});
427         }
428 
429         if (!parameterMap.containsKey(
430                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES)) {
431 
432             parameterMap.put(
433                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
434                 new String[] {Boolean.TRUE.toString()});
435         }
436 
437         if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME)) {
438             parameterMap.put(
439                 PortletDataHandlerKeys.THEME,
440                 new String[] {Boolean.FALSE.toString()});
441         }
442 
443         if (!parameterMap.containsKey(
444                 PortletDataHandlerKeys.USER_ID_STRATEGY)) {
445 
446             parameterMap.put(
447                 PortletDataHandlerKeys.USER_ID_STRATEGY,
448                 new String[] {UserIdStrategy.CURRENT_USER_ID});
449         }
450 
451         return parameterMap;
452     }
453 
454     public static void publishLayout(
455             long plid, long liveGroupId, boolean includeChildren)
456         throws Exception {
457 
458         Map<String, String[]> parameterMap = getStagingParameters();
459 
460         parameterMap.put(
461             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
462             new String[] {Boolean.FALSE.toString()});
463 
464         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
465 
466         List<Layout> layouts = new ArrayList<Layout>();
467 
468         layouts.add(layout);
469 
470         layouts.addAll(getMissingParents(layout, liveGroupId));
471 
472         if (includeChildren) {
473             layouts.addAll(layout.getAllChildren());
474         }
475 
476         Iterator<Layout> itr = layouts.iterator();
477 
478         long[] layoutIds = new long[layouts.size()];
479 
480         for (int i = 0; itr.hasNext(); i++) {
481             Layout curLayout = itr.next();
482 
483             layoutIds[i] = curLayout.getLayoutId();
484         }
485 
486         publishLayouts(
487             layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
488             layoutIds, parameterMap, null, null);
489     }
490 
491     public static void publishLayouts(
492             long sourceGroupId, long targetGroupId, boolean privateLayout,
493             Map<String, String[]> parameterMap, Date startDate, Date endDate)
494         throws Exception {
495 
496         publishLayouts(
497             sourceGroupId, targetGroupId, privateLayout, (long[])null,
498             parameterMap, startDate, endDate);
499     }
500 
501     public static void publishLayouts(
502             long sourceGroupId, long targetGroupId, boolean privateLayout,
503             long[] layoutIds, Map<String, String[]> parameterMap,
504             Date startDate, Date endDate)
505         throws Exception {
506 
507         FileCacheOutputStream fileCacheOutputStream =
508             LayoutLocalServiceUtil.exportLayoutsAsStream(
509                 sourceGroupId, privateLayout, layoutIds, parameterMap,
510                 startDate, endDate);
511 
512         try {
513             LayoutServiceUtil.importLayouts(
514                 targetGroupId, privateLayout, parameterMap,
515                 fileCacheOutputStream.getFileInputStream());
516         }
517         finally {
518             fileCacheOutputStream.close();
519         }
520     }
521 
522     public static void publishLayouts(
523             long sourceGroupId, long targetGroupId, boolean privateLayout,
524             Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
525             Date startDate, Date endDate)
526         throws Exception {
527 
528         parameterMap.put(
529             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
530             new String[] {Boolean.FALSE.toString()});
531 
532         List<Layout> layouts = new ArrayList<Layout>();
533 
534         Iterator<Map.Entry<Long, Boolean>> itr1 =
535             layoutIdMap.entrySet().iterator();
536 
537         while (itr1.hasNext()) {
538             Entry<Long, Boolean> entry = itr1.next();
539 
540             long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
541             boolean includeChildren = entry.getValue();
542 
543             Layout layout = LayoutLocalServiceUtil.getLayout(plid);
544 
545             if (!layouts.contains(layout)) {
546                 layouts.add(layout);
547             }
548 
549             Iterator<Layout> itr2 = getMissingParents(
550                 layout, targetGroupId).iterator();
551 
552             while (itr2.hasNext()) {
553                 Layout parentLayout = itr2.next();
554 
555                 if (!layouts.contains(parentLayout)) {
556                     layouts.add(parentLayout);
557                 }
558             }
559 
560             if (includeChildren) {
561                 itr2 = layout.getAllChildren().iterator();
562 
563                 while (itr2.hasNext()) {
564                     Layout childLayout = itr2.next();
565 
566                     if (!layouts.contains(childLayout)) {
567                         layouts.add(childLayout);
568                     }
569                 }
570             }
571         }
572 
573         long[] layoutIds = new long[layouts.size()];
574 
575         for (int i = 0; i < layouts.size(); i++) {
576             Layout curLayout = layouts.get(i);
577 
578             layoutIds[i] = curLayout.getLayoutId();
579         }
580 
581         publishLayouts(
582             sourceGroupId, targetGroupId, privateLayout, layoutIds,
583             parameterMap, startDate, endDate);
584     }
585 
586     public static void publishToLive(ActionRequest actionRequest)
587         throws Exception {
588 
589         long stagingGroupId = ParamUtil.getLong(
590             actionRequest, "stagingGroupId");
591 
592         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
593 
594         long liveGroupId = stagingGroup.getLiveGroupId();
595 
596         Map<String, String[]> parameterMap = getStagingParameters(
597             actionRequest);
598 
599         _publishLayouts(
600             actionRequest, stagingGroupId, liveGroupId, parameterMap, false);
601     }
602 
603     public static void publishToLive(
604             ActionRequest actionRequest, Portlet portlet)
605         throws Exception {
606 
607         long plid = ParamUtil.getLong(actionRequest, "plid");
608 
609         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
610 
611         Group stagingGroup = sourceLayout.getGroup();
612         Group liveGroup = stagingGroup.getLiveGroup();
613 
614         Layout targetLayout = LayoutLocalServiceUtil.getLayout(
615             liveGroup.getGroupId(), sourceLayout.isPrivateLayout(),
616             sourceLayout.getLayoutId());
617 
618         copyPortlet(
619             actionRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
620             sourceLayout.getPlid(), targetLayout.getPlid(),
621             portlet.getPortletId());
622     }
623 
624     public static void publishToRemote(ActionRequest actionRequest)
625         throws Exception {
626 
627         _publishToRemote(actionRequest, false);
628     }
629 
630     public static void scheduleCopyFromLive(ActionRequest actionRequest)
631         throws Exception {
632 
633         long stagingGroupId = ParamUtil.getLong(
634             actionRequest, "stagingGroupId");
635 
636         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
637 
638         long liveGroupId = stagingGroup.getLiveGroupId();
639 
640         Map<String, String[]> parameterMap = getStagingParameters(
641             actionRequest);
642 
643         _publishLayouts(
644             actionRequest, liveGroupId, stagingGroupId, parameterMap, true);
645     }
646 
647     public static void schedulePublishToLive(ActionRequest actionRequest)
648         throws Exception {
649 
650         long stagingGroupId = ParamUtil.getLong(
651             actionRequest, "stagingGroupId");
652 
653         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
654 
655         long liveGroupId = stagingGroup.getLiveGroupId();
656 
657         Map<String, String[]> parameterMap = getStagingParameters(
658             actionRequest);
659 
660         _publishLayouts(
661             actionRequest, stagingGroupId, liveGroupId, parameterMap, true);
662     }
663 
664     public static void schedulePublishToRemote(ActionRequest actionRequest)
665         throws Exception {
666 
667         _publishToRemote(actionRequest, true);
668     }
669 
670     public static void unscheduleCopyFromLive(ActionRequest actionRequest)
671         throws Exception {
672 
673         long stagingGroupId = ParamUtil.getLong(
674             actionRequest, "stagingGroupId");
675 
676         String jobName = ParamUtil.getString(actionRequest, "jobName");
677         String groupName = getSchedulerGroupName(
678             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
679 
680         LayoutServiceUtil.unschedulePublishToLive(
681             stagingGroupId, jobName, groupName);
682     }
683 
684     public static void unschedulePublishToLive(ActionRequest actionRequest)
685         throws Exception {
686 
687         long stagingGroupId = ParamUtil.getLong(
688             actionRequest, "stagingGroupId");
689 
690         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
691 
692         long liveGroupId = stagingGroup.getLiveGroupId();
693 
694         String jobName = ParamUtil.getString(actionRequest, "jobName");
695         String groupName = getSchedulerGroupName(
696             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
697 
698         LayoutServiceUtil.unschedulePublishToLive(
699             liveGroupId, jobName, groupName);
700     }
701 
702     public static void unschedulePublishToRemote(ActionRequest actionRequest)
703         throws Exception {
704 
705         long groupId = ParamUtil.getLong(actionRequest, "groupId");
706 
707         String jobName = ParamUtil.getString(actionRequest, "jobName");
708         String groupName = getSchedulerGroupName(
709             DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
710 
711         LayoutServiceUtil.unschedulePublishToRemote(
712             groupId, jobName, groupName);
713     }
714 
715     public static void updateStaging(ActionRequest actionRequest)
716         throws Exception {
717 
718         ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
719             WebKeys.THEME_DISPLAY);
720 
721         PermissionChecker permissionChecker =
722             themeDisplay.getPermissionChecker();
723 
724         long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
725 
726         if (!GroupPermissionUtil.contains(
727                 permissionChecker, liveGroupId, ActionKeys.MANAGE_STAGING)) {
728 
729             throw new PrincipalException();
730         }
731 
732         long stagingGroupId = ParamUtil.getLong(
733             actionRequest, "stagingGroupId");
734 
735         boolean stagingEnabled = ParamUtil.getBoolean(
736             actionRequest, "stagingEnabled");
737 
738         if ((stagingGroupId > 0) && !stagingEnabled) {
739             GroupServiceUtil.deleteGroup(stagingGroupId);
740 
741             GroupServiceUtil.updateWorkflow(liveGroupId, false, 0, null);
742         }
743         else if ((stagingGroupId == 0) && stagingEnabled) {
744             Group liveGroup = GroupServiceUtil.getGroup(liveGroupId);
745 
746             Group stagingGroup = GroupServiceUtil.addGroup(
747                 liveGroup.getGroupId(),
748                 liveGroup.getDescriptiveName() + " (Staging)",
749                 liveGroup.getDescription(),
750                 GroupConstants.TYPE_COMMUNITY_PRIVATE, null,
751                 liveGroup.isActive(), null);
752 
753             if (liveGroup.hasPrivateLayouts()) {
754                 Map<String, String[]> parameterMap = getStagingParameters();
755 
756                 publishLayouts(
757                     liveGroup.getGroupId(), stagingGroup.getGroupId(), true,
758                     parameterMap, null, null);
759             }
760 
761             if (liveGroup.hasPublicLayouts()) {
762                 Map<String, String[]> parameterMap = getStagingParameters();
763 
764                 publishLayouts(
765                     liveGroup.getGroupId(), stagingGroup.getGroupId(), false,
766                     parameterMap, null, null);
767             }
768         }
769     }
770 
771     private static void _addWeeklyDayPos(
772         ActionRequest actionRequest, List<DayAndPosition> list, int day) {
773 
774         if (ParamUtil.getBoolean(actionRequest, "weeklyDayPos" + day)) {
775             list.add(new DayAndPosition(day, 0));
776         }
777     }
778 
779     private static String _getCronText(
780             ActionRequest actionRequest, Calendar startDate,
781             boolean timeZoneSensitive, int recurrenceType)
782         throws Exception {
783 
784         Calendar startCal = null;
785 
786         if (timeZoneSensitive) {
787             startCal = CalendarFactoryUtil.getCalendar();
788 
789             startCal.setTime(startDate.getTime());
790         }
791         else {
792             startCal = (Calendar)startDate.clone();
793         }
794 
795         Recurrence recurrence = new Recurrence(
796             startCal, new Duration(1, 0, 0, 0), recurrenceType);
797 
798         recurrence.setWeekStart(Calendar.SUNDAY);
799 
800         if (recurrenceType == Recurrence.DAILY) {
801             int dailyType = ParamUtil.getInteger(actionRequest, "dailyType");
802 
803             if (dailyType == 0) {
804                 int dailyInterval = ParamUtil.getInteger(
805                     actionRequest, "dailyInterval", 1);
806 
807                 recurrence.setInterval(dailyInterval);
808             }
809             else {
810                 DayAndPosition[] dayPos = {
811                     new DayAndPosition(Calendar.MONDAY, 0),
812                     new DayAndPosition(Calendar.TUESDAY, 0),
813                     new DayAndPosition(Calendar.WEDNESDAY, 0),
814                     new DayAndPosition(Calendar.THURSDAY, 0),
815                     new DayAndPosition(Calendar.FRIDAY, 0)};
816 
817                 recurrence.setByDay(dayPos);
818             }
819         }
820         else if (recurrenceType == Recurrence.WEEKLY) {
821             int weeklyInterval = ParamUtil.getInteger(
822                 actionRequest, "weeklyInterval", 1);
823 
824             recurrence.setInterval(weeklyInterval);
825 
826             List<DayAndPosition> dayPos = new ArrayList<DayAndPosition>();
827 
828             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SUNDAY);
829             _addWeeklyDayPos(actionRequest, dayPos, Calendar.MONDAY);
830             _addWeeklyDayPos(actionRequest, dayPos, Calendar.TUESDAY);
831             _addWeeklyDayPos(actionRequest, dayPos, Calendar.WEDNESDAY);
832             _addWeeklyDayPos(actionRequest, dayPos, Calendar.THURSDAY);
833             _addWeeklyDayPos(actionRequest, dayPos, Calendar.FRIDAY);
834             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SATURDAY);
835 
836             if (dayPos.size() == 0) {
837                 dayPos.add(new DayAndPosition(Calendar.MONDAY, 0));
838             }
839 
840             recurrence.setByDay(dayPos.toArray(new DayAndPosition[0]));
841         }
842         else if (recurrenceType == Recurrence.MONTHLY) {
843             int monthlyType = ParamUtil.getInteger(
844                 actionRequest, "monthlyType");
845 
846             if (monthlyType == 0) {
847                 int monthlyDay = ParamUtil.getInteger(
848                     actionRequest, "monthlyDay0", 1);
849 
850                 recurrence.setByMonthDay(new int[] {monthlyDay});
851 
852                 int monthlyInterval = ParamUtil.getInteger(
853                     actionRequest, "monthlyInterval0", 1);
854 
855                 recurrence.setInterval(monthlyInterval);
856             }
857             else {
858                 int monthlyPos = ParamUtil.getInteger(
859                     actionRequest, "monthlyPos");
860                 int monthlyDay = ParamUtil.getInteger(
861                     actionRequest, "monthlyDay1");
862 
863                 DayAndPosition[] dayPos = {
864                     new DayAndPosition(monthlyDay, monthlyPos)};
865 
866                 recurrence.setByDay(dayPos);
867 
868                 int monthlyInterval = ParamUtil.getInteger(
869                     actionRequest, "monthlyInterval1", 1);
870 
871                 recurrence.setInterval(monthlyInterval);
872             }
873         }
874         else if (recurrenceType == Recurrence.YEARLY) {
875             int yearlyType = ParamUtil.getInteger(actionRequest, "yearlyType");
876 
877             if (yearlyType == 0) {
878                 int yearlyMonth = ParamUtil.getInteger(
879                     actionRequest, "yearlyMonth0");
880                 int yearlyDay = ParamUtil.getInteger(
881                     actionRequest, "yearlyDay0", 1);
882 
883                 recurrence.setByMonth(new int[] {yearlyMonth});
884                 recurrence.setByMonthDay(new int[] {yearlyDay});
885 
886                 int yearlyInterval = ParamUtil.getInteger(
887                     actionRequest, "yearlyInterval0", 1);
888 
889                 recurrence.setInterval(yearlyInterval);
890             }
891             else {
892                 int yearlyPos = ParamUtil.getInteger(
893                     actionRequest, "yearlyPos");
894                 int yearlyDay = ParamUtil.getInteger(
895                     actionRequest, "yearlyDay1");
896                 int yearlyMonth = ParamUtil.getInteger(
897                     actionRequest, "yearlyMonth1");
898 
899                 DayAndPosition[] dayPos = {
900                     new DayAndPosition(yearlyDay, yearlyPos)};
901 
902                 recurrence.setByDay(dayPos);
903 
904                 recurrence.setByMonth(new int[] {yearlyMonth});
905 
906                 int yearlyInterval = ParamUtil.getInteger(
907                     actionRequest, "yearlyInterval1", 1);
908 
909                 recurrence.setInterval(yearlyInterval);
910             }
911         }
912 
913         return RecurrenceSerializer.toCronText(recurrence);
914     }
915 
916     private static Calendar _getDate(
917             ActionRequest actionRequest, String paramPrefix,
918             boolean timeZoneSensitive)
919         throws Exception {
920 
921         int dateMonth = ParamUtil.getInteger(
922             actionRequest, paramPrefix + "Month");
923         int dateDay = ParamUtil.getInteger(actionRequest, paramPrefix + "Day");
924         int dateYear = ParamUtil.getInteger(
925             actionRequest, paramPrefix + "Year");
926         int dateHour = ParamUtil.getInteger(
927             actionRequest, paramPrefix + "Hour");
928         int dateMinute = ParamUtil.getInteger(
929             actionRequest, paramPrefix + "Minute");
930         int dateAmPm = ParamUtil.getInteger(
931             actionRequest, paramPrefix + "AmPm");
932 
933         if (dateAmPm == Calendar.PM) {
934             dateHour += 12;
935         }
936 
937         Locale locale = null;
938         TimeZone timeZone = null;
939 
940         if (timeZoneSensitive) {
941             ThemeDisplay themeDisplay =
942                 (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
943 
944             locale = themeDisplay.getLocale();
945             timeZone = themeDisplay.getTimeZone();
946         }
947         else {
948             locale = LocaleUtil.getDefault();
949             timeZone = TimeZoneUtil.getDefault();
950         }
951 
952         Calendar cal = CalendarFactoryUtil.getCalendar(timeZone, locale);
953 
954         cal.set(Calendar.MONTH, dateMonth);
955         cal.set(Calendar.DATE, dateDay);
956         cal.set(Calendar.YEAR, dateYear);
957         cal.set(Calendar.HOUR_OF_DAY, dateHour);
958         cal.set(Calendar.MINUTE, dateMinute);
959         cal.set(Calendar.SECOND, 0);
960         cal.set(Calendar.MILLISECOND, 0);
961 
962         return cal;
963     }
964 
965     private static void _publishLayouts(
966             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
967             Map<String, String[]> parameterMap, boolean schedule)
968         throws Exception {
969 
970         ThemeDisplay themeDisplay =
971             (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
972 
973         String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
974 
975         boolean privateLayout = true;
976 
977         if (tabs1.equals("public-pages")) {
978             privateLayout = false;
979         }
980 
981         String scope = ParamUtil.getString(actionRequest, "scope");
982 
983         Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
984 
985         if (scope.equals("selected-pages")) {
986             long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
987 
988             for (long selPlid : rowIds) {
989                 boolean includeChildren = ParamUtil.getBoolean(
990                     actionRequest, "includeChildren_" + selPlid);
991 
992                 layoutIdMap.put(selPlid, includeChildren);
993             }
994         }
995 
996         String range = ParamUtil.getString(actionRequest, "range");
997 
998         Date startDate = null;
999         Date endDate = null;
1000
1001        if (range.equals("dateRange")) {
1002            startDate = _getDate(actionRequest, "startDate", true).getTime();
1003
1004            endDate = _getDate(actionRequest, "endDate", true).getTime();
1005        }
1006        else if (range.equals("last")) {
1007            int rangeLast = ParamUtil.getInteger(actionRequest, "last");
1008
1009            Date now = new Date();
1010
1011            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1012
1013            endDate = now;
1014        }
1015
1016        if (schedule) {
1017            String groupName = getSchedulerGroupName(
1018                DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
1019
1020            int recurrenceType = ParamUtil.getInteger(
1021                actionRequest, "recurrenceType");
1022
1023            Calendar startCal = _getDate(
1024                actionRequest, "schedulerStartDate", false);
1025
1026            String cronText = _getCronText(
1027                actionRequest, startCal, false, recurrenceType);
1028
1029            Date schedulerEndDate = null;
1030
1031            int endDateType = ParamUtil.getInteger(
1032                actionRequest, "endDateType");
1033
1034            if (endDateType == 1) {
1035                Calendar endCal = _getDate(
1036                    actionRequest, "schedulerEndDate", false);
1037
1038                schedulerEndDate = endCal.getTime();
1039            }
1040
1041            String description = ParamUtil.getString(
1042                actionRequest, "description");
1043
1044            LayoutServiceUtil.schedulePublishToLive(
1045                sourceGroupId, targetGroupId, privateLayout, layoutIdMap,
1046                parameterMap, scope, startDate, endDate, groupName, cronText,
1047                startCal.getTime(), schedulerEndDate, description);
1048        }
1049        else {
1050            MessageStatus messageStatus = new MessageStatus();
1051
1052            messageStatus.startTimer();
1053
1054            String command =
1055                LayoutsLocalPublisherRequest.COMMAND_SELECTED_PAGES;
1056
1057            try {
1058                if (scope.equals("all-pages")) {
1059                    command = LayoutsLocalPublisherRequest.COMMAND_ALL_PAGES;
1060
1061                    publishLayouts(
1062                        sourceGroupId, targetGroupId, privateLayout,
1063                        parameterMap, startDate, endDate);
1064                }
1065                else {
1066                    publishLayouts(
1067                        sourceGroupId, targetGroupId, privateLayout,
1068                        layoutIdMap, parameterMap, startDate, endDate);
1069                }
1070            }
1071            catch (Exception e) {
1072                messageStatus.setException(e);
1073
1074                throw e;
1075            }
1076            finally {
1077                messageStatus.stopTimer();
1078
1079                LayoutsLocalPublisherRequest publisherRequest =
1080                    new LayoutsLocalPublisherRequest(
1081                        command, themeDisplay.getUserId(), sourceGroupId,
1082                        targetGroupId, privateLayout, layoutIdMap, parameterMap,
1083                        startDate, endDate);
1084
1085                messageStatus.setPayload(publisherRequest);
1086
1087                MessageBusUtil.sendMessage(
1088                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1089            }
1090        }
1091    }
1092
1093    private static void _publishToRemote(
1094            ActionRequest actionRequest, boolean schedule)
1095        throws Exception {
1096
1097        ThemeDisplay themeDisplay =
1098            (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
1099
1100        String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
1101
1102        long groupId = ParamUtil.getLong(actionRequest, "groupId");
1103
1104        boolean privateLayout = true;
1105
1106        if (tabs1.equals("public-pages")) {
1107            privateLayout = false;
1108        }
1109
1110        String scope = ParamUtil.getString(actionRequest, "scope");
1111
1112        if (Validator.isNull(scope)) {
1113            scope = "all-pages";
1114        }
1115
1116        Map<Long, Boolean> layoutIdMap = null;
1117        Map<String, String[]> parameterMap = actionRequest.getParameterMap();
1118
1119        if (scope.equals("selected-pages")) {
1120            layoutIdMap = new LinkedHashMap<Long, Boolean>();
1121
1122            long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
1123
1124            for (long selPlid : rowIds) {
1125                boolean includeChildren = ParamUtil.getBoolean(
1126                    actionRequest, "includeChildren_" + selPlid);
1127
1128                layoutIdMap.put(selPlid, includeChildren);
1129            }
1130        }
1131
1132        String remoteAddress = ParamUtil.getString(
1133            actionRequest, "remoteAddress");
1134        int remotePort = ParamUtil.getInteger(actionRequest, "remotePort");
1135        boolean secureConnection = ParamUtil.getBoolean(
1136            actionRequest, "secureConnection");
1137
1138        long remoteGroupId = ParamUtil.getLong(actionRequest, "remoteGroupId");
1139        boolean remotePrivateLayout = ParamUtil.getBoolean(
1140            actionRequest, "remotePrivateLayout");
1141
1142        String range = ParamUtil.getString(actionRequest, "range");
1143
1144        Date startDate = null;
1145        Date endDate = null;
1146
1147        if (range.equals("dateRange")) {
1148            startDate = _getDate(actionRequest, "startDate", true).getTime();
1149
1150            endDate = _getDate(actionRequest, "endDate", true).getTime();
1151        }
1152        else if (range.equals("last")) {
1153            int rangeLast = ParamUtil.getInteger(actionRequest, "last");
1154
1155            Date now = new Date();
1156
1157            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1158
1159            endDate = now;
1160        }
1161
1162        if (schedule) {
1163            String groupName = getSchedulerGroupName(
1164                DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1165
1166            int recurrenceType = ParamUtil.getInteger(
1167                actionRequest, "recurrenceType");
1168
1169            Calendar startCal = _getDate(
1170                actionRequest, "schedulerStartDate", false);
1171
1172            String cronText = _getCronText(
1173                actionRequest, startCal, false, recurrenceType);
1174
1175            Date schedulerEndDate = null;
1176
1177            int endDateType = ParamUtil.getInteger(
1178                actionRequest, "endDateType");
1179
1180            if (endDateType == 1) {
1181                Calendar endCal = _getDate(
1182                    actionRequest, "schedulerEndDate", false);
1183
1184                schedulerEndDate = endCal.getTime();
1185            }
1186
1187            String description = ParamUtil.getString(
1188                actionRequest, "description");
1189
1190            LayoutServiceUtil.schedulePublishToRemote(
1191                groupId, privateLayout, layoutIdMap,
1192                getStagingParameters(actionRequest), remoteAddress, remotePort,
1193                secureConnection, remoteGroupId, remotePrivateLayout, startDate,
1194                endDate, groupName, cronText, startCal.getTime(),
1195                schedulerEndDate, description);
1196        }
1197        else {
1198            MessageStatus messageStatus = new MessageStatus();
1199
1200            messageStatus.startTimer();
1201
1202            try {
1203                copyRemoteLayouts(
1204                    groupId, privateLayout, layoutIdMap, parameterMap,
1205                    remoteAddress, remotePort, secureConnection, remoteGroupId,
1206                    remotePrivateLayout, getStagingParameters(actionRequest),
1207                    startDate, endDate);
1208            }
1209            catch (Exception e) {
1210                messageStatus.setException(e);
1211
1212                throw e;
1213            }
1214            finally {
1215                messageStatus.stopTimer();
1216
1217                LayoutsRemotePublisherRequest publisherRequest =
1218                    new LayoutsRemotePublisherRequest(
1219                        themeDisplay.getUserId(), groupId, privateLayout,
1220                        layoutIdMap, parameterMap, remoteAddress, remotePort,
1221                        secureConnection, remoteGroupId, remotePrivateLayout,
1222                        startDate, endDate);
1223
1224                messageStatus.setPayload(publisherRequest);
1225
1226                MessageBusUtil.sendMessage(
1227                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1228            }
1229        }
1230    }
1231
1232}