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