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