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