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