1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
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.PortalException;
20  import com.liferay.portal.RemoteExportException;
21  import com.liferay.portal.SystemException;
22  import com.liferay.portal.kernel.cal.DayAndPosition;
23  import com.liferay.portal.kernel.cal.Duration;
24  import com.liferay.portal.kernel.cal.Recurrence;
25  import com.liferay.portal.kernel.cal.RecurrenceSerializer;
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.Layout;
44  import com.liferay.portal.model.Portlet;
45  import com.liferay.portal.model.User;
46  import com.liferay.portal.security.auth.HttpPrincipal;
47  import com.liferay.portal.security.auth.PrincipalException;
48  import com.liferay.portal.security.permission.ActionKeys;
49  import com.liferay.portal.security.permission.PermissionChecker;
50  import com.liferay.portal.security.permission.PermissionThreadLocal;
51  import com.liferay.portal.service.GroupLocalServiceUtil;
52  import com.liferay.portal.service.GroupServiceUtil;
53  import com.liferay.portal.service.LayoutLocalServiceUtil;
54  import com.liferay.portal.service.LayoutServiceUtil;
55  import com.liferay.portal.service.UserLocalServiceUtil;
56  import com.liferay.portal.service.http.GroupServiceHttp;
57  import com.liferay.portal.service.http.LayoutServiceHttp;
58  import com.liferay.portal.service.permission.GroupPermissionUtil;
59  import com.liferay.portal.theme.ThemeDisplay;
60  import com.liferay.portal.util.WebKeys;
61  import com.liferay.portlet.communities.messaging.LayoutsLocalPublisherRequest;
62  import com.liferay.portlet.communities.messaging.LayoutsRemotePublisherRequest;
63  
64  import java.io.File;
65  
66  import java.util.ArrayList;
67  import java.util.Calendar;
68  import java.util.Date;
69  import java.util.Iterator;
70  import java.util.LinkedHashMap;
71  import java.util.List;
72  import java.util.Locale;
73  import java.util.Map.Entry;
74  import java.util.Map;
75  import java.util.TimeZone;
76  
77  import javax.portlet.ActionRequest;
78  
79  /**
80   * <a href="StagingUtil.java.html"><b><i>View Source</i></b></a>
81   *
82   * @author Raymond Augé
83   * @author Bruno Farache
84   * @author Wesley Gong
85   */
86  public class StagingUtil {
87  
88      public static void copyFromLive(ActionRequest actionRequest)
89          throws Exception {
90  
91          long stagingGroupId = ParamUtil.getLong(
92              actionRequest, "stagingGroupId");
93  
94          Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
95  
96          long liveGroupId = stagingGroup.getLiveGroupId();
97  
98          Map<String, String[]> parameterMap = getStagingParameters(
99              actionRequest);
100 
101         _publishLayouts(
102             actionRequest, liveGroupId, stagingGroupId, parameterMap, false);
103     }
104 
105     public static void copyFromLive(
106             ActionRequest actionRequest, Portlet portlet)
107         throws Exception {
108 
109         long plid = ParamUtil.getLong(actionRequest, "plid");
110 
111         Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
112 
113         Group stagingGroup = targetLayout.getGroup();
114         Group liveGroup = stagingGroup.getLiveGroup();
115 
116         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(
117             liveGroup.getGroupId(), targetLayout.isPrivateLayout(),
118             targetLayout.getLayoutId());
119 
120         copyPortlet(
121             actionRequest, liveGroup.getGroupId(), stagingGroup.getGroupId(),
122             sourceLayout.getPlid(), targetLayout.getPlid(),
123             portlet.getPortletId());
124     }
125 
126     public static void copyPortlet(
127             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
128             long sourcePlid, long targetPlid, String portletId)
129         throws Exception {
130 
131         Map<String, String[]> parameterMap = getStagingParameters(
132             actionRequest);
133 
134         File file = LayoutLocalServiceUtil.exportPortletInfoAsFile(
135             sourcePlid, sourceGroupId, portletId, parameterMap, null, null);
136 
137         try {
138             LayoutServiceUtil.importPortletInfo(
139                 targetPlid, targetGroupId, portletId, parameterMap, file);
140         }
141         finally {
142             file.delete();
143         }
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         StringBundler sb = new StringBundler(4);
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 = GetterUtil.getLong(String.valueOf(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 = getMissingParentLayouts(
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> getMissingParentLayouts(
275             Layout layout, long liveGroupId)
276         throws PortalException, SystemException {
277 
278         List<Layout> missingParentLayouts = new ArrayList<Layout>();
279 
280         long parentLayoutId = layout.getParentLayoutId();
281 
282         Layout parentLayout = null;
283 
284         while (parentLayoutId > 0) {
285             parentLayout = LayoutLocalServiceUtil.getLayout(
286                 layout.getGroupId(), layout.isPrivateLayout(),
287                 parentLayoutId);
288 
289             try {
290                 LayoutLocalServiceUtil.getFriendlyURLLayout(
291                     liveGroupId, parentLayout.isPrivateLayout(),
292                     parentLayout.getFriendlyURL());
293 
294                 // If one parent is found all others are assumed to exist
295 
296                 break;
297             }
298             catch (NoSuchLayoutException nsle) {
299                 missingParentLayouts.add(parentLayout);
300 
301                 parentLayoutId = parentLayout.getParentLayoutId();
302             }
303         }
304 
305         return missingParentLayouts;
306     }
307 
308     public static String getSchedulerGroupName(
309         String destinationName, long groupId) {
310 
311         return destinationName.concat(StringPool.SLASH).concat(
312             String.valueOf(groupId));
313     }
314 
315     public static Map<String, String[]> getStagingParameters() {
316         Map<String, String[]> parameterMap =
317             new LinkedHashMap<String, String[]>();
318 
319         parameterMap.put(
320             PortletDataHandlerKeys.CATEGORIES,
321             new String[] {Boolean.TRUE.toString()});
322         parameterMap.put(
323             PortletDataHandlerKeys.DATA_STRATEGY,
324             new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
325         parameterMap.put(
326             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
327             new String[] {Boolean.TRUE.toString()});
328         parameterMap.put(
329             PortletDataHandlerKeys.DELETE_PORTLET_DATA,
330             new String[] {Boolean.FALSE.toString()});
331         parameterMap.put(
332             PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
333             new String[] {
334                 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID});
335         parameterMap.put(
336             PortletDataHandlerKeys.PERMISSIONS,
337             new String[] {Boolean.TRUE.toString()});
338         parameterMap.put(
339             PortletDataHandlerKeys.PORTLET_DATA,
340             new String[] {Boolean.TRUE.toString()});
341         parameterMap.put(
342             PortletDataHandlerKeys.PORTLET_DATA_ALL,
343             new String[] {Boolean.TRUE.toString()});
344         parameterMap.put(
345             PortletDataHandlerKeys.PORTLET_SETUP,
346             new String[] {Boolean.TRUE.toString()});
347         parameterMap.put(
348             PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
349             new String[] {Boolean.TRUE.toString()});
350         parameterMap.put(
351             PortletDataHandlerKeys.THEME,
352             new String[] {Boolean.FALSE.toString()});
353         parameterMap.put(
354             PortletDataHandlerKeys.USER_ID_STRATEGY,
355             new String[] {UserIdStrategy.CURRENT_USER_ID});
356         parameterMap.put(
357             PortletDataHandlerKeys.USER_PERMISSIONS,
358             new String[] {Boolean.FALSE.toString()});
359 
360         return parameterMap;
361     }
362 
363     public static Map<String, String[]> getStagingParameters(
364         ActionRequest actionRequest) {
365 
366         Map<String, String[]> parameterMap =
367             new LinkedHashMap<String, String[]>(
368                 actionRequest.getParameterMap());
369 
370         if (!parameterMap.containsKey(PortletDataHandlerKeys.DATA_STRATEGY)) {
371             parameterMap.put(
372                 PortletDataHandlerKeys.DATA_STRATEGY,
373                 new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
374         }
375 
376         if (!parameterMap.containsKey(
377                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS)) {
378 
379             parameterMap.put(
380                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
381                 new String[] {Boolean.TRUE.toString()});
382         }
383 
384         if (!parameterMap.containsKey(
385                 PortletDataHandlerKeys.DELETE_PORTLET_DATA)) {
386 
387             parameterMap.put(
388                 PortletDataHandlerKeys.DELETE_PORTLET_DATA,
389                 new String[] {Boolean.FALSE.toString()});
390         }
391 
392         if (!parameterMap.containsKey(
393                 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE)) {
394 
395             parameterMap.put(
396                 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
397                 new String[] {
398                 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID});
399         }
400 
401         if (!parameterMap.containsKey(
402                 PortletDataHandlerKeys.PORTLET_DATA)) {
403 
404             parameterMap.put(
405                 PortletDataHandlerKeys.PORTLET_DATA,
406                 new String[] {Boolean.FALSE.toString()});
407         }
408 
409         if (!parameterMap.containsKey(
410                 PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
411 
412             Boolean portletDataAll = Boolean.FALSE;
413 
414             if (MapUtil.getBoolean(
415                     parameterMap, PortletDataHandlerKeys.PORTLET_DATA)) {
416 
417                 portletDataAll = Boolean.TRUE;
418             }
419 
420             parameterMap.put(
421                 PortletDataHandlerKeys.PORTLET_DATA_ALL,
422                 new String[] {portletDataAll.toString()});
423         }
424 
425         if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_SETUP)) {
426             parameterMap.put(
427                 PortletDataHandlerKeys.PORTLET_SETUP,
428                 new String[] {Boolean.TRUE.toString()});
429         }
430 
431         if (!parameterMap.containsKey(
432                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES)) {
433 
434             parameterMap.put(
435                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
436                 new String[] {Boolean.TRUE.toString()});
437         }
438 
439         if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME)) {
440             parameterMap.put(
441                 PortletDataHandlerKeys.THEME,
442                 new String[] {Boolean.FALSE.toString()});
443         }
444 
445         if (!parameterMap.containsKey(
446                 PortletDataHandlerKeys.USER_ID_STRATEGY)) {
447 
448             parameterMap.put(
449                 PortletDataHandlerKeys.USER_ID_STRATEGY,
450                 new String[] {UserIdStrategy.CURRENT_USER_ID});
451         }
452 
453         return parameterMap;
454     }
455 
456     public static void publishLayout(
457             long plid, long liveGroupId, boolean includeChildren)
458         throws Exception {
459 
460         Map<String, String[]> parameterMap = getStagingParameters();
461 
462         parameterMap.put(
463             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
464             new String[] {Boolean.FALSE.toString()});
465 
466         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
467 
468         List<Layout> layouts = new ArrayList<Layout>();
469 
470         layouts.add(layout);
471 
472         layouts.addAll(getMissingParentLayouts(layout, liveGroupId));
473 
474         if (includeChildren) {
475             layouts.addAll(layout.getAllChildren());
476         }
477 
478         Iterator<Layout> itr = layouts.iterator();
479 
480         long[] layoutIds = new long[layouts.size()];
481 
482         for (int i = 0; itr.hasNext(); i++) {
483             Layout curLayout = itr.next();
484 
485             layoutIds[i] = curLayout.getLayoutId();
486         }
487 
488         publishLayouts(
489             layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
490             layoutIds, parameterMap, null, null);
491     }
492 
493     public static void publishLayouts(
494             long sourceGroupId, long targetGroupId, boolean privateLayout,
495             long[] layoutIds, Map<String, String[]> parameterMap,
496             Date startDate, Date endDate)
497         throws Exception {
498 
499         File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
500             sourceGroupId, privateLayout, layoutIds, parameterMap, startDate,
501             endDate);
502 
503         try {
504             LayoutServiceUtil.importLayouts(
505                 targetGroupId, privateLayout, parameterMap, file);
506         }
507         finally {
508             file.delete();
509         }
510     }
511 
512     public static void publishLayouts(
513             long sourceGroupId, long targetGroupId, boolean privateLayout,
514             Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
515             Date startDate, Date endDate)
516         throws Exception {
517 
518         parameterMap.put(
519             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
520             new String[] {Boolean.FALSE.toString()});
521 
522         List<Layout> layouts = new ArrayList<Layout>();
523 
524         Iterator<Map.Entry<Long, Boolean>> itr1 =
525             layoutIdMap.entrySet().iterator();
526 
527         while (itr1.hasNext()) {
528             Entry<Long, Boolean> entry = itr1.next();
529 
530             long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
531             boolean includeChildren = entry.getValue();
532 
533             Layout layout = LayoutLocalServiceUtil.getLayout(plid);
534 
535             if (!layouts.contains(layout)) {
536                 layouts.add(layout);
537             }
538 
539             Iterator<Layout> itr2 = getMissingParentLayouts(
540                 layout, targetGroupId).iterator();
541 
542             while (itr2.hasNext()) {
543                 Layout parentLayout = itr2.next();
544 
545                 if (!layouts.contains(parentLayout)) {
546                     layouts.add(parentLayout);
547                 }
548             }
549 
550             if (includeChildren) {
551                 itr2 = layout.getAllChildren().iterator();
552 
553                 while (itr2.hasNext()) {
554                     Layout childLayout = itr2.next();
555 
556                     if (!layouts.contains(childLayout)) {
557                         layouts.add(childLayout);
558                     }
559                 }
560             }
561         }
562 
563         long[] layoutIds = new long[layouts.size()];
564 
565         for (int i = 0; i < layouts.size(); i++) {
566             Layout curLayout = layouts.get(i);
567 
568             layoutIds[i] = curLayout.getLayoutId();
569         }
570 
571         publishLayouts(
572             sourceGroupId, targetGroupId, privateLayout, layoutIds,
573             parameterMap, startDate, endDate);
574     }
575 
576     public static void publishLayouts(
577             long sourceGroupId, long targetGroupId, boolean privateLayout,
578             Map<String, String[]> parameterMap, Date startDate, Date endDate)
579         throws Exception {
580 
581         publishLayouts(
582             sourceGroupId, targetGroupId, privateLayout, (long[])null,
583             parameterMap, startDate, endDate);
584     }
585 
586     public static void publishToLive(ActionRequest actionRequest)
587         throws Exception {
588 
589         long stagingGroupId = ParamUtil.getLong(
590             actionRequest, "stagingGroupId");
591 
592         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
593 
594         long liveGroupId = stagingGroup.getLiveGroupId();
595 
596         Map<String, String[]> parameterMap = getStagingParameters(
597             actionRequest);
598 
599         _publishLayouts(
600             actionRequest, stagingGroupId, liveGroupId, parameterMap, false);
601     }
602 
603     public static void publishToLive(
604             ActionRequest actionRequest, Portlet portlet)
605         throws Exception {
606 
607         long plid = ParamUtil.getLong(actionRequest, "plid");
608 
609         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
610 
611         Group stagingGroup = sourceLayout.getGroup();
612         Group liveGroup = stagingGroup.getLiveGroup();
613 
614         Layout targetLayout = LayoutLocalServiceUtil.getLayout(
615             liveGroup.getGroupId(), sourceLayout.isPrivateLayout(),
616             sourceLayout.getLayoutId());
617 
618         copyPortlet(
619             actionRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
620             sourceLayout.getPlid(), targetLayout.getPlid(),
621             portlet.getPortletId());
622     }
623 
624     public static void publishToRemote(ActionRequest actionRequest)
625         throws Exception {
626 
627         _publishToRemote(actionRequest, false);
628     }
629 
630     public static void scheduleCopyFromLive(ActionRequest actionRequest)
631         throws Exception {
632 
633         long stagingGroupId = ParamUtil.getLong(
634             actionRequest, "stagingGroupId");
635 
636         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
637 
638         long liveGroupId = stagingGroup.getLiveGroupId();
639 
640         Map<String, String[]> parameterMap = getStagingParameters(
641             actionRequest);
642 
643         _publishLayouts(
644             actionRequest, liveGroupId, stagingGroupId, parameterMap, true);
645     }
646 
647     public static void schedulePublishToLive(ActionRequest actionRequest)
648         throws Exception {
649 
650         long stagingGroupId = ParamUtil.getLong(
651             actionRequest, "stagingGroupId");
652 
653         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
654 
655         long liveGroupId = stagingGroup.getLiveGroupId();
656 
657         Map<String, String[]> parameterMap = getStagingParameters(
658             actionRequest);
659 
660         _publishLayouts(
661             actionRequest, stagingGroupId, liveGroupId, parameterMap, true);
662     }
663 
664     public static void schedulePublishToRemote(ActionRequest actionRequest)
665         throws Exception {
666 
667         _publishToRemote(actionRequest, true);
668     }
669 
670     public static void unscheduleCopyFromLive(ActionRequest actionRequest)
671         throws Exception {
672 
673         long stagingGroupId = ParamUtil.getLong(
674             actionRequest, "stagingGroupId");
675 
676         String jobName = ParamUtil.getString(actionRequest, "jobName");
677         String groupName = getSchedulerGroupName(
678             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
679 
680         LayoutServiceUtil.unschedulePublishToLive(
681             stagingGroupId, jobName, groupName);
682     }
683 
684     public static void unschedulePublishToLive(ActionRequest actionRequest)
685         throws Exception {
686 
687         long stagingGroupId = ParamUtil.getLong(
688             actionRequest, "stagingGroupId");
689 
690         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
691 
692         long liveGroupId = stagingGroup.getLiveGroupId();
693 
694         String jobName = ParamUtil.getString(actionRequest, "jobName");
695         String groupName = getSchedulerGroupName(
696             DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
697 
698         LayoutServiceUtil.unschedulePublishToLive(
699             liveGroupId, jobName, groupName);
700     }
701 
702     public static void unschedulePublishToRemote(ActionRequest actionRequest)
703         throws Exception {
704 
705         long groupId = ParamUtil.getLong(actionRequest, "groupId");
706 
707         String jobName = ParamUtil.getString(actionRequest, "jobName");
708         String groupName = getSchedulerGroupName(
709             DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
710 
711         LayoutServiceUtil.unschedulePublishToRemote(
712             groupId, jobName, groupName);
713     }
714 
715     public static void updateStaging(ActionRequest actionRequest)
716         throws Exception {
717 
718         ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
719             WebKeys.THEME_DISPLAY);
720 
721         PermissionChecker permissionChecker =
722             themeDisplay.getPermissionChecker();
723 
724         long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
725 
726         if (!GroupPermissionUtil.contains(
727                 permissionChecker, liveGroupId, ActionKeys.MANAGE_STAGING)) {
728 
729             throw new PrincipalException();
730         }
731 
732         long stagingGroupId = ParamUtil.getLong(
733             actionRequest, "stagingGroupId");
734 
735         boolean stagingEnabled = ParamUtil.getBoolean(
736             actionRequest, "stagingEnabled");
737 
738         if ((stagingGroupId > 0) && !stagingEnabled) {
739             GroupServiceUtil.deleteGroup(stagingGroupId);
740 
741             GroupServiceUtil.updateWorkflow(liveGroupId, false, 0, null);
742         }
743         else if ((stagingGroupId == 0) && stagingEnabled) {
744             Group liveGroup = GroupServiceUtil.getGroup(liveGroupId);
745 
746             Group stagingGroup = GroupServiceUtil.addGroup(
747                 liveGroup.getGroupId(),
748                 liveGroup.getDescriptiveName() + " (Staging)",
749                 liveGroup.getDescription(), liveGroup.getType(),
750                 liveGroup.getFriendlyURL().concat("-staging"),
751                 liveGroup.isActive(), null);
752 
753             if (liveGroup.hasPrivateLayouts()) {
754                 Map<String, String[]> parameterMap = getStagingParameters();
755 
756                 publishLayouts(
757                     liveGroup.getGroupId(), stagingGroup.getGroupId(), true,
758                     parameterMap, null, null);
759             }
760 
761             if (liveGroup.hasPublicLayouts()) {
762                 Map<String, String[]> parameterMap = getStagingParameters();
763 
764                 publishLayouts(
765                     liveGroup.getGroupId(), stagingGroup.getGroupId(), false,
766                     parameterMap, null, null);
767             }
768         }
769     }
770 
771     private static void _addWeeklyDayPos(
772         ActionRequest actionRequest, List<DayAndPosition> list, int day) {
773 
774         if (ParamUtil.getBoolean(actionRequest, "weeklyDayPos" + day)) {
775             list.add(new DayAndPosition(day, 0));
776         }
777     }
778 
779     private static String _getCronText(
780             ActionRequest actionRequest, Calendar startDate,
781             boolean timeZoneSensitive, int recurrenceType)
782         throws Exception {
783 
784         Calendar startCal = null;
785 
786         if (timeZoneSensitive) {
787             startCal = CalendarFactoryUtil.getCalendar();
788 
789             startCal.setTime(startDate.getTime());
790         }
791         else {
792             startCal = (Calendar)startDate.clone();
793         }
794 
795         Recurrence recurrence = new Recurrence(
796             startCal, new Duration(1, 0, 0, 0), recurrenceType);
797 
798         recurrence.setWeekStart(Calendar.SUNDAY);
799 
800         if (recurrenceType == Recurrence.DAILY) {
801             int dailyType = ParamUtil.getInteger(actionRequest, "dailyType");
802 
803             if (dailyType == 0) {
804                 int dailyInterval = ParamUtil.getInteger(
805                     actionRequest, "dailyInterval", 1);
806 
807                 recurrence.setInterval(dailyInterval);
808             }
809             else {
810                 DayAndPosition[] dayPos = {
811                     new DayAndPosition(Calendar.MONDAY, 0),
812                     new DayAndPosition(Calendar.TUESDAY, 0),
813                     new DayAndPosition(Calendar.WEDNESDAY, 0),
814                     new DayAndPosition(Calendar.THURSDAY, 0),
815                     new DayAndPosition(Calendar.FRIDAY, 0)};
816 
817                 recurrence.setByDay(dayPos);
818             }
819         }
820         else if (recurrenceType == Recurrence.WEEKLY) {
821             int weeklyInterval = ParamUtil.getInteger(
822                 actionRequest, "weeklyInterval", 1);
823 
824             recurrence.setInterval(weeklyInterval);
825 
826             List<DayAndPosition> dayPos = new ArrayList<DayAndPosition>();
827 
828             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SUNDAY);
829             _addWeeklyDayPos(actionRequest, dayPos, Calendar.MONDAY);
830             _addWeeklyDayPos(actionRequest, dayPos, Calendar.TUESDAY);
831             _addWeeklyDayPos(actionRequest, dayPos, Calendar.WEDNESDAY);
832             _addWeeklyDayPos(actionRequest, dayPos, Calendar.THURSDAY);
833             _addWeeklyDayPos(actionRequest, dayPos, Calendar.FRIDAY);
834             _addWeeklyDayPos(actionRequest, dayPos, Calendar.SATURDAY);
835 
836             if (dayPos.size() == 0) {
837                 dayPos.add(new DayAndPosition(Calendar.MONDAY, 0));
838             }
839 
840             recurrence.setByDay(dayPos.toArray(new DayAndPosition[0]));
841         }
842         else if (recurrenceType == Recurrence.MONTHLY) {
843             int monthlyType = ParamUtil.getInteger(
844                 actionRequest, "monthlyType");
845 
846             if (monthlyType == 0) {
847                 int monthlyDay = ParamUtil.getInteger(
848                     actionRequest, "monthlyDay0", 1);
849 
850                 recurrence.setByMonthDay(new int[] {monthlyDay});
851 
852                 int monthlyInterval = ParamUtil.getInteger(
853                     actionRequest, "monthlyInterval0", 1);
854 
855                 recurrence.setInterval(monthlyInterval);
856             }
857             else {
858                 int monthlyPos = ParamUtil.getInteger(
859                     actionRequest, "monthlyPos");
860                 int monthlyDay = ParamUtil.getInteger(
861                     actionRequest, "monthlyDay1");
862 
863                 DayAndPosition[] dayPos = {
864                     new DayAndPosition(monthlyDay, monthlyPos)};
865 
866                 recurrence.setByDay(dayPos);
867 
868                 int monthlyInterval = ParamUtil.getInteger(
869                     actionRequest, "monthlyInterval1", 1);
870 
871                 recurrence.setInterval(monthlyInterval);
872             }
873         }
874         else if (recurrenceType == Recurrence.YEARLY) {
875             int yearlyType = ParamUtil.getInteger(actionRequest, "yearlyType");
876 
877             if (yearlyType == 0) {
878                 int yearlyMonth = ParamUtil.getInteger(
879                     actionRequest, "yearlyMonth0");
880                 int yearlyDay = ParamUtil.getInteger(
881                     actionRequest, "yearlyDay0", 1);
882 
883                 recurrence.setByMonth(new int[] {yearlyMonth});
884                 recurrence.setByMonthDay(new int[] {yearlyDay});
885 
886                 int yearlyInterval = ParamUtil.getInteger(
887                     actionRequest, "yearlyInterval0", 1);
888 
889                 recurrence.setInterval(yearlyInterval);
890             }
891             else {
892                 int yearlyPos = ParamUtil.getInteger(
893                     actionRequest, "yearlyPos");
894                 int yearlyDay = ParamUtil.getInteger(
895                     actionRequest, "yearlyDay1");
896                 int yearlyMonth = ParamUtil.getInteger(
897                     actionRequest, "yearlyMonth1");
898 
899                 DayAndPosition[] dayPos = {
900                     new DayAndPosition(yearlyDay, yearlyPos)};
901 
902                 recurrence.setByDay(dayPos);
903 
904                 recurrence.setByMonth(new int[] {yearlyMonth});
905 
906                 int yearlyInterval = ParamUtil.getInteger(
907                     actionRequest, "yearlyInterval1", 1);
908 
909                 recurrence.setInterval(yearlyInterval);
910             }
911         }
912 
913         return RecurrenceSerializer.toCronText(recurrence);
914     }
915 
916     private static Calendar _getDate(
917             ActionRequest actionRequest, String paramPrefix,
918             boolean timeZoneSensitive)
919         throws Exception {
920 
921         int dateMonth = ParamUtil.getInteger(
922             actionRequest, paramPrefix + "Month");
923         int dateDay = ParamUtil.getInteger(actionRequest, paramPrefix + "Day");
924         int dateYear = ParamUtil.getInteger(
925             actionRequest, paramPrefix + "Year");
926         int dateHour = ParamUtil.getInteger(
927             actionRequest, paramPrefix + "Hour");
928         int dateMinute = ParamUtil.getInteger(
929             actionRequest, paramPrefix + "Minute");
930         int dateAmPm = ParamUtil.getInteger(
931             actionRequest, paramPrefix + "AmPm");
932 
933         if (dateAmPm == Calendar.PM) {
934             dateHour += 12;
935         }
936 
937         Locale locale = null;
938         TimeZone timeZone = null;
939 
940         if (timeZoneSensitive) {
941             ThemeDisplay themeDisplay =
942                 (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
943 
944             locale = themeDisplay.getLocale();
945             timeZone = themeDisplay.getTimeZone();
946         }
947         else {
948             locale = LocaleUtil.getDefault();
949             timeZone = TimeZoneUtil.getDefault();
950         }
951 
952         Calendar cal = CalendarFactoryUtil.getCalendar(timeZone, locale);
953 
954         cal.set(Calendar.MONTH, dateMonth);
955         cal.set(Calendar.DATE, dateDay);
956         cal.set(Calendar.YEAR, dateYear);
957         cal.set(Calendar.HOUR_OF_DAY, dateHour);
958         cal.set(Calendar.MINUTE, dateMinute);
959         cal.set(Calendar.SECOND, 0);
960         cal.set(Calendar.MILLISECOND, 0);
961 
962         return cal;
963     }
964 
965     private static void _publishLayouts(
966             ActionRequest actionRequest, long sourceGroupId, long targetGroupId,
967             Map<String, String[]> parameterMap, boolean schedule)
968         throws Exception {
969 
970         ThemeDisplay themeDisplay =
971             (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
972 
973         String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
974 
975         boolean privateLayout = true;
976 
977         if (tabs1.equals("public-pages")) {
978             privateLayout = false;
979         }
980 
981         String scope = ParamUtil.getString(actionRequest, "scope");
982 
983         Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
984 
985         if (scope.equals("selected-pages")) {
986             long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
987 
988             for (long selPlid : rowIds) {
989                 boolean includeChildren = ParamUtil.getBoolean(
990                     actionRequest, "includeChildren_" + selPlid);
991 
992                 layoutIdMap.put(selPlid, includeChildren);
993             }
994         }
995 
996         String range = ParamUtil.getString(actionRequest, "range");
997 
998         Date startDate = null;
999         Date endDate = null;
1000
1001        if (range.equals("dateRange")) {
1002            startDate = _getDate(actionRequest, "startDate", true).getTime();
1003
1004            endDate = _getDate(actionRequest, "endDate", true).getTime();
1005        }
1006        else if (range.equals("last")) {
1007            int rangeLast = ParamUtil.getInteger(actionRequest, "last");
1008
1009            Date now = new Date();
1010
1011            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1012
1013            endDate = now;
1014        }
1015
1016        if (schedule) {
1017            String groupName = getSchedulerGroupName(
1018                DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
1019
1020            int recurrenceType = ParamUtil.getInteger(
1021                actionRequest, "recurrenceType");
1022
1023            Calendar startCal = _getDate(
1024                actionRequest, "schedulerStartDate", true);
1025
1026            String cronText = _getCronText(
1027                actionRequest, startCal, true, recurrenceType);
1028
1029            Date schedulerEndDate = null;
1030
1031            int endDateType = ParamUtil.getInteger(
1032                actionRequest, "endDateType");
1033
1034            if (endDateType == 1) {
1035                Calendar endCal = _getDate(
1036                    actionRequest, "schedulerEndDate", true);
1037
1038                schedulerEndDate = endCal.getTime();
1039            }
1040
1041            String description = ParamUtil.getString(
1042                actionRequest, "description");
1043
1044            LayoutServiceUtil.schedulePublishToLive(
1045                sourceGroupId, targetGroupId, privateLayout, layoutIdMap,
1046                parameterMap, scope, startDate, endDate, groupName, cronText,
1047                startCal.getTime(), schedulerEndDate, description);
1048        }
1049        else {
1050            MessageStatus messageStatus = new MessageStatus();
1051
1052            messageStatus.startTimer();
1053
1054            String command =
1055                LayoutsLocalPublisherRequest.COMMAND_SELECTED_PAGES;
1056
1057            try {
1058                if (scope.equals("all-pages")) {
1059                    command = LayoutsLocalPublisherRequest.COMMAND_ALL_PAGES;
1060
1061                    publishLayouts(
1062                        sourceGroupId, targetGroupId, privateLayout,
1063                        parameterMap, startDate, endDate);
1064                }
1065                else {
1066                    publishLayouts(
1067                        sourceGroupId, targetGroupId, privateLayout,
1068                        layoutIdMap, parameterMap, startDate, endDate);
1069                }
1070            }
1071            catch (Exception e) {
1072                messageStatus.setException(e);
1073
1074                throw e;
1075            }
1076            finally {
1077                messageStatus.stopTimer();
1078
1079                LayoutsLocalPublisherRequest publisherRequest =
1080                    new LayoutsLocalPublisherRequest(
1081                        command, themeDisplay.getUserId(), sourceGroupId,
1082                        targetGroupId, privateLayout, layoutIdMap, parameterMap,
1083                        startDate, endDate);
1084
1085                messageStatus.setPayload(publisherRequest);
1086
1087                MessageBusUtil.sendMessage(
1088                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1089            }
1090        }
1091    }
1092
1093    private static void _publishToRemote(
1094            ActionRequest actionRequest, boolean schedule)
1095        throws Exception {
1096
1097        ThemeDisplay themeDisplay =
1098            (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
1099
1100        String tabs1 = ParamUtil.getString(actionRequest, "tabs1");
1101
1102        long groupId = ParamUtil.getLong(actionRequest, "groupId");
1103
1104        boolean privateLayout = true;
1105
1106        if (tabs1.equals("public-pages")) {
1107            privateLayout = false;
1108        }
1109
1110        String scope = ParamUtil.getString(actionRequest, "scope");
1111
1112        if (Validator.isNull(scope)) {
1113            scope = "all-pages";
1114        }
1115
1116        Map<Long, Boolean> layoutIdMap = null;
1117        Map<String, String[]> parameterMap = actionRequest.getParameterMap();
1118
1119        if (scope.equals("selected-pages")) {
1120            layoutIdMap = new LinkedHashMap<Long, Boolean>();
1121
1122            long[] rowIds = ParamUtil.getLongValues(actionRequest, "rowIds");
1123
1124            for (long selPlid : rowIds) {
1125                boolean includeChildren = ParamUtil.getBoolean(
1126                    actionRequest, "includeChildren_" + selPlid);
1127
1128                layoutIdMap.put(selPlid, includeChildren);
1129            }
1130        }
1131
1132        String remoteAddress = ParamUtil.getString(
1133            actionRequest, "remoteAddress");
1134        int remotePort = ParamUtil.getInteger(actionRequest, "remotePort");
1135        boolean secureConnection = ParamUtil.getBoolean(
1136            actionRequest, "secureConnection");
1137
1138        long remoteGroupId = ParamUtil.getLong(actionRequest, "remoteGroupId");
1139        boolean remotePrivateLayout = ParamUtil.getBoolean(
1140            actionRequest, "remotePrivateLayout");
1141
1142        String range = ParamUtil.getString(actionRequest, "range");
1143
1144        Date startDate = null;
1145        Date endDate = null;
1146
1147        if (range.equals("dateRange")) {
1148            startDate = _getDate(actionRequest, "startDate", true).getTime();
1149
1150            endDate = _getDate(actionRequest, "endDate", true).getTime();
1151        }
1152        else if (range.equals("last")) {
1153            int rangeLast = ParamUtil.getInteger(actionRequest, "last");
1154
1155            Date now = new Date();
1156
1157            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
1158
1159            endDate = now;
1160        }
1161
1162        if (schedule) {
1163            String groupName = getSchedulerGroupName(
1164                DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1165
1166            int recurrenceType = ParamUtil.getInteger(
1167                actionRequest, "recurrenceType");
1168
1169            Calendar startCal = _getDate(
1170                actionRequest, "schedulerStartDate", true);
1171
1172            String cronText = _getCronText(
1173                actionRequest, startCal, true, recurrenceType);
1174
1175            Date schedulerEndDate = null;
1176
1177            int endDateType = ParamUtil.getInteger(
1178                actionRequest, "endDateType");
1179
1180            if (endDateType == 1) {
1181                Calendar endCal = _getDate(
1182                    actionRequest, "schedulerEndDate", true);
1183
1184                schedulerEndDate = endCal.getTime();
1185            }
1186
1187            String description = ParamUtil.getString(
1188                actionRequest, "description");
1189
1190            LayoutServiceUtil.schedulePublishToRemote(
1191                groupId, privateLayout, layoutIdMap,
1192                getStagingParameters(actionRequest), remoteAddress, remotePort,
1193                secureConnection, remoteGroupId, remotePrivateLayout, startDate,
1194                endDate, groupName, cronText, startCal.getTime(),
1195                schedulerEndDate, description);
1196        }
1197        else {
1198            MessageStatus messageStatus = new MessageStatus();
1199
1200            messageStatus.startTimer();
1201
1202            try {
1203                copyRemoteLayouts(
1204                    groupId, privateLayout, layoutIdMap, parameterMap,
1205                    remoteAddress, remotePort, secureConnection, remoteGroupId,
1206                    remotePrivateLayout, getStagingParameters(actionRequest),
1207                    startDate, endDate);
1208            }
1209            catch (Exception e) {
1210                messageStatus.setException(e);
1211
1212                throw e;
1213            }
1214            finally {
1215                messageStatus.stopTimer();
1216
1217                LayoutsRemotePublisherRequest publisherRequest =
1218                    new LayoutsRemotePublisherRequest(
1219                        themeDisplay.getUserId(), groupId, privateLayout,
1220                        layoutIdMap, parameterMap, remoteAddress, remotePort,
1221                        secureConnection, remoteGroupId, remotePrivateLayout,
1222                        startDate, endDate);
1223
1224                messageStatus.setPayload(publisherRequest);
1225
1226                MessageBusUtil.sendMessage(
1227                    DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
1228            }
1229        }
1230    }
1231
1232}