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.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 mapping, ActionForm form, PortletConfig portletConfig,
065                            RenderRequest renderRequest, RenderResponse renderResponse)
066                    throws Exception {
067    
068                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
069                            WebKeys.THEME_DISPLAY);
070    
071                    Portlet portlet = (Portlet)renderRequest.getAttribute(
072                            WebKeys.RENDER_PORTLET);
073    
074                    PortletPreferences preferences =
075                            PortletPreferencesFactoryUtil.getPortletSetup(
076                                    renderRequest, portlet.getPortletId());
077    
078                    String layoutTemplateId = preferences.getValue(
079                            "layoutTemplateId",
080                            PropsValues.NESTED_PORTLETS_LAYOUT_TEMPLATE_DEFAULT);
081    
082                    String velocityTemplateId = StringPool.BLANK;
083                    String velocityTemplateContent = StringPool.BLANK;
084    
085                    Map<String, String> columnIds = new HashMap<String, String>();
086    
087                    if (Validator.isNotNull(layoutTemplateId)) {
088                            Theme theme = themeDisplay.getTheme();
089    
090                            LayoutTemplate layoutTemplate =
091                                    LayoutTemplateLocalServiceUtil.getLayoutTemplate(
092                                            layoutTemplateId, false, theme.getThemeId());
093    
094                            String content = layoutTemplate.getContent();
095    
096                            Matcher processColumnMatcher = _processColumnPattern.matcher(
097                                    content);
098    
099                            while (processColumnMatcher.find()) {
100                                    String columnId = processColumnMatcher.group(2);
101    
102                                    if (Validator.isNotNull(columnId)) {
103                                            columnIds.put(
104                                                    columnId,
105                                                    renderResponse.getNamespace() + StringPool.UNDERLINE +
106                                                            columnId);
107                                    }
108                            }
109    
110                            processColumnMatcher.reset();
111    
112                            StringBundler sb = new StringBundler(4);
113    
114                            sb.append(theme.getThemeId());
115                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
116                            sb.append(renderResponse.getNamespace());
117                            sb.append(layoutTemplateId);
118    
119                            velocityTemplateId = sb.toString();
120    
121                            content = processColumnMatcher.replaceAll("$1\\${$2}$3");
122    
123                            Matcher columnIdMatcher = _columnIdPattern.matcher(content);
124    
125                            velocityTemplateContent = columnIdMatcher.replaceAll(
126                                    "$1" + renderResponse.getNamespace() + "$2$3");
127                    }
128    
129                    checkLayout(themeDisplay.getLayout(), columnIds.values());
130    
131                    renderRequest.setAttribute(
132                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_ID, velocityTemplateId);
133                    renderRequest.setAttribute(
134                            WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_CONTENT,
135                            velocityTemplateContent);
136    
137                    Map<String, Object> vmVariables =
138                            (Map<String, Object>)renderRequest.getAttribute(
139                                    WebKeys.VM_VARIABLES);
140    
141                    if (vmVariables != null) {
142                            vmVariables.putAll(columnIds);
143                    }
144                    else {
145                            renderRequest.setAttribute(WebKeys.VM_VARIABLES, columnIds);
146                    }
147    
148                    return mapping.findForward("portlet.nested_portlets.view");
149            }
150    
151            protected void checkLayout(Layout layout, Collection<String> columnIds) {
152                    UnicodeProperties properties = layout.getTypeSettingsProperties();
153    
154                    String[] layoutColumnIds = StringUtil.split(
155                            properties.get(LayoutTypePortletConstants.NESTED_COLUMN_IDS));
156    
157                    boolean updateColumnIds = false;
158    
159                    for (String columnId : columnIds) {
160                            String portletIds = properties.getProperty(columnId);
161    
162                            if (Validator.isNotNull(portletIds) &&
163                                    !ArrayUtil.contains(layoutColumnIds, columnId)) {
164    
165                                    layoutColumnIds = ArrayUtil.append(layoutColumnIds, columnId);
166    
167                                    updateColumnIds = true;
168                            }
169                    }
170    
171                    if (updateColumnIds) {
172                            properties.setProperty(
173                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS,
174                                    StringUtil.merge(layoutColumnIds));
175    
176                            layout.setTypeSettingsProperties(properties);
177    
178                            try {
179                                    LayoutLocalServiceUtil.updateLayout(
180                                            layout.getGroupId(), layout.isPrivateLayout(),
181                                            layout.getLayoutId(), layout.getTypeSettings());
182                            }
183                            catch (Exception e) {
184                                    if (_log.isWarnEnabled()) {
185                                            _log.warn(e, e);
186                                    }
187                            }
188                    }
189            }
190    
191            private static Log _log = LogFactoryUtil.getLog(ViewAction.class);
192    
193            private static Pattern _columnIdPattern = Pattern.compile(
194                    "([<].*?id=[\"'])([^ ]*?)([\"'].*?[>])", Pattern.DOTALL);
195            private static Pattern _processColumnPattern = Pattern.compile(
196                    "(processColumn[(]\")(.*?)(\"(?:, *\"(?:.*?)\")?[)])", Pattern.DOTALL);
197    
198    }