001    /**
002     * Copyright (c) 2000-2010 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.nestedportlets.action;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.ArrayUtil;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.StringUtil;
022    import com.liferay.portal.kernel.util.UnicodeProperties;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.model.Layout;
025    import com.liferay.portal.model.LayoutTemplate;
026    import com.liferay.portal.model.LayoutTemplateConstants;
027    import com.liferay.portal.model.LayoutTypePortletConstants;
028    import com.liferay.portal.model.Portlet;
029    import com.liferay.portal.model.Theme;
030    import com.liferay.portal.service.LayoutLocalServiceUtil;
031    import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
032    import com.liferay.portal.struts.PortletAction;
033    import com.liferay.portal.theme.ThemeDisplay;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portal.util.WebKeys;
036    import com.liferay.portlet.PortletPreferencesFactoryUtil;
037    
038    import java.util.Collection;
039    import java.util.HashMap;
040    import java.util.Map;
041    import java.util.regex.Matcher;
042    import java.util.regex.Pattern;
043    
044    import javax.portlet.PortletConfig;
045    import javax.portlet.PortletPreferences;
046    import javax.portlet.RenderRequest;
047    import javax.portlet.RenderResponse;
048    
049    import org.apache.struts.action.ActionForm;
050    import org.apache.struts.action.ActionForward;
051    import org.apache.struts.action.ActionMapping;
052    
053    /**
054     * @author Berentey Zsolt
055     * @author Jorge Ferrer
056     * @author Raymond Augé
057     * @author Jesper Weissglas
058     */
059    public class ViewAction extends PortletAction {
060    
061            public ActionForward render(
062                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
063                            RenderRequest renderRequest, RenderResponse renderResponse)
064                    throws Exception {
065    
066                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
067                            WebKeys.THEME_DISPLAY);
068    
069                    Portlet portlet = (Portlet)renderRequest.getAttribute(
070                            WebKeys.RENDER_PORTLET);
071    
072                    PortletPreferences preferences =
073                            PortletPreferencesFactoryUtil.getPortletSetup(
074                                    renderRequest, portlet.getPortletId());
075    
076                    String layoutTemplateId = preferences.getValue(
077                            "layout-template-id",
078                            PropsValues.NESTED_PORTLETS_LAYOUT_TEMPLATE_DEFAULT);
079    
080                    String velocityTemplateId = StringPool.BLANK;
081                    String velocityTemplateContent = StringPool.BLANK;
082    
083                    Map<String, String> columnIds = new HashMap<String, String>();
084    
085                    if (Validator.isNotNull(layoutTemplateId)) {
086                            Theme theme = themeDisplay.getTheme();
087    
088                            LayoutTemplate layoutTemplate =
089                                    LayoutTemplateLocalServiceUtil.getLayoutTemplate(
090                                            layoutTemplateId, false, theme.getThemeId());
091    
092                            String content = layoutTemplate.getContent();
093    
094                            Matcher processColumnMatcher = _processColumnPattern.matcher(
095                                    content);
096    
097                            while (processColumnMatcher.find()) {
098                                    String columnId = processColumnMatcher.group(2);
099    
100                                    if (Validator.isNotNull(columnId)) {
101                                            columnIds.put(
102                                                    columnId,
103                                                    renderResponse.getNamespace() + StringPool.UNDERLINE +
104                                                            columnId);
105                                    }
106                            }
107    
108                            processColumnMatcher.reset();
109    
110                            content = processColumnMatcher.replaceAll("$1\\${$2}$3");
111    
112                            velocityTemplateId =
113                                    theme.getThemeId() + LayoutTemplateConstants.CUSTOM_SEPARATOR +
114                                            layoutTemplateId;
115    
116                            Matcher columnIdMatcher = _columnIdPattern.matcher(content);
117    
118                            velocityTemplateContent = columnIdMatcher.replaceAll(
119                                    "$1" + renderResponse.getNamespace() + "$2$3");
120                    }
121    
122                    checkLayout(themeDisplay.getLayout(), columnIds.values());
123    
124                    renderRequest.setAttribute(
125                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_ID, velocityTemplateId);
126                    renderRequest.setAttribute(
127                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_CONTENT,
128                            velocityTemplateContent);
129    
130                    Map<String, Object> vmVariables =
131                            (Map<String, Object>)renderRequest.getAttribute(
132                                    WebKeys.VM_VARIABLES);
133    
134                    if (vmVariables != null) {
135                            vmVariables.putAll(columnIds);
136                    }
137                    else {
138                            renderRequest.setAttribute(WebKeys.VM_VARIABLES, columnIds);
139                    }
140    
141                    return mapping.findForward("portlet.nested_portlets.view");
142            }
143    
144            protected void checkLayout(Layout layout, Collection<String> columnIds) {
145                    UnicodeProperties properties = layout.getTypeSettingsProperties();
146    
147                    String[] layoutColumnIds = StringUtil.split(
148                            properties.get(LayoutTypePortletConstants.NESTED_COLUMN_IDS));
149    
150                    boolean updateColumnIds = false;
151    
152                    for (String columnId : columnIds) {
153                            String portletIds = properties.getProperty(columnId);
154    
155                            if (Validator.isNotNull(portletIds) &&
156                                    !ArrayUtil.contains(layoutColumnIds, columnId)) {
157    
158                                    layoutColumnIds = ArrayUtil.append(layoutColumnIds, columnId);
159    
160                                    updateColumnIds = true;
161                            }
162                    }
163    
164                    if (updateColumnIds) {
165                            properties.setProperty(
166                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS,
167                                    StringUtil.merge(layoutColumnIds));
168    
169                            layout.setTypeSettingsProperties(properties);
170    
171                            try {
172                                    LayoutLocalServiceUtil.updateLayout(
173                                            layout.getGroupId(), layout.isPrivateLayout(),
174                                            layout.getLayoutId(), layout.getTypeSettings());
175                            }
176                            catch (Exception e) {
177                                    if (_log.isWarnEnabled()) {
178                                            _log.warn(e, e);
179                                    }
180                            }
181                    }
182            }
183    
184            private static Log _log = LogFactoryUtil.getLog(ViewAction.class);
185    
186            private static Pattern _columnIdPattern = Pattern.compile(
187                    "([<].*?id=[\"'])([^ ]*?)([\"'].*?[>])", Pattern.DOTALL);
188            private static Pattern _processColumnPattern = Pattern.compile(
189                    "(processColumn[(]\")(.*?)(\"(?:, *\"(?:.*?)\")?[)])", Pattern.DOTALL);
190    
191    }