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.action;
24  
25  import com.germinus.easyconf.Filter;
26  
27  import com.liferay.portal.LayoutFriendlyURLException;
28  import com.liferay.portal.LayoutHiddenException;
29  import com.liferay.portal.LayoutNameException;
30  import com.liferay.portal.LayoutParentLayoutIdException;
31  import com.liferay.portal.LayoutSetVirtualHostException;
32  import com.liferay.portal.LayoutTypeException;
33  import com.liferay.portal.NoSuchGroupException;
34  import com.liferay.portal.NoSuchLayoutException;
35  import com.liferay.portal.PortalException;
36  import com.liferay.portal.RequiredLayoutException;
37  import com.liferay.portal.SystemException;
38  import com.liferay.portal.events.EventsProcessor;
39  import com.liferay.portal.kernel.language.LanguageUtil;
40  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
41  import com.liferay.portal.kernel.lar.UserIdStrategy;
42  import com.liferay.portal.kernel.security.permission.ActionKeys;
43  import com.liferay.portal.kernel.security.permission.PermissionChecker;
44  import com.liferay.portal.kernel.util.Constants;
45  import com.liferay.portal.kernel.util.LocaleUtil;
46  import com.liferay.portal.kernel.util.ParamUtil;
47  import com.liferay.portal.kernel.util.StringUtil;
48  import com.liferay.portal.kernel.util.Validator;
49  import com.liferay.portal.model.ColorScheme;
50  import com.liferay.portal.model.Group;
51  import com.liferay.portal.model.Layout;
52  import com.liferay.portal.model.LayoutTypePortlet;
53  import com.liferay.portal.model.PortletPreferencesIds;
54  import com.liferay.portal.model.User;
55  import com.liferay.portal.model.impl.GroupImpl;
56  import com.liferay.portal.model.impl.LayoutImpl;
57  import com.liferay.portal.security.auth.PrincipalException;
58  import com.liferay.portal.service.GroupLocalServiceUtil;
59  import com.liferay.portal.service.GroupServiceUtil;
60  import com.liferay.portal.service.LayoutLocalServiceUtil;
61  import com.liferay.portal.service.LayoutServiceUtil;
62  import com.liferay.portal.service.LayoutSetServiceUtil;
63  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
64  import com.liferay.portal.service.UserLocalServiceUtil;
65  import com.liferay.portal.service.impl.ThemeLocalUtil;
66  import com.liferay.portal.service.permission.GroupPermissionUtil;
67  import com.liferay.portal.service.permission.OrganizationPermissionUtil;
68  import com.liferay.portal.service.permission.UserPermissionUtil;
69  import com.liferay.portal.struts.PortletAction;
70  import com.liferay.portal.theme.ThemeDisplay;
71  import com.liferay.portal.util.PortalUtil;
72  import com.liferay.portal.util.PortletKeys;
73  import com.liferay.portal.util.PropsUtil;
74  import com.liferay.portal.util.PropsValues;
75  import com.liferay.portal.util.WebKeys;
76  import com.liferay.portlet.ActionResponseImpl;
77  import com.liferay.portlet.PortletPreferencesFactoryUtil;
78  import com.liferay.portlet.communities.form.PageForm;
79  import com.liferay.portlet.communities.util.CommunitiesUtil;
80  import com.liferay.util.FileUtil;
81  import com.liferay.util.servlet.SessionErrors;
82  import com.liferay.util.servlet.UploadException;
83  import com.liferay.util.servlet.UploadPortletRequest;
84  
85  import java.io.ByteArrayInputStream;
86  import java.io.File;
87  
88  import java.util.ArrayList;
89  import java.util.HashMap;
90  import java.util.Iterator;
91  import java.util.LinkedHashMap;
92  import java.util.List;
93  import java.util.Locale;
94  import java.util.Map.Entry;
95  import java.util.Map;
96  import java.util.Properties;
97  
98  import javax.portlet.ActionRequest;
99  import javax.portlet.ActionResponse;
100 import javax.portlet.PortletConfig;
101 import javax.portlet.PortletPreferences;
102 import javax.portlet.PortletRequest;
103 import javax.portlet.RenderRequest;
104 import javax.portlet.RenderResponse;
105 
106 import javax.servlet.http.HttpServletRequest;
107 import javax.servlet.http.HttpServletResponse;
108 
109 import org.apache.commons.logging.Log;
110 import org.apache.commons.logging.LogFactory;
111 import org.apache.struts.action.ActionForm;
112 import org.apache.struts.action.ActionForward;
113 import org.apache.struts.action.ActionMapping;
114 
115 /**
116  * <a href="EditPagesAction.java.html"><b><i>View Source</i></b></a>
117  *
118  * @author Brian Wing Shun Chan
119  *
120  */
121 public class EditPagesAction extends PortletAction {
122 
123     public void processAction(
124             ActionMapping mapping, ActionForm form, PortletConfig config,
125             ActionRequest req, ActionResponse res)
126         throws Exception {
127 
128         try {
129             checkPermissions(req);
130         }
131         catch (PrincipalException pe) {
132             return;
133         }
134 
135         PageForm pageForm = (PageForm)form;
136 
137         String cmd = ParamUtil.getString(req, Constants.CMD);
138 
139         try {
140             if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
141                 updateLayout(pageForm, req, res);
142             }
143             else if (cmd.equals(Constants.DELETE)) {
144                 CommunitiesUtil.deleteLayout(req, res);
145             }
146             else if (cmd.equals("copy_from_live")) {
147                 copyFromLive(req);
148             }
149             else if (cmd.equals("display_order")) {
150                 updateDisplayOrder(req);
151             }
152             else if (cmd.equals("logo")) {
153                 updateLogo(req);
154             }
155             else if (cmd.equals("look_and_feel")) {
156                 updateLookAndFeel(req);
157             }
158             else if (cmd.equals("merge_pages")) {
159                 updateMergePages(req);
160             }
161             else if (cmd.equals("monitoring")) {
162                 updateMonitoring(req);
163             }
164             else if (cmd.equals("publish_to_live")) {
165                 publishToLive(req);
166             }
167             else if (cmd.equals("update_staging_state")) {
168                 updateStagingState(req);
169             }
170             else if (cmd.equals("virtual_host")) {
171                 updateVirtualHost(req);
172             }
173 
174             String redirect = ParamUtil.getString(req, "pagesRedirect");
175 
176             sendRedirect(req, res, redirect);
177         }
178         catch (Exception e) {
179             if (e instanceof NoSuchLayoutException ||
180                 e instanceof PrincipalException) {
181 
182                 SessionErrors.add(req, e.getClass().getName());
183 
184                 setForward(req, "portlet.communities.error");
185             }
186             else if (e instanceof LayoutFriendlyURLException ||
187                      e instanceof LayoutHiddenException ||
188                      e instanceof LayoutNameException ||
189                      e instanceof LayoutParentLayoutIdException ||
190                      e instanceof LayoutSetVirtualHostException ||
191                      e instanceof LayoutTypeException ||
192                      e instanceof RequiredLayoutException ||
193                      e instanceof UploadException) {
194 
195                 if (e instanceof LayoutFriendlyURLException) {
196                     SessionErrors.add(
197                         req, LayoutFriendlyURLException.class.getName(), e);
198                 }
199                 else {
200                     SessionErrors.add(req, e.getClass().getName(), e);
201                 }
202             }
203             else {
204                 throw e;
205             }
206         }
207     }
208 
209     public ActionForward render(
210             ActionMapping mapping, ActionForm form, PortletConfig config,
211             RenderRequest req, RenderResponse res)
212         throws Exception {
213 
214         try {
215             checkPermissions(req);
216         }
217         catch (PrincipalException pe) {
218             SessionErrors.add(req, PrincipalException.class.getName());
219 
220             return mapping.findForward("portlet.communities.error");
221         }
222 
223         try {
224             ActionUtil.getGroup(req);
225         }
226         catch (Exception e) {
227             if (e instanceof NoSuchGroupException ||
228                 e instanceof PrincipalException) {
229 
230                 SessionErrors.add(req, e.getClass().getName());
231 
232                 return mapping.findForward("portlet.communities.error");
233             }
234             else {
235                 throw e;
236             }
237         }
238 
239         return mapping.findForward(
240             getForward(req, "portlet.communities.edit_pages"));
241     }
242 
243     protected void checkPermissions(PortletRequest req) throws Exception {
244 
245         // LEP-850
246 
247         ThemeDisplay themeDisplay =
248             (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
249 
250         PermissionChecker permissionChecker =
251             themeDisplay.getPermissionChecker();
252 
253         long groupId = ParamUtil.getLong(req, "groupId");
254 
255         Group group = GroupLocalServiceUtil.getGroup(groupId);
256 
257         if (group.isCommunity()) {
258             GroupPermissionUtil.check(
259                 permissionChecker, group.getGroupId(),
260                 ActionKeys.MANAGE_LAYOUTS);
261         }
262         else if (group.isOrganization()) {
263             long organizationId = group.getClassPK();
264 
265             OrganizationPermissionUtil.check(
266                 permissionChecker, organizationId, ActionKeys.MANAGE_LAYOUTS);
267         }
268         else if (group.isUser()) {
269             long groupUserId = group.getClassPK();
270 
271             User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
272 
273             long[] organizationIds = groupUser.getOrganizationIds();
274 
275             UserPermissionUtil.check(
276                 permissionChecker, groupUserId, organizationIds,
277                 ActionKeys.UPDATE);
278 
279             if (!groupUser.isLayoutsRequired()) {
280                 throw new PrincipalException();
281             }
282         }
283     }
284 
285     protected void copyFromLive(ActionRequest req) throws Exception {
286         String tabs2 = ParamUtil.getString(req, "tabs2");
287 
288         long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
289 
290         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
291 
292         boolean privateLayout = true;
293 
294         if (tabs2.equals("public")) {
295             privateLayout = false;
296         }
297 
298         if (_log.isDebugEnabled()) {
299             _log.debug(
300                 "Copying live to staging for group " +
301                     stagingGroup.getLiveGroupId());
302         }
303 
304         String scope = ParamUtil.getString(req, "scope");
305 
306         if (scope.equals("all-pages")) {
307             copyLayouts(
308                 stagingGroup.getLiveGroupId(), stagingGroup.getGroupId(),
309                 privateLayout);
310         }
311         else if (scope.equals("selected-pages")) {
312             Map layoutIdMap = new LinkedHashMap();
313 
314             long[] rowIds = ParamUtil.getLongValues(req, "rowIds");
315 
316             for (int i = 0; i < rowIds.length; i++) {
317                 long selPlid = rowIds[i];
318                 boolean includeChildren = ParamUtil.getBoolean(
319                     req, "includeChildren_" + selPlid);
320 
321                 layoutIdMap.put(
322                     new Long(selPlid), new Boolean(includeChildren));
323             }
324 
325             publishLayouts(
326                 layoutIdMap, stagingGroup.getLiveGroupId(),
327                 stagingGroup.getGroupId(), privateLayout);
328         }
329     }
330 
331     protected void copyLayouts(
332             long sourceGroupId, long targetGroupId, boolean privateLayout)
333         throws Exception {
334 
335         Map parameterMap = getStagingParameters();
336 
337         byte[] data = LayoutServiceUtil.exportLayouts(
338             sourceGroupId, privateLayout, parameterMap);
339 
340         ByteArrayInputStream bais = new ByteArrayInputStream(data);
341 
342         LayoutServiceUtil.importLayouts(
343             targetGroupId, privateLayout, parameterMap, bais);
344     }
345 
346     protected void copyPreferences(
347             ActionRequest req, Layout layout, Layout copyLayout)
348         throws Exception {
349 
350         long companyId = layout.getCompanyId();
351 
352         LayoutTypePortlet copyLayoutTypePortlet =
353             (LayoutTypePortlet)copyLayout.getLayoutType();
354 
355         List copyPortletIds = copyLayoutTypePortlet.getPortletIds();
356 
357         for (int i = 0; i < copyPortletIds.size(); i++) {
358             String copyPortletId = (String)copyPortletIds.get(i);
359 
360             HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
361 
362             // Copy preference
363 
364             PortletPreferencesIds portletPreferencesIds =
365                 PortletPreferencesFactoryUtil.getPortletPreferencesIds(
366                     httpReq, layout, copyPortletId);
367 
368             PortletPreferencesLocalServiceUtil.getPreferences(
369                 portletPreferencesIds);
370 
371             PortletPreferencesIds copyPortletPreferencesIds =
372                 PortletPreferencesFactoryUtil.getPortletPreferencesIds(
373                     httpReq, copyLayout, copyPortletId);
374 
375             PortletPreferences copyPrefs =
376                 PortletPreferencesLocalServiceUtil.getPreferences(
377                     copyPortletPreferencesIds);
378 
379             PortletPreferencesLocalServiceUtil.updatePreferences(
380                 portletPreferencesIds.getOwnerId(),
381                 portletPreferencesIds.getOwnerType(),
382                 portletPreferencesIds.getPlid(),
383                 portletPreferencesIds.getPortletId(), copyPrefs);
384 
385             // Copy portlet setup
386 
387             PortletPreferencesLocalServiceUtil.getPreferences(
388                 companyId, PortletKeys.PREFS_OWNER_ID_DEFAULT,
389                 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
390                 copyPortletId);
391 
392             copyPrefs =
393                 PortletPreferencesLocalServiceUtil.getPreferences(
394                     companyId, PortletKeys.PREFS_OWNER_ID_DEFAULT,
395                     PortletKeys.PREFS_OWNER_TYPE_LAYOUT, copyLayout.getPlid(),
396                     copyPortletId);
397 
398             PortletPreferencesLocalServiceUtil.updatePreferences(
399                 PortletKeys.PREFS_OWNER_ID_DEFAULT,
400                 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
401                 copyPortletId, copyPrefs);
402         }
403     }
404 
405     protected List getMissingParents(Layout layout, long liveGroupId)
406         throws PortalException, SystemException {
407 
408         List missingParents = new ArrayList();
409 
410         long parentLayoutId = layout.getParentLayoutId();
411 
412         while (parentLayoutId > 0) {
413             try {
414                 LayoutLocalServiceUtil.getLayout(
415                     liveGroupId, layout.isPrivateLayout(), parentLayoutId);
416 
417                 // If one parent is found all others are assumed to exist
418 
419                 break;
420             }
421             catch (NoSuchLayoutException nsle) {
422                 Layout parent = LayoutLocalServiceUtil.getLayout(
423                     layout.getGroupId(), layout.isPrivateLayout(),
424                     parentLayoutId);
425 
426                 missingParents.add(parent);
427 
428                 parentLayoutId = parent.getParentLayoutId();
429             }
430         }
431 
432         return missingParents;
433     }
434 
435     protected Map getStagingParameters() {
436         Map parameterMap = new HashMap();
437 
438         parameterMap.put(
439             PortletDataHandlerKeys.PERMISSIONS, Boolean.TRUE.toString());
440         parameterMap.put(
441             PortletDataHandlerKeys.USER_PERMISSIONS, Boolean.FALSE.toString());
442         parameterMap.put(
443             PortletDataHandlerKeys.PORTLET_DATA, Boolean.TRUE.toString());
444         parameterMap.put(
445             PortletDataHandlerKeys.PORTLET_DATA_ALL, Boolean.TRUE.toString());
446         parameterMap.put(
447             PortletDataHandlerKeys.PORTLET_SETUP, Boolean.TRUE.toString());
448         parameterMap.put(
449             PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
450             Boolean.TRUE.toString());
451         parameterMap.put(
452             PortletDataHandlerKeys.THEME, Boolean.FALSE.toString());
453         parameterMap.put(
454             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
455             Boolean.TRUE.toString());
456         parameterMap.put(
457             PortletDataHandlerKeys.DELETE_PORTLET_DATA,
458             Boolean.FALSE.toString());
459         parameterMap.put(
460             PortletDataHandlerKeys.DATA_STRATEGY,
461             PortletDataHandlerKeys.DATA_STRATEGY_MIRROR);
462         parameterMap.put(
463             PortletDataHandlerKeys.USER_ID_STRATEGY,
464             UserIdStrategy.CURRENT_USER_ID);
465 
466         return parameterMap;
467     }
468 
469     protected void publishLayout(
470             long plid, long liveGroupId, boolean includeChildren)
471         throws Exception {
472 
473         Map parameterMap = getStagingParameters();
474 
475         parameterMap.put(
476             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
477             Boolean.FALSE.toString());
478 
479         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
480 
481         List layouts = new ArrayList();
482 
483         layouts.add(layout);
484 
485         layouts.addAll(getMissingParents(layout, liveGroupId));
486 
487         if (includeChildren) {
488             layouts.addAll(layout.getAllChildren());
489         }
490 
491         Iterator itr = layouts.iterator();
492 
493         long[] layoutIds = new long[layouts.size()];
494 
495         for (int i = 0; itr.hasNext(); i++) {
496             Layout curLayout = (Layout)itr.next();
497 
498             layoutIds[i] = curLayout.getLayoutId();
499         }
500 
501         byte[] data = LayoutServiceUtil.exportLayouts(
502             layout.getGroupId(), layout.isPrivateLayout(), layoutIds,
503             parameterMap);
504 
505         ByteArrayInputStream bais = new ByteArrayInputStream(data);
506 
507         LayoutServiceUtil.importLayouts(
508             liveGroupId, layout.isPrivateLayout(), parameterMap, bais);
509     }
510 
511     protected void publishLayouts(
512             Map layoutIdMap, long stagingGroupId, long liveGroupId,
513             boolean privateLayout)
514         throws Exception {
515 
516         Map parameterMap = getStagingParameters();
517 
518         parameterMap.put(
519             PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
520             Boolean.FALSE.toString());
521 
522         List layouts = new ArrayList();
523 
524         Iterator itr1 = layoutIdMap.entrySet().iterator();
525 
526         while (itr1.hasNext()) {
527             Entry entry = (Entry)itr1.next();
528 
529             long plid = ((Long)entry.getKey()).longValue();
530             boolean includeChildren =
531                 ((Boolean)entry.getValue()).booleanValue();
532 
533             Layout layout = LayoutLocalServiceUtil.getLayout(plid);
534 
535             if (!layouts.contains(layout)) {
536                 layouts.add(layout);
537             }
538 
539             Iterator itr2 = getMissingParents(layout, liveGroupId).iterator();
540 
541             while (itr2.hasNext()) {
542                 Layout parentLayout = (Layout)itr2.next();
543 
544                 if (!layouts.contains(parentLayout)) {
545                     layouts.add(parentLayout);
546                 }
547             }
548 
549             if (includeChildren) {
550                 itr2 = layout.getAllChildren().iterator();
551 
552                 while (itr2.hasNext()) {
553                     Layout childLayout = (Layout)itr2.next();
554 
555                     if (!layouts.contains(childLayout)) {
556                         layouts.add(childLayout);
557                     }
558                 }
559             }
560         }
561 
562         itr1 = layouts.iterator();
563 
564         long[] layoutIds = new long[layouts.size()];
565 
566         for (int i = 0; itr1.hasNext(); i++) {
567             Layout curLayout = (Layout)itr1.next();
568 
569             layoutIds[i] = curLayout.getLayoutId();
570         }
571 
572         byte[] data = LayoutServiceUtil.exportLayouts(
573             stagingGroupId, privateLayout, layoutIds, parameterMap);
574 
575         ByteArrayInputStream bais = new ByteArrayInputStream(data);
576 
577         LayoutServiceUtil.importLayouts(
578             liveGroupId, privateLayout, parameterMap, bais);
579     }
580 
581     protected void publishToLive(ActionRequest req) throws Exception {
582         String tabs2 = ParamUtil.getString(req, "tabs2");
583 
584         long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
585 
586         Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
587 
588         boolean privateLayout = true;
589 
590         if (tabs2.equals("public")) {
591             privateLayout = false;
592         }
593 
594         if (_log.isDebugEnabled()) {
595             _log.debug(
596                 "Copying staging to live for group " +
597                     stagingGroup.getLiveGroupId());
598         }
599 
600         String scope = ParamUtil.getString(req, "scope");
601 
602         if (scope.equals("all-pages")) {
603             copyLayouts(
604                 stagingGroup.getGroupId(), stagingGroup.getLiveGroupId(),
605                 privateLayout);
606         }
607         else if (scope.equals("selected-pages")) {
608             Map layoutIdMap = new LinkedHashMap();
609 
610             long[] rowIds = ParamUtil.getLongValues(req, "rowIds");
611 
612             for (int i = 0; i < rowIds.length; i++) {
613                 long selPlid = rowIds[i];
614                 boolean includeChildren = ParamUtil.getBoolean(
615                     req, "includeChildren_" + selPlid);
616 
617                 layoutIdMap.put(
618                     new Long(selPlid), new Boolean(includeChildren));
619             }
620 
621             publishLayouts(
622                 layoutIdMap, stagingGroup.getGroupId(),
623                 stagingGroup.getLiveGroupId(), privateLayout);
624         }
625     }
626 
627     protected void updateDisplayOrder(ActionRequest req) throws Exception {
628         long groupId = ParamUtil.getLong(req, "groupId");
629         boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
630         long parentLayoutId = ParamUtil.getLong(req, "parentLayoutId");
631         long[] layoutIds = StringUtil.split(
632             ParamUtil.getString(req, "layoutIds"), 0L);
633 
634         LayoutServiceUtil.setLayouts(
635             groupId, privateLayout, parentLayoutId, layoutIds);
636     }
637 
638     protected void updateLayout(
639             PageForm pageForm, ActionRequest req, ActionResponse res)
640         throws Exception {
641 
642         UploadPortletRequest uploadReq =
643             PortalUtil.getUploadPortletRequest(req);
644 
645         String cmd = ParamUtil.getString(uploadReq, Constants.CMD);
646 
647         long groupId = ParamUtil.getLong(req, "groupId");
648         boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
649         long layoutId = ParamUtil.getLong(req, "layoutId");
650         long parentLayoutId = ParamUtil.getLong(uploadReq, "parentLayoutId");
651         String description = ParamUtil.getString(uploadReq, "description");
652         String type = ParamUtil.getString(uploadReq, "type");
653         boolean hidden = ParamUtil.getBoolean(uploadReq, "hidden");
654         String friendlyURL = ParamUtil.getString(uploadReq, "friendlyURL");
655         boolean iconImage = ParamUtil.getBoolean(uploadReq, "iconImage");
656         byte[] iconBytes = FileUtil.getBytes(
657             uploadReq.getFile("iconFileName"));
658 
659         boolean inheritFromParentLayoutId = ParamUtil.getBoolean(
660             uploadReq, "inheritFromParentLayoutId");
661 
662         long copyLayoutId = ParamUtil.getLong(uploadReq, "copyLayoutId");
663 
664         Locale[] locales = LanguageUtil.getAvailableLocales();
665 
666         Map localeNamesMap = new HashMap();
667         Map localeTitlesMap = new HashMap();
668 
669         for (int i = 0; i < locales.length; i++) {
670             String languageId = LocaleUtil.toLanguageId(locales[i]);
671 
672             localeNamesMap.put(
673                 locales[i],
674                 ParamUtil.getString(uploadReq, "name_" + languageId));
675             localeTitlesMap.put(
676                 locales[i],
677                 ParamUtil.getString(uploadReq, "title_" + languageId));
678         }
679 
680         if (cmd.equals(Constants.ADD)) {
681 
682             // Add layout
683 
684             if (inheritFromParentLayoutId && (parentLayoutId > 0)) {
685                 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
686                     groupId, privateLayout, parentLayoutId);
687 
688                 Layout layout = LayoutServiceUtil.addLayout(
689                     groupId, privateLayout, parentLayoutId, localeNamesMap,
690                     localeTitlesMap, description, parentLayout.getType(),
691                     parentLayout.isHidden(), friendlyURL);
692 
693                 LayoutServiceUtil.updateLayout(
694                     layout.getGroupId(), layout.isPrivateLayout(),
695                     layout.getLayoutId(), parentLayout.getTypeSettings());
696             }
697             else {
698                 Layout layout = LayoutServiceUtil.addLayout(
699                     groupId, privateLayout, parentLayoutId, localeNamesMap,
700                     localeTitlesMap, description, type, hidden, friendlyURL);
701 
702                 if (type.equals(LayoutImpl.TYPE_PORTLET)) {
703                     LayoutTypePortlet layoutTypePortlet =
704                         (LayoutTypePortlet)layout.getLayoutType();
705 
706                     if (Validator.isNull(
707                             layoutTypePortlet.getLayoutTemplateId())) {
708 
709                         layoutTypePortlet.setLayoutTemplateId(
710                             0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
711 
712                         LayoutServiceUtil.updateLayout(
713                             layout.getGroupId(), layout.isPrivateLayout(),
714                             layout.getLayoutId(), layout.getTypeSettings());
715                     }
716                 }
717             }
718         }
719         else {
720 
721             // Update layout
722 
723             Layout layout = LayoutLocalServiceUtil.getLayout(
724                 groupId, privateLayout, layoutId);
725 
726             layout = LayoutServiceUtil.updateLayout(
727                 groupId, privateLayout, layoutId, layout.getParentLayoutId(),
728                 localeNamesMap, localeTitlesMap, description, type, hidden,
729                 friendlyURL, Boolean.valueOf(iconImage), iconBytes);
730 
731             if (type.equals(LayoutImpl.TYPE_PORTLET)) {
732                 if ((copyLayoutId > 0) &&
733                     (copyLayoutId != layout.getLayoutId())) {
734 
735                     try {
736                         Layout copyLayout = LayoutLocalServiceUtil.getLayout(
737                             groupId, privateLayout, copyLayoutId);
738 
739                         if (copyLayout.getType().equals(
740                                 LayoutImpl.TYPE_PORTLET)) {
741 
742                             LayoutServiceUtil.updateLayout(
743                                 groupId, privateLayout, layoutId,
744                                 copyLayout.getTypeSettings());
745 
746                             copyPreferences(req, layout, copyLayout);
747                         }
748                     }
749                     catch (NoSuchLayoutException nsle) {
750                     }
751                 }
752                 else {
753                     Properties formProperties =
754                         pageForm.getTypeSettingsProperties();
755 
756                     Properties layoutProperties =
757                         layout.getTypeSettingsProperties();
758 
759                     layoutProperties.setProperty(
760                         "meta-robots",
761                         formProperties.getProperty("meta-robots"));
762                     layoutProperties.setProperty(
763                         "meta-description",
764                         formProperties.getProperty("meta-description"));
765                     layoutProperties.setProperty(
766                         "meta-keywords",
767                         formProperties.getProperty("meta-keywords"));
768 
769                     layoutProperties.setProperty(
770                         "javascript-1",
771                         formProperties.getProperty("javascript-1"));
772                     layoutProperties.setProperty(
773                         "javascript-2",
774                         formProperties.getProperty("javascript-2"));
775                     layoutProperties.setProperty(
776                         "javascript-3",
777                         formProperties.getProperty("javascript-3"));
778                     layoutProperties.setProperty(
779                         "sitemap-include",
780                         formProperties.getProperty("sitemap-include"));
781                     layoutProperties.setProperty(
782                         "sitemap-priority",
783                         formProperties.getProperty("sitemap-priority"));
784                     layoutProperties.setProperty(
785                         "sitemap-changefreq",
786                         formProperties.getProperty("sitemap-changefreq"));
787 
788                     LayoutServiceUtil.updateLayout(
789                         groupId, privateLayout, layoutId,
790                         layout.getTypeSettings());
791                 }
792             }
793             else {
794                 layout.setTypeSettingsProperties(
795                     pageForm.getTypeSettingsProperties());
796 
797                 LayoutServiceUtil.updateLayout(
798                     groupId, privateLayout, layoutId, layout.getTypeSettings());
799             }
800 
801             HttpServletResponse httpRes = (HttpServletResponse)
802                 ((ActionResponseImpl)res).getHttpServletResponse();
803 
804             String[] eventClasses = StringUtil.split(
805                 PropsUtil.getComponentProperties().getString(
806                     PropsUtil.LAYOUT_CONFIGURATION_ACTION_UPDATE,
807                     Filter.by(type)));
808 
809             EventsProcessor.process(eventClasses, uploadReq, httpRes);
810         }
811     }
812 
813     protected void updateLogo(ActionRequest req) throws Exception {
814         UploadPortletRequest uploadReq =
815             PortalUtil.getUploadPortletRequest(req);
816 
817         long groupId = ParamUtil.getLong(req, "groupId");
818         boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
819         boolean logo = ParamUtil.getBoolean(req, "logo");
820 
821         File file = uploadReq.getFile("logoFileName");
822         byte[] bytes = FileUtil.getBytes(file);
823 
824         if (logo && ((bytes == null) || (bytes.length == 0))) {
825             throw new UploadException();
826         }
827 
828         LayoutSetServiceUtil.updateLogo(groupId, privateLayout, logo, file);
829     }
830 
831     protected void updateLookAndFeel(ActionRequest req) throws Exception {
832         long companyId = PortalUtil.getCompanyId(req);
833 
834         long groupId = ParamUtil.getLong(req, "groupId");
835         boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
836         long layoutId = ParamUtil.getLong(req, "layoutId");
837         String themeId = ParamUtil.getString(req, "themeId");
838         String colorSchemeId = ParamUtil.getString(req, "colorSchemeId");
839         String css = ParamUtil.getString(req, "css");
840         boolean wapTheme = ParamUtil.getBoolean(req, "wapTheme");
841 
842         if (Validator.isNotNull(themeId) && Validator.isNull(colorSchemeId)) {
843             ColorScheme colorScheme = ThemeLocalUtil.getColorScheme(
844                 companyId, themeId, colorSchemeId, wapTheme);
845 
846             colorSchemeId = colorScheme.getColorSchemeId();
847         }
848 
849         if (layoutId <= 0) {
850 
851             // Update layout set
852 
853             LayoutSetServiceUtil.updateLookAndFeel(
854                 groupId, privateLayout, themeId, colorSchemeId, css, wapTheme);
855         }
856         else {
857 
858             // Update layout
859 
860             LayoutServiceUtil.updateLookAndFeel(
861                 groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
862                 wapTheme);
863         }
864     }
865 
866     protected void updateMergePages(ActionRequest req) throws Exception {
867         long groupId = ParamUtil.getLong(req, "groupId");
868 
869         Group group = GroupLocalServiceUtil.getGroup(groupId);
870 
871         boolean mergeGuestPublicPages = ParamUtil.getBoolean(
872             req, "mergeGuestPublicPages");
873 
874         Properties props = group.getTypeSettingsProperties();
875 
876         props.setProperty(
877             "mergeGuestPublicPages", String.valueOf(mergeGuestPublicPages));
878 
879         GroupServiceUtil.updateGroup(groupId, group.getTypeSettings());
880     }
881 
882     protected void updateMonitoring(ActionRequest req) throws Exception {
883         long groupId = ParamUtil.getLong(req, "groupId");
884 
885         Group group = GroupLocalServiceUtil.getGroup(groupId);
886 
887         String googleAnalyticsId = ParamUtil.getString(
888             req, "googleAnalyticsId");
889 
890         Properties props = group.getTypeSettingsProperties();
891 
892         props.setProperty("googleAnalyticsId", googleAnalyticsId);
893 
894         GroupServiceUtil.updateGroup(groupId, group.getTypeSettings());
895     }
896 
897     protected void updateStagingState(ActionRequest req) throws Exception {
898         long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
899         long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
900         boolean activateStaging = ParamUtil.getBoolean(req, "activateStaging");
901 
902         if ((stagingGroupId > 0) && !activateStaging) {
903             GroupServiceUtil.deleteGroup(stagingGroupId);
904         }
905         else if ((stagingGroupId == 0) && activateStaging) {
906             Group group = GroupServiceUtil.getGroup(liveGroupId);
907 
908             Group stagingGroup = GroupServiceUtil.addGroup(
909                 group.getGroupId(), group.getName() + " (Staging)",
910                 group.getDescription(), GroupImpl.TYPE_COMMUNITY_PRIVATE, null,
911                 group.isActive());
912 
913             if (group.hasPrivateLayouts()) {
914                 copyLayouts(
915                     group.getGroupId(), stagingGroup.getGroupId(), true);
916             }
917 
918             if (group.hasPublicLayouts()) {
919                 copyLayouts(
920                     group.getGroupId(), stagingGroup.getGroupId(), false);
921             }
922         }
923     }
924 
925     protected void updateVirtualHost(ActionRequest req) throws Exception {
926 
927         // Public virtual host
928 
929         long groupId = ParamUtil.getLong(req, "groupId");
930 
931         String publicVirtualHost = ParamUtil.getString(
932             req, "publicVirtualHost");
933 
934         LayoutSetServiceUtil.updateVirtualHost(
935             groupId, false, publicVirtualHost);
936 
937         // Private virtual host
938 
939         String privateVirtualHost = ParamUtil.getString(
940             req, "privateVirtualHost");
941 
942         LayoutSetServiceUtil.updateVirtualHost(
943             groupId, true, privateVirtualHost);
944 
945         // Friendly URL
946 
947         String friendlyURL = ParamUtil.getString(req, "friendlyURL");
948 
949         Group group = GroupLocalServiceUtil.getGroup(groupId);
950 
951         GroupServiceUtil.updateGroup(
952             groupId, group.getName(), group.getDescription(), group.getType(),
953             friendlyURL, group.isActive());
954     }
955 
956     private static Log _log = LogFactory.getLog(EditPagesAction.class);
957 
958 }