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