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