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