1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.communities.util;
16  
17  import com.liferay.portal.NoSuchGroupException;
18  import com.liferay.portal.NoSuchLayoutException;
19  import com.liferay.portal.RemoteExportException;
20  import com.liferay.portal.kernel.cal.DayAndPosition;
21  import com.liferay.portal.kernel.cal.Duration;
22  import com.liferay.portal.kernel.cal.Recurrence;
23  import com.liferay.portal.kernel.cal.RecurrenceSerializer;
24  import com.liferay.portal.kernel.exception.PortalException;
25  import com.liferay.portal.kernel.exception.SystemException;
26  import com.liferay.portal.kernel.messaging.DestinationNames;
27  import com.liferay.portal.kernel.messaging.MessageBusUtil;
28  import com.liferay.portal.kernel.messaging.MessageStatus;
29  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.Http;
32  import com.liferay.portal.kernel.util.LocaleUtil;
33  import com.liferay.portal.kernel.util.MapUtil;
34  import com.liferay.portal.kernel.util.ParamUtil;
35  import com.liferay.portal.kernel.util.StringBundler;
36  import com.liferay.portal.kernel.util.StringPool;
37  import com.liferay.portal.kernel.util.Time;
38  import com.liferay.portal.kernel.util.TimeZoneUtil;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.lar.PortletDataHandlerKeys;
41  import com.liferay.portal.lar.UserIdStrategy;
42  import com.liferay.portal.model.Group;
43  import com.liferay.portal.model.GroupConstants;
44  import com.liferay.portal.model.Layout;
45  import com.liferay.portal.model.Portlet;
46  import com.liferay.portal.model.User;
47  import com.liferay.portal.security.auth.HttpPrincipal;
48  import com.liferay.portal.security.auth.PrincipalException;
49  import com.liferay.portal.security.permission.ActionKeys;
50  import com.liferay.portal.security.permission.PermissionChecker;
51  import com.liferay.portal.security.permission.PermissionThreadLocal;
52  import com.liferay.portal.service.GroupLocalServiceUtil;
53  import com.liferay.portal.service.GroupServiceUtil;
54  import com.liferay.portal.service.LayoutLocalServiceUtil;
55  import com.liferay.portal.service.LayoutServiceUtil;
56  import com.liferay.portal.service.UserLocalServiceUtil;
57  import com.liferay.portal.service.http.GroupServiceHttp;
58  import com.liferay.portal.service.http.LayoutServiceHttp;
59  import com.liferay.portal.service.permission.GroupPermissionUtil;
60  import com.liferay.portal.theme.ThemeDisplay;
61  import com.liferay.portal.util.WebKeys;
62  import com.liferay.portlet.communities.messaging.LayoutsLocalPublisherRequest;
63  import com.liferay.portlet.communities.messaging.LayoutsRemotePublisherRequest;
64  
65  import java.io.File;
66  
67  import java.util.ArrayList;
68  import java.util.Calendar;
69  import java.util.Date;
70  import java.util.Iterator;
71  import java.util.LinkedHashMap;
72  import java.util.List;
73  import java.util.Locale;
74  import java.util.Map.Entry;
75  import java.util.Map;
76  import java.util.TimeZone;
77  
78  import javax.portlet.ActionRequest;
79  
80  /**
81   * <a href="StagingUtil.java.html"><b><i>View Source</i></b></a>
82   *
83   * @author Raymond Augé
84   * @author Bruno Farache
85   * @author Wesley Gong
86   */
87  public class StagingUtil {
88  
89      public static void copyFromLive(ActionRequest actionRequest)
90          throws Exception {
91  
92          long stagingGroupId = ParamUtil.getLong(
93              actionRequest, "stagingGroupId");
94  
95          Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
96  
97          long liveGroupId = stagingGroup.getLiveGroupId();
98  
99          Map<String, String[]> parameterMap = getStagingParameters(
100             actionRequest);
101 
102         _publishLayouts(
103             actionRequest, liveGroupId, stagingGroupId, parameterMap, false);
104     }
105 
106     public static void copyFromLive(
107             ActionRequest actionRequest, Portlet portlet)
108         throws Exception {
109 
110         long plid = ParamUtil.getLong(actionRequest, "plid");
111 
112         Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
113 
114         Group stagingGroup = targetLayout.getGroup();
115         Group liveGroup = stagingGroup.getLiveGroup();
116 
117         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(
118             liveGroup.getGroupId(), targetLayout.isPrivateLayout(),
119             targetLayout.getLayoutId());
120 
121         copyPortlet(
122             actionRequest, liveGroup.getGroupId(), stagingGroup.getGroupId(),
123             sourceLayout.getPlid(), targetLayout.getPlid(),
124             portlet.getPortletId());
125     }
126 
127     public static void copyPortlet(
128             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
129             long sourcePlid, long targetPlid, String portletId)
130         throws Exception {
131 
132         Map<String, String[]> parameterMap = getStagingParameters(
133             actionRequest);
134 
135         File file = LayoutLocalServiceUtil.exportPortletInfoAsFile(
136             sourcePlid, sourceGroupId, portletId, parameterMap, null, null);
137 
138         try {
139             LayoutServiceUtil.importPortletInfo(
140                 targetPlid, targetGroupId, portletId, parameterMap, file);
141         }
142         finally {
143             file.delete();
144         }
145     }
146 
147     public static void copyRemoteLayouts(
148             long sourceGroupId, boolean privateLayout,
149             Map<Long, Boolean> layoutIdMap,
150             Map<String, String[]> exportParameterMap, String remoteAddress,
151             int remotePort, boolean secureConnection, long remoteGroupId,
152             boolean remotePrivateLayout,
153             Map<String, String[]> importParameterMap, Date startDate,
154             Date endDate)
155         throws Exception {
156 
157         PermissionChecker permissionChecker =
158             PermissionThreadLocal.getPermissionChecker();
159 
160         User user = UserLocalServiceUtil.getUser(permissionChecker.getUserId());
161 
162         StringBundler sb = new StringBundler(4);
163 
164         if (secureConnection) {
165             sb.append(Http.HTTPS_WITH_SLASH);
166         }
167         else {
168             sb.append(Http.HTTP_WITH_SLASH);
169         }
170 
171         sb.append(remoteAddress);
172         sb.append(StringPool.COLON);
173         sb.append(remotePort);
174 
175         String url = sb.toString();
176 
177         HttpPrincipal httpPrincipal = new HttpPrincipal(
178             url, user.getEmailAddress(), user.getPassword(),
179             user.getPasswordEncrypted());
180 
181         // Ping remote host and verify that the group exists
182 
183         try {
184             GroupServiceHttp.getGroup(httpPrincipal, remoteGroupId);
185         }
186         catch (NoSuchGroupException nsge) {
187             RemoteExportException ree = new RemoteExportException(
188                 RemoteExportException.NO_GROUP);
189 
190             ree.setGroupId(remoteGroupId);
191 
192             throw ree;
193         }
194         catch (SystemException se) {
195             RemoteExportException ree = new RemoteExportException(
196                 RemoteExportException.BAD_CONNECTION);
197 
198             ree.setURL(url);
199 
200             throw ree;
201         }
202 
203         byte[] bytes = null;
204 
205         if (layoutIdMap == null) {
206             bytes = LayoutServiceUtil.exportLayouts(
207                 sourceGroupId, privateLayout, exportParameterMap, startDate,
208                 endDate);
209         }
210         else {
211             List<Layout> layouts = new ArrayList<Layout>();
212 
213             Iterator<Map.Entry<Long, Boolean>> itr1 =
214                 layoutIdMap.entrySet().iterator();
215 
216             while (itr1.hasNext()) {
217                 Entry<Long, Boolean> entry = itr1.next();
218 
219                 long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
220                 boolean includeChildren = entry.getValue();
221 
222                 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
223 
224                 if (!layouts.contains(layout)) {
225                     layouts.add(layout);
226                 }
227 
228                 Iterator<Layout> itr2 = getMissingParents(
229                     layout, sourceGroupId).iterator();
230 
231                 while (itr2.hasNext()) {
232                     Layout parentLayout = itr2.next();
233 
234                     if (!layouts.contains(parentLayout)) {
235                         layouts.add(parentLayout);
236                     }
237                 }
238 
239                 if (includeChildren) {
240                     itr2 = layout.getAllChildren().iterator();
241 
242                     while (itr2.hasNext()) {
243                         Layout childLayout = itr2.next();
244 
245                         if (!layouts.contains(childLayout)) {
246                             layouts.add(childLayout);
247                         }
248                     }
249                 }
250             }
251 
252             long[] layoutIds = new long[layouts.size()];
253 
254             for (int i = 0; i < layouts.size(); i++) {
255                 Layout curLayout = layouts.get(i);
256 
257                 layoutIds[i] = curLayout.getLayoutId();
258             }
259 
260             if (layoutIds.length <= 0) {
261                 throw new RemoteExportException(
262                     RemoteExportException.NO_LAYOUTS);
263             }
264 
265             bytes = LayoutServiceUtil.exportLayouts(
266                 sourceGroupId, privateLayout, layoutIds, exportParameterMap,
267                 startDate, endDate);
268         }
269 
270         LayoutServiceHttp.importLayouts(
271             httpPrincipal, remoteGroupId, remotePrivateLayout,
272             importParameterMap, bytes);
273     }
274 
275     public static List<Layout> getMissingParents(
276             Layout layout, long liveGroupId)
277         throws PortalException, SystemException {
278 
279         List<Layout> missingParents = new ArrayList<Layout>();
280 
281         long parentLayoutId = layout.getParentLayoutId();
282 
283         while (parentLayoutId > 0) {
284             try {
285                 LayoutLocalServiceUtil.getLayout(
286                     liveGroupId, layout.isPrivateLayout(), parentLayoutId);
287 
288                 // If one parent is found all others are assumed to exist
289 
290                 break;
291             }
292             catch (NoSuchLayoutException nsle) {
293                 Layout parent = LayoutLocalServiceUtil.getLayout(
294                     layout.getGroupId(), layout.isPrivateLayout(),
295                     parentLayoutId);
296 
297                 missingParents.add(parent);
298 
299                 parentLayoutId = parent.getParentLayoutId();
300             }
301         }
302 
303         return missingParents;
304     }
305 
306     public static String getSchedulerGroupName(
307         String destinationName, long groupId) {
308 
309         return destinationName.concat(StringPool.SLASH).concat(
310             String.valueOf(groupId));
311     }
312 
313     public static Map<String, String[]> getStagingParameters() {
314         Map<String, String[]> parameterMap =
315             new LinkedHashMap<String, String[]>();
316 
317         parameterMap.put(
318             PortletDataHandlerKeys.CATEGORIES,
319             new String[] {Boolean.TRUE.toString()});
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         publishLayouts(
474             layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
475             layoutIds, parameterMap, null, null);
476     }
477 
478     public static void publishLayouts(
479             long sourceGroupId, long targetGroupId, boolean privateLayout,
480             long[] layoutIds, Map<String, String[]> parameterMap,
481             Date startDate, Date endDate)
482         throws Exception {
483 
484         File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
485             sourceGroupId, privateLayout, layoutIds, parameterMap, startDate,
486             endDate);
487 
488         try {
489             LayoutServiceUtil.importLayouts(
490                 targetGroupId, privateLayout, parameterMap, file);
491         }
492         finally {
493             file.delete();
494         }
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 = GetterUtil.getLong(String.valueOf(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         publishLayouts(
557             sourceGroupId, targetGroupId, privateLayout, layoutIds,
558             parameterMap, startDate, endDate);
559     }
560 
561     public static void publishLayouts(
562             long sourceGroupId, long targetGroupId, boolean privateLayout,
563             Map<String, String[]> parameterMap, Date startDate, Date endDate)
564         throws Exception {
565 
566         publishLayouts(
567             sourceGroupId, targetGroupId, privateLayout, (long[])null,
568             parameterMap, startDate, endDate);
569     }
570 
571     public static void publishToLive(ActionRequest actionRequest)
572         throws Exception {
573 
574         long stagingGroupId = ParamUtil.getLong(
575             actionRequest, "stagingGroupId");
576 
577         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
578 
579         long liveGroupId = stagingGroup.getLiveGroupId();
580 
581         Map<String, String[]> parameterMap = getStagingParameters(
582             actionRequest);
583 
584         _publishLayouts(
585             actionRequest, stagingGroupId, liveGroupId, parameterMap, false);
586     }
587 
588     public static void publishToLive(
589             ActionRequest actionRequest, Portlet portlet)
590         throws Exception {
591 
592         long plid = ParamUtil.getLong(actionRequest, "plid");
593 
594         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
595 
596         Group stagingGroup = sourceLayout.getGroup();
597         Group liveGroup = stagingGroup.getLiveGroup();
598 
599         Layout targetLayout = LayoutLocalServiceUtil.getLayout(
600             liveGroup.getGroupId(), sourceLayout.isPrivateLayout(),
601             sourceLayout.getLayoutId());
602 
603         copyPortlet(
604             actionRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
605             sourceLayout.getPlid(), targetLayout.getPlid(),
606             portlet.getPortletId());
607     }
608 
609     public static void publishToRemote(ActionRequest actionRequest)
610         throws Exception {
611 
612         _publishToRemote(actionRequest, false);
613     }
614 
615     public static void scheduleCopyFromLive(ActionRequest actionRequest)
616         throws Exception {
617 
618         long stagingGroupId = ParamUtil.getLong(
619             actionRequest, "stagingGroupId");
620 
621         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
622 
623         long liveGroupId = stagingGroup.getLiveGroupId();
624 
625         Map<String, String[]> parameterMap = getStagingParameters(
626             actionRequest);
627 
628         _publishLayouts(
629             actionRequest, liveGroupId, stagingGroupId, parameterMap, true);
630     }
631 
632     public static void schedulePublishToLive(ActionRequest actionRequest)
633         throws Exception {
634 
635         long stagingGroupId = ParamUtil.getLong(
636             actionRequest, "stagingGroupId");
637 
638         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
639 
640         long liveGroupId = stagingGroup.getLiveGroupId();
641 
642         Map<String, String[]> parameterMap = getStagingParameters(
643             actionRequest);
644 
645         _publishLayouts(
646             actionRequest, stagingGroupId, liveGroupId, parameterMap, true);
647     }
648 
649     public static void schedulePublishToRemote(ActionRequest actionRequest)
650         throws Exception {
651 
652         _publishToRemote(actionRequest, true);
653     }
654 
655     public static void unscheduleCopyFromLive(ActionRequest actionRequest)
656         throws Exception {
657 
658         long stagingGroupId = ParamUtil.getLong(
659             actionRequest, "stagingGroupId");
660 
661         String jobName = ParamUtil.getString(actionRequest, "jobName");
662         String groupName = getSchedulerGroupName(
663             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
664 
665         LayoutServiceUtil.unschedulePublishToLive(
666             stagingGroupId, jobName, groupName);
667     }
668 
669     public static void unschedulePublishToLive(ActionRequest actionRequest)
670         throws Exception {
671 
672         long stagingGroupId = ParamUtil.getLong(
673             actionRequest, "stagingGroupId");
674 
675         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
676 
677         long liveGroupId = stagingGroup.getLiveGroupId();
678 
679         String jobName = ParamUtil.getString(actionRequest, "jobName");
680         String groupName = getSchedulerGroupName(
681             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
682 
683         LayoutServiceUtil.unschedulePublishToLive(
684             liveGroupId, jobName, groupName);
685     }
686 
687     public static void unschedulePublishToRemote(ActionRequest actionRequest)
688         throws Exception {
689 
690         long groupId = ParamUtil.getLong(actionRequest, "groupId");
691 
692         String jobName = ParamUtil.getString(actionRequest, "jobName");
693         String groupName = getSchedulerGroupName(
694             DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
695 
696         LayoutServiceUtil.unschedulePublishToRemote(
697             groupId, jobName, groupName);
698     }
699 
700     public static void updateStaging(ActionRequest actionRequest)
701         throws Exception {
702 
703         ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
704             WebKeys.THEME_DISPLAY);
705 
706         PermissionChecker permissionChecker =
707             themeDisplay.getPermissionChecker();
708 
709         long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
710 
711         if (!GroupPermissionUtil.contains(
712                 permissionChecker, liveGroupId, ActionKeys.MANAGE_STAGING)) {
713 
714             throw new PrincipalException();
715         }
716 
717         long stagingGroupId = ParamUtil.getLong(
718             actionRequest, "stagingGroupId");
719 
720         boolean stagingEnabled = ParamUtil.getBoolean(
721             actionRequest, "stagingEnabled");
722 
723         if ((stagingGroupId > 0) && !stagingEnabled) {
724             GroupServiceUtil.deleteGroup(stagingGroupId);
725 
726             GroupServiceUtil.updateWorkflow(liveGroupId, false, 0, null);
727         }
728         else if ((stagingGroupId == 0) && stagingEnabled) {
729             Group liveGroup = GroupServiceUtil.getGroup(liveGroupId);
730 
731             Group stagingGroup = GroupServiceUtil.addGroup(
732                 liveGroup.getGroupId(),
733                 liveGroup.getDescriptiveName() + " (Staging)",
734                 liveGroup.getDescription(),
735                 GroupConstants.TYPE_COMMUNITY_PRIVATE, null,
736                 liveGroup.isActive(), null);
737 
738             if (liveGroup.hasPrivateLayouts()) {
739                 Map<String, String[]> parameterMap = getStagingParameters();
740 
741                 publishLayouts(
742                     liveGroup.getGroupId(), stagingGroup.getGroupId(), true,
743                     parameterMap, null, null);
744             }
745 
746             if (liveGroup.hasPublicLayouts()) {
747                 Map<String, String[]> parameterMap = getStagingParameters();
748 
749                 publishLayouts(
750                     liveGroup.getGroupId(), stagingGroup.getGroupId(), false,
751                     parameterMap, null, null);
752             }
753         }
754     }
755 
756     private static void _addWeeklyDayPos(
757         ActionRequest actionRequest, List<DayAndPosition> list, int day) {
758 
759         if (ParamUtil.getBoolean(actionRequest, "weeklyDayPos" + day)) {
760             list.add(new DayAndPosition(day, 0));
761         }
762     }
763 
764     private static String _getCronText(
765             ActionRequest actionRequest, Calendar startDate,
766             boolean timeZoneSensitive, int recurrenceType)
767         throws Exception {
768 
769         Calendar startCal = null;
770 
771         if (timeZoneSensitive) {
772             startCal = CalendarFactoryUtil.getCalendar();
773 
774             startCal.setTime(startDate.getTime());
775         }
776         else {
777             startCal = (Calendar)startDate.clone();
778         }
779 
780         Recurrence recurrence = new Recurrence(
781             startCal, new Duration(1, 0, 0, 0), recurrenceType);
782 
783         recurrence.setWeekStart(Calendar.SUNDAY);
784 
785         if (recurrenceType == Recurrence.DAILY) {
786             int dailyType = ParamUtil.getInteger(actionRequest, "dailyType");
787 
788             if (dailyType == 0) {
789                 int dailyInterval = ParamUtil.getInteger(
790                     actionRequest, "dailyInterval", 1);
791 
792                 recurrence.setInterval(dailyInterval);
793             }
794             else {
795                 DayAndPosition[] dayPos = {
796                     new DayAndPosition(Calendar.MONDAY, 0),
797                     new DayAndPosition(Calendar.TUESDAY, 0),
798                     new DayAndPosition(Calendar.WEDNESDAY, 0),
799                     new DayAndPosition(Calendar.THURSDAY, 0),
800                     new DayAndPosition(Calendar.FRIDAY, 0)};
801 
802                 recurrence.setByDay(dayPos);
803             }
804         }
805         else if (recurrenceType == Recurrence.WEEKLY) {
806             int weeklyInterval = ParamUtil.getInteger(
807                 actionRequest, "weeklyInterval", 1);
808 
809             recurrence.setInterval(weeklyInterval);
810 
811             List<DayAndPosition> dayPos = new ArrayList<DayAndPosition>();
812 
813             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SUNDAY);
814             _addWeeklyDayPos(actionRequest, dayPos, Calendar.MONDAY);
815             _addWeeklyDayPos(actionRequest, dayPos, Calendar.TUESDAY);
816             _addWeeklyDayPos(actionRequest, dayPos, Calendar.WEDNESDAY);
817             _addWeeklyDayPos(actionRequest, dayPos, Calendar.THURSDAY);
818             _addWeeklyDayPos(actionRequest, dayPos, Calendar.FRIDAY);
819             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SATURDAY);
820 
821             if (dayPos.size() == 0) {
822                 dayPos.add(new DayAndPosition(Calendar.MONDAY, 0));
823             }
824 
825             recurrence.setByDay(dayPos.toArray(new DayAndPosition[0]));
826         }
827         else if (recurrenceType == Recurrence.MONTHLY) {
828             int monthlyType = ParamUtil.getInteger(
829                 actionRequest, "monthlyType");
830 
831             if (monthlyType == 0) {
832                 int monthlyDay = ParamUtil.getInteger(
833                     actionRequest, "monthlyDay0", 1);
834 
835                 recurrence.setByMonthDay(new int[] {monthlyDay});
836 
837                 int monthlyInterval = ParamUtil.getInteger(
838                     actionRequest, "monthlyInterval0", 1);
839 
840                 recurrence.setInterval(monthlyInterval);
841             }
842             else {
843                 int monthlyPos = ParamUtil.getInteger(
844                     actionRequest, "monthlyPos");
845                 int monthlyDay = ParamUtil.getInteger(
846                     actionRequest, "monthlyDay1");
847 
848                 DayAndPosition[] dayPos = {
849                     new DayAndPosition(monthlyDay, monthlyPos)};
850 
851                 recurrence.setByDay(dayPos);
852 
853                 int monthlyInterval = ParamUtil.getInteger(
854                     actionRequest, "monthlyInterval1", 1);
855 
856                 recurrence.setInterval(monthlyInterval);
857             }
858         }
859         else if (recurrenceType == Recurrence.YEARLY) {
860             int yearlyType = ParamUtil.getInteger(actionRequest, "yearlyType");
861 
862             if (yearlyType == 0) {
863                 int yearlyMonth = ParamUtil.getInteger(
864                     actionRequest, "yearlyMonth0");
865                 int yearlyDay = ParamUtil.getInteger(
866                     actionRequest, "yearlyDay0", 1);
867 
868                 recurrence.setByMonth(new int[] {yearlyMonth});
869                 recurrence.setByMonthDay(new int[] {yearlyDay});
870 
871                 int yearlyInterval = ParamUtil.getInteger(
872                     actionRequest, "yearlyInterval0", 1);
873 
874                 recurrence.setInterval(yearlyInterval);
875             }
876             else {
877                 int yearlyPos = ParamUtil.getInteger(
878                     actionRequest, "yearlyPos");
879                 int yearlyDay = ParamUtil.getInteger(
880                     actionRequest, "yearlyDay1");
881                 int yearlyMonth = ParamUtil.getInteger(
882                     actionRequest, "yearlyMonth1");
883 
884                 DayAndPosition[] dayPos = {
885                     new DayAndPosition(yearlyDay, yearlyPos)};
886 
887                 recurrence.setByDay(dayPos);
888 
889                 recurrence.setByMonth(new int[] {yearlyMonth});
890 
891                 int yearlyInterval = ParamUtil.getInteger(
892                     actionRequest, "yearlyInterval1", 1);
893 
894                 recurrence.setInterval(yearlyInterval);
895             }
896         }
897 
898         return RecurrenceSerializer.toCronText(recurrence);
899     }
900 
901     private static Calendar _getDate(
902             ActionRequest actionRequest, String paramPrefix,
903             boolean timeZoneSensitive)
904         throws Exception {
905 
906         int dateMonth = ParamUtil.getInteger(
907             actionRequest, paramPrefix + "Month");
908         int dateDay = ParamUtil.getInteger(actionRequest, paramPrefix + "Day");
909         int dateYear = ParamUtil.getInteger(
910             actionRequest, paramPrefix + "Year");
911         int dateHour = ParamUtil.getInteger(
912             actionRequest, paramPrefix + "Hour");
913         int dateMinute = ParamUtil.getInteger(
914             actionRequest, paramPrefix + "Minute");
915         int dateAmPm = ParamUtil.getInteger(
916             actionRequest, paramPrefix + "AmPm");
917 
918         if (dateAmPm == Calendar.PM) {
919             dateHour += 12;
920         }
921 
922         Locale locale = null;
923         TimeZone timeZone = null;
924 
925         if (timeZoneSensitive) {
926             ThemeDisplay themeDisplay =
927                 (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
928 
929             locale = themeDisplay.getLocale();
930             timeZone = themeDisplay.getTimeZone();
931         }
932         else {
933             locale = LocaleUtil.getDefault();
934             timeZone = TimeZoneUtil.getDefault();
935         }
936 
937         Calendar cal = CalendarFactoryUtil.getCalendar(timeZone, locale);
938 
939         cal.set(Calendar.MONTH, dateMonth);
940         cal.set(Calendar.DATE, dateDay);
941         cal.set(Calendar.YEAR, dateYear);
942         cal.set(Calendar.HOUR_OF_DAY, dateHour);
943         cal.set(Calendar.MINUTE, dateMinute);
944         cal.set(Calendar.SECOND, 0);
945         cal.set(Calendar.MILLISECOND, 0);
946 
947         return cal;
948     }
949 
950     private static void _publishLayouts(
951             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
952             Map<String, String[]> parameterMap, boolean schedule)
953         throws Exception {
954 
955         ThemeDisplay themeDisplay =
956             (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
957 
958         String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
959 
960         boolean privateLayout = true;
961 
962         if (tabs1.equals("public-pages")) {
963             privateLayout = false;
964         }
965 
966         String scope = ParamUtil.getString(actionRequest, "scope");
967 
968         Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
969 
970         if (scope.equals("selected-pages")) {
971             long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
972 
973             for (long selPlid : rowIds) {
974                 boolean includeChildren = ParamUtil.getBoolean(
975                     actionRequest, "includeChildren_" + selPlid);
976 
977                 layoutIdMap.put(selPlid, includeChildren);
978             }
979         }
980 
981         String range = ParamUtil.getString(actionRequest, "range");
982 
983         Date startDate = null;
984         Date endDate = null;
985 
986         if (range.equals("dateRange")) {
987             startDate = _getDate(actionRequest, "startDate", true).getTime();
988 
989             endDate = _getDate(actionRequest, "endDate", true).getTime();
990         }
991         else if (range.equals("last")) {
992             int rangeLast = ParamUtil.getInteger(actionRequest, "last");
993 
994             Date now = new Date();
995 
996             startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
997 
998             endDate = now;
999         }
1000
1001        if (schedule) {
1002            String groupName = getSchedulerGroupName(
1003                DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
1004
1005            int recurrenceType = ParamUtil.getInteger(
1006                actionRequest, "recurrenceType");
1007
1008            Calendar startCal = _getDate(
1009                actionRequest, "schedulerStartDate", true);
1010
1011            String cronText = _getCronText(
1012                actionRequest, startCal, true, recurrenceType);
1013
1014            Date schedulerEndDate = null;
1015
1016            int endDateType = ParamUtil.getInteger(
1017                actionRequest, "endDateType");
1018
1019            if (endDateType == 1) {
1020                Calendar endCal = _getDate(
1021                    actionRequest, "schedulerEndDate", true);
1022
1023                schedulerEndDate = endCal.getTime();
1024            }
1025
1026            String description = ParamUtil.getString(
1027                actionRequest, "description");
1028
1029            LayoutServiceUtil.schedulePublishToLive(
1030                sourceGroupId, targetGroupId, privateLayout, layoutIdMap,
1031                parameterMap, scope, startDate, endDate, groupName, cronText,
1032                startCal.getTime(), schedulerEndDate, description);
1033        }
1034        else {
1035            MessageStatus messageStatus = new MessageStatus();
1036
1037            messageStatus.startTimer();
1038
1039            String command =
1040                LayoutsLocalPublisherRequest.COMMAND_SELECTED_PAGES;
1041
1042            try {
1043                if (scope.equals("all-pages")) {
1044                    command = LayoutsLocalPublisherRequest.COMMAND_ALL_PAGES;
1045
1046                    publishLayouts(
1047                        sourceGroupId, targetGroupId, privateLayout,
1048                        parameterMap, startDate, endDate);
1049                }
1050                else {
1051                    publishLayouts(
1052                        sourceGroupId, targetGroupId, privateLayout,
1053                        layoutIdMap, parameterMap, startDate, endDate);
1054                }
1055            }
1056            catch (Exception e) {
1057                messageStatus.setException(e);
1058
1059                throw e;
1060            }
1061            finally {
1062                messageStatus.stopTimer();
1063
1064                LayoutsLocalPublisherRequest publisherRequest =
1065                    new LayoutsLocalPublisherRequest(
1066                        command, themeDisplay.getUserId(), sourceGroupId,
1067                        targetGroupId, privateLayout, layoutIdMap, parameterMap,
1068                        startDate, endDate);
1069
1070                messageStatus.setPayload(publisherRequest);
1071
1072                MessageBusUtil.sendMessage(
1073                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1074            }
1075        }
1076    }
1077
1078    private static void _publishToRemote(
1079            ActionRequest actionRequest, boolean schedule)
1080        throws Exception {
1081
1082        ThemeDisplay themeDisplay =
1083            (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
1084
1085        String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
1086
1087        long groupId = ParamUtil.getLong(actionRequest, "groupId");
1088
1089        boolean privateLayout = true;
1090
1091        if (tabs1.equals("public-pages")) {
1092            privateLayout = false;
1093        }
1094
1095        String scope = ParamUtil.getString(actionRequest, "scope");
1096
1097        if (Validator.isNull(scope)) {
1098            scope = "all-pages";
1099        }
1100
1101        Map<Long, Boolean> layoutIdMap = null;
1102        Map<String, String[]> parameterMap = actionRequest.getParameterMap();
1103
1104        if (scope.equals("selected-pages")) {
1105            layoutIdMap = new LinkedHashMap<Long, Boolean>();
1106
1107            long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
1108
1109            for (long selPlid : rowIds) {
1110                boolean includeChildren = ParamUtil.getBoolean(
1111                    actionRequest, "includeChildren_" + selPlid);
1112
1113                layoutIdMap.put(selPlid, includeChildren);
1114            }
1115        }
1116
1117        String remoteAddress = ParamUtil.getString(
1118            actionRequest, "remoteAddress");
1119        int remotePort = ParamUtil.getInteger(actionRequest, "remotePort");
1120        boolean secureConnection = ParamUtil.getBoolean(
1121            actionRequest, "secureConnection");
1122
1123        long remoteGroupId = ParamUtil.getLong(actionRequest, "remoteGroupId");
1124        boolean remotePrivateLayout = ParamUtil.getBoolean(
1125            actionRequest, "remotePrivateLayout");
1126
1127        String range = ParamUtil.getString(actionRequest, "range");
1128
1129        Date startDate = null;
1130        Date endDate = null;
1131
1132        if (range.equals("dateRange")) {
1133            startDate = _getDate(actionRequest, "startDate", true).getTime();
1134
1135            endDate = _getDate(actionRequest, "endDate", true).getTime();
1136        }
1137        else if (range.equals("last")) {
1138            int rangeLast = ParamUtil.getInteger(actionRequest, "last");
1139
1140            Date now = new Date();
1141
1142            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1143
1144            endDate = now;
1145        }
1146
1147        if (schedule) {
1148            String groupName = getSchedulerGroupName(
1149                DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1150
1151            int recurrenceType = ParamUtil.getInteger(
1152                actionRequest, "recurrenceType");
1153
1154            Calendar startCal = _getDate(
1155                actionRequest, "schedulerStartDate", true);
1156
1157            String cronText = _getCronText(
1158                actionRequest, startCal, true, recurrenceType);
1159
1160            Date schedulerEndDate = null;
1161
1162            int endDateType = ParamUtil.getInteger(
1163                actionRequest, "endDateType");
1164
1165            if (endDateType == 1) {
1166                Calendar endCal = _getDate(
1167                    actionRequest, "schedulerEndDate", true);
1168
1169                schedulerEndDate = endCal.getTime();
1170            }
1171
1172            String description = ParamUtil.getString(
1173                actionRequest, "description");
1174
1175            LayoutServiceUtil.schedulePublishToRemote(
1176                groupId, privateLayout, layoutIdMap,
1177                getStagingParameters(actionRequest), remoteAddress, remotePort,
1178                secureConnection, remoteGroupId, remotePrivateLayout, startDate,
1179                endDate, groupName, cronText, startCal.getTime(),
1180                schedulerEndDate, description);
1181        }
1182        else {
1183            MessageStatus messageStatus = new MessageStatus();
1184
1185            messageStatus.startTimer();
1186
1187            try {
1188                copyRemoteLayouts(
1189                    groupId, privateLayout, layoutIdMap, parameterMap,
1190                    remoteAddress, remotePort, secureConnection, remoteGroupId,
1191                    remotePrivateLayout, getStagingParameters(actionRequest),
1192                    startDate, endDate);
1193            }
1194            catch (Exception e) {
1195                messageStatus.setException(e);
1196
1197                throw e;
1198            }
1199            finally {
1200                messageStatus.stopTimer();
1201
1202                LayoutsRemotePublisherRequest publisherRequest =
1203                    new LayoutsRemotePublisherRequest(
1204                        themeDisplay.getUserId(), groupId, privateLayout,
1205                        layoutIdMap, parameterMap, remoteAddress, remotePort,
1206                        secureConnection, remoteGroupId, remotePrivateLayout,
1207                        startDate, endDate);
1208
1209                messageStatus.setPayload(publisherRequest);
1210
1211                MessageBusUtil.sendMessage(
1212                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1213            }
1214        }
1215    }
1216
1217}