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