1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.nestedportlets.action;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.ArrayUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.util.UnicodeProperties;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.model.Layout;
33  import com.liferay.portal.model.LayoutTemplate;
34  import com.liferay.portal.model.LayoutTemplateConstants;
35  import com.liferay.portal.model.Portlet;
36  import com.liferay.portal.model.Theme;
37  import com.liferay.portal.model.impl.LayoutTypePortletImpl;
38  import com.liferay.portal.service.LayoutLocalServiceUtil;
39  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
40  import com.liferay.portal.struts.PortletAction;
41  import com.liferay.portal.theme.ThemeDisplay;
42  import com.liferay.portal.util.PropsValues;
43  import com.liferay.portal.util.WebKeys;
44  import com.liferay.portlet.PortletPreferencesFactoryUtil;
45  
46  import java.util.Collection;
47  import java.util.HashMap;
48  import java.util.Map;
49  import java.util.regex.Matcher;
50  import java.util.regex.Pattern;
51  
52  import javax.portlet.PortletConfig;
53  import javax.portlet.PortletPreferences;
54  import javax.portlet.RenderRequest;
55  import javax.portlet.RenderResponse;
56  
57  import org.apache.struts.action.ActionForm;
58  import org.apache.struts.action.ActionForward;
59  import org.apache.struts.action.ActionMapping;
60  
61  /**
62   * <a href="ViewAction.java.html"><b><i>View Source</i></b></a>
63   *
64   * @author Berentey Zsolt
65   * @author Jorge Ferrer
66   * @author Raymond Augé
67   * @author Jesper Weissglas
68   */
69  public class ViewAction extends PortletAction {
70  
71      public ActionForward render(
72              ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
73              RenderRequest renderRequest, RenderResponse renderResponse)
74          throws Exception {
75  
76          ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
77              WebKeys.THEME_DISPLAY);
78  
79          Portlet portlet = (Portlet)renderRequest.getAttribute(
80              WebKeys.RENDER_PORTLET);
81  
82          PortletPreferences preferences =
83              PortletPreferencesFactoryUtil.getPortletSetup(
84                  renderRequest, portlet.getPortletId());
85  
86          String layoutTemplateId = preferences.getValue(
87              "layout-template-id",
88              PropsValues.NESTED_PORTLETS_LAYOUT_TEMPLATE_DEFAULT);
89  
90          String velocityTemplateId = StringPool.BLANK;
91          String velocityTemplateContent = StringPool.BLANK;
92  
93          Map<String, String> columnIds = new HashMap<String, String>();
94  
95          if (Validator.isNotNull(layoutTemplateId)) {
96              Theme theme = themeDisplay.getTheme();
97  
98              LayoutTemplate layoutTemplate =
99                  LayoutTemplateLocalServiceUtil.getLayoutTemplate(
100                     layoutTemplateId, false, theme.getThemeId());
101 
102             String content = layoutTemplate.getContent();
103 
104             Matcher processColumnMatcher = _processColumnPattern.matcher(
105                 content);
106 
107             while (processColumnMatcher.find()) {
108                 String columnId = processColumnMatcher.group(2);
109 
110                 if (Validator.isNotNull(columnId)) {
111                     columnIds.put(
112                         columnId,
113                         renderResponse.getNamespace() + StringPool.UNDERLINE +
114                             columnId);
115                 }
116             }
117 
118             processColumnMatcher.reset();
119 
120             content = processColumnMatcher.replaceAll("$1\\${$2}$3");
121 
122             velocityTemplateId =
123                 theme.getThemeId() + LayoutTemplateConstants.CUSTOM_SEPARATOR +
124                     layoutTemplateId;
125 
126             Matcher columnIdMatcher = _columnIdPattern.matcher(content);
127 
128             velocityTemplateContent = columnIdMatcher.replaceAll(
129                 "$1" + renderResponse.getNamespace() + "$2$3");
130         }
131 
132         checkLayout(themeDisplay.getLayout(), columnIds.values());
133 
134         renderRequest.setAttribute(
135             WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_ID, velocityTemplateId);
136         renderRequest.setAttribute(
137             WebKeys.NESTED_PORTLET_VELOCITY_TEMPLATE_CONTENT,
138             velocityTemplateContent);
139 
140         Map<String, Object> vmVariables =
141             (Map<String, Object>)renderRequest.getAttribute(
142                 WebKeys.VM_VARIABLES);
143 
144         if (vmVariables != null) {
145             vmVariables.putAll(columnIds);
146         }
147         else {
148             renderRequest.setAttribute(WebKeys.VM_VARIABLES, columnIds);
149         }
150 
151         return mapping.findForward("portlet.nested_portlets.view");
152     }
153 
154     protected void checkLayout(Layout layout, Collection<String> columnIds) {
155         UnicodeProperties properties = layout.getTypeSettingsProperties();
156 
157         String[] layoutColumnIds = StringUtil.split(
158             properties.get(LayoutTypePortletImpl.NESTED_COLUMN_IDS));
159 
160         boolean updateColumnIds = false;
161 
162         for (String columnId : columnIds) {
163             String portletIds = properties.getProperty(columnId);
164 
165             if (Validator.isNotNull(portletIds) &&
166                 !ArrayUtil.contains(layoutColumnIds, columnId)) {
167 
168                 layoutColumnIds = ArrayUtil.append(layoutColumnIds, columnId);
169 
170                 updateColumnIds = true;
171             }
172         }
173 
174         if (updateColumnIds) {
175             properties.setProperty(
176                 LayoutTypePortletImpl.NESTED_COLUMN_IDS,
177                 StringUtil.merge(layoutColumnIds));
178 
179             layout.setTypeSettingsProperties(properties);
180 
181             try {
182                 LayoutLocalServiceUtil.updateLayout(
183                     layout.getGroupId(), layout.isPrivateLayout(),
184                     layout.getLayoutId(), layout.getTypeSettings());
185             }
186             catch (Exception e) {
187                 if (_log.isWarnEnabled()) {
188                     _log.warn(e, e);
189                 }
190             }
191         }
192     }
193 
194     private static Log _log = LogFactoryUtil.getLog(ViewAction.class);
195 
196     private static Pattern _columnIdPattern = Pattern.compile(
197         "([<].*?id=[\"'])([^ ]*?)([\"'].*?[>])", Pattern.DOTALL);
198     private static Pattern _processColumnPattern = Pattern.compile(
199         "(processColumn[(]\")(.*?)(\"[)])", Pattern.DOTALL);
200 
201 }