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