1   /**
2    * Copyright (c) 2000-2008 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.NoSuchLayoutException;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
29  import com.liferay.portal.kernel.lar.UserIdStrategy;
30  import com.liferay.portal.kernel.util.ParamUtil;
31  import com.liferay.portal.model.Group;
32  import com.liferay.portal.model.Layout;
33  import com.liferay.portal.model.Portlet;
34  import com.liferay.portal.model.impl.GroupImpl;
35  import com.liferay.portal.security.auth.PrincipalException;
36  import com.liferay.portal.security.permission.ActionKeys;
37  import com.liferay.portal.security.permission.PermissionChecker;
38  import com.liferay.portal.service.GroupLocalServiceUtil;
39  import com.liferay.portal.service.GroupServiceUtil;
40  import com.liferay.portal.service.LayoutLocalServiceUtil;
41  import com.liferay.portal.service.LayoutServiceUtil;
42  import com.liferay.portal.service.permission.GroupPermissionUtil;
43  import com.liferay.portal.theme.ThemeDisplay;
44  import com.liferay.portal.util.WebKeys;
45  
46  import java.io.ByteArrayInputStream;
47  
48  import java.util.ArrayList;
49  import java.util.Iterator;
50  import java.util.LinkedHashMap;
51  import java.util.List;
52  import java.util.Map.Entry;
53  import java.util.Map;
54  
55  import javax.portlet.ActionRequest;
56  
57  import org.apache.commons.logging.Log;
58  import org.apache.commons.logging.LogFactory;
59  
60  /**
61   * <a href="StagingUtil.java.html"><b><i>View Source</i></b></a>
62   *
63   * @author Raymond Augé
64   *
65   */
66  public class StagingUtil {
67  
68      public static void copyFromLive(ActionRequest req) throws Exception {
69          String tabs1 = ParamUtil.getString(req, "tabs1");
70  
71          long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
72  
73          Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
74  
75          boolean privateLayout = true;
76  
77          if (tabs1.equals("public-pages")) {
78              privateLayout = false;
79          }
80  
81          if (_log.isDebugEnabled()) {
82              _log.debug(
83                  "Copying live to staging for group " +
84                      stagingGroup.getLiveGroupId());
85          }
86  
87          Map<String, String[]> parameterMap = getStagingParameters();
88  
89          String scope = ParamUtil.getString(req, "scope");
90  
91          if (scope.equals("all-pages")) {
92              copyLayouts(
93                  stagingGroup.getLiveGroupId(), stagingGroup.getGroupId(),
94                  privateLayout, parameterMap);
95          }
96          else if (scope.equals("selected-pages")) {
97              Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
98  
99              long[] rowIds = ParamUtil.getLongValues(req, "rowIds");
100 
101             for (int i = 0; i < rowIds.length; i++) {
102                 long selPlid = rowIds[i];
103                 boolean includeChildren = ParamUtil.getBoolean(
104                     req, "includeChildren_" + selPlid);
105 
106                 layoutIdMap.put(
107                     new Long(selPlid), new Boolean(includeChildren));
108             }
109 
110             publishLayouts(
111                 layoutIdMap, stagingGroup.getLiveGroupId(),
112                 stagingGroup.getGroupId(), privateLayout, parameterMap);
113         }
114     }
115 
116     public static void copyFromLive(ActionRequest req, Portlet portlet)
117         throws Exception {
118 
119         long plid = ParamUtil.getLong(req, "plid");
120 
121         Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
122 
123         Group stagingGroup = targetLayout.getGroup();
124         Group liveGroup = stagingGroup.getLiveGroup();
125 
126         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(
127             liveGroup.getGroupId(), targetLayout.isPrivateLayout(),
128             targetLayout.getLayoutId());
129 
130         copyPortlet(
131             req, sourceLayout.getPlid(), targetLayout.getPlid(),
132             portlet.getPortletId());
133     }
134 
135     public static void copyLayouts(
136             long sourceGroupId, long targetGroupId, boolean privateLayout,
137             Map<String, String[]> parameterMap)
138         throws Exception {
139 
140         byte[] data = LayoutServiceUtil.exportLayouts(
141             sourceGroupId, privateLayout, parameterMap);
142 
143         ByteArrayInputStream bais = new ByteArrayInputStream(data);
144 
145         LayoutServiceUtil.importLayouts(
146             targetGroupId, privateLayout, parameterMap, bais);
147     }
148 
149     public static void copyPortlet(
150             ActionRequest req, long sourcePlid, long targetPlid,
151             String portletId)
152         throws Exception {
153 
154         Map<String, String[]> parameterMap = getStagingParameters(req);
155 
156         byte[] data = LayoutLocalServiceUtil.exportPortletInfo(
157             sourcePlid, portletId, parameterMap);
158 
159         ByteArrayInputStream bais = new ByteArrayInputStream(data);
160 
161         LayoutServiceUtil.importPortletInfo(
162             targetPlid, portletId, parameterMap, bais);
163     }
164 
165     public static List<Layout> getMissingParents(
166             Layout layout, long liveGroupId)
167         throws PortalException, SystemException {
168 
169         List<Layout> missingParents = new ArrayList<Layout>();
170 
171         long parentLayoutId = layout.getParentLayoutId();
172 
173         while (parentLayoutId > 0) {
174             try {
175                 LayoutLocalServiceUtil.getLayout(
176                     liveGroupId, layout.isPrivateLayout(), parentLayoutId);
177 
178                 // If one parent is found all others are assumed to exist
179 
180                 break;
181             }
182             catch (NoSuchLayoutException nsle) {
183                 Layout parent = LayoutLocalServiceUtil.getLayout(
184                     layout.getGroupId(), layout.isPrivateLayout(),
185                     parentLayoutId);
186 
187                 missingParents.add(parent);
188 
189                 parentLayoutId = parent.getParentLayoutId();
190             }
191         }
192 
193         return missingParents;
194     }
195 
196     public static Map<String, String[]> getStagingParameters(
197         ActionRequest req) {
198 
199         Map<String, String[]> parameterMap =
200             new LinkedHashMap<String, String[]>(req.getParameterMap());
201 
202         if (!parameterMap.containsKey(
203                 PortletDataHandlerKeys.PORTLET_DATA)) {
204 
205             parameterMap.put(
206                 PortletDataHandlerKeys.PORTLET_DATA,
207                 new String[] {Boolean.FALSE.toString()});
208         }
209 
210         if (!parameterMap.containsKey(
211                 PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
212 
213             parameterMap.put(
214                 PortletDataHandlerKeys.PORTLET_DATA_ALL,
215                 new String[] {Boolean.FALSE.toString()});
216         }
217 
218         if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_SETUP)) {
219             parameterMap.put(
220                 PortletDataHandlerKeys.PORTLET_SETUP,
221                 new String[] {Boolean.TRUE.toString()});
222         }
223 
224         if (!parameterMap.containsKey(
225                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES)) {
226 
227             parameterMap.put(
228                 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
229                 new String[] {Boolean.TRUE.toString()});
230         }
231 
232         if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME)) {
233             parameterMap.put(
234                 PortletDataHandlerKeys.THEME,
235                 new String[] {Boolean.FALSE.toString()});
236         }
237 
238         if (!parameterMap.containsKey(
239                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS)) {
240 
241             parameterMap.put(
242                 PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
243                 new String[] {Boolean.TRUE.toString()});
244         }
245 
246         if (!parameterMap.containsKey(
247                 PortletDataHandlerKeys.DELETE_PORTLET_DATA)) {
248 
249             parameterMap.put(
250                 PortletDataHandlerKeys.DELETE_PORTLET_DATA,
251                 new String[] {Boolean.FALSE.toString()});
252         }
253 
254         if (!parameterMap.containsKey(PortletDataHandlerKeys.DATA_STRATEGY)) {
255             parameterMap.put(
256                 PortletDataHandlerKeys.DATA_STRATEGY,
257                 new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
258         }
259 
260         if (!parameterMap.containsKey(
261                 PortletDataHandlerKeys.USER_ID_STRATEGY)) {
262 
263             parameterMap.put(
264                 PortletDataHandlerKeys.USER_ID_STRATEGY,
265                 new String[] {UserIdStrategy.CURRENT_USER_ID});
266         }
267 
268         return parameterMap;
269     }
270 
271     public static Map<String, String[]> getStagingParameters() {
272         Map<String, String[]> parameterMap =
273             new LinkedHashMap<String, String[]>();
274 
275         parameterMap.put(
276             PortletDataHandlerKeys.PERMISSIONS,
277             new String[] {Boolean.TRUE.toString()});
278         parameterMap.put(
279             PortletDataHandlerKeys.USER_PERMISSIONS,
280             new String[] {Boolean.FALSE.toString()});
281         parameterMap.put(
282             PortletDataHandlerKeys.PORTLET_DATA,
283             new String[] {Boolean.TRUE.toString()});
284         parameterMap.put(
285             PortletDataHandlerKeys.PORTLET_DATA_ALL,
286             new String[] {Boolean.TRUE.toString()});
287         parameterMap.put(
288             PortletDataHandlerKeys.PORTLET_SETUP,
289             new String[] {Boolean.TRUE.toString()});
290         parameterMap.put(
291             PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
292             new String[] {Boolean.TRUE.toString()});
293         parameterMap.put(
294             PortletDataHandlerKeys.THEME,
295             new String[] {Boolean.FALSE.toString()});
296         parameterMap.put(
297             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
298             new String[] {Boolean.TRUE.toString()});
299         parameterMap.put(
300             PortletDataHandlerKeys.DELETE_PORTLET_DATA,
301             new String[] {Boolean.FALSE.toString()});
302         parameterMap.put(
303             PortletDataHandlerKeys.DATA_STRATEGY,
304             new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
305         parameterMap.put(
306             PortletDataHandlerKeys.USER_ID_STRATEGY,
307             new String[] {UserIdStrategy.CURRENT_USER_ID});
308 
309         return parameterMap;
310     }
311 
312     public static void publishLayout(
313             long plid, long liveGroupId, boolean includeChildren)
314         throws Exception {
315 
316         Map<String, String[]> parameterMap = getStagingParameters();
317 
318         parameterMap.put(
319             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
320             new String[] {Boolean.FALSE.toString()});
321 
322         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
323 
324         List<Layout> layouts = new ArrayList<Layout>();
325 
326         layouts.add(layout);
327 
328         layouts.addAll(getMissingParents(layout, liveGroupId));
329 
330         if (includeChildren) {
331             layouts.addAll(layout.getAllChildren());
332         }
333 
334         Iterator<Layout> itr = layouts.iterator();
335 
336         long[] layoutIds = new long[layouts.size()];
337 
338         for (int i = 0; itr.hasNext(); i++) {
339             Layout curLayout = itr.next();
340 
341             layoutIds[i] = curLayout.getLayoutId();
342         }
343 
344         byte[] data = LayoutServiceUtil.exportLayouts(
345             layout.getGroupId(), layout.isPrivateLayout(), layoutIds,
346             parameterMap);
347 
348         ByteArrayInputStream bais = new ByteArrayInputStream(data);
349 
350         LayoutServiceUtil.importLayouts(
351             liveGroupId, layout.isPrivateLayout(), parameterMap, bais);
352     }
353 
354     public static void publishLayouts(
355             Map<Long, Boolean> layoutIdMap, long stagingGroupId,
356             long liveGroupId, boolean privateLayout,
357             Map<String, String[]> parameterMap)
358         throws Exception {
359 
360         parameterMap.put(
361             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
362             new String[] {Boolean.FALSE.toString()});
363 
364         List<Layout> layouts = new ArrayList<Layout>();
365 
366         Iterator<Map.Entry<Long, Boolean>> itr1 =
367             layoutIdMap.entrySet().iterator();
368 
369         while (itr1.hasNext()) {
370             Entry<Long, Boolean> entry = itr1.next();
371 
372             long plid = entry.getKey();
373             boolean includeChildren = entry.getValue();
374 
375             Layout layout = LayoutLocalServiceUtil.getLayout(plid);
376 
377             if (!layouts.contains(layout)) {
378                 layouts.add(layout);
379             }
380 
381             Iterator<Layout> itr2 = getMissingParents(
382                 layout, liveGroupId).iterator();
383 
384             while (itr2.hasNext()) {
385                 Layout parentLayout = itr2.next();
386 
387                 if (!layouts.contains(parentLayout)) {
388                     layouts.add(parentLayout);
389                 }
390             }
391 
392             if (includeChildren) {
393                 itr2 = layout.getAllChildren().iterator();
394 
395                 while (itr2.hasNext()) {
396                     Layout childLayout = itr2.next();
397 
398                     if (!layouts.contains(childLayout)) {
399                         layouts.add(childLayout);
400                     }
401                 }
402             }
403         }
404 
405         long[] layoutIds = new long[layouts.size()];
406 
407         for (int i = 0; i < layouts.size(); i++) {
408             Layout curLayout = layouts.get(i);
409 
410             layoutIds[i] = curLayout.getLayoutId();
411         }
412 
413         byte[] data = LayoutServiceUtil.exportLayouts(
414             stagingGroupId, privateLayout, layoutIds, parameterMap);
415 
416         ByteArrayInputStream bais = new ByteArrayInputStream(data);
417 
418         LayoutServiceUtil.importLayouts(
419             liveGroupId, privateLayout, parameterMap, bais);
420     }
421 
422     public static void publishToLive(ActionRequest req) throws Exception {
423         String tabs1 = ParamUtil.getString(req, "tabs1");
424 
425         long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
426 
427         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
428 
429         boolean privateLayout = true;
430 
431         if (tabs1.equals("public-pages")) {
432             privateLayout = false;
433         }
434 
435         if (_log.isDebugEnabled()) {
436             _log.debug(
437                 "Copying staging to live for group " +
438                     stagingGroup.getLiveGroupId());
439         }
440 
441         String scope = ParamUtil.getString(req, "scope");
442 
443         Map<String, String[]> parameterMap = getStagingParameters(req);
444 
445         if (scope.equals("all-pages")) {
446             copyLayouts(
447                 stagingGroup.getGroupId(), stagingGroup.getLiveGroupId(),
448                 privateLayout, parameterMap);
449         }
450         else if (scope.equals("selected-pages")) {
451             Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
452 
453             long[] rowIds = ParamUtil.getLongValues(req, "rowIds");
454 
455             for (int i = 0; i < rowIds.length; i++) {
456                 long selPlid = rowIds[i];
457                 boolean includeChildren = ParamUtil.getBoolean(
458                     req, "includeChildren_" + selPlid);
459 
460                 layoutIdMap.put(selPlid, includeChildren);
461             }
462 
463             publishLayouts(
464                 layoutIdMap, stagingGroup.getGroupId(),
465                 stagingGroup.getLiveGroupId(), privateLayout, parameterMap);
466         }
467     }
468 
469     public static void publishToLive(ActionRequest req, Portlet portlet)
470         throws Exception {
471 
472         long plid = ParamUtil.getLong(req, "plid");
473 
474         Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
475 
476         Group stagingGroup = sourceLayout.getGroup();
477         Group liveGroup = stagingGroup.getLiveGroup();
478 
479         Layout targetLayout = LayoutLocalServiceUtil.getLayout(
480             liveGroup.getGroupId(), sourceLayout.isPrivateLayout(),
481             sourceLayout.getLayoutId());
482 
483         copyPortlet(
484             req, sourceLayout.getPlid(), targetLayout.getPlid(),
485             portlet.getPortletId());
486     }
487 
488     public static void updateStaging(ActionRequest req) throws Exception {
489         ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
490             WebKeys.THEME_DISPLAY);
491 
492         PermissionChecker permissionChecker =
493             themeDisplay.getPermissionChecker();
494 
495         long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
496 
497         if (!GroupPermissionUtil.contains(
498                 permissionChecker, liveGroupId, ActionKeys.MANAGE_STAGING)) {
499 
500             throw new PrincipalException();
501         }
502 
503         long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
504 
505         boolean stagingEnabled = ParamUtil.getBoolean(req, "stagingEnabled");
506 
507         if ((stagingGroupId > 0) && !stagingEnabled) {
508             GroupServiceUtil.deleteGroup(stagingGroupId);
509 
510             GroupServiceUtil.updateWorkflow(liveGroupId, false, 0, null);
511         }
512         else if ((stagingGroupId == 0) && stagingEnabled) {
513             Group liveGroup = GroupServiceUtil.getGroup(liveGroupId);
514 
515             Group stagingGroup = GroupServiceUtil.addGroup(
516                 liveGroup.getGroupId(), liveGroup.getName() + " (Staging)",
517                 liveGroup.getDescription(), GroupImpl.TYPE_COMMUNITY_PRIVATE,
518                 null, liveGroup.isActive());
519 
520             if (liveGroup.hasPrivateLayouts()) {
521                 Map<String, String[]> parameterMap = getStagingParameters();
522 
523                 copyLayouts(
524                     liveGroup.getGroupId(), stagingGroup.getGroupId(), true,
525                     parameterMap);
526             }
527 
528             if (liveGroup.hasPublicLayouts()) {
529                 Map<String, String[]> parameterMap = getStagingParameters();
530 
531                 copyLayouts(
532                     liveGroup.getGroupId(), stagingGroup.getGroupId(), false,
533                     parameterMap);
534             }
535         }
536     }
537 
538     private static Log _log = LogFactory.getLog(StagingUtil.class);
539 
540 }