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