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("schedule_copy_from_live")) {
209                                    StagingUtil.scheduleCopyFromLive(actionRequest);
210                            }
211                            else if (cmd.equals("schedule_publish_to_live")) {
212                                    StagingUtil.schedulePublishToLive(actionRequest);
213                            }
214                            else if (cmd.equals("schedule_publish_to_remote")) {
215                                    StagingUtil.schedulePublishToRemote(actionRequest);
216                            }
217                            else if (cmd.equals("select_layout_set_branch")) {
218                                    selectLayoutSetBranch(actionRequest);
219                            }
220                            else if (cmd.equals("select_layout_branch")) {
221                                    selectLayoutBranch(actionRequest);
222                            }
223                            else if (cmd.equals("unschedule_copy_from_live")) {
224                                    StagingUtil.unscheduleCopyFromLive(actionRequest);
225                            }
226                            else if (cmd.equals("unschedule_publish_to_live")) {
227                                    StagingUtil.unschedulePublishToLive(actionRequest);
228                            }
229                            else if (cmd.equals("unschedule_publish_to_remote")) {
230                                    StagingUtil.unschedulePublishToRemote(actionRequest);
231                            }
232                            else if (cmd.equals("update_layout_revision")) {
233                                    updateLayoutRevision(actionRequest);
234                            }
235    
236                            if (Validator.isNotNull(closeRedirect)) {
237                                    SessionMessages.add(
238                                            actionRequest,
239                                            portletConfig.getPortletName() +
240                                                    SessionMessages.KEY_SUFFIX_CLOSE_REDIRECT,
241                                            closeRedirect);
242                            }
243    
244                            sendRedirect(actionRequest, actionResponse, redirect);
245                    }
246                    catch (Exception e) {
247                            if (e instanceof NoSuchLayoutException ||
248                                    e instanceof PrincipalException) {
249    
250                                    SessionErrors.add(actionRequest, e.getClass().getName());
251    
252                                    setForward(actionRequest, "portlet.layouts_admin.error");
253                            }
254                            else if (e instanceof ImageTypeException ||
255                                             e instanceof LayoutFriendlyURLException ||
256                                             e instanceof LayoutHiddenException ||
257                                             e instanceof LayoutNameException ||
258                                             e instanceof LayoutParentLayoutIdException ||
259                                             e instanceof LayoutSetVirtualHostException ||
260                                             e instanceof LayoutTypeException ||
261                                             e instanceof RequiredLayoutException ||
262                                             e instanceof UploadException) {
263    
264                                    if (e instanceof LayoutFriendlyURLException) {
265                                            SessionErrors.add(
266                                                    actionRequest,
267                                                    LayoutFriendlyURLException.class.getName(), e);
268                                    }
269                                    else {
270                                            SessionErrors.add(actionRequest, e.getClass().getName(), e);
271                                    }
272                            }
273                            else if (e instanceof RemoteExportException ||
274                                             e instanceof RemoteOptionsException ||
275                                             e instanceof SystemException) {
276    
277                                    SessionErrors.add(actionRequest, e.getClass().getName(), e);
278    
279                                    String redirect = ParamUtil.getString(
280                                            actionRequest, "pagesRedirect");
281    
282                                    sendRedirect(actionRequest, actionResponse, redirect);
283                            }
284                            else {
285                                    throw e;
286                            }
287                    }
288            }
289    
290            @Override
291            public ActionForward render(
292                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
293                            RenderRequest renderRequest, RenderResponse renderResponse)
294                    throws Exception {
295    
296                    try {
297                            checkPermissions(renderRequest);
298                    }
299                    catch (PrincipalException pe) {
300                            SessionErrors.add(
301                                    renderRequest, PrincipalException.class.getName());
302    
303                            return mapping.findForward("portlet.layouts_admin.error");
304                    }
305    
306                    try {
307                            getGroup(renderRequest);
308                    }
309                    catch (Exception e) {
310                            if (e instanceof NoSuchGroupException ||
311                                    e instanceof PrincipalException) {
312    
313                                    SessionErrors.add(renderRequest, e.getClass().getName());
314    
315                                    return mapping.findForward("portlet.layouts_admin.error");
316                            }
317                            else {
318                                    throw e;
319                            }
320                    }
321    
322                    return mapping.findForward(
323                            getForward(renderRequest, "portlet.layouts_admin.edit_layouts"));
324            }
325    
326            @Override
327            public void serveResource(
328                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
329                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
330                    throws Exception {
331    
332                    String cmd = ParamUtil.getString(resourceRequest, Constants.CMD);
333    
334                    PortletContext portletContext = portletConfig.getPortletContext();
335    
336                    PortletRequestDispatcher portletRequestDispatcher = null;
337    
338                    if (cmd.equals(ActionKeys.PUBLISH_STAGING)) {
339                            portletRequestDispatcher = portletContext.getRequestDispatcher(
340                                    "/html/portlet/layouts_admin/scheduled_publishing_events.jsp");
341                    }
342                    else if (cmd.equals(ActionKeys.VIEW_TREE)) {
343                            getGroup(resourceRequest);
344    
345                            portletRequestDispatcher = portletContext.getRequestDispatcher(
346                                    "/html/portlet/layouts_admin/tree_js.jsp");
347                    }
348                    else {
349                            getGroup(resourceRequest);
350    
351                            portletRequestDispatcher = portletContext.getRequestDispatcher(
352                                    "/html/portlet/layouts_admin/view_resources.jsp");
353                    }
354    
355                    portletRequestDispatcher.include(resourceRequest, resourceResponse);
356            }
357    
358            protected void checkPermissions(PortletRequest portletRequest)
359                    throws Exception {
360    
361                    // LEP-850
362    
363                    Group group = getGroup(portletRequest);
364    
365                    if (group == null) {
366                            throw new PrincipalException();
367                    }
368    
369                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
370                            WebKeys.THEME_DISPLAY);
371    
372                    PermissionChecker permissionChecker =
373                            themeDisplay.getPermissionChecker();
374    
375                    Layout layout = themeDisplay.getLayout();
376    
377                    String cmd = ParamUtil.getString(portletRequest, Constants.CMD);
378    
379                    long selPlid = ParamUtil.getLong(portletRequest, "selPlid");
380    
381                    if (selPlid > 0) {
382                            layout = LayoutLocalServiceUtil.getLayout(selPlid);
383                    }
384    
385                    if (cmd.equals(Constants.ADD)) {
386                            long parentPlid = ParamUtil.getLong(portletRequest, "parentPlid");
387    
388                            if ((parentPlid == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
389                                    if (!GroupPermissionUtil.contains(
390                                                    permissionChecker, group.getGroupId(),
391                                                    ActionKeys.ADD_LAYOUT)) {
392    
393                                            throw new PrincipalException();
394                                    }
395                                    else {
396                                            return;
397                                    }
398                            }
399                            else {
400                                    layout = LayoutLocalServiceUtil.getLayout(parentPlid);
401    
402                                    if (!LayoutPermissionUtil.contains(
403                                                    permissionChecker, layout, ActionKeys.ADD_LAYOUT)) {
404    
405                                            throw new PrincipalException();
406                                    }
407                                    else {
408                                            return;
409                                    }
410                            }
411                    }
412                    else if (cmd.equals(Constants.DELETE)) {
413                            if (!LayoutPermissionUtil.contains(
414                                            permissionChecker, layout, ActionKeys.DELETE)) {
415    
416                                    throw new PrincipalException();
417                            }
418                            else {
419                                    return;
420                            }
421                    }
422                    else if (cmd.equals("reset_customized_view")) {
423                            if (!LayoutPermissionUtil.contains(
424                                            permissionChecker, layout, ActionKeys.CUSTOMIZE)) {
425    
426                                    throw new PrincipalException();
427                            }
428                            else {
429                                    return;
430                            }
431                    }
432    
433                    boolean hasUpdateLayoutPermission = false;
434    
435                    if (layout != null) {
436                            hasUpdateLayoutPermission = LayoutPermissionUtil.contains(
437                                    permissionChecker, layout, ActionKeys.UPDATE);
438                    }
439    
440                    boolean hasPermission = true;
441    
442                    if (cmd.equals("publish_to_live")) {
443                            if (group.isSite()) {
444                                    boolean publishToLive = GroupPermissionUtil.contains(
445                                            permissionChecker, group.getGroupId(),
446                                            ActionKeys.PUBLISH_STAGING);
447    
448                                    if (!hasUpdateLayoutPermission && !publishToLive) {
449                                            hasPermission = false;
450                                    }
451                            }
452                            else if (group.isOrganization()) {
453                                    boolean publishToLive = OrganizationPermissionUtil.contains(
454                                            permissionChecker, group.getOrganizationId(),
455                                            ActionKeys.PUBLISH_STAGING);
456    
457                                    if (!hasUpdateLayoutPermission && !publishToLive) {
458                                            hasPermission = false;
459                                    }
460                            }
461                    }
462    
463                    if (group.isCompany()) {
464                            if (!permissionChecker.isCompanyAdmin()) {
465                                    hasPermission = false;
466                            }
467                    }
468                    else if (group.isLayoutPrototype()) {
469                            LayoutPrototypePermissionUtil.check(
470                                    permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
471                    }
472                    else if (group.isLayoutSetPrototype()) {
473                            LayoutSetPrototypePermissionUtil.check(
474                                    permissionChecker, group.getClassPK(), ActionKeys.UPDATE);
475                    }
476                    else if (group.isUser()) {
477                            long groupUserId = group.getClassPK();
478    
479                            User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
480    
481                            long[] organizationIds = groupUser.getOrganizationIds();
482    
483                            UserPermissionUtil.check(
484                                    permissionChecker, groupUserId, organizationIds,
485                                    ActionKeys.UPDATE);
486    
487                            if (!PropsValues.LAYOUT_USER_PRIVATE_LAYOUTS_MODIFIABLE &&
488                                    !PropsValues.LAYOUT_USER_PUBLIC_LAYOUTS_MODIFIABLE) {
489    
490                                    hasPermission = false;
491                            }
492                    }
493    
494                    if (!hasPermission) {
495                            throw new PrincipalException();
496                    }
497            }
498    
499            protected void deleteLayoutRevision(ActionRequest actionRequest)
500                    throws Exception {
501    
502                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
503                            actionRequest);
504    
505                    long layoutRevisionId = ParamUtil.getLong(
506                            actionRequest, "layoutRevisionId");
507    
508                    LayoutRevision layoutRevision =
509                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
510    
511                    LayoutRevisionLocalServiceUtil.deleteLayoutRevision(layoutRevision);
512    
513                    boolean updateRecentLayoutRevisionId = ParamUtil.getBoolean(
514                            actionRequest, "updateRecentLayoutRevisionId");
515    
516                    if (updateRecentLayoutRevisionId) {
517                            StagingUtil.setRecentLayoutRevisionId(
518                                    request, layoutRevision.getLayoutSetBranchId(),
519                                    layoutRevision.getPlid(),
520                                    layoutRevision.getParentLayoutRevisionId());
521                    }
522            }
523    
524            protected void deleteThemeSettings(
525                    UnicodeProperties typeSettingsProperties, String device) {
526    
527                    String keyPrefix = ThemeSettingImpl.namespaceProperty(device);
528    
529                    Set<String> keys = typeSettingsProperties.keySet();
530    
531                    Iterator<String> itr = keys.iterator();
532    
533                    while (itr.hasNext()) {
534                            String key = itr.next();
535    
536                            if (key.startsWith(keyPrefix)) {
537                                    itr.remove();
538                            }
539                    }
540            }
541    
542            protected void enableLayout(ActionRequest actionRequest) throws Exception {
543                    long incompleteLayoutRevisionId = ParamUtil.getLong(
544                            actionRequest, "incompleteLayoutRevisionId");
545    
546                    LayoutRevision incompleteLayoutRevision =
547                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
548                                    incompleteLayoutRevisionId);
549    
550                    long layoutBranchId = ParamUtil.getLong(
551                            actionRequest, "layoutBranchId",
552                            incompleteLayoutRevision.getLayoutBranchId());
553    
554                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
555                            actionRequest);
556    
557                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
558    
559                    LayoutRevisionLocalServiceUtil.updateLayoutRevision(
560                            serviceContext.getUserId(),
561                            incompleteLayoutRevision.getLayoutRevisionId(), layoutBranchId,
562                            incompleteLayoutRevision.getName(),
563                            incompleteLayoutRevision.getTitle(),
564                            incompleteLayoutRevision.getDescription(),
565                            incompleteLayoutRevision.getKeywords(),
566                            incompleteLayoutRevision.getRobots(),
567                            incompleteLayoutRevision.getTypeSettings(),
568                            incompleteLayoutRevision.getIconImage(),
569                            incompleteLayoutRevision.getIconImageId(),
570                            incompleteLayoutRevision.getThemeId(),
571                            incompleteLayoutRevision.getColorSchemeId(),
572                            incompleteLayoutRevision.getWapThemeId(),
573                            incompleteLayoutRevision.getWapColorSchemeId(),
574                            incompleteLayoutRevision.getCss(), serviceContext);
575            }
576    
577            protected String getColorSchemeId(
578                            ActionRequest actionRequest, long companyId,
579                            UnicodeProperties typeSettingsProperties, String device,
580                            String themeId, String colorSchemeId, boolean wapTheme)
581                    throws Exception {
582    
583                    Theme theme = ThemeLocalServiceUtil.getTheme(
584                            companyId, themeId, wapTheme);
585    
586                    if (!theme.hasColorSchemes()) {
587                            colorSchemeId = StringPool.BLANK;
588                    }
589    
590                    if (Validator.isNull(colorSchemeId)) {
591                            ColorScheme colorScheme =
592                                    ThemeLocalServiceUtil.getColorScheme(
593                                            companyId, themeId, colorSchemeId, wapTheme);
594    
595                            colorSchemeId = colorScheme.getColorSchemeId();
596                    }
597    
598                    deleteThemeSettings(typeSettingsProperties, device);
599    
600                    Map<String, ThemeSetting> configurableSettings =
601                            theme.getConfigurableSettings();
602    
603                    if (configurableSettings.isEmpty()) {
604                            return colorSchemeId;
605                    }
606    
607                    for (String key : configurableSettings.keySet()) {
608                            ThemeSetting themeSetting = configurableSettings.get(key);
609    
610                            String type = GetterUtil.getString(themeSetting.getType(), "text");
611    
612                            String property =
613                                    device + "ThemeSettingsProperties--" + key +
614                                            StringPool.DOUBLE_DASH;
615    
616                            String value = ParamUtil.getString(actionRequest, property);
617    
618                            if (type.equals("checkbox")) {
619                                    value = String.valueOf(GetterUtil.getBoolean(value));
620                            }
621    
622                            if (!value.equals(themeSetting.getValue())) {
623                                    typeSettingsProperties.setProperty(
624                                            ThemeSettingImpl.namespaceProperty(device, key),
625                                            value);
626                            }
627                    }
628    
629                    return colorSchemeId;
630            }
631    
632            protected Group getGroup(PortletRequest portletRequest) throws Exception {
633                    return ActionUtil.getGroup(portletRequest);
634            }
635    
636            protected byte[] getIconBytes(
637                    UploadPortletRequest uploadPortletRequest, String iconFileName) {
638    
639                    InputStream inputStream = null;
640    
641                    try {
642                            inputStream = uploadPortletRequest.getFileAsStream(iconFileName);
643    
644                            if (inputStream != null) {
645                                    return FileUtil.getBytes(inputStream);
646                            }
647                    }
648                    catch (IOException e) {
649                            if (_log.isWarnEnabled()) {
650                                    _log.warn("Unable to retrieve icon", e);
651                            }
652                    }
653    
654                    return new byte[0];
655            }
656    
657            @Override
658            protected boolean isCheckMethodOnProcessAction() {
659                    return _CHECK_METHOD_ON_PROCESS_ACTION;
660            }
661    
662            protected void selectLayoutBranch(ActionRequest actionRequest)
663                    throws Exception {
664    
665                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
666                            actionRequest);
667    
668                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
669                            WebKeys.THEME_DISPLAY);
670    
671                    long layoutSetBranchId = ParamUtil.getLong(
672                            actionRequest, "layoutSetBranchId");
673    
674                    long layoutBranchId = ParamUtil.getLong(
675                            actionRequest, "layoutBranchId");
676    
677                    StagingUtil.setRecentLayoutBranchId(
678                            request, layoutSetBranchId, themeDisplay.getPlid(),
679                            layoutBranchId);
680            }
681    
682            protected void selectLayoutSetBranch(ActionRequest actionRequest)
683                    throws Exception {
684    
685                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
686                            actionRequest);
687    
688                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
689                    boolean privateLayout = ParamUtil.getBoolean(
690                            actionRequest, "privateLayout");
691    
692                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
693                            groupId, privateLayout);
694    
695                    long layoutSetBranchId = ParamUtil.getLong(
696                            actionRequest, "layoutSetBranchId");
697    
698                    // Ensure layout set branch exists
699    
700                    LayoutSetBranch layoutSetBranch =
701                            LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
702                                    layoutSetBranchId);
703    
704                    StagingUtil.setRecentLayoutSetBranchId(
705                            request, layoutSet.getLayoutSetId(),
706                            layoutSetBranch.getLayoutSetBranchId());
707            }
708    
709            protected String updateCloseRedirect(
710                    String closeRedirect, Group group, Layout layout,
711                    String oldLayoutFriendlyURL) {
712    
713                    if (Validator.isNull(closeRedirect) ||
714                            Validator.isNull(oldLayoutFriendlyURL)) {
715    
716                            return closeRedirect;
717                    }
718    
719                    if (layout != null) {
720                            String oldPath = oldLayoutFriendlyURL;
721                            String newPath = layout.getFriendlyURL();
722    
723                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
724                    }
725                    else if (group != null) {
726                            String oldPath = group.getFriendlyURL() + oldLayoutFriendlyURL;
727                            String newPath = group.getFriendlyURL();
728    
729                            return PortalUtil.updateRedirect(closeRedirect, oldPath, newPath);
730                    }
731    
732                    return closeRedirect;
733            }
734    
735            protected void updateDisplayOrder(ActionRequest actionRequest)
736                    throws Exception {
737    
738                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
739                    boolean privateLayout = ParamUtil.getBoolean(
740                            actionRequest, "privateLayout");
741                    long parentLayoutId = ParamUtil.getLong(
742                            actionRequest, "parentLayoutId");
743                    long[] layoutIds = StringUtil.split(
744                            ParamUtil.getString(actionRequest, "layoutIds"), 0L);
745    
746                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
747                            actionRequest);
748    
749                    LayoutServiceUtil.setLayouts(
750                            groupId, privateLayout, parentLayoutId, layoutIds, serviceContext);
751            }
752    
753            protected Object[] updateLayout(
754                            ActionRequest actionRequest, ActionResponse actionResponse)
755                    throws Exception {
756    
757                    UploadPortletRequest uploadPortletRequest =
758                            PortalUtil.getUploadPortletRequest(actionRequest);
759    
760                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
761                            WebKeys.THEME_DISPLAY);
762    
763                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
764    
765                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
766                    long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
767                    long stagingGroupId = ParamUtil.getLong(
768                            actionRequest, "stagingGroupId");
769                    boolean privateLayout = ParamUtil.getBoolean(
770                            actionRequest, "privateLayout");
771                    long layoutId = ParamUtil.getLong(actionRequest, "layoutId");
772                    long parentLayoutId = ParamUtil.getLong(
773                            uploadPortletRequest, "parentLayoutId");
774                    Map<Locale, String> nameMap =
775                            LocalizationUtil.getLocalizationMap(actionRequest, "name");
776                    Map<Locale, String> titleMap =
777                            LocalizationUtil.getLocalizationMap(actionRequest, "title");
778                    Map<Locale, String> descriptionMap =
779                            LocalizationUtil.getLocalizationMap(actionRequest, "description");
780                    Map<Locale, String> keywordsMap =
781                            LocalizationUtil.getLocalizationMap(actionRequest, "keywords");
782                    Map<Locale, String> robotsMap =
783                            LocalizationUtil.getLocalizationMap(actionRequest, "robots");
784                    String type = ParamUtil.getString(uploadPortletRequest, "type");
785                    boolean hidden = ParamUtil.getBoolean(uploadPortletRequest, "hidden");
786                    String friendlyURL = ParamUtil.getString(
787                            uploadPortletRequest, "friendlyURL");
788                    boolean iconImage = ParamUtil.getBoolean(
789                            uploadPortletRequest, "iconImage");
790                    byte[] iconBytes = getIconBytes(uploadPortletRequest, "iconFileName");
791                    long layoutPrototypeId = ParamUtil.getLong(
792                            uploadPortletRequest, "layoutPrototypeId");
793    
794                    boolean inheritFromParentLayoutId = ParamUtil.getBoolean(
795                            uploadPortletRequest, "inheritFromParentLayoutId");
796    
797                    long copyLayoutId = ParamUtil.getLong(
798                            uploadPortletRequest, "copyLayoutId");
799    
800                    String layoutTemplateId = ParamUtil.getString(
801                            uploadPortletRequest, "layoutTemplateId",
802                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID);
803    
804                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
805                            Layout.class.getName(), actionRequest);
806    
807                    Layout layout = null;
808                    UnicodeProperties layoutTypeSettingsProperties = null;
809                    String oldFriendlyURL = StringPool.BLANK;
810    
811                    if (cmd.equals(Constants.ADD)) {
812    
813                            // Add layout
814    
815                            if (inheritFromParentLayoutId && (parentLayoutId > 0)) {
816                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
817                                            groupId, privateLayout, parentLayoutId);
818    
819                                    layout = LayoutServiceUtil.addLayout(
820                                            groupId, privateLayout, parentLayoutId, nameMap,
821                                            titleMap, descriptionMap, keywordsMap, robotsMap,
822                                            parentLayout.getType(), hidden, friendlyURL,
823                                            serviceContext);
824    
825                                    LayoutServiceUtil.updateLayout(
826                                            layout.getGroupId(), layout.isPrivateLayout(),
827                                            layout.getLayoutId(), parentLayout.getTypeSettings());
828    
829                                    if (parentLayout.isTypePortlet()) {
830                                            ActionUtil.copyPreferences(
831                                                    actionRequest, layout, parentLayout);
832    
833                                            SitesUtil.copyLookAndFeel(layout, parentLayout);
834                                    }
835                            }
836                            else if (layoutPrototypeId > 0) {
837                                    LayoutPrototype layoutPrototype =
838                                            LayoutPrototypeServiceUtil.getLayoutPrototype(
839                                                    layoutPrototypeId);
840    
841                                    serviceContext.setAttribute("layoutPrototypeLinkEnabled", true);
842                                    serviceContext.setAttribute(
843                                            "layoutPrototypeUuid", layoutPrototype.getUuid());
844    
845                                    layout = LayoutServiceUtil.addLayout(
846                                            groupId, privateLayout, parentLayoutId, nameMap,
847                                            titleMap, descriptionMap, keywordsMap, robotsMap,
848                                            LayoutConstants.TYPE_PORTLET, hidden, friendlyURL,
849                                            serviceContext);
850                            }
851                            else {
852                                    layout = LayoutServiceUtil.addLayout(
853                                            groupId, privateLayout, parentLayoutId, nameMap,
854                                            titleMap, descriptionMap, keywordsMap, robotsMap, type,
855                                            hidden, friendlyURL, serviceContext);
856                            }
857    
858                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
859                    }
860                    else {
861    
862                            // Update layout
863    
864                            layout = LayoutLocalServiceUtil.getLayout(
865                                    groupId, privateLayout, layoutId);
866    
867                            oldFriendlyURL = layout.getFriendlyURL();
868    
869                            layout = LayoutServiceUtil.updateLayout(
870                                    groupId, privateLayout, layoutId, layout.getParentLayoutId(),
871                                    nameMap, titleMap, descriptionMap, keywordsMap, robotsMap,
872                                    type, hidden, friendlyURL, Boolean.valueOf(iconImage),
873                                    iconBytes, serviceContext);
874    
875                            layoutTypeSettingsProperties = layout.getTypeSettingsProperties();
876    
877                            if (oldFriendlyURL.equals(layout.getFriendlyURL())) {
878                                    oldFriendlyURL = StringPool.BLANK;
879                            }
880    
881                            UnicodeProperties formTypeSettingsProperties =
882                                    PropertiesParamUtil.getProperties(
883                                            actionRequest, "TypeSettingsProperties--");
884    
885                            if (type.equals(LayoutConstants.TYPE_PORTLET)) {
886                                    LayoutTypePortlet layoutTypePortlet =
887                                            (LayoutTypePortlet)layout.getLayoutType();
888    
889                                    layoutTypePortlet.setLayoutTemplateId(
890                                            themeDisplay.getUserId(), layoutTemplateId);
891    
892                                    if ((copyLayoutId > 0) &&
893                                            (copyLayoutId != layout.getLayoutId())) {
894    
895                                            try {
896                                                    Layout copyLayout = LayoutLocalServiceUtil.getLayout(
897                                                            groupId, privateLayout, copyLayoutId);
898    
899                                                    if (copyLayout.isTypePortlet()) {
900                                                            layoutTypeSettingsProperties =
901                                                                    copyLayout.getTypeSettingsProperties();
902    
903                                                            ActionUtil.copyPreferences(
904                                                                    actionRequest, layout, copyLayout);
905    
906                                                            SitesUtil.copyLookAndFeel(layout, copyLayout);
907                                                    }
908                                            }
909                                            catch (NoSuchLayoutException nsle) {
910                                            }
911                                    }
912                                    else {
913                                            layoutTypeSettingsProperties.putAll(
914                                                    formTypeSettingsProperties);
915    
916                                            LayoutServiceUtil.updateLayout(
917                                                    groupId, privateLayout, layoutId,
918                                                    layout.getTypeSettings());
919                                    }
920                            }
921                            else {
922                                    layout.setTypeSettingsProperties(formTypeSettingsProperties);
923    
924                                    layoutTypeSettingsProperties.putAll(
925                                            layout.getTypeSettingsProperties());
926    
927                                    LayoutServiceUtil.updateLayout(
928                                            groupId, privateLayout, layoutId, layout.getTypeSettings());
929                            }
930    
931                            HttpServletResponse response = PortalUtil.getHttpServletResponse(
932                                    actionResponse);
933    
934                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
935    
936                            EventsProcessorUtil.process(
937                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_UPDATE,
938                                    layoutSettings.getConfigurationActionUpdate(),
939                                    uploadPortletRequest, response);
940                    }
941    
942                    updateLookAndFeel(
943                            actionRequest, themeDisplay.getCompanyId(), liveGroupId,
944                            stagingGroupId, privateLayout, layout.getLayoutId(),
945                            layoutTypeSettingsProperties);
946    
947                    return new Object[] {layout, oldFriendlyURL};
948            }
949    
950            protected void updateLayoutRevision(ActionRequest actionRequest)
951                    throws Exception {
952    
953                    long layoutRevisionId = ParamUtil.getLong(
954                            actionRequest, "layoutRevisionId");
955    
956                    LayoutRevision layoutRevision =
957                            LayoutRevisionLocalServiceUtil.getLayoutRevision(layoutRevisionId);
958    
959                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
960                            actionRequest);
961    
962                    LayoutRevisionLocalServiceUtil.updateLayoutRevision(
963                            serviceContext.getUserId(), layoutRevisionId,
964                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
965                            layoutRevision.getTitle(), layoutRevision.getDescription(),
966                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
967                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
968                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
969                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
970                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
971                            serviceContext);
972            }
973    
974            protected void updateLookAndFeel(
975                            ActionRequest actionRequest, long companyId, long liveGroupId,
976                            long stagingGroupId, boolean privateLayout, long layoutId,
977                            UnicodeProperties typeSettingsProperties)
978                    throws Exception {
979    
980                    String[] devices = StringUtil.split(
981                            ParamUtil.getString(actionRequest, "devices"));
982    
983                    for (String device : devices) {
984                            String themeId = ParamUtil.getString(
985                                    actionRequest, device + "ThemeId");
986                            String colorSchemeId = ParamUtil.getString(
987                                    actionRequest, device + "ColorSchemeId");
988                            String css = ParamUtil.getString(actionRequest, device + "Css");
989                            boolean wapTheme = device.equals("wap");
990    
991                            boolean inheritLookAndFeel = ParamUtil.getBoolean(
992                                    actionRequest, device + "InheritLookAndFeel");
993    
994                            if (inheritLookAndFeel) {
995                                    themeId = ThemeImpl.getDefaultRegularThemeId(companyId);
996                                    colorSchemeId = StringPool.BLANK;
997    
998                                    deleteThemeSettings(typeSettingsProperties, device);
999                            }
1000                            else if (Validator.isNotNull(themeId)) {
1001                                    colorSchemeId = getColorSchemeId(
1002                                            actionRequest, companyId, typeSettingsProperties, device,
1003                                            themeId, colorSchemeId, wapTheme);
1004                            }
1005    
1006                            long groupId = liveGroupId;
1007    
1008                            if (stagingGroupId > 0) {
1009                                    groupId = stagingGroupId;
1010                            }
1011    
1012                            LayoutServiceUtil.updateLayout(
1013                                    groupId, privateLayout, layoutId,
1014                                    typeSettingsProperties.toString());
1015    
1016                            LayoutServiceUtil.updateLookAndFeel(
1017                                    groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
1018                                    wapTheme);
1019                    }
1020            }
1021    
1022            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
1023    
1024            private static Log _log = LogFactoryUtil.getLog(EditLayoutsAction.class);
1025    
1026    }