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