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