1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.layoutconfiguration.util;
24  
25  import com.liferay.portal.kernel.servlet.StringServletResponse;
26  import com.liferay.portal.kernel.util.JavaConstants;
27  import com.liferay.portal.kernel.util.MethodInvoker;
28  import com.liferay.portal.kernel.util.MethodWrapper;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.model.Portlet;
33  import com.liferay.portal.service.PortletLocalServiceUtil;
34  import com.liferay.portal.theme.PortletDisplay;
35  import com.liferay.portal.theme.PortletDisplayFactory;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portal.util.PortalUtil;
38  import com.liferay.portal.util.WebKeys;
39  import com.liferay.portal.velocity.VelocityVariables;
40  import com.liferay.portlet.layoutconfiguration.util.velocity.TemplateProcessor;
41  import com.liferay.portlet.layoutconfiguration.util.xml.RuntimeLogic;
42  
43  import java.io.StringWriter;
44  
45  import java.util.Iterator;
46  import java.util.Map;
47  
48  import javax.portlet.PortletConfig;
49  import javax.portlet.RenderRequest;
50  import javax.portlet.RenderResponse;
51  
52  import javax.servlet.ServletContext;
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  import javax.servlet.jsp.PageContext;
56  
57  import org.apache.commons.logging.Log;
58  import org.apache.commons.logging.LogFactory;
59  import org.apache.velocity.VelocityContext;
60  import org.apache.velocity.app.Velocity;
61  
62  /**
63   * <a href="RuntimePortletUtil.java.html"><b><i>View Source</i></b></a>
64   *
65   * @author Brian Wing Shun Chan
66   * @author Raymond Aug�
67   *
68   */
69  public class RuntimePortletUtil {
70  
71      public static void processPortlet(
72              StringBuilder sb, ServletContext servletContext,
73              HttpServletRequest request, HttpServletResponse response,
74              RenderRequest renderRequest, RenderResponse renderResponse,
75              String portletId, String queryString)
76          throws Exception {
77  
78          processPortlet(
79              sb, servletContext, request, response, renderRequest,
80              renderResponse, portletId, queryString, null, null, null);
81      }
82  
83      public static void processPortlet(
84              StringBuilder sb, ServletContext servletContext,
85              HttpServletRequest request, HttpServletResponse response,
86              RenderRequest renderRequest, RenderResponse renderResponse,
87              String portletId, String queryString, String columnId,
88              Integer columnPos, Integer columnCount)
89          throws Exception {
90  
91          processPortlet(
92              sb, servletContext, request, response, renderRequest,
93              renderResponse, null, portletId, queryString, columnId, columnPos,
94              columnCount, null);
95      }
96  
97      public static void processPortlet(
98              StringBuilder sb, ServletContext servletContext,
99              HttpServletRequest request, HttpServletResponse response,
100             Portlet portlet, String queryString, String columnId,
101             Integer columnPos, Integer columnCount, String path)
102         throws Exception {
103 
104         processPortlet(
105             sb, servletContext, request, response, null, null, portlet,
106             portlet.getPortletId(), queryString, columnId, columnPos,
107             columnCount, path);
108     }
109 
110     public static void processPortlet(
111             StringBuilder sb, ServletContext servletContext,
112             HttpServletRequest request, HttpServletResponse response,
113             RenderRequest renderRequest, RenderResponse renderResponse,
114             Portlet portlet, String portletId, String queryString,
115             String columnId, Integer columnPos, Integer columnCount,
116             String path)
117         throws Exception {
118 
119         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
120             WebKeys.THEME_DISPLAY);
121 
122         if (portlet == null) {
123             portlet = PortletLocalServiceUtil.getPortletById(
124                 themeDisplay.getCompanyId(), portletId);
125         }
126 
127         if ((portlet != null) && portlet.isInstanceable()) {
128             String instanceId = portlet.getInstanceId();
129 
130             if (Validator.isNotNull(instanceId) &&
131                 Validator.isPassword(instanceId) &&
132                 (instanceId.length() == 4)) {
133 
134                 /*portletId +=
135                     PortletConstants.INSTANCE_SEPARATOR + instanceId;
136 
137                 portlet = PortletLocalServiceUtil.getPortletById(
138                     themeDisplay.getCompanyId(), portletId);*/
139             }
140             else {
141                 if (_log.isDebugEnabled()) {
142                     _log.debug(
143                         "Portlet " + portlet.getPortletId() +
144                             " is instanceable but does not have a " +
145                                 "valid instance id");
146                 }
147 
148                 portlet = null;
149             }
150         }
151 
152         if (portlet == null) {
153             return;
154         }
155 
156         // Capture the current portlet's settings to reset them once the child
157         // portlet is rendered
158 
159         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
160 
161         PortletDisplay portletDisplayClone = PortletDisplayFactory.create();
162 
163         portletDisplay.copyTo(portletDisplayClone);
164 
165         PortletConfig portletConfig = (PortletConfig)request.getAttribute(
166             JavaConstants.JAVAX_PORTLET_CONFIG);
167 
168         try {
169             PortalUtil.renderPortlet(
170                 sb, servletContext, request, response, portlet, queryString,
171                 columnId, columnPos, columnCount, path);
172         }
173         finally {
174             portletDisplay.copyFrom(portletDisplayClone);
175 
176             try {
177                 PortletDisplayFactory.recycle(portletDisplayClone);
178             }
179             catch (Exception e) {
180                 _log.error(e);
181             }
182 
183             _defineObjects(
184                 request, portletConfig, renderRequest, renderResponse);
185         }
186     }
187 
188     public static String processTemplate(
189             ServletContext servletContext, HttpServletRequest request,
190             HttpServletResponse response, PageContext pageContext,
191             String content)
192         throws Exception {
193 
194         return processTemplate(
195             servletContext, request, response, pageContext, null, content);
196     }
197 
198     public static String processTemplate(
199             ServletContext servletContext, HttpServletRequest request,
200             HttpServletResponse response, PageContext pageContext,
201             String portletId, String content)
202         throws Exception {
203 
204         if (Validator.isNull(content)) {
205             return StringPool.BLANK;
206         }
207 
208         TemplateProcessor processor = new TemplateProcessor(
209             servletContext, request, response, portletId);
210 
211         VelocityContext velocityContext = null;
212 
213         // LEP-6865
214 
215         if (_innerVelocityContext == null) {
216             velocityContext = new VelocityContext();
217 
218             _innerVelocityContext = velocityContext;
219         }
220         else {
221             velocityContext = new VelocityContext(_innerVelocityContext);
222         }
223 
224         velocityContext.put("processor", processor);
225 
226         // Velocity variables
227 
228         VelocityVariables.insertVariables(velocityContext, request);
229 
230         // liferay:include tag library
231 
232         StringServletResponse stringResponse = new StringServletResponse(
233             response);
234 
235         MethodWrapper methodWrapper = new MethodWrapper(
236             "com.liferay.taglib.util.VelocityTaglib", "init",
237             new Object[] {
238                 servletContext, request, stringResponse, pageContext
239             });
240 
241         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
242 
243         velocityContext.put("taglibLiferay", velocityTaglib);
244         velocityContext.put("theme", velocityTaglib);
245 
246         StringWriter sw = new StringWriter();
247 
248         try {
249             Velocity.evaluate(
250                 velocityContext, sw, RuntimePortletUtil.class.getName(),
251                 content);
252         }
253         catch (Exception e) {
254             _log.error(e, e);
255 
256             throw e;
257         }
258 
259         String output = sw.toString();
260 
261         Map<String, String> columnsMap = processor.getColumnsMap();
262 
263         Iterator<Map.Entry<String, String>> columnsMapItr =
264             columnsMap.entrySet().iterator();
265 
266         while (columnsMapItr.hasNext()) {
267             Map.Entry<String, String> entry = columnsMapItr.next();
268 
269             String key = entry.getKey();
270             String value = entry.getValue();
271 
272             output = StringUtil.replace(output, key, value);
273         }
274 
275         Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
276 
277         Iterator<Map.Entry<Portlet, Object[]>> portletsMapItr =
278             portletsMap.entrySet().iterator();
279 
280         while (portletsMapItr.hasNext()) {
281             Map.Entry<Portlet, Object[]> entry = portletsMapItr.next();
282 
283             Portlet portlet = entry.getKey();
284             Object[] value = entry.getValue();
285 
286             String queryString = (String)value[0];
287             String columnId = (String)value[1];
288             Integer columnPos = (Integer)value[2];
289             Integer columnCount = (Integer)value[3];
290 
291             StringBuilder sb = new StringBuilder();
292 
293             processPortlet(
294                 sb, servletContext, request, response, portlet, queryString,
295                 columnId, columnPos, columnCount, null);
296 
297             output = StringUtil.replace(
298                 output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]",
299                 sb.toString());
300         }
301 
302         return output;
303     }
304 
305     public static String processXML(
306             HttpServletRequest request, String content,
307             RuntimeLogic runtimeLogic)
308         throws Exception {
309 
310         if (Validator.isNull(content)) {
311             return StringPool.BLANK;
312         }
313 
314         try {
315             request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
316 
317             StringBuilder sb = new StringBuilder();
318 
319             int x = 0;
320             int y = content.indexOf(runtimeLogic.getOpenTag());
321 
322             while (y != -1) {
323                 sb.append(content.substring(x, y));
324 
325                 int close1 = content.indexOf(runtimeLogic.getClose1Tag(), y);
326                 int close2 = content.indexOf(runtimeLogic.getClose2Tag(), y);
327 
328                 if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
329                     x = close1 + runtimeLogic.getClose1Tag().length();
330                 }
331                 else {
332                     x = close2 + runtimeLogic.getClose2Tag().length();
333                 }
334 
335                 runtimeLogic.processXML(sb, content.substring(y, x));
336 
337                 y = content.indexOf(runtimeLogic.getOpenTag(), x);
338             }
339 
340             if (y == -1) {
341                 sb.append(content.substring(x, content.length()));
342             }
343 
344             return sb.toString();
345         }
346         finally {
347             request.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
348         }
349     }
350 
351     private static void _defineObjects(
352         HttpServletRequest request, PortletConfig portletConfig,
353         RenderRequest renderRequest, RenderResponse renderResponse) {
354 
355         if (portletConfig != null) {
356             request.setAttribute(
357                 JavaConstants.JAVAX_PORTLET_CONFIG, portletConfig);
358         }
359 
360         if (renderRequest != null) {
361             request.setAttribute(
362                 JavaConstants.JAVAX_PORTLET_REQUEST, renderRequest);
363         }
364 
365         if (renderResponse != null) {
366             request.setAttribute(
367                 JavaConstants.JAVAX_PORTLET_RESPONSE, renderResponse);
368         }
369     }
370 
371     private static Log _log = LogFactory.getLog(RuntimePortletUtil.class);
372 
373     private static VelocityContext _innerVelocityContext;
374 
375 }