001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.layoutsadmin.action;
016    
017    import com.liferay.portal.ImageTypeException;
018    import com.liferay.portal.LayoutFriendlyURLException;
019    import com.liferay.portal.LayoutFriendlyURLsException;
020    import com.liferay.portal.LayoutNameException;
021    import com.liferay.portal.LayoutParentLayoutIdException;
022    import com.liferay.portal.LayoutSetVirtualHostException;
023    import com.liferay.portal.LayoutTypeException;
024    import com.liferay.portal.NoSuchGroupException;
025    import com.liferay.portal.NoSuchLayoutException;
026    import com.liferay.portal.RequiredLayoutException;
027    import com.liferay.portal.SitemapChangeFrequencyException;
028    import com.liferay.portal.SitemapIncludeException;
029    import com.liferay.portal.SitemapPagePriorityException;
030    import com.liferay.portal.events.EventsProcessorUtil;
031    import com.liferay.portal.kernel.exception.PortalException;
032    import com.liferay.portal.kernel.exception.SystemException;
033    import com.liferay.portal.kernel.log.Log;
034    import com.liferay.portal.kernel.log.LogFactoryUtil;
035    import com.liferay.portal.kernel.repository.model.FileEntry;
036    import com.liferay.portal.kernel.servlet.MultiSessionMessages;
037    import com.liferay.portal.kernel.servlet.SessionErrors;
038    import com.liferay.portal.kernel.servlet.SessionMessages;
039    import com.liferay.portal.kernel.staging.StagingUtil;
040    import com.liferay.portal.kernel.upload.UploadException;
041    import com.liferay.portal.kernel.upload.UploadPortletRequest;
042    import com.liferay.portal.kernel.util.Constants;
043    import com.liferay.portal.kernel.util.FileUtil;
044    import com.liferay.portal.kernel.util.HttpUtil;
045    import com.liferay.portal.kernel.util.LocalizationUtil;
046    import com.liferay.portal.kernel.util.ParamUtil;
047    import com.liferay.portal.kernel.util.PropertiesParamUtil;
048    import com.liferay.portal.kernel.util.PropsKeys;
049    import com.liferay.portal.kernel.util.StringPool;
050    import com.liferay.portal.kernel.util.StringUtil;
051    import com.liferay.portal.kernel.util.ThemeFactoryUtil;
052    import com.liferay.portal.kernel.util.UnicodeProperties;
053    import com.liferay.portal.kernel.util.Validator;
054    import com.liferay.portal.kernel.workflow.WorkflowConstants;
055    import com.liferay.portal.model.ColorScheme;
056    import com.liferay.portal.model.Group;
057    import com.liferay.portal.model.Layout;
058    import com.liferay.portal.model.LayoutConstants;
059    import com.liferay.portal.model.LayoutPrototype;
060    import com.liferay.portal.model.LayoutRevision;
061    import com.liferay.portal.model.LayoutSet;
062    import com.liferay.portal.model.LayoutSetBranch;
063    import com.liferay.portal.model.LayoutTypePortlet;
064    import com.liferay.portal.model.Theme;
065    import com.liferay.portal.model.ThemeSetting;
066    import com.liferay.portal.model.User;
067    import com.liferay.portal.model.impl.ThemeSettingImpl;
068    import com.liferay.portal.security.auth.PrincipalException;
069    import com.liferay.portal.security.permission.ActionKeys;
070    import com.liferay.portal.security.permission.PermissionChecker;
071    import com.liferay.portal.service.LayoutLocalServiceUtil;
072    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
073    import com.liferay.portal.service.LayoutPrototypeServiceUtil;
074    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
075    import com.liferay.portal.service.LayoutServiceUtil;
076    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
077    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
078    import com.liferay.portal.service.PortletLocalServiceUtil;
079    import com.liferay.portal.service.ServiceContext;
080    import com.liferay.portal.service.ServiceContextFactory;
081    import com.liferay.portal.service.ThemeLocalServiceUtil;
082    import com.liferay.portal.service.UserLocalServiceUtil;
083    import com.liferay.portal.service.permission.GroupPermissionUtil;
084    import com.liferay.portal.service.permission.LayoutPermissionUtil;
085    import com.liferay.portal.service.permission.LayoutPrototypePermissionUtil;
086    import com.liferay.portal.service.permission.LayoutSetPrototypePermissionUtil;
087    import com.liferay.portal.service.permission.UserPermissionUtil;
088    import com.liferay.portal.struts.PortletAction;
089    import com.liferay.portal.theme.ThemeDisplay;
090    import com.liferay.portal.util.PortalUtil;
091    import com.liferay.portal.util.PropsValues;
092    import com.liferay.portal.util.WebKeys;
093    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
094    import com.liferay.portlet.mobiledevicerules.model.MDRAction;
095    import com.liferay.portlet.mobiledevicerules.model.MDRRuleGroupInstance;
096    import com.liferay.portlet.mobiledevicerules.service.MDRActionLocalServiceUtil;
097    import com.liferay.portlet.mobiledevicerules.service.MDRActionServiceUtil;
098    import com.liferay.portlet.mobiledevicerules.service.MDRRuleGroupInstanceLocalServiceUtil;
099    import com.liferay.portlet.mobiledevicerules.service.MDRRuleGroupInstanceServiceUtil;
100    import com.liferay.portlet.sites.action.ActionUtil;
101    import com.liferay.portlet.sites.util.SitesUtil;
102    
103    import java.io.IOException;
104    import java.io.InputStream;
105    
106    import java.util.Iterator;
107    import java.util.List;
108    import java.util.Locale;
109    import java.util.Map;
110    import java.util.Set;
111    
112    import javax.portlet.ActionRequest;
113    import javax.portlet.ActionResponse;
114    import javax.portlet.PortletConfig;
115    import javax.portlet.PortletRequest;
116    import javax.portlet.RenderRequest;
117    import javax.portlet.RenderResponse;
118    
119    import javax.servlet.http.HttpServletRequest;
120    import javax.servlet.http.HttpServletResponse;
121    
122    import org.apache.struts.action.ActionForm;
123    import org.apache.struts.action.ActionForward;
124    import org.apache.struts.action.ActionMapping;
125    
126    /**
127     * @author Brian Wing Shun Chan
128     * @author Julio Camarero
129     */
130    public class EditLayoutsAction extends PortletAction {
131    
132            @Override
133            public void processAction(
134                            ActionMapping actionMapping, ActionForm actionForm,
135                            PortletConfig portletConfig, ActionRequest actionRequest,
136                            ActionResponse actionResponse)
137                    throws Exception {
138    
139                    try {
140                            checkPermissions(actionRequest);
141                    }
142                    catch (PrincipalException pe) {
143                            return;
144                    }
145    
146                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
147                            WebKeys.THEME_DISPLAY);
148    
149                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
150    
151                    String redirect = ParamUtil.getString(actionRequest, "redirect");
152                    String closeRedirect = ParamUtil.getString(
153                            actionRequest, "closeRedirect");
154    
155                    try {
156                            Layout layout = null;
157                            String oldFriendlyURL = StringPool.BLANK;
158    
159                            if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
160                                    Object[] returnValue = updateLayout(
161                                            actionRequest, actionResponse);
162    
163                                    layout = (Layout)returnValue[0];
164                                    oldFriendlyURL = (String)returnValue[1];
165    
166                                    if (cmd.equals(Constants.ADD)) {
167                                            SessionMessages.add(
168                                                    actionRequest,
169                                                    PortalUtil.getPortletId(actionRequest) + "pageAdded",
170                                                    layout);
171                                    }
172                                    else if (cmd.equals(Constants.UPDATE)) {
173                                            redirect = updateRedirect(
174                                                    themeDisplay, redirect, null, layout, oldFriendlyURL);
175                                            closeRedirect = updateCloseRedirect(
176                                                    themeDisplay, closeRedirect, null, layout,
177                                                    oldFriendlyURL);
178                                    }
179                            }
180                            else if (cmd.equals(Constants.DELETE)) {
181                                    long plid = ParamUtil.getLong(actionRequest, "plid");
182    
183                                    if (plid <= 0) {
184                                            long groupId = ParamUtil.getLong(actionRequest, "groupId");
185                                            boolean privateLayout = ParamUtil.getBoolean(
186                                                    actionRequest, "privateLayout");
187                                            long layoutId = ParamUtil.getLong(
188                                                    actionRequest, "layoutId");
189    
190                                            layout = LayoutLocalServiceUtil.getLayout(
191                                                    groupId, privateLayout, layoutId);
192    
193                                            plid = layout.getPlid();
194                                    }
195    
196                                    Object[] returnValue = SitesUtil.deleteLayout(
197                                            actionRequest, actionResponse);
198    
199                                    Group group = (Group)returnValue[0];
200                                    oldFriendlyURL = (String)returnValue[1];
201                                    long newRefererPlid = (Long)returnValue[2];
202    
203                                    redirect = updateCloseRedirect(
204                                            themeDisplay, redirect, group, null, oldFriendlyURL);
205    
206                                    long refererPlid = themeDisplay.getRefererPlid();
207    
208                                    if (plid == refererPlid) {
209                                            redirect = HttpUtil.setParameter(
210                                                    redirect, "refererPlid", newRefererPlid);
211                                            redirect = HttpUtil.setParameter(
212                                                    redirect, actionResponse.getNamespace() + "selPlid", 0);
213                                    }
214    
215                                    closeRedirect = updateCloseRedirect(
216                                            themeDisplay, closeRedirect, group, null, oldFriendlyURL);
217    
218                                    redirect = HttpUtil.addParameter(
219                                            redirect, actionResponse.getNamespace() + "closeRedirect",
220                                            closeRedirect);
221                            }
222                            else if (cmd.equals("display_order")) {
223                                    updateDisplayOrder(actionRequest);
224                            }
225                            else if (cmd.equals("delete_layout_revision")) {
226                                    deleteLayoutRevision(actionRequest);
227                            }
228                            else if (cmd.equals("enable")) {
229                                    enableLayout(actionRequest);
230                            }
231                            else if (cmd.equals("reset_customized_view")) {
232                                    LayoutTypePortlet layoutTypePortlet =
233                                            themeDisplay.getLayoutTypePortlet();
234    
235                                    if ((layoutTypePortlet != null) &&
236                                            layoutTypePortlet.isCustomizable() &&
237                                            layoutTypePortlet.isCustomizedView()) {
238    
239                                            layoutTypePortlet.resetUserPreferences();
240                                    }
241                            }
242                            else if (cmd.equals("reset_merge_fail_count_and_merge")) {
243                                    resetMergeFailCountAndMerge(actionRequest);
244                            }
245                            else if (cmd.equals("reset_prototype")) {
246                                    SitesUtil.resetPrototype(themeDisplay.getLayout());
247                            }
248                            else if (cmd.equals("select_layout_set_branch")) {
249                                    selectLayoutSetBranch(actionRequest);
250                            }
251                            else if (cmd.equals("select_layout_branch")) {
252                                    selectLayoutBranch(actionRequest);
253                            }
254                            else if (cmd.equals("update_layout_revision")) {
255                                    updateLayoutRevision(actionRequest, themeDisplay);
256                            }
257    
258                            MultiSessionMessages.add(
259                                    actionRequest,
260                                    PortalUtil.getPortletId(actionRequest) + "requestProcessed");
261    
262                            sendRedirect(
263                                    portletConfig, actionRequest, actionResponse, redirect,
264                                    closeRedirect);
265                    }
266                    catch (Exception e) {
267                            if (e instanceof NoSuchLayoutException ||
268                                    e instanceof PrincipalException) {
269    
270                                    SessionErrors.add(actionRequest, e.getClass());
271    
272                                    setForward(actionRequest, "portlet.layouts_admin.error");
273                            }
274                            else if (e instanceof ImageTypeException ||
275                                             e instanceof LayoutFriendlyURLException ||
276                                             e instanceof LayoutFriendlyURLsException ||
277                                             e instanceof LayoutNameException ||
278                                             e instanceof LayoutParentLayoutIdException ||
279                                             e instanceof LayoutSetVirtualHostException ||
280                                             e instanceof LayoutTypeException ||
281                                             e instanceof RequiredLayoutException ||
282                                             e instanceof SitemapChangeFrequencyException ||
283                                             e instanceof SitemapIncludeException ||
284                                             e instanceof SitemapPagePriorityException ||
285                                             e instanceof UploadException) {
286    
287                                    SessionErrors.add(actionRequest, e.getClass(), e);
288    
289                                    if (cmd.equals(Constants.ADD)) {
290                                            SessionMessages.add(
291                                                    actionRequest,
292                                                    PortalUtil.getPortletId(actionRequest) + "addError", e);
293                                    }
294                            }
295                            else if (e instanceof SystemException) {
296                                    SessionErrors.add(actionRequest, e.getClass(), e);
297    
298                                    redirect = ParamUtil.getString(actionRequest, "pagesRedirect");
299    
300                                    sendRedirect(
301                                            portletConfig, actionRequest, actionResponse, redirect,
302                                            closeRedirect);
303                            }
304                            else {
305                                    throw e;
306                            }
307                    }
308            }
309    
310            @Override
311            public ActionForward render(
312                            ActionMapping actionMapping, ActionForm actionForm,
313                            PortletConfig portletConfig, RenderRequest renderRequest,
314                            RenderResponse renderResponse)
315                    throws Exception {
316    
317                    try {
318                            checkPermissions(renderRequest);
319                    }
320                    catch (PrincipalException pe) {
321                            SessionErrors.add(
322                                    renderRequest, PrincipalException.class.getName());
323    
324                            return actionMapping.findForward("portlet.layouts_admin.error");
325                    }
326    
327                    try {
328                            getGroup(renderRequest);
329                    }
330                    catch (Exception e) {
331                            if (e instanceof NoSuchGroupException ||
332                                    e instanceof PrincipalException) {
333    
334                                    SessionErrors.add(renderRequest, e.getClass());
335    
336                                    return actionMapping.findForward("portlet.layouts_admin.error");
337                            }
338                            else {
339                                    throw e;
340                            }
341                    }
342    
343                    return actionMapping.findForward(
344                            getForward(renderRequest, "portlet.layouts_admin.edit_layouts"));
345            }
346    
347            protected void checkPermission(
348                            PermissionChecker permissionChecker, Group group, Layout layout,
349                            long selPlid)
350                    throws PortalException {
351    
352                    if (selPlid > 0) {
353                            LayoutPermissionUtil.check(
354                                    permissionChecker, layout, ActionKeys.VIEW);
355                    }
356                    else {
357                            GroupPermissionUtil.check(
358                                    permissionChecker, group, ActionKeys.VIEW);
359                    }
360            }
361    
362            protected void checkPermissions(PortletRequest portletRequest)
363                    throws Exception {
364    
365                    Group group = getGroup(portletRequest);
366    
367                    if (group == null) {
368                            throw new PrincipalException();
369                    }
370    
371                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
372                            WebKeys.THEME_DISPLAY);
373    
374                    PermissionChecker permissionChecker =
375                            themeDisplay.getPermissionChecker();
376    
377                    Layout layout = themeDisplay.getLayout();
378    
379                    String cmd = ParamUtil.getString(portletRequest, Constants.CMD);
380    
381                    long selPlid = ParamUtil.getLong(portletRequest, "selPlid");
382    
383                    if (selPlid > 0) {
384                            layout = LayoutLocalServiceUtil.getLayout(selPlid);
385                    }
386    
387                    if (cmd.equals(Constants.ADD)) {
388                            long parentPlid = ParamUtil.getLong(portletRequest, "parentPlid");
389    
390                            if (parentPlid == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
391                                    if (!GroupPermissionUtil.contains(
392                                                    permissionChecker, group, ActionKeys.ADD_LAYOUT)) {
393    
394                                            throw new PrincipalException();
395                                    }
396                            }
397                            else {
398                                    layout = LayoutLocalServiceUtil.getLayout(parentPlid);
399    
400                                    if (!LayoutPermissionUtil.contains(
401                                                    permissionChecker, layout, ActionKeys.ADD_LAYOUT)) {
402    
403                                            throw new PrincipalException();
404                                    }
405                            }
406                    }
407                    else if (cmd.equals(Constants.DELETE)) {
408                            if (!LayoutPermissionUtil.contains(
409                                            permissionChecker, layout, ActionKeys.DELETE)) {
410    
411                                    throw new PrincipalException();
412                            }
413                    }
414                    else if (cmd.equals(Constants.PUBLISH_TO_LIVE) ||
415                                     cmd.equals(Constants.PUBLISH_TO_REMOTE)) {
416    
417                            boolean hasUpdateLayoutPermission = false;
418    
419                            if (layout != null) {
420                                    hasUpdateLayoutPermission = LayoutPermissionUtil.contains(
421                                            permissionChecker, layout, ActionKeys.UPDATE);
422                            }
423    
424                            if (group.isCompany() || group.isSite()) {
425                                    boolean publishToLive = GroupPermissionUtil.contains(
426                                            permissionChecker, group, ActionKeys.PUBLISH_STAGING);
427    
428                                    if (!hasUpdateLayoutPermission && !publishToLive) {
429                                            throw new PrincipalException();
430                                    }
431                            }
432                            else {
433                                    checkPermission(permissionChecker, group, layout, selPlid);
434                            }
435                    }
436                    else if (cmd.equals(Constants.UPDATE)) {
437                            if (group.isCompany()) {
438                                    if (!permissionChecker.isCompanyAdmin()) {
439                                            throw new PrincipalException();
440                                    }
441                            }
442                            else if (group.isLayoutPrototype()) {
443                                    LayoutPrototypePermissionUtil.check(
444                                            permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
445                            }
446                            else if (group.isLayoutSetPrototype()) {
447                                    LayoutSetPrototypePermissionUtil.check(
448                                            permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
449                            }
450                            else if (group.isUser()) {
451                                    long groupUserId = group.getClassPK();
452    
453                                    User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
454    
455                                    long[] organizationIds = groupUser.getOrganizationIds();
456    
457                                    UserPermissionUtil.check(
458                                            permissionChecker, groupUserId, organizationIds,
459                                            ActionKeys.UPDATE);
460                            }
461                            else {
462                                    checkPermission(permissionChecker, group, layout, selPlid);
463                            }
464                    }
465                    else if (cmd.equals("reset_customized_view")) {
466                            if (!LayoutPermissionUtil.contains(
467                                            permissionChecker, layout, ActionKeys.CUSTOMIZE)) {
468    
469                                    throw new PrincipalException();
470                            }
471                    }
472                    else {
473                            checkPermission(permissionChecker, group, layout, selPlid);
474                    }
475            }
476    
477            protected void deleteLayoutRevision(ActionRequest actionRequest)
478                    throws Exception {
479    
480                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
481                            actionRequest);
482    
483                    long layoutRevisionId = ParamUtil.getLong(
484                            actionRequest, "layoutRevisionId");
485    
486                    LayoutRevision layoutRevision =
487                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
488    
489                    LayoutRevisionLocalServiceUtil.deleteLayoutRevision(layoutRevision);
490    
491                    boolean updateRecentLayoutRevisionId = ParamUtil.getBoolean(
492                            actionRequest, "updateRecentLayoutRevisionId");
493    
494                    if (updateRecentLayoutRevisionId) {
495                            StagingUtil.setRecentLayoutRevisionId(
496                                    request, layoutRevision.getLayoutSetBranchId(),
497                                    layoutRevision.getPlid(),
498                                    layoutRevision.getParentLayoutRevisionId());
499                    }
500            }
501    
502            protected void deleteThemeSettingsProperties(
503                    UnicodeProperties typeSettingsProperties, String device) {
504    
505                    String keyPrefix = ThemeSettingImpl.namespaceProperty(device);
506    
507                    Set<String> keys = typeSettingsProperties.keySet();
508    
509                    Iterator<String> itr = keys.iterator();
510    
511                    while (itr.hasNext()) {
512                            String key = itr.next();
513    
514                            if (key.startsWith(keyPrefix)) {
515                                    itr.remove();
516                            }
517                    }
518            }
519    
520            protected void enableLayout(ActionRequest actionRequest) throws Exception {
521                    long incompleteLayoutRevisionId = ParamUtil.getLong(
522                            actionRequest, "incompleteLayoutRevisionId");
523    
524                    LayoutRevision incompleteLayoutRevision =
525                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
526                                    incompleteLayoutRevisionId);
527    
528                    long layoutBranchId = ParamUtil.getLong(
529                            actionRequest, "layoutBranchId",
530                            incompleteLayoutRevision.getLayoutBranchId());
531    
532                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
533                            actionRequest);
534    
535                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
536    
537                    LayoutRevisionLocalServiceUtil.updateLayoutRevision(
538                            serviceContext.getUserId(),
539                            incompleteLayoutRevision.getLayoutRevisionId(), layoutBranchId,
540                            incompleteLayoutRevision.getName(),
541                            incompleteLayoutRevision.getTitle(),
542                            incompleteLayoutRevision.getDescription(),
543                            incompleteLayoutRevision.getKeywords(),
544                            incompleteLayoutRevision.getRobots(),
545                            incompleteLayoutRevision.getTypeSettings(),
546                            incompleteLayoutRevision.getIconImage(),
547                            incompleteLayoutRevision.getIconImageId(),
548                            incompleteLayoutRevision.getThemeId(),
549                            incompleteLayoutRevision.getColorSchemeId(),
550                            incompleteLayoutRevision.getWapThemeId(),
551                            incompleteLayoutRevision.getWapColorSchemeId(),
552                            incompleteLayoutRevision.getCss(), serviceContext);
553            }
554    
555            protected String getColorSchemeId(
556                            long companyId, String themeId, String colorSchemeId,
557                            boolean wapTheme)
558                    throws Exception {
559    
560                    Theme theme = ThemeLocalServiceUtil.getTheme(
561                            companyId, themeId, wapTheme);
562    
563                    if (!theme.hasColorSchemes()) {
564                            colorSchemeId = StringPool.BLANK;
565                    }
566    
567                    if (Validator.isNull(colorSchemeId)) {
568                            ColorScheme colorScheme = ThemeLocalServiceUtil.getColorScheme(
569                                    companyId, themeId, colorSchemeId, wapTheme);
570    
571                            colorSchemeId = colorScheme.getColorSchemeId();
572                    }
573    
574                    return colorSchemeId;
575            }
576    
577            protected Group getGroup(PortletRequest portletRequest) throws Exception {
578                    return ActionUtil.getGroup(portletRequest);
579            }
580    
581            protected byte[] getIconBytes(
582                    UploadPortletRequest uploadPortletRequest, String iconFileName) {
583    
584                    InputStream inputStream = null;
585    
586                    try {
587                            inputStream = uploadPortletRequest.getFileAsStream(iconFileName);
588    
589                            if (inputStream != null) {
590                                    return FileUtil.getBytes(inputStream);
591                            }
592                    }
593                    catch (IOException ioe) {
594                            if (_log.isWarnEnabled()) {
595                                    _log.warn("Unable to retrieve icon", ioe);
596                            }
597                    }
598    
599                    return new byte[0];
600            }
601    
602            protected void inheritMobileRuleGroups(
603                            Layout layout, ServiceContext serviceContext)
604                    throws PortalException {
605    
606                    List<MDRRuleGroupInstance> parentMDRRuleGroupInstances =
607                            MDRRuleGroupInstanceLocalServiceUtil.getRuleGroupInstances(
608                                    Layout.class.getName(), layout.getParentPlid());
609    
610                    for (MDRRuleGroupInstance parentMDRRuleGroupInstance :
611                                    parentMDRRuleGroupInstances) {
612    
613                            MDRRuleGroupInstance mdrRuleGroupInstance =
614                                    MDRRuleGroupInstanceServiceUtil.addRuleGroupInstance(
615                                            layout.getGroupId(), Layout.class.getName(),
616                                            layout.getPlid(),
617                                            parentMDRRuleGroupInstance.getRuleGroupId(),
618                                            parentMDRRuleGroupInstance.getPriority(), serviceContext);
619    
620                            List<MDRAction> parentMDRActions =
621                                    MDRActionLocalServiceUtil.getActions(
622                                            parentMDRRuleGroupInstance.getRuleGroupInstanceId());
623    
624                            for (MDRAction mdrAction : parentMDRActions) {
625                                    MDRActionServiceUtil.addAction(
626                                            mdrRuleGroupInstance.getRuleGroupInstanceId(),
627                                            mdrAction.getNameMap(), mdrAction.getDescriptionMap(),
628                                            mdrAction.getType(), mdrAction.getTypeSettings(),
629                                            serviceContext);
630                            }
631                    }
632            }
633    
634            @Override
635            protected boolean isCheckMethodOnProcessAction() {
636                    return _CHECK_METHOD_ON_PROCESS_ACTION;
637            }
638    
639            /**
640             * Resets the number of failed merge attempts for the page template, which
641             * is accessed from the action request's <code>layoutPrototypeId</code>
642             * param. Once the counter is reset, the modified page template is merged
643             * back into its linked page, which is accessed from the action request's
644             * <code>selPlid</code> param.
645             *
646             * <p>
647             * If the number of failed merge attempts is not equal to zero after the
648             * merge, an error key is submitted into the {@link SessionErrors}.
649             * </p>
650             *
651             * @param  actionRequest the action request
652             * @throws Exception if an exception occurred
653             */
654            protected void resetMergeFailCountAndMerge(ActionRequest actionRequest)
655                    throws Exception {
656    
657                    long layoutPrototypeId = ParamUtil.getLong(
658                            actionRequest, "layoutPrototypeId");
659    
660                    LayoutPrototype layoutPrototype =
661                            LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
662                                    layoutPrototypeId);
663    
664                    SitesUtil.setMergeFailCount(layoutPrototype, 0);
665    
666                    long selPlid = ParamUtil.getLong(actionRequest, "selPlid");
667    
668                    Layout selLayout = LayoutLocalServiceUtil.getLayout(selPlid);
669    
670                    SitesUtil.resetPrototype(selLayout);
671    
672                    SitesUtil.mergeLayoutPrototypeLayout(selLayout.getGroup(), selLayout);
673    
674                    layoutPrototype = LayoutPrototypeServiceUtil.getLayoutPrototype(
675                            layoutPrototypeId);
676    
677                    int mergeFailCountAfterMerge = SitesUtil.getMergeFailCount(
678                            layoutPrototype);
679    
680                    if (mergeFailCountAfterMerge > 0) {
681                            SessionErrors.add(actionRequest, "resetMergeFailCountAndMerge");
682                    }
683            }
684    
685            protected void selectLayoutBranch(ActionRequest actionRequest)
686                    throws Exception {
687    
688                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
689                            actionRequest);
690    
691                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
692                            WebKeys.THEME_DISPLAY);
693    
694                    long layoutSetBranchId = ParamUtil.getLong(
695                            actionRequest, "layoutSetBranchId");
696    
697                    long layoutBranchId = ParamUtil.getLong(
698                            actionRequest, "layoutBranchId");
699    
700                    StagingUtil.setRecentLayoutBranchId(
701                            request, layoutSetBranchId, themeDisplay.getPlid(), layoutBranchId);
702            }
703    
704            protected void selectLayoutSetBranch(ActionRequest actionRequest)
705                    throws Exception {
706    
707                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
708                            actionRequest);
709    
710                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
711                    boolean privateLayout = ParamUtil.getBoolean(
712                            actionRequest, "privateLayout");
713    
714                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
715                            groupId, privateLayout);
716    
717                    long layoutSetBranchId = ParamUtil.getLong(
718                            actionRequest, "layoutSetBranchId");
719    
720                    // Ensure layout set branch exists
721    
722                    LayoutSetBranch layoutSetBranch =
723                            LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
724                                    layoutSetBranchId);
725    
726                    StagingUtil.setRecentLayoutSetBranchId(
727                            request, layoutSet.getLayoutSetId(),
728                            layoutSetBranch.getLayoutSetBranchId());
729            }
730    
731            protected void setThemeSettingProperties(
732                            ActionRequest actionRequest,
733                            UnicodeProperties typeSettingsProperties,
734                            Map<String, ThemeSetting> themeSettings, String device,
735                            String deviceThemeId)
736                    throws PortalException {
737    
738                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
739                    boolean privateLayout = ParamUtil.getBoolean(
740                            actionRequest, "privateLayout");
741                    long layoutId = ParamUtil.getLong(actionRequest, "layoutId");
742    
743                    Layout layout = LayoutLocalServiceUtil.getLayout(
744                            groupId, privateLayout, layoutId);
745    
746                    for (String key : themeSettings.keySet()) {
747                            ThemeSetting themeSetting = themeSettings.get(key);
748    
749                            String property =
750                                    device + "ThemeSettingsProperties--" + key +
751                                            StringPool.DOUBLE_DASH;
752    
753                            String value = ParamUtil.getString(
754                                    actionRequest, property, themeSetting.getValue());
755    
756                            if (!Validator.equals(
757                                            value, layout.getDefaultThemeSetting(key, device, false))) {
758    
759                                    typeSettingsProperties.setProperty(
760                                            ThemeSettingImpl.namespaceProperty(device, key), value);
761                            }
762                    }
763            }
764    
765            protected String updateCloseRedirect(
766                    ThemeDisplay themeDisplay, String closeRedirect, Group group,
767                    Layout layout, String oldLayoutFriendlyURL) {
768    
769                    if (Validator.isNull(closeRedirect) ||
770                            Validator.isNull(oldLayoutFriendlyURL)) {
771    
772                            return closeRedirect;
773                    }
774    
775                    if (layout != null) {
776                            String oldPath = oldLayoutFriendlyURL;
777                            String newPath = layout.getFriendlyURL(themeDisplay.getLocale());
778    
779                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
780                    }
781                    else if (group != null) {
782                            String oldPath = group.getFriendlyURL() + oldLayoutFriendlyURL;
783                            String newPath = group.getFriendlyURL();
784    
785                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
786                    }
787    
788                    return closeRedirect;
789            }
790    
791            protected void updateDisplayOrder(ActionRequest actionRequest)
792                    throws Exception {
793    
794                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
795                    boolean privateLayout = ParamUtil.getBoolean(
796                            actionRequest, "privateLayout");
797                    long parentLayoutId = ParamUtil.getLong(
798                            actionRequest, "parentLayoutId");
799                    long[] layoutIds = StringUtil.split(
800                            ParamUtil.getString(actionRequest, "layoutIds"), 0L);
801    
802                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
803                            actionRequest);
804    
805                    LayoutServiceUtil.setLayouts(
806                            groupId, privateLayout, parentLayoutId, layoutIds, serviceContext);
807            }
808    
809            protected Object[] updateLayout(
810                            ActionRequest actionRequest, ActionResponse actionResponse)
811                    throws Exception {
812    
813                    UploadPortletRequest uploadPortletRequest =
814                            PortalUtil.getUploadPortletRequest(actionRequest);
815    
816                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
817                            WebKeys.THEME_DISPLAY);
818    
819                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
820    
821                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
822                    long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
823                    long stagingGroupId = ParamUtil.getLong(
824                            actionRequest, "stagingGroupId");
825                    boolean privateLayout = ParamUtil.getBoolean(
826                            actionRequest, "privateLayout");
827                    long layoutId = ParamUtil.getLong(actionRequest, "layoutId");
828                    long parentLayoutId = ParamUtil.getLong(
829                            uploadPortletRequest, "parentLayoutId");
830                    Map<Locale, String> nameMap = LocalizationUtil.getLocalizationMap(
831                            actionRequest, "name");
832                    Map<Locale, String> titleMap = LocalizationUtil.getLocalizationMap(
833                            actionRequest, "title");
834                    Map<Locale, String> descriptionMap =
835                            LocalizationUtil.getLocalizationMap(actionRequest, "description");
836                    Map<Locale, String> keywordsMap = LocalizationUtil.getLocalizationMap(
837                            actionRequest, "keywords");
838                    Map<Locale, String> robotsMap = LocalizationUtil.getLocalizationMap(
839                            actionRequest, "robots");
840                    String type = ParamUtil.getString(uploadPortletRequest, "type");
841                    boolean hidden = ParamUtil.getBoolean(uploadPortletRequest, "hidden");
842                    Map<Locale, String> friendlyURLMap =
843                            LocalizationUtil.getLocalizationMap(actionRequest, "friendlyURL");
844                    boolean deleteLogo = ParamUtil.getBoolean(actionRequest, "deleteLogo");
845    
846                    byte[] iconBytes = null;
847    
848                    long fileEntryId = ParamUtil.getLong(
849                            uploadPortletRequest, "fileEntryId");
850    
851                    if (fileEntryId > 0) {
852                            FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(
853                                    fileEntryId);
854    
855                            iconBytes = FileUtil.getBytes(fileEntry.getContentStream());
856                    }
857    
858                    long layoutPrototypeId = ParamUtil.getLong(
859                            uploadPortletRequest, "layoutPrototypeId");
860    
861                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
862                            Layout.class.getName(), actionRequest);
863    
864                    Layout layout = null;
865                    UnicodeProperties layoutTypeSettingsProperties = null;
866                    String oldFriendlyURL = StringPool.BLANK;
867    
868                    if (cmd.equals(Constants.ADD)) {
869    
870                            // Add layout
871    
872                            boolean inheritFromParentLayoutId = ParamUtil.getBoolean(
873                                    uploadPortletRequest, "inheritFromParentLayoutId");
874    
875                            UnicodeProperties typeSettingsProperties =
876                                    PropertiesParamUtil.getProperties(
877                                            actionRequest, "TypeSettingsProperties--");
878    
879                            if (inheritFromParentLayoutId && (parentLayoutId > 0)) {
880                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
881                                            groupId, privateLayout, parentLayoutId);
882    
883                                    layout = LayoutServiceUtil.addLayout(
884                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
885                                            parentLayout.getDescriptionMap(),
886                                            parentLayout.getKeywordsMap(), parentLayout.getRobotsMap(),
887                                            parentLayout.getType(), parentLayout.getTypeSettings(),
888                                            hidden, friendlyURLMap, serviceContext);
889    
890                                    inheritMobileRuleGroups(layout, serviceContext);
891    
892                                    if (parentLayout.isTypePortlet()) {
893                                            ActionUtil.copyPreferences(
894                                                    actionRequest, layout, parentLayout);
895    
896                                            SitesUtil.copyLookAndFeel(layout, parentLayout);
897                                    }
898                            }
899                            else if (layoutPrototypeId > 0) {
900                                    LayoutPrototype layoutPrototype =
901                                            LayoutPrototypeServiceUtil.getLayoutPrototype(
902                                                    layoutPrototypeId);
903    
904                                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
905                                            uploadPortletRequest, "layoutPrototypeLinkEnabled");
906    
907                                    serviceContext.setAttribute(
908                                            "layoutPrototypeLinkEnabled", layoutPrototypeLinkEnabled);
909    
910                                    serviceContext.setAttribute(
911                                            "layoutPrototypeUuid", layoutPrototype.getUuid());
912    
913                                    layout = LayoutServiceUtil.addLayout(
914                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
915                                            descriptionMap, keywordsMap, robotsMap,
916                                            LayoutConstants.TYPE_PORTLET,
917                                            typeSettingsProperties.toString(), hidden, friendlyURLMap,
918                                            serviceContext);
919    
920                                    // Force propagation from page template to page. See LPS-48430.
921    
922                                    SitesUtil.mergeLayoutPrototypeLayout(layout.getGroup(), layout);
923                            }
924                            else {
925                                    long copyLayoutId = ParamUtil.getLong(
926                                            uploadPortletRequest, "copyLayoutId");
927    
928                                    Layout copyLayout = null;
929    
930                                    String layoutTemplateId = ParamUtil.getString(
931                                            uploadPortletRequest, "layoutTemplateId",
932                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID);
933    
934                                    if (copyLayoutId > 0) {
935                                            try {
936                                                    copyLayout = LayoutLocalServiceUtil.getLayout(
937                                                            groupId, privateLayout, copyLayoutId);
938    
939                                                    if (copyLayout.isTypePortlet()) {
940                                                            LayoutTypePortlet copyLayoutTypePortlet =
941                                                                    (LayoutTypePortlet)copyLayout.getLayoutType();
942    
943                                                            layoutTemplateId =
944                                                                    copyLayoutTypePortlet.getLayoutTemplateId();
945    
946                                                            typeSettingsProperties =
947                                                                    copyLayout.getTypeSettingsProperties();
948                                                    }
949                                            }
950                                            catch (NoSuchLayoutException nsle) {
951                                            }
952                                    }
953    
954                                    layout = LayoutServiceUtil.addLayout(
955                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
956                                            descriptionMap, keywordsMap, robotsMap, type,
957                                            typeSettingsProperties.toString(), hidden, friendlyURLMap,
958                                            serviceContext);
959    
960                                    LayoutTypePortlet layoutTypePortlet =
961                                            (LayoutTypePortlet)layout.getLayoutType();
962    
963                                    layoutTypePortlet.setLayoutTemplateId(
964                                            themeDisplay.getUserId(), layoutTemplateId);
965    
966                                    LayoutServiceUtil.updateLayout(
967                                            groupId, privateLayout, layout.getLayoutId(),
968                                            layout.getTypeSettings());
969    
970                                    if (copyLayout != null) {
971                                            if (copyLayout.isTypePortlet()) {
972                                                    ActionUtil.copyPreferences(
973                                                            actionRequest, layout, copyLayout);
974    
975                                                    SitesUtil.copyLookAndFeel(layout, copyLayout);
976                                            }
977                                    }
978                            }
979    
980                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
981                    }
982                    else {
983    
984                            // Update layout
985    
986                            layout = LayoutLocalServiceUtil.getLayout(
987                                    groupId, privateLayout, layoutId);
988    
989                            oldFriendlyURL = layout.getFriendlyURL(themeDisplay.getLocale());
990    
991                            layout = LayoutServiceUtil.updateLayout(
992                                    groupId, privateLayout, layoutId, layout.getParentLayoutId(),
993                                    nameMap, titleMap, descriptionMap, keywordsMap, robotsMap, type,
994                                    hidden, friendlyURLMap, !deleteLogo, iconBytes, serviceContext);
995    
996                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
997    
998                            if (!layout.isTypeURL() && !layout.isTypeLinkToLayout() &&
999                                    oldFriendlyURL.equals(
1000                                            layout.getFriendlyURL(themeDisplay.getLocale()))) {
1001    
1002                                    oldFriendlyURL = StringPool.BLANK;
1003                            }
1004    
1005                            UnicodeProperties formTypeSettingsProperties =
1006                                    PropertiesParamUtil.getProperties(
1007                                            actionRequest, "TypeSettingsProperties--");
1008    
1009                            LayoutTypePortlet layoutTypePortlet =
1010                                    (LayoutTypePortlet)layout.getLayoutType();
1011    
1012                            if (type.equals(LayoutConstants.TYPE_PORTLET)) {
1013                                    String layoutTemplateId = ParamUtil.getString(
1014                                            uploadPortletRequest, "layoutTemplateId",
1015                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID);
1016    
1017                                    layoutTypePortlet.setLayoutTemplateId(
1018                                            themeDisplay.getUserId(), layoutTemplateId);
1019    
1020                                    long copyLayoutId = ParamUtil.getLong(
1021                                            uploadPortletRequest, "copyLayoutId");
1022    
1023                                    if ((copyLayoutId > 0) &&
1024                                            (copyLayoutId != layout.getLayoutId())) {
1025    
1026                                            try {
1027                                                    Layout copyLayout = LayoutLocalServiceUtil.getLayout(
1028                                                            groupId, privateLayout, copyLayoutId);
1029    
1030                                                    if (copyLayout.isTypePortlet()) {
1031                                                            layoutTypeSettingsProperties =
1032                                                                    copyLayout.getTypeSettingsProperties();
1033    
1034                                                            ActionUtil.copyPreferences(
1035                                                                    actionRequest, layout, copyLayout);
1036    
1037                                                            SitesUtil.copyLookAndFeel(layout, copyLayout);
1038                                                    }
1039                                            }
1040                                            catch (NoSuchLayoutException nsle) {
1041                                            }
1042                                    }
1043                                    else {
1044                                            layoutTypeSettingsProperties.putAll(
1045                                                    formTypeSettingsProperties);
1046    
1047                                            LayoutServiceUtil.updateLayout(
1048                                                    groupId, privateLayout, layoutId,
1049                                                    layout.getTypeSettings());
1050                                    }
1051                            }
1052                            else {
1053                                    layout.setTypeSettingsProperties(formTypeSettingsProperties);
1054    
1055                                    layoutTypeSettingsProperties.putAll(
1056                                            layout.getTypeSettingsProperties());
1057    
1058                                    LayoutServiceUtil.updateLayout(
1059                                            groupId, privateLayout, layoutId, layout.getTypeSettings());
1060                            }
1061    
1062                            String[] removeEmbeddedPortletIds = ParamUtil.getParameterValues(
1063                                    actionRequest, "removeEmbeddedPortletIds");
1064    
1065                            if (removeEmbeddedPortletIds.length > 0) {
1066                                    PortletLocalServiceUtil.deletePortlets(
1067                                            themeDisplay.getCompanyId(), removeEmbeddedPortletIds,
1068                                            layout.getPlid());
1069                            }
1070    
1071                            HttpServletResponse response = PortalUtil.getHttpServletResponse(
1072                                    actionResponse);
1073    
1074                            EventsProcessorUtil.process(
1075                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_UPDATE,
1076                                    layoutTypePortlet.getConfigurationActionUpdate(),
1077                                    uploadPortletRequest, response);
1078                    }
1079    
1080                    updateLookAndFeel(
1081                            actionRequest, themeDisplay.getCompanyId(), liveGroupId,
1082                            stagingGroupId, privateLayout, layout.getLayoutId(),
1083                            layoutTypeSettingsProperties);
1084    
1085                    return new Object[] {layout, oldFriendlyURL};
1086            }
1087    
1088            protected void updateLayoutRevision(
1089                            ActionRequest actionRequest, ThemeDisplay themeDisplay)
1090                    throws Exception {
1091    
1092                    long layoutRevisionId = ParamUtil.getLong(
1093                            actionRequest, "layoutRevisionId");
1094    
1095                    LayoutRevision layoutRevision =
1096                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
1097    
1098                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
1099                            actionRequest);
1100    
1101                    LayoutRevision enableLayoutRevision =
1102                            LayoutRevisionLocalServiceUtil.updateLayoutRevision(
1103                                    serviceContext.getUserId(), layoutRevisionId,
1104                                    layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
1105                                    layoutRevision.getTitle(), layoutRevision.getDescription(),
1106                                    layoutRevision.getKeywords(), layoutRevision.getRobots(),
1107                                    layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
1108                                    layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
1109                                    layoutRevision.getColorSchemeId(),
1110                                    layoutRevision.getWapThemeId(),
1111                                    layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
1112                                    serviceContext);
1113    
1114                    if (layoutRevision.getStatus() != WorkflowConstants.STATUS_INCOMPLETE) {
1115                            StagingUtil.setRecentLayoutRevisionId(
1116                                    themeDisplay.getUser(), layoutRevision.getLayoutSetBranchId(),
1117                                    layoutRevision.getPlid(), layoutRevision.getLayoutRevisionId());
1118    
1119                            return;
1120                    }
1121    
1122                    LayoutRevision lastLayoutRevision =
1123                            LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision(
1124                                    enableLayoutRevision.getPlid(), true);
1125    
1126                    if (lastLayoutRevision != null) {
1127                            LayoutRevision newLayoutRevision =
1128                                    LayoutRevisionLocalServiceUtil.addLayoutRevision(
1129                                            serviceContext.getUserId(),
1130                                            layoutRevision.getLayoutSetBranchId(),
1131                                            layoutRevision.getLayoutBranchId(),
1132                                            enableLayoutRevision.getLayoutRevisionId(), false,
1133                                            layoutRevision.getPlid(),
1134                                            lastLayoutRevision.getLayoutRevisionId(),
1135                                            lastLayoutRevision.isPrivateLayout(),
1136                                            lastLayoutRevision.getName(), lastLayoutRevision.getTitle(),
1137                                            lastLayoutRevision.getDescription(),
1138                                            lastLayoutRevision.getKeywords(),
1139                                            lastLayoutRevision.getRobots(),
1140                                            lastLayoutRevision.getTypeSettings(),
1141                                            lastLayoutRevision.isIconImage(),
1142                                            lastLayoutRevision.getIconImageId(),
1143                                            lastLayoutRevision.getThemeId(),
1144                                            lastLayoutRevision.getColorSchemeId(),
1145                                            lastLayoutRevision.getWapThemeId(),
1146                                            lastLayoutRevision.getWapColorSchemeId(),
1147                                            lastLayoutRevision.getCss(), serviceContext);
1148    
1149                            StagingUtil.setRecentLayoutRevisionId(
1150                                    themeDisplay.getUser(),
1151                                    newLayoutRevision.getLayoutSetBranchId(),
1152                                    newLayoutRevision.getPlid(),
1153                                    newLayoutRevision.getLayoutRevisionId());
1154                    }
1155            }
1156    
1157            protected void updateLookAndFeel(
1158                            ActionRequest actionRequest, long companyId, long liveGroupId,
1159                            long stagingGroupId, boolean privateLayout, long layoutId,
1160                            UnicodeProperties typeSettingsProperties)
1161                    throws Exception {
1162    
1163                    String[] devices = StringUtil.split(
1164                            ParamUtil.getString(actionRequest, "devices"));
1165    
1166                    for (String device : devices) {
1167                            String deviceThemeId = ParamUtil.getString(
1168                                    actionRequest, device + "ThemeId");
1169                            String deviceColorSchemeId = ParamUtil.getString(
1170                                    actionRequest, device + "ColorSchemeId");
1171                            String deviceCss = ParamUtil.getString(
1172                                    actionRequest, device + "Css");
1173                            boolean deviceWapTheme = device.equals("wap");
1174    
1175                            boolean deviceInheritLookAndFeel = ParamUtil.getBoolean(
1176                                    actionRequest, device + "InheritLookAndFeel");
1177    
1178                            if (deviceInheritLookAndFeel) {
1179                                    deviceThemeId = ThemeFactoryUtil.getDefaultRegularThemeId(
1180                                            companyId);
1181                                    deviceColorSchemeId = StringPool.BLANK;
1182    
1183                                    deleteThemeSettingsProperties(typeSettingsProperties, device);
1184                            }
1185                            else if (Validator.isNotNull(deviceThemeId)) {
1186                                    deviceColorSchemeId = getColorSchemeId(
1187                                            companyId, deviceThemeId, deviceColorSchemeId,
1188                                            deviceWapTheme);
1189    
1190                                    updateThemeSettingsProperties(
1191                                            actionRequest, companyId, typeSettingsProperties, device,
1192                                            deviceThemeId, deviceWapTheme);
1193                            }
1194    
1195                            long groupId = liveGroupId;
1196    
1197                            if (stagingGroupId > 0) {
1198                                    groupId = stagingGroupId;
1199                            }
1200    
1201                            LayoutServiceUtil.updateLayout(
1202                                    groupId, privateLayout, layoutId,
1203                                    typeSettingsProperties.toString());
1204    
1205                            LayoutServiceUtil.updateLookAndFeel(
1206                                    groupId, privateLayout, layoutId, deviceThemeId,
1207                                    deviceColorSchemeId, deviceCss, deviceWapTheme);
1208                    }
1209            }
1210    
1211            protected String updateRedirect(
1212                    ThemeDisplay themeDisplay, String redirect, Group group, Layout layout,
1213                    String oldLayoutFriendlyURL) {
1214    
1215                    if (Validator.isNull(redirect) ||
1216                            Validator.isNull(oldLayoutFriendlyURL)) {
1217    
1218                            return redirect;
1219                    }
1220    
1221                    if (layout != null) {
1222                            String oldPath = oldLayoutFriendlyURL;
1223    
1224                            if (layout.isTypeLinkToLayout() || layout.isTypeURL()) {
1225                                    try {
1226                                            layout = LayoutLocalServiceUtil.fetchFirstLayout(
1227                                                    layout.getGroupId(), layout.getPrivateLayout(),
1228                                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
1229                                    }
1230                                    catch (Exception e) {
1231                                    }
1232    
1233                                    if (layout == null) {
1234                                            if (_log.isDebugEnabled()) {
1235                                                    _log.debug("Unable to fetch first layout");
1236                                            }
1237                                    }
1238                            }
1239    
1240                            String newPath = layout.getFriendlyURL(themeDisplay.getLocale());
1241    
1242                            return PortalUtil.updateRedirect(redirect, oldPath, newPath);
1243                    }
1244                    else if (group != null) {
1245                            String oldPath = group.getFriendlyURL() + oldLayoutFriendlyURL;
1246                            String newPath = group.getFriendlyURL();
1247    
1248                            return PortalUtil.updateRedirect(redirect, oldPath, newPath);
1249                    }
1250    
1251                    return redirect;
1252            }
1253    
1254            protected UnicodeProperties updateThemeSettingsProperties(
1255                            ActionRequest actionRequest, long companyId,
1256                            UnicodeProperties typeSettingsProperties, String device,
1257                            String deviceThemeId, boolean wapTheme)
1258                    throws Exception {
1259    
1260                    Theme theme = ThemeLocalServiceUtil.getTheme(
1261                            companyId, deviceThemeId, wapTheme);
1262    
1263                    deleteThemeSettingsProperties(typeSettingsProperties, device);
1264    
1265                    Map<String, ThemeSetting> themeSettings =
1266                            theme.getConfigurableSettings();
1267    
1268                    if (themeSettings.isEmpty()) {
1269                            return typeSettingsProperties;
1270                    }
1271    
1272                    setThemeSettingProperties(
1273                            actionRequest, typeSettingsProperties, themeSettings, device,
1274                            deviceThemeId);
1275    
1276                    return typeSettingsProperties;
1277            }
1278    
1279            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
1280    
1281            private static Log _log = LogFactoryUtil.getLog(EditLayoutsAction.class);
1282    
1283    }