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