001    /**
002     * Copyright (c) 2000-2012 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.LayoutHiddenException;
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.RemoteExportException;
027    import com.liferay.portal.RemoteOptionsException;
028    import com.liferay.portal.RequiredLayoutException;
029    import com.liferay.portal.events.EventsProcessorUtil;
030    import com.liferay.portal.kernel.exception.SystemException;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.servlet.SessionErrors;
034    import com.liferay.portal.kernel.servlet.SessionMessages;
035    import com.liferay.portal.kernel.staging.StagingUtil;
036    import com.liferay.portal.kernel.upload.UploadException;
037    import com.liferay.portal.kernel.upload.UploadPortletRequest;
038    import com.liferay.portal.kernel.util.Constants;
039    import com.liferay.portal.kernel.util.FileUtil;
040    import com.liferay.portal.kernel.util.GetterUtil;
041    import com.liferay.portal.kernel.util.HttpUtil;
042    import com.liferay.portal.kernel.util.LocalizationUtil;
043    import com.liferay.portal.kernel.util.ParamUtil;
044    import com.liferay.portal.kernel.util.PropertiesParamUtil;
045    import com.liferay.portal.kernel.util.PropsKeys;
046    import com.liferay.portal.kernel.util.StringPool;
047    import com.liferay.portal.kernel.util.StringUtil;
048    import com.liferay.portal.kernel.util.UnicodeProperties;
049    import com.liferay.portal.kernel.util.Validator;
050    import com.liferay.portal.kernel.workflow.WorkflowConstants;
051    import com.liferay.portal.model.ColorScheme;
052    import com.liferay.portal.model.Group;
053    import com.liferay.portal.model.Layout;
054    import com.liferay.portal.model.LayoutConstants;
055    import com.liferay.portal.model.LayoutPrototype;
056    import com.liferay.portal.model.LayoutRevision;
057    import com.liferay.portal.model.LayoutSet;
058    import com.liferay.portal.model.LayoutSetBranch;
059    import com.liferay.portal.model.LayoutTypePortlet;
060    import com.liferay.portal.model.Theme;
061    import com.liferay.portal.model.ThemeSetting;
062    import com.liferay.portal.model.User;
063    import com.liferay.portal.model.impl.ThemeImpl;
064    import com.liferay.portal.model.impl.ThemeSettingImpl;
065    import com.liferay.portal.security.auth.PrincipalException;
066    import com.liferay.portal.security.permission.ActionKeys;
067    import com.liferay.portal.security.permission.PermissionChecker;
068    import com.liferay.portal.service.LayoutLocalServiceUtil;
069    import com.liferay.portal.service.LayoutPrototypeServiceUtil;
070    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
071    import com.liferay.portal.service.LayoutServiceUtil;
072    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
073    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
074    import com.liferay.portal.service.ServiceContext;
075    import com.liferay.portal.service.ServiceContextFactory;
076    import com.liferay.portal.service.ThemeLocalServiceUtil;
077    import com.liferay.portal.service.UserLocalServiceUtil;
078    import com.liferay.portal.service.permission.GroupPermissionUtil;
079    import com.liferay.portal.service.permission.LayoutPermissionUtil;
080    import com.liferay.portal.service.permission.LayoutPrototypePermissionUtil;
081    import com.liferay.portal.service.permission.LayoutSetPrototypePermissionUtil;
082    import com.liferay.portal.service.permission.OrganizationPermissionUtil;
083    import com.liferay.portal.service.permission.UserPermissionUtil;
084    import com.liferay.portal.struts.PortletAction;
085    import com.liferay.portal.theme.ThemeDisplay;
086    import com.liferay.portal.util.LayoutSettings;
087    import com.liferay.portal.util.PortalUtil;
088    import com.liferay.portal.util.PropsValues;
089    import com.liferay.portal.util.WebKeys;
090    import com.liferay.portlet.sites.action.ActionUtil;
091    import com.liferay.portlet.sites.util.SitesUtil;
092    
093    import java.io.IOException;
094    import java.io.InputStream;
095    
096    import java.util.Iterator;
097    import java.util.Locale;
098    import java.util.Map;
099    import java.util.Set;
100    
101    import javax.portlet.ActionRequest;
102    import javax.portlet.ActionResponse;
103    import javax.portlet.PortletConfig;
104    import javax.portlet.PortletContext;
105    import javax.portlet.PortletRequest;
106    import javax.portlet.PortletRequestDispatcher;
107    import javax.portlet.RenderRequest;
108    import javax.portlet.RenderResponse;
109    import javax.portlet.ResourceRequest;
110    import javax.portlet.ResourceResponse;
111    
112    import javax.servlet.http.HttpServletRequest;
113    import javax.servlet.http.HttpServletResponse;
114    
115    import org.apache.struts.action.ActionForm;
116    import org.apache.struts.action.ActionForward;
117    import org.apache.struts.action.ActionMapping;
118    
119    /**
120     * @author Brian Wing Shun Chan
121     * @author Julio Camarero
122     */
123    public class EditLayoutsAction extends PortletAction {
124    
125            @Override
126            public void processAction(
127                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
128                            ActionRequest actionRequest, ActionResponse actionResponse)
129                    throws Exception {
130    
131                    try {
132                            checkPermissions(actionRequest);
133                    }
134                    catch (PrincipalException pe) {
135                            return;
136                    }
137    
138                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
139                            WebKeys.THEME_DISPLAY);
140    
141                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
142    
143                    try {
144                            String redirect = ParamUtil.getString(actionRequest, "redirect");
145                            String closeRedirect = ParamUtil.getString(
146                                    actionRequest, "closeRedirect");
147    
148                            Layout layout = null;
149                            String oldFriendlyURL = StringPool.BLANK;
150    
151                            if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
152                                    Object[] returnValue = updateLayout(
153                                            actionRequest, actionResponse);
154    
155                                    layout = (Layout)returnValue[0];
156                                    oldFriendlyURL = (String)returnValue[1];
157    
158                                    redirect = updateCloseRedirect(
159                                            redirect, null, layout, oldFriendlyURL);
160                                    closeRedirect = updateCloseRedirect(
161                                            closeRedirect, null, layout, oldFriendlyURL);
162                            }
163                            else if (cmd.equals(Constants.DELETE)) {
164                                    Object[] returnValue = SitesUtil.deleteLayout(
165                                            actionRequest, actionResponse);
166    
167                                    Group group = (Group)returnValue[0];
168                                    oldFriendlyURL = (String)returnValue[1];
169                                    long newRefererPlid = (Long)returnValue[2];
170    
171                                    redirect = updateCloseRedirect(
172                                            redirect, group, null, oldFriendlyURL);
173                                    redirect = HttpUtil.setParameter(
174                                            redirect, "refererPlid", newRefererPlid);
175    
176                                    closeRedirect = updateCloseRedirect(
177                                            closeRedirect, group, null, oldFriendlyURL);
178                            }
179                            else if (cmd.equals("copy_from_live")) {
180                                    StagingUtil.copyFromLive(actionRequest);
181                            }
182                            else if (cmd.equals("display_order")) {
183                                    updateDisplayOrder(actionRequest);
184                            }
185                            else if (cmd.equals("delete_layout_revision")) {
186                                    deleteLayoutRevision(actionRequest);
187                            }
188                            else if (cmd.equals("enable")) {
189                                    enableLayout(actionRequest);
190                            }
191                            else if (cmd.equals("publish_to_live")) {
192                                    StagingUtil.publishToLive(actionRequest);
193                            }
194                            else if (cmd.equals("publish_to_remote")) {
195                                    StagingUtil.publishToRemote(actionRequest);
196                            }
197                            else if (cmd.equals("reset_customized_view")) {
198                                    LayoutTypePortlet layoutTypePortlet =
199                                            themeDisplay.getLayoutTypePortlet();
200    
201                                    if ((layoutTypePortlet != null) &&
202                                            layoutTypePortlet.isCustomizable() &&
203                                            layoutTypePortlet.isCustomizedView()) {
204    
205                                            layoutTypePortlet.resetUserPreferences();
206                                    }
207                            }
208                            else if (cmd.equals("reset_prototype")) {
209                                    SitesUtil.resetPrototype(themeDisplay.getLayout());
210                            }
211                            else if (cmd.equals("schedule_copy_from_live")) {
212                                    StagingUtil.scheduleCopyFromLive(actionRequest);
213                            }
214                            else if (cmd.equals("schedule_publish_to_live")) {
215                                    StagingUtil.schedulePublishToLive(actionRequest);
216                            }
217                            else if (cmd.equals("schedule_publish_to_remote")) {
218                                    StagingUtil.schedulePublishToRemote(actionRequest);
219                            }
220                            else if (cmd.equals("select_layout_set_branch")) {
221                                    selectLayoutSetBranch(actionRequest);
222                            }
223                            else if (cmd.equals("select_layout_branch")) {
224                                    selectLayoutBranch(actionRequest);
225                            }
226                            else if (cmd.equals("unschedule_copy_from_live")) {
227                                    StagingUtil.unscheduleCopyFromLive(actionRequest);
228                            }
229                            else if (cmd.equals("unschedule_publish_to_live")) {
230                                    StagingUtil.unschedulePublishToLive(actionRequest);
231                            }
232                            else if (cmd.equals("unschedule_publish_to_remote")) {
233                                    StagingUtil.unschedulePublishToRemote(actionRequest);
234                            }
235                            else if (cmd.equals("update_layout_revision")) {
236                                    updateLayoutRevision(actionRequest, themeDisplay);
237                            }
238    
239                            if (Validator.isNotNull(closeRedirect)) {
240                                    SessionMessages.add(
241                                            actionRequest,
242                                            portletConfig.getPortletName() +
243                                                    SessionMessages.KEY_SUFFIX_CLOSE_REDIRECT,
244                                            closeRedirect);
245                            }
246    
247                            sendRedirect(actionRequest, actionResponse, redirect);
248                    }
249                    catch (Exception e) {
250                            if (e instanceof NoSuchLayoutException ||
251                                    e instanceof PrincipalException) {
252    
253                                    SessionErrors.add(actionRequest, e.getClass().getName());
254    
255                                    setForward(actionRequest, "portlet.layouts_admin.error");
256                            }
257                            else if (e instanceof ImageTypeException ||
258                                             e instanceof LayoutFriendlyURLException ||
259                                             e instanceof LayoutHiddenException ||
260                                             e instanceof LayoutNameException ||
261                                             e instanceof LayoutParentLayoutIdException ||
262                                             e instanceof LayoutSetVirtualHostException ||
263                                             e instanceof LayoutTypeException ||
264                                             e instanceof RequiredLayoutException ||
265                                             e instanceof UploadException) {
266    
267                                    if (e instanceof LayoutFriendlyURLException) {
268                                            SessionErrors.add(
269                                                    actionRequest,
270                                                    LayoutFriendlyURLException.class.getName(), e);
271                                    }
272                                    else {
273                                            SessionErrors.add(actionRequest, e.getClass().getName(), e);
274                                    }
275                            }
276                            else if (e instanceof RemoteExportException ||
277                                             e instanceof RemoteOptionsException ||
278                                             e instanceof SystemException) {
279    
280                                    SessionErrors.add(actionRequest, e.getClass().getName(), e);
281    
282                                    String redirect = ParamUtil.getString(
283                                            actionRequest, "pagesRedirect");
284    
285                                    sendRedirect(actionRequest, actionResponse, redirect);
286                            }
287                            else {
288                                    throw e;
289                            }
290                    }
291            }
292    
293            @Override
294            public ActionForward render(
295                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
296                            RenderRequest renderRequest, RenderResponse renderResponse)
297                    throws Exception {
298    
299                    try {
300                            checkPermissions(renderRequest);
301                    }
302                    catch (PrincipalException pe) {
303                            SessionErrors.add(
304                                    renderRequest, PrincipalException.class.getName());
305    
306                            return mapping.findForward("portlet.layouts_admin.error");
307                    }
308    
309                    try {
310                            getGroup(renderRequest);
311                    }
312                    catch (Exception e) {
313                            if (e instanceof NoSuchGroupException ||
314                                    e instanceof PrincipalException) {
315    
316                                    SessionErrors.add(renderRequest, e.getClass().getName());
317    
318                                    return mapping.findForward("portlet.layouts_admin.error");
319                            }
320                            else {
321                                    throw e;
322                            }
323                    }
324    
325                    return mapping.findForward(
326                            getForward(renderRequest, "portlet.layouts_admin.edit_layouts"));
327            }
328    
329            @Override
330            public void serveResource(
331                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
332                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
333                    throws Exception {
334    
335                    String cmd = ParamUtil.getString(resourceRequest, Constants.CMD);
336    
337                    PortletContext portletContext = portletConfig.getPortletContext();
338    
339                    PortletRequestDispatcher portletRequestDispatcher = null;
340    
341                    if (cmd.equals(ActionKeys.PUBLISH_STAGING)) {
342                            portletRequestDispatcher = portletContext.getRequestDispatcher(
343                                    "/html/portlet/layouts_admin/scheduled_publishing_events.jsp");
344                    }
345                    else if (cmd.equals(ActionKeys.VIEW_TREE)) {
346                            getGroup(resourceRequest);
347    
348                            portletRequestDispatcher = portletContext.getRequestDispatcher(
349                                    "/html/portlet/layouts_admin/tree_js.jsp");
350                    }
351                    else {
352                            getGroup(resourceRequest);
353    
354                            portletRequestDispatcher = portletContext.getRequestDispatcher(
355                                    "/html/portlet/layouts_admin/view_resources.jsp");
356                    }
357    
358                    portletRequestDispatcher.include(resourceRequest, resourceResponse);
359            }
360    
361            protected void checkPermissions(PortletRequest portletRequest)
362                    throws Exception {
363    
364                    // LEP-850
365    
366                    Group group = getGroup(portletRequest);
367    
368                    if (group == null) {
369                            throw new PrincipalException();
370                    }
371    
372                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
373                            WebKeys.THEME_DISPLAY);
374    
375                    PermissionChecker permissionChecker =
376                            themeDisplay.getPermissionChecker();
377    
378                    Layout layout = themeDisplay.getLayout();
379    
380                    String cmd = ParamUtil.getString(portletRequest, Constants.CMD);
381    
382                    long selPlid = ParamUtil.getLong(portletRequest, "selPlid");
383    
384                    if (selPlid > 0) {
385                            layout = LayoutLocalServiceUtil.getLayout(selPlid);
386                    }
387    
388                    if (cmd.equals(Constants.ADD)) {
389                            long parentPlid = ParamUtil.getLong(portletRequest, "parentPlid");
390    
391                            if ((parentPlid == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
392                                    if (!GroupPermissionUtil.contains(
393                                                    permissionChecker, group.getGroupId(),
394                                                    ActionKeys.ADD_LAYOUT)) {
395    
396                                            throw new PrincipalException();
397                                    }
398                                    else {
399                                            return;
400                                    }
401                            }
402                            else {
403                                    layout = LayoutLocalServiceUtil.getLayout(parentPlid);
404    
405                                    if (!LayoutPermissionUtil.contains(
406                                                    permissionChecker, layout, ActionKeys.ADD_LAYOUT)) {
407    
408                                            throw new PrincipalException();
409                                    }
410                                    else {
411                                            return;
412                                    }
413                            }
414                    }
415                    else if (cmd.equals(Constants.DELETE)) {
416                            if (!LayoutPermissionUtil.contains(
417                                            permissionChecker, layout, ActionKeys.DELETE)) {
418    
419                                    throw new PrincipalException();
420                            }
421                            else {
422                                    return;
423                            }
424                    }
425                    else if (cmd.equals("reset_customized_view")) {
426                            if (!LayoutPermissionUtil.contains(
427                                            permissionChecker, layout, ActionKeys.CUSTOMIZE)) {
428    
429                                    throw new PrincipalException();
430                            }
431                            else {
432                                    return;
433                            }
434                    }
435                    else if (cmd.equals("reset_prototype")) {
436                            if (!LayoutPermissionUtil.contains(
437                                            permissionChecker, layout, ActionKeys.UPDATE) ||
438                                    !GroupPermissionUtil.contains(
439                                            permissionChecker, layout.getGroupId(),
440                                            ActionKeys.UPDATE)) {
441    
442                                    throw new PrincipalException();
443                            }
444                            else {
445                                    return;
446                            }
447                    }
448    
449                    boolean hasUpdateLayoutPermission = false;
450    
451                    if (layout != null) {
452                            hasUpdateLayoutPermission = LayoutPermissionUtil.contains(
453                                    permissionChecker, layout, ActionKeys.UPDATE);
454                    }
455    
456                    boolean hasPermission = true;
457    
458                    if (cmd.equals("publish_to_live")) {
459                            if (group.isSite()) {
460                                    boolean publishToLive = GroupPermissionUtil.contains(
461                                            permissionChecker, group.getGroupId(),
462                                            ActionKeys.PUBLISH_STAGING);
463    
464                                    if (!hasUpdateLayoutPermission && !publishToLive) {
465                                            hasPermission = false;
466                                    }
467                            }
468                            else if (group.isOrganization()) {
469                                    boolean publishToLive = OrganizationPermissionUtil.contains(
470                                            permissionChecker, group.getOrganizationId(),
471                                            ActionKeys.PUBLISH_STAGING);
472    
473                                    if (!hasUpdateLayoutPermission && !publishToLive) {
474                                            hasPermission = false;
475                                    }
476                            }
477                    }
478    
479                    if (group.isCompany()) {
480                            if (!permissionChecker.isCompanyAdmin()) {
481                                    hasPermission = false;
482                            }
483                    }
484                    else if (group.isLayoutPrototype()) {
485                            LayoutPrototypePermissionUtil.check(
486                                    permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
487                    }
488                    else if (group.isLayoutSetPrototype()) {
489                            LayoutSetPrototypePermissionUtil.check(
490                                    permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
491                    }
492                    else if (group.isUser()) {
493                            long groupUserId = group.getClassPK();
494    
495                            User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
496    
497                            long[] organizationIds = groupUser.getOrganizationIds();
498    
499                            UserPermissionUtil.check(
500                                    permissionChecker, groupUserId, organizationIds,
501                                    ActionKeys.UPDATE);
502                    }
503    
504                    if (!hasPermission) {
505                            throw new PrincipalException();
506                    }
507            }
508    
509            protected void deleteLayoutRevision(ActionRequest actionRequest)
510                    throws Exception {
511    
512                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
513                            actionRequest);
514    
515                    long layoutRevisionId = ParamUtil.getLong(
516                            actionRequest, "layoutRevisionId");
517    
518                    LayoutRevision layoutRevision =
519                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
520    
521                    LayoutRevisionLocalServiceUtil.deleteLayoutRevision(layoutRevision);
522    
523                    boolean updateRecentLayoutRevisionId = ParamUtil.getBoolean(
524                            actionRequest, "updateRecentLayoutRevisionId");
525    
526                    if (updateRecentLayoutRevisionId) {
527                            StagingUtil.setRecentLayoutRevisionId(
528                                    request, layoutRevision.getLayoutSetBranchId(),
529                                    layoutRevision.getPlid(),
530                                    layoutRevision.getParentLayoutRevisionId());
531                    }
532            }
533    
534            protected void deleteThemeSettingsProperties(
535                    UnicodeProperties typeSettingsProperties, String device) {
536    
537                    String keyPrefix = ThemeSettingImpl.namespaceProperty(device);
538    
539                    Set<String> keys = typeSettingsProperties.keySet();
540    
541                    Iterator<String> itr = keys.iterator();
542    
543                    while (itr.hasNext()) {
544                            String key = itr.next();
545    
546                            if (key.startsWith(keyPrefix)) {
547                                    itr.remove();
548                            }
549                    }
550            }
551    
552            protected void enableLayout(ActionRequest actionRequest) throws Exception {
553                    long incompleteLayoutRevisionId = ParamUtil.getLong(
554                            actionRequest, "incompleteLayoutRevisionId");
555    
556                    LayoutRevision incompleteLayoutRevision =
557                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
558                                    incompleteLayoutRevisionId);
559    
560                    long layoutBranchId = ParamUtil.getLong(
561                            actionRequest, "layoutBranchId",
562                            incompleteLayoutRevision.getLayoutBranchId());
563    
564                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
565                            actionRequest);
566    
567                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
568    
569                    LayoutRevisionLocalServiceUtil.updateLayoutRevision(
570                            serviceContext.getUserId(),
571                            incompleteLayoutRevision.getLayoutRevisionId(), layoutBranchId,
572                            incompleteLayoutRevision.getName(),
573                            incompleteLayoutRevision.getTitle(),
574                            incompleteLayoutRevision.getDescription(),
575                            incompleteLayoutRevision.getKeywords(),
576                            incompleteLayoutRevision.getRobots(),
577                            incompleteLayoutRevision.getTypeSettings(),
578                            incompleteLayoutRevision.getIconImage(),
579                            incompleteLayoutRevision.getIconImageId(),
580                            incompleteLayoutRevision.getThemeId(),
581                            incompleteLayoutRevision.getColorSchemeId(),
582                            incompleteLayoutRevision.getWapThemeId(),
583                            incompleteLayoutRevision.getWapColorSchemeId(),
584                            incompleteLayoutRevision.getCss(), serviceContext);
585            }
586    
587            protected String getColorSchemeId(
588                            long companyId, String themeId, String colorSchemeId,
589                            boolean wapTheme)
590                    throws Exception {
591    
592                    Theme theme = ThemeLocalServiceUtil.getTheme(
593                            companyId, themeId, wapTheme);
594    
595                    if (!theme.hasColorSchemes()) {
596                            colorSchemeId = StringPool.BLANK;
597                    }
598    
599                    if (Validator.isNull(colorSchemeId)) {
600                            ColorScheme colorScheme = ThemeLocalServiceUtil.getColorScheme(
601                                    companyId, themeId, colorSchemeId, wapTheme);
602    
603                            colorSchemeId = colorScheme.getColorSchemeId();
604                    }
605    
606                    return colorSchemeId;
607            }
608    
609            protected Group getGroup(PortletRequest portletRequest) throws Exception {
610                    return ActionUtil.getGroup(portletRequest);
611            }
612    
613            protected byte[] getIconBytes(
614                    UploadPortletRequest uploadPortletRequest, String iconFileName) {
615    
616                    InputStream inputStream = null;
617    
618                    try {
619                            inputStream = uploadPortletRequest.getFileAsStream(iconFileName);
620    
621                            if (inputStream != null) {
622                                    return FileUtil.getBytes(inputStream);
623                            }
624                    }
625                    catch (IOException e) {
626                            if (_log.isWarnEnabled()) {
627                                    _log.warn("Unable to retrieve icon", e);
628                            }
629                    }
630    
631                    return new byte[0];
632            }
633    
634            protected UnicodeProperties getThemeSettingsProperties(
635                            ActionRequest actionRequest, long companyId,
636                            UnicodeProperties typeSettingsProperties, String device,
637                            String themeId, boolean wapTheme)
638                    throws Exception {
639    
640                    Theme theme = ThemeLocalServiceUtil.getTheme(
641                            companyId, themeId, wapTheme);
642    
643                    deleteThemeSettingsProperties(typeSettingsProperties, device);
644    
645                    Map<String, ThemeSetting> configurableSettings =
646                            theme.getConfigurableSettings();
647    
648                    if (configurableSettings.isEmpty()) {
649                            return typeSettingsProperties;
650                    }
651    
652                    for (String key : configurableSettings.keySet()) {
653                            ThemeSetting themeSetting = configurableSettings.get(key);
654    
655                            String type = GetterUtil.getString(themeSetting.getType(), "text");
656    
657                            String property =
658                                    device + "ThemeSettingsProperties--" + key +
659                                            StringPool.DOUBLE_DASH;
660    
661                            String value = ParamUtil.getString(actionRequest, property);
662    
663                            if (type.equals("checkbox")) {
664                                    value = String.valueOf(GetterUtil.getBoolean(value));
665                            }
666    
667                            if (!value.equals(themeSetting.getValue())) {
668                                    typeSettingsProperties.setProperty(
669                                            ThemeSettingImpl.namespaceProperty(device, key), value);
670                            }
671                    }
672    
673                    return typeSettingsProperties;
674            }
675    
676            @Override
677            protected boolean isCheckMethodOnProcessAction() {
678                    return _CHECK_METHOD_ON_PROCESS_ACTION;
679            }
680    
681            protected void selectLayoutBranch(ActionRequest actionRequest)
682                    throws Exception {
683    
684                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
685                            actionRequest);
686    
687                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
688                            WebKeys.THEME_DISPLAY);
689    
690                    long layoutSetBranchId = ParamUtil.getLong(
691                            actionRequest, "layoutSetBranchId");
692    
693                    long layoutBranchId = ParamUtil.getLong(
694                            actionRequest, "layoutBranchId");
695    
696                    StagingUtil.setRecentLayoutBranchId(
697                            request, layoutSetBranchId, themeDisplay.getPlid(), layoutBranchId);
698            }
699    
700            protected void selectLayoutSetBranch(ActionRequest actionRequest)
701                    throws Exception {
702    
703                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
704                            actionRequest);
705    
706                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
707                    boolean privateLayout = ParamUtil.getBoolean(
708                            actionRequest, "privateLayout");
709    
710                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
711                            groupId, privateLayout);
712    
713                    long layoutSetBranchId = ParamUtil.getLong(
714                            actionRequest, "layoutSetBranchId");
715    
716                    // Ensure layout set branch exists
717    
718                    LayoutSetBranch layoutSetBranch =
719                            LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
720                                    layoutSetBranchId);
721    
722                    StagingUtil.setRecentLayoutSetBranchId(
723                            request, layoutSet.getLayoutSetId(),
724                            layoutSetBranch.getLayoutSetBranchId());
725            }
726    
727            protected String updateCloseRedirect(
728                    String closeRedirect, Group group, Layout layout,
729                    String oldLayoutFriendlyURL) {
730    
731                    if (Validator.isNull(closeRedirect) ||
732                            Validator.isNull(oldLayoutFriendlyURL)) {
733    
734                            return closeRedirect;
735                    }
736    
737                    if (layout != null) {
738                            String oldPath = oldLayoutFriendlyURL;
739                            String newPath = layout.getFriendlyURL();
740    
741                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
742                    }
743                    else if (group != null) {
744                            String oldPath = group.getFriendlyURL() + oldLayoutFriendlyURL;
745                            String newPath = group.getFriendlyURL();
746    
747                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
748                    }
749    
750                    return closeRedirect;
751            }
752    
753            protected void updateDisplayOrder(ActionRequest actionRequest)
754                    throws Exception {
755    
756                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
757                    boolean privateLayout = ParamUtil.getBoolean(
758                            actionRequest, "privateLayout");
759                    long parentLayoutId = ParamUtil.getLong(
760                            actionRequest, "parentLayoutId");
761                    long[] layoutIds = StringUtil.split(
762                            ParamUtil.getString(actionRequest, "layoutIds"), 0L);
763    
764                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
765                            actionRequest);
766    
767                    LayoutServiceUtil.setLayouts(
768                            groupId, privateLayout, parentLayoutId, layoutIds, serviceContext);
769            }
770    
771            protected Object[] updateLayout(
772                            ActionRequest actionRequest, ActionResponse actionResponse)
773                    throws Exception {
774    
775                    UploadPortletRequest uploadPortletRequest =
776                            PortalUtil.getUploadPortletRequest(actionRequest);
777    
778                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
779                            WebKeys.THEME_DISPLAY);
780    
781                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
782    
783                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
784                    long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
785                    long stagingGroupId = ParamUtil.getLong(
786                            actionRequest, "stagingGroupId");
787                    boolean privateLayout = ParamUtil.getBoolean(
788                            actionRequest, "privateLayout");
789                    long layoutId = ParamUtil.getLong(actionRequest, "layoutId");
790                    long parentLayoutId = ParamUtil.getLong(
791                            uploadPortletRequest, "parentLayoutId");
792                    Map<Locale, String> nameMap = LocalizationUtil.getLocalizationMap(
793                            actionRequest, "name");
794                    Map<Locale, String> titleMap = LocalizationUtil.getLocalizationMap(
795                            actionRequest, "title");
796                    Map<Locale, String> descriptionMap =
797                            LocalizationUtil.getLocalizationMap(actionRequest, "description");
798                    Map<Locale, String> keywordsMap = LocalizationUtil.getLocalizationMap(
799                            actionRequest, "keywords");
800                    Map<Locale, String> robotsMap = LocalizationUtil.getLocalizationMap(
801                            actionRequest, "robots");
802                    String type = ParamUtil.getString(uploadPortletRequest, "type");
803                    boolean hidden = ParamUtil.getBoolean(uploadPortletRequest, "hidden");
804                    String friendlyURL = ParamUtil.getString(
805                            uploadPortletRequest, "friendlyURL");
806                    boolean iconImage = ParamUtil.getBoolean(
807                            uploadPortletRequest, "iconImage");
808                    byte[] iconBytes = getIconBytes(uploadPortletRequest, "iconFileName");
809                    long layoutPrototypeId = ParamUtil.getLong(
810                            uploadPortletRequest, "layoutPrototypeId");
811    
812                    boolean inheritFromParentLayoutId = ParamUtil.getBoolean(
813                            uploadPortletRequest, "inheritFromParentLayoutId");
814    
815                    long copyLayoutId = ParamUtil.getLong(
816                            uploadPortletRequest, "copyLayoutId");
817    
818                    String layoutTemplateId = ParamUtil.getString(
819                            uploadPortletRequest, "layoutTemplateId",
820                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID);
821    
822                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
823                            Layout.class.getName(), actionRequest);
824    
825                    Layout layout = null;
826                    UnicodeProperties layoutTypeSettingsProperties = null;
827                    String oldFriendlyURL = StringPool.BLANK;
828    
829                    if (cmd.equals(Constants.ADD)) {
830    
831                            // Add layout
832    
833                            if (inheritFromParentLayoutId && (parentLayoutId > 0)) {
834                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
835                                            groupId, privateLayout, parentLayoutId);
836    
837                                    layout = LayoutServiceUtil.addLayout(
838                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
839                                            descriptionMap, keywordsMap, robotsMap,
840                                            parentLayout.getType(), hidden, friendlyURL,
841                                            serviceContext);
842    
843                                    LayoutServiceUtil.updateLayout(
844                                            layout.getGroupId(), layout.isPrivateLayout(),
845                                            layout.getLayoutId(), parentLayout.getTypeSettings());
846    
847                                    if (parentLayout.isTypePortlet()) {
848                                            ActionUtil.copyPreferences(
849                                                    actionRequest, layout, parentLayout);
850    
851                                            SitesUtil.copyLookAndFeel(layout, parentLayout);
852                                    }
853                            }
854                            else if (layoutPrototypeId > 0) {
855                                    LayoutPrototype layoutPrototype =
856                                            LayoutPrototypeServiceUtil.getLayoutPrototype(
857                                                    layoutPrototypeId);
858    
859                                    serviceContext.setAttribute("layoutPrototypeLinkEnabled", true);
860                                    serviceContext.setAttribute(
861                                            "layoutPrototypeUuid", layoutPrototype.getUuid());
862    
863                                    layout = LayoutServiceUtil.addLayout(
864                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
865                                            descriptionMap, keywordsMap, robotsMap,
866                                            LayoutConstants.TYPE_PORTLET, hidden, friendlyURL,
867                                            serviceContext);
868                            }
869                            else {
870                                    layout = LayoutServiceUtil.addLayout(
871                                            groupId, privateLayout, parentLayoutId, nameMap, titleMap,
872                                            descriptionMap, keywordsMap, robotsMap, type, hidden,
873                                            friendlyURL, serviceContext);
874                            }
875    
876                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
877                    }
878                    else {
879    
880                            // Update layout
881    
882                            layout = LayoutLocalServiceUtil.getLayout(
883                                    groupId, privateLayout, layoutId);
884    
885                            oldFriendlyURL = layout.getFriendlyURL();
886    
887                            layout = LayoutServiceUtil.updateLayout(
888                                    groupId, privateLayout, layoutId, layout.getParentLayoutId(),
889                                    nameMap, titleMap, descriptionMap, keywordsMap, robotsMap, type,
890                                    hidden, friendlyURL, Boolean.valueOf(iconImage), iconBytes,
891                                    serviceContext);
892    
893                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
894    
895                            if (oldFriendlyURL.equals(layout.getFriendlyURL())) {
896                                    oldFriendlyURL = StringPool.BLANK;
897                            }
898    
899                            UnicodeProperties formTypeSettingsProperties =
900                                    PropertiesParamUtil.getProperties(
901                                            actionRequest, "TypeSettingsProperties--");
902    
903                            if (type.equals(LayoutConstants.TYPE_PORTLET)) {
904                                    LayoutTypePortlet layoutTypePortlet =
905                                            (LayoutTypePortlet)layout.getLayoutType();
906    
907                                    layoutTypePortlet.setLayoutTemplateId(
908                                            themeDisplay.getUserId(), layoutTemplateId);
909    
910                                    if ((copyLayoutId > 0) &&
911                                            (copyLayoutId != layout.getLayoutId())) {
912    
913                                            try {
914                                                    Layout copyLayout = LayoutLocalServiceUtil.getLayout(
915                                                            groupId, privateLayout, copyLayoutId);
916    
917                                                    if (copyLayout.isTypePortlet()) {
918                                                            layoutTypeSettingsProperties =
919                                                                    copyLayout.getTypeSettingsProperties();
920    
921                                                            ActionUtil.copyPreferences(
922                                                                    actionRequest, layout, copyLayout);
923    
924                                                            SitesUtil.copyLookAndFeel(layout, copyLayout);
925                                                    }
926                                            }
927                                            catch (NoSuchLayoutException nsle) {
928                                            }
929                                    }
930                                    else {
931                                            layoutTypeSettingsProperties.putAll(
932                                                    formTypeSettingsProperties);
933    
934                                            LayoutServiceUtil.updateLayout(
935                                                    groupId, privateLayout, layoutId,
936                                                    layout.getTypeSettings());
937                                    }
938                            }
939                            else {
940                                    layout.setTypeSettingsProperties(formTypeSettingsProperties);
941    
942                                    layoutTypeSettingsProperties.putAll(
943                                            layout.getTypeSettingsProperties());
944    
945                                    LayoutServiceUtil.updateLayout(
946                                            groupId, privateLayout, layoutId, layout.getTypeSettings());
947                            }
948    
949                            HttpServletResponse response = PortalUtil.getHttpServletResponse(
950                                    actionResponse);
951    
952                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
953    
954                            EventsProcessorUtil.process(
955                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_UPDATE,
956                                    layoutSettings.getConfigurationActionUpdate(),
957                                    uploadPortletRequest, response);
958                    }
959    
960                    updateLookAndFeel(
961                            actionRequest, themeDisplay.getCompanyId(), liveGroupId,
962                            stagingGroupId, privateLayout, layout.getLayoutId(),
963                            layoutTypeSettingsProperties);
964    
965                    return new Object[] {layout, oldFriendlyURL};
966            }
967    
968            protected void updateLayoutRevision(
969                            ActionRequest actionRequest, ThemeDisplay themeDisplay)
970                    throws Exception {
971    
972                    long layoutRevisionId = ParamUtil.getLong(
973                            actionRequest, "layoutRevisionId");
974    
975                    LayoutRevision layoutRevision =
976                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
977    
978                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
979                            actionRequest);
980    
981                    LayoutRevision enableLayoutRevision =
982                            LayoutRevisionLocalServiceUtil.updateLayoutRevision(
983                            serviceContext.getUserId(), layoutRevisionId,
984                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
985                            layoutRevision.getTitle(), layoutRevision.getDescription(),
986                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
987                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
988                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
989                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
990                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
991                            serviceContext);
992    
993                    if (layoutRevision.getStatus() == WorkflowConstants.STATUS_INCOMPLETE) {
994                            LayoutRevision lastLayoutRevision =
995                                    LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision(
996                                            enableLayoutRevision.getPlid(), true);
997    
998                            if (lastLayoutRevision != null) {
999                                    LayoutRevision newLayoutRevision =
1000                                            LayoutRevisionLocalServiceUtil.addLayoutRevision(
1001                                                    serviceContext.getUserId(),
1002                                                    layoutRevision.getLayoutSetBranchId(),
1003                                                    layoutRevision.getLayoutBranchId(),
1004                                                    enableLayoutRevision.getLayoutRevisionId(), false,
1005                                                    layoutRevision.getPlid(),
1006                                                    lastLayoutRevision.getLayoutRevisionId(),
1007                                                    lastLayoutRevision.getPrivateLayout(),
1008                                                    lastLayoutRevision.getName(),
1009                                                    lastLayoutRevision.getTitle(),
1010                                                    lastLayoutRevision.getDescription(),
1011                                                    lastLayoutRevision.getKeywords(),
1012                                                    lastLayoutRevision.getRobots(),
1013                                                    lastLayoutRevision.getTypeSettings(),
1014                                                    lastLayoutRevision.isIconImage(),
1015                                                    lastLayoutRevision.getIconImageId(),
1016                                                    lastLayoutRevision.getThemeId(),
1017                                                    lastLayoutRevision.getColorSchemeId(),
1018                                                    lastLayoutRevision.getWapThemeId(),
1019                                                    lastLayoutRevision.getWapColorSchemeId(),
1020                                                    lastLayoutRevision.getCss(), serviceContext);
1021    
1022                                    StagingUtil.setRecentLayoutRevisionId(
1023                                            themeDisplay.getUser(),
1024                                            newLayoutRevision.getLayoutSetBranchId(),
1025                                            newLayoutRevision.getPlid(),
1026                                            newLayoutRevision.getLayoutRevisionId());
1027                            }
1028                    }
1029            }
1030    
1031            protected void updateLookAndFeel(
1032                            ActionRequest actionRequest, long companyId, long liveGroupId,
1033                            long stagingGroupId, boolean privateLayout, long layoutId,
1034                            UnicodeProperties typeSettingsProperties)
1035                    throws Exception {
1036    
1037                    String[] devices = StringUtil.split(
1038                            ParamUtil.getString(actionRequest, "devices"));
1039    
1040                    for (String device : devices) {
1041                            String themeId = ParamUtil.getString(
1042                                    actionRequest, device + "ThemeId");
1043                            String colorSchemeId = ParamUtil.getString(
1044                                    actionRequest, device + "ColorSchemeId");
1045                            String css = ParamUtil.getString(actionRequest, device + "Css");
1046                            boolean wapTheme = device.equals("wap");
1047    
1048                            boolean inheritLookAndFeel = ParamUtil.getBoolean(
1049                                    actionRequest, device + "InheritLookAndFeel");
1050    
1051                            if (inheritLookAndFeel) {
1052                                    themeId = ThemeImpl.getDefaultRegularThemeId(companyId);
1053                                    colorSchemeId = StringPool.BLANK;
1054    
1055                                    deleteThemeSettingsProperties(typeSettingsProperties, device);
1056                            }
1057                            else if (Validator.isNotNull(themeId)) {
1058                                    colorSchemeId = getColorSchemeId(
1059                                            companyId, themeId, colorSchemeId, wapTheme);
1060    
1061                                    getThemeSettingsProperties(
1062                                            actionRequest, companyId, typeSettingsProperties, device,
1063                                            themeId, wapTheme);
1064                            }
1065    
1066                            long groupId = liveGroupId;
1067    
1068                            if (stagingGroupId > 0) {
1069                                    groupId = stagingGroupId;
1070                            }
1071    
1072                            LayoutServiceUtil.updateLayout(
1073                                    groupId, privateLayout, layoutId,
1074                                    typeSettingsProperties.toString());
1075    
1076                            LayoutServiceUtil.updateLookAndFeel(
1077                                    groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
1078                                    wapTheme);
1079                    }
1080            }
1081    
1082            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
1083    
1084            private static Log _log = LogFactoryUtil.getLog(EditLayoutsAction.class);
1085    
1086    }