1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.layoutconfiguration.util;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.servlet.StringServletResponse;
21  import com.liferay.portal.kernel.util.JavaConstants;
22  import com.liferay.portal.kernel.util.MethodInvoker;
23  import com.liferay.portal.kernel.util.MethodWrapper;
24  import com.liferay.portal.kernel.util.StringPool;
25  import com.liferay.portal.kernel.util.StringUtil;
26  import com.liferay.portal.kernel.util.Validator;
27  import com.liferay.portal.kernel.velocity.VelocityContext;
28  import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
29  import com.liferay.portal.model.Portlet;
30  import com.liferay.portal.service.PortletLocalServiceUtil;
31  import com.liferay.portal.theme.PortletDisplay;
32  import com.liferay.portal.theme.PortletDisplayFactory;
33  import com.liferay.portal.theme.ThemeDisplay;
34  import com.liferay.portal.util.PortalUtil;
35  import com.liferay.portal.util.WebKeys;
36  import com.liferay.portal.velocity.VelocityVariables;
37  import com.liferay.portlet.layoutconfiguration.util.velocity.TemplateProcessor;
38  import com.liferay.portlet.layoutconfiguration.util.xml.RuntimeLogic;
39  
40  import java.util.Iterator;
41  import java.util.Map;
42  
43  import javax.portlet.PortletConfig;
44  import javax.portlet.RenderRequest;
45  import javax.portlet.RenderResponse;
46  
47  import javax.servlet.ServletContext;
48  import javax.servlet.http.HttpServletRequest;
49  import javax.servlet.http.HttpServletResponse;
50  import javax.servlet.jsp.PageContext;
51  
52  /**
53   * <a href="RuntimePortletUtil.java.html"><b><i>View Source</i></b></a>
54   *
55   * @author Brian Wing Shun Chan
56   * @author Raymond Augé
57   */
58  public class RuntimePortletUtil {
59  
60      public static void processPortlet(
61              StringBuilder sb, ServletContext servletContext,
62              HttpServletRequest request, HttpServletResponse response,
63              RenderRequest renderRequest, RenderResponse renderResponse,
64              String portletId, String queryString)
65          throws Exception {
66  
67          processPortlet(
68              sb, servletContext, request, response, renderRequest,
69              renderResponse, portletId, queryString, null, null, null);
70      }
71  
72      public static void processPortlet(
73              StringBuilder sb, ServletContext servletContext,
74              HttpServletRequest request, HttpServletResponse response,
75              RenderRequest renderRequest, RenderResponse renderResponse,
76              String portletId, String queryString, String columnId,
77              Integer columnPos, Integer columnCount)
78          throws Exception {
79  
80          processPortlet(
81              sb, servletContext, request, response, renderRequest,
82              renderResponse, null, portletId, queryString, columnId, columnPos,
83              columnCount, null);
84      }
85  
86      public static void processPortlet(
87              StringBuilder sb, ServletContext servletContext,
88              HttpServletRequest request, HttpServletResponse response,
89              Portlet portlet, String queryString, String columnId,
90              Integer columnPos, Integer columnCount, String path)
91          throws Exception {
92  
93          processPortlet(
94              sb, servletContext, request, response, null, null, portlet,
95              portlet.getPortletId(), queryString, columnId, columnPos,
96              columnCount, path);
97      }
98  
99      public static void processPortlet(
100             StringBuilder sb, ServletContext servletContext,
101             HttpServletRequest request, HttpServletResponse response,
102             RenderRequest renderRequest, RenderResponse renderResponse,
103             Portlet portlet, String portletId, String queryString,
104             String columnId, Integer columnPos, Integer columnCount,
105             String path)
106         throws Exception {
107 
108         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
109             WebKeys.THEME_DISPLAY);
110 
111         if (portlet == null) {
112             portlet = PortletLocalServiceUtil.getPortletById(
113                 themeDisplay.getCompanyId(), portletId);
114         }
115 
116         if ((portlet != null) && (portlet.isInstanceable()) &&
117             (!portlet.isAddDefaultResource())) {
118 
119             String instanceId = portlet.getInstanceId();
120 
121             if (Validator.isNotNull(instanceId) &&
122                 Validator.isPassword(instanceId) &&
123                 (instanceId.length() == 4)) {
124 
125                 /*portletId +=
126                     PortletConstants.INSTANCE_SEPARATOR + instanceId;
127 
128                 portlet = PortletLocalServiceUtil.getPortletById(
129                     themeDisplay.getCompanyId(), portletId);*/
130             }
131             else {
132                 if (_log.isDebugEnabled()) {
133                     _log.debug(
134                         "Portlet " + portlet.getPortletId() +
135                             " is instanceable but does not have a " +
136                                 "valid instance id");
137                 }
138 
139                 portlet = null;
140             }
141         }
142 
143         if (portlet == null) {
144             return;
145         }
146 
147         // Capture the current portlet's settings to reset them once the child
148         // portlet is rendered
149 
150         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
151 
152         PortletDisplay portletDisplayClone = PortletDisplayFactory.create();
153 
154         portletDisplay.copyTo(portletDisplayClone);
155 
156         PortletConfig portletConfig = (PortletConfig)request.getAttribute(
157             JavaConstants.JAVAX_PORTLET_CONFIG);
158 
159         try {
160             PortalUtil.renderPortlet(
161                 sb, servletContext, request, response, portlet, queryString,
162                 columnId, columnPos, columnCount, path);
163         }
164         finally {
165             portletDisplay.copyFrom(portletDisplayClone);
166 
167             portletDisplayClone.recycle();
168 
169             _defineObjects(
170                 request, portletConfig, renderRequest, renderResponse);
171         }
172     }
173 
174     public static String processTemplate(
175             ServletContext servletContext, HttpServletRequest request,
176             HttpServletResponse response, PageContext pageContext,
177             String velocityTemplateId, String velocityTemplateContent)
178         throws Exception {
179 
180         return processTemplate(
181             servletContext, request, response, pageContext, null,
182             velocityTemplateId, velocityTemplateContent);
183     }
184 
185     public static String processTemplate(
186             ServletContext servletContext, HttpServletRequest request,
187             HttpServletResponse response, PageContext pageContext,
188             String portletId, String velocityTemplateId,
189             String velocityTemplateContent)
190         throws Exception {
191 
192         if (Validator.isNull(velocityTemplateContent)) {
193             return StringPool.BLANK;
194         }
195 
196         TemplateProcessor processor = new TemplateProcessor(
197             servletContext, request, response, portletId);
198 
199         VelocityContext velocityContext =
200             VelocityEngineUtil.getWrappedStandardToolsContext();
201 
202         velocityContext.put("processor", processor);
203 
204         // Velocity variables
205 
206         VelocityVariables.insertVariables(velocityContext, request);
207 
208         // liferay:include tag library
209 
210         StringServletResponse stringResponse = new StringServletResponse(
211             response);
212 
213         MethodWrapper methodWrapper = new MethodWrapper(
214             "com.liferay.taglib.util.VelocityTaglib", "init",
215             new Object[] {
216                 servletContext, request, stringResponse, pageContext
217             });
218 
219         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
220 
221         velocityContext.put("taglibLiferay", velocityTaglib);
222         velocityContext.put("theme", velocityTaglib);
223 
224         UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter(true);
225 
226         try {
227             VelocityEngineUtil.mergeTemplate(
228                 velocityTemplateId, velocityTemplateContent, velocityContext,
229                 unsyncStringWriter);
230         }
231         catch (Exception e) {
232             _log.error(e, e);
233 
234             throw e;
235         }
236 
237         String output = unsyncStringWriter.toString();
238 
239         Map<String, String> columnsMap = processor.getColumnsMap();
240 
241         Iterator<Map.Entry<String, String>> columnsMapItr =
242             columnsMap.entrySet().iterator();
243 
244         while (columnsMapItr.hasNext()) {
245             Map.Entry<String, String> entry = columnsMapItr.next();
246 
247             String key = entry.getKey();
248             String value = entry.getValue();
249 
250             output = StringUtil.replace(output, key, value);
251         }
252 
253         Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
254 
255         Iterator<Map.Entry<Portlet, Object[]>> portletsMapItr =
256             portletsMap.entrySet().iterator();
257 
258         while (portletsMapItr.hasNext()) {
259             Map.Entry<Portlet, Object[]> entry = portletsMapItr.next();
260 
261             Portlet portlet = entry.getKey();
262             Object[] value = entry.getValue();
263 
264             String queryString = (String)value[0];
265             String columnId = (String)value[1];
266             Integer columnPos = (Integer)value[2];
267             Integer columnCount = (Integer)value[3];
268 
269             StringBuilder sb = new StringBuilder();
270 
271             processPortlet(
272                 sb, servletContext, request, response, portlet, queryString,
273                 columnId, columnPos, columnCount, null);
274 
275             output = StringUtil.replace(
276                 output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]",
277                 sb.toString());
278         }
279 
280         return output;
281     }
282 
283     public static String processXML(
284             HttpServletRequest request, String content,
285             RuntimeLogic runtimeLogic)
286         throws Exception {
287 
288         if (Validator.isNull(content)) {
289             return StringPool.BLANK;
290         }
291 
292         try {
293             request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
294 
295             StringBuilder sb = new StringBuilder();
296 
297             int x = 0;
298             int y = content.indexOf(runtimeLogic.getOpenTag());
299 
300             while (y != -1) {
301                 sb.append(content.substring(x, y));
302 
303                 int close1 = content.indexOf(runtimeLogic.getClose1Tag(), y);
304                 int close2 = content.indexOf(runtimeLogic.getClose2Tag(), y);
305 
306                 if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
307                     x = close1 + runtimeLogic.getClose1Tag().length();
308                 }
309                 else {
310                     x = close2 + runtimeLogic.getClose2Tag().length();
311                 }
312 
313                 runtimeLogic.processXML(sb, content.substring(y, x));
314 
315                 y = content.indexOf(runtimeLogic.getOpenTag(), x);
316             }
317 
318             if (y == -1) {
319                 sb.append(content.substring(x, content.length()));
320             }
321 
322             return sb.toString();
323         }
324         finally {
325             request.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
326         }
327     }
328 
329     private static void _defineObjects(
330         HttpServletRequest request, PortletConfig portletConfig,
331         RenderRequest renderRequest, RenderResponse renderResponse) {
332 
333         if (portletConfig != null) {
334             request.setAttribute(
335                 JavaConstants.JAVAX_PORTLET_CONFIG, portletConfig);
336         }
337 
338         if (renderRequest != null) {
339             request.setAttribute(
340                 JavaConstants.JAVAX_PORTLET_REQUEST, renderRequest);
341         }
342 
343         if (renderResponse != null) {
344             request.setAttribute(
345                 JavaConstants.JAVAX_PORTLET_RESPONSE, renderResponse);
346         }
347     }
348 
349     private static Log _log = LogFactoryUtil.getLog(RuntimePortletUtil.class);
350 
351 }