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