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