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