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 vc = new VelocityContext();
212 
213         vc.put("processor", processor);
214 
215         // Velocity variables
216 
217         VelocityVariables.insertVariables(vc, request);
218 
219         // liferay:include tag library
220 
221         StringServletResponse stringResponse = new StringServletResponse(
222             response);
223 
224         MethodWrapper methodWrapper = new MethodWrapper(
225             "com.liferay.taglib.util.VelocityTaglib", "init",
226             new Object[] {
227                 servletContext, request, stringResponse, pageContext
228             });
229 
230         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
231 
232         vc.put("taglibLiferay", velocityTaglib);
233         vc.put("theme", velocityTaglib);
234 
235         StringWriter sw = new StringWriter();
236 
237         try {
238             Velocity.evaluate(
239                 vc, sw, RuntimePortletUtil.class.getName(), content);
240         }
241         catch (Exception e) {
242             _log.error(e, e);
243 
244             throw e;
245         }
246 
247         String output = sw.toString();
248 
249         Map<String, String> columnsMap = processor.getColumnsMap();
250 
251         Iterator<Map.Entry<String, String>> columnsMapItr =
252             columnsMap.entrySet().iterator();
253 
254         while (columnsMapItr.hasNext()) {
255             Map.Entry<String, String> entry = columnsMapItr.next();
256 
257             String key = entry.getKey();
258             String value = entry.getValue();
259 
260             output = StringUtil.replace(output, key, value);
261         }
262 
263         Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
264 
265         Iterator<Map.Entry<Portlet, Object[]>> portletsMapItr =
266             portletsMap.entrySet().iterator();
267 
268         while (portletsMapItr.hasNext()) {
269             Map.Entry<Portlet, Object[]> entry = portletsMapItr.next();
270 
271             Portlet portlet = entry.getKey();
272             Object[] value = entry.getValue();
273 
274             String queryString = (String)value[0];
275             String columnId = (String)value[1];
276             Integer columnPos = (Integer)value[2];
277             Integer columnCount = (Integer)value[3];
278 
279             StringBuilder sb = new StringBuilder();
280 
281             processPortlet(
282                 sb, servletContext, request, response, portlet, queryString,
283                 columnId, columnPos, columnCount, null);
284 
285             output = StringUtil.replace(
286                 output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]",
287                 sb.toString());
288         }
289 
290         return output;
291     }
292 
293     public static String processXML(
294             HttpServletRequest request, String content,
295             RuntimeLogic runtimeLogic)
296         throws Exception {
297 
298         if (Validator.isNull(content)) {
299             return StringPool.BLANK;
300         }
301 
302         try {
303             request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
304 
305             StringBuilder sb = new StringBuilder();
306 
307             int x = 0;
308             int y = content.indexOf(runtimeLogic.getOpenTag());
309 
310             while (y != -1) {
311                 sb.append(content.substring(x, y));
312 
313                 int close1 = content.indexOf(runtimeLogic.getClose1Tag(), y);
314                 int close2 = content.indexOf(runtimeLogic.getClose2Tag(), y);
315 
316                 if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
317                     x = close1 + runtimeLogic.getClose1Tag().length();
318                 }
319                 else {
320                     x = close2 + runtimeLogic.getClose2Tag().length();
321                 }
322 
323                 runtimeLogic.processXML(sb, content.substring(y, x));
324 
325                 y = content.indexOf(runtimeLogic.getOpenTag(), x);
326             }
327 
328             if (y == -1) {
329                 sb.append(content.substring(x, content.length()));
330             }
331 
332             return sb.toString();
333         }
334         finally {
335             request.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
336         }
337     }
338 
339     private static void _defineObjects(
340         HttpServletRequest request, PortletConfig portletConfig,
341         RenderRequest renderRequest, RenderResponse renderResponse) {
342 
343         if (portletConfig != null) {
344             request.setAttribute(
345                 JavaConstants.JAVAX_PORTLET_CONFIG, portletConfig);
346         }
347 
348         if (renderRequest != null) {
349             request.setAttribute(
350                 JavaConstants.JAVAX_PORTLET_REQUEST, renderRequest);
351         }
352 
353         if (renderResponse != null) {
354             request.setAttribute(
355                 JavaConstants.JAVAX_PORTLET_RESPONSE, renderResponse);
356         }
357     }
358 
359     private static Log _log = LogFactory.getLog(RuntimePortletUtil.class);
360 
361 }