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