001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.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.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.UnicodeProperties;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.model.Layout;
026    import com.liferay.portal.model.LayoutTemplate;
027    import com.liferay.portal.model.LayoutTemplateConstants;
028    import com.liferay.portal.model.LayoutTypePortletConstants;
029    import com.liferay.portal.model.Portlet;
030    import com.liferay.portal.model.Theme;
031    import com.liferay.portal.service.LayoutLocalServiceUtil;
032    import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
033    import com.liferay.portal.struts.PortletAction;
034    import com.liferay.portal.theme.ThemeDisplay;
035    import com.liferay.portal.util.PropsValues;
036    import com.liferay.portal.util.WebKeys;
037    import com.liferay.portlet.PortletPreferencesFactoryUtil;
038    
039    import java.util.Collection;
040    import java.util.HashMap;
041    import java.util.Map;
042    import java.util.regex.Matcher;
043    import java.util.regex.Pattern;
044    
045    import javax.portlet.PortletConfig;
046    import javax.portlet.PortletPreferences;
047    import javax.portlet.RenderRequest;
048    import javax.portlet.RenderResponse;
049    
050    import org.apache.struts.action.ActionForm;
051    import org.apache.struts.action.ActionForward;
052    import org.apache.struts.action.ActionMapping;
053    
054    /**
055     * @author Berentey Zsolt
056     * @author Jorge Ferrer
057     * @author Raymond Aug??
058     * @author Jesper Weissglas
059     */
060    public class ViewAction extends PortletAction {
061    
062            @Override
063            public ActionForward render(
064                            ActionMapping actionMapping, ActionForm actionForm,
065                            PortletConfig portletConfig, RenderRequest renderRequest,
066                            RenderResponse renderResponse)
067                    throws Exception {
068    
069                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
070                            WebKeys.THEME_DISPLAY);
071    
072                    Portlet portlet = (Portlet)renderRequest.getAttribute(
073                            WebKeys.RENDER_PORTLET);
074    
075                    PortletPreferences preferences =
076                            PortletPreferencesFactoryUtil.getPortletSetup(
077                                    renderRequest, portlet.getPortletId());
078    
079                    String layoutTemplateId = preferences.getValue(
080                            "layoutTemplateId",
081                            PropsValues.NESTED_PORTLETS_LAYOUT_TEMPLATE_DEFAULT);
082    
083                    String velocityTemplateId = StringPool.BLANK;
084                    String velocityTemplateContent = StringPool.BLANK;
085    
086                    Map<String, String> columnIds = new HashMap<String, String>();
087    
088                    if (Validator.isNotNull(layoutTemplateId)) {
089                            Theme theme = themeDisplay.getTheme();
090    
091                            LayoutTemplate layoutTemplate =
092                                    LayoutTemplateLocalServiceUtil.getLayoutTemplate(
093                                            layoutTemplateId, false, theme.getThemeId());
094    
095                            String content = layoutTemplate.getContent();
096    
097                            Matcher processColumnMatcher = _processColumnPattern.matcher(
098                                    content);
099    
100                            while (processColumnMatcher.find()) {
101                                    String columnId = processColumnMatcher.group(2);
102    
103                                    if (Validator.isNotNull(columnId)) {
104                                            columnIds.put(
105                                                    columnId,
106                                                    renderResponse.getNamespace() + StringPool.UNDERLINE +
107                                                            columnId);
108                                    }
109                            }
110    
111                            processColumnMatcher.reset();
112    
113                            StringBundler sb = new StringBundler(4);
114    
115                            sb.append(theme.getThemeId());
116                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
117                            sb.append(renderResponse.getNamespace());
118                            sb.append(layoutTemplateId);
119    
120                            velocityTemplateId = sb.toString();
121    
122                            content = processColumnMatcher.replaceAll("$1\\${$2}$3");
123    
124                            Matcher columnIdMatcher = _columnIdPattern.matcher(content);
125    
126                            velocityTemplateContent = columnIdMatcher.replaceAll(
127                                    "$1" + renderResponse.getNamespace() + "$2$3");
128                    }
129    
130                    checkLayout(themeDisplay.getLayout(), columnIds.values());
131    
132                    renderRequest.setAttribute(
133                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_ID, velocityTemplateId);
134                    renderRequest.setAttribute(
135                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_CONTENT,
136                            velocityTemplateContent);
137    
138                    Map<String, Object> vmVariables =
139                            (Map<String, Object>)renderRequest.getAttribute(
140                                    WebKeys.VM_VARIABLES);
141    
142                    if (vmVariables != null) {
143                            vmVariables.putAll(columnIds);
144                    }
145                    else {
146                            renderRequest.setAttribute(WebKeys.VM_VARIABLES, columnIds);
147                    }
148    
149                    return actionMapping.findForward("portlet.nested_portlets.view");
150            }
151    
152            protected void checkLayout(Layout layout, Collection<String> columnIds) {
153                    UnicodeProperties properties = layout.getTypeSettingsProperties();
154    
155                    String[] layoutColumnIds = StringUtil.split(
156                            properties.get(LayoutTypePortletConstants.NESTED_COLUMN_IDS));
157    
158                    boolean updateColumnIds = false;
159    
160                    for (String columnId : columnIds) {
161                            String portletIds = properties.getProperty(columnId);
162    
163                            if (Validator.isNotNull(portletIds) &&
164                                    !ArrayUtil.contains(layoutColumnIds, columnId)) {
165    
166                                    layoutColumnIds = ArrayUtil.append(layoutColumnIds, columnId);
167    
168                                    updateColumnIds = true;
169                            }
170                    }
171    
172                    if (updateColumnIds) {
173                            properties.setProperty(
174                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS,
175                                    StringUtil.merge(layoutColumnIds));
176    
177                            layout.setTypeSettingsProperties(properties);
178    
179                            try {
180                                    LayoutLocalServiceUtil.updateLayout(
181                                            layout.getGroupId(), layout.isPrivateLayout(),
182                                            layout.getLayoutId(), layout.getTypeSettings());
183                            }
184                            catch (Exception e) {
185                                    if (_log.isWarnEnabled()) {
186                                            _log.warn(e, e);
187                                    }
188                            }
189                    }
190            }
191    
192            private static Log _log = LogFactoryUtil.getLog(ViewAction.class);
193    
194            private static Pattern _columnIdPattern = Pattern.compile(
195                    "([<].*?id=[\"'])([^ ]*?)([\"'].*?[>])", Pattern.DOTALL);
196            private static Pattern _processColumnPattern = Pattern.compile(
197                    "(processColumn[(]\")(.*?)(\"(?:, *\"(?:.*?)\")?[)])", Pattern.DOTALL);
198    
199    }