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.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.HashMap;
41  import java.util.Iterator;
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.PageContext;
52  
53  /**
54   * <a href="RuntimePortletUtil.java.html"><b><i>View Source</i></b></a>
55   *
56   * @author Brian Wing Shun Chan
57   * @author Raymond Augé
58   * @author Shuyang Zhou
59   */
60  public class RuntimePortletUtil {
61  
62      public static String processPortlet(
63              ServletContext servletContext, HttpServletRequest request,
64              HttpServletResponse response, RenderRequest renderRequest,
65              RenderResponse renderResponse, String portletId, String queryString)
66          throws Exception {
67  
68          return processPortlet(
69              servletContext, request, response, renderRequest, renderResponse,
70              portletId, queryString, null, null, null);
71      }
72  
73      public static String processPortlet(
74              ServletContext servletContext, HttpServletRequest request,
75              HttpServletResponse response, RenderRequest renderRequest,
76              RenderResponse renderResponse, String portletId, String queryString,
77              String columnId, Integer columnPos, Integer columnCount)
78          throws Exception {
79  
80          return processPortlet(
81              servletContext, request, response, renderRequest, renderResponse,
82              null, portletId, queryString, columnId, columnPos, columnCount,
83              null);
84      }
85  
86      public static String processPortlet(
87              ServletContext servletContext, HttpServletRequest request,
88              HttpServletResponse response, Portlet portlet, String queryString,
89              String columnId, Integer columnPos, Integer columnCount,
90              String path)
91          throws Exception {
92  
93          return processPortlet(
94              servletContext, request, response, null, null, portlet,
95              portlet.getPortletId(), queryString, columnId, columnPos,
96              columnCount, path);
97      }
98  
99      public static String processPortlet(
100             ServletContext servletContext, HttpServletRequest request,
101             HttpServletResponse response, RenderRequest renderRequest,
102             RenderResponse renderResponse, Portlet portlet, String portletId,
103             String queryString, String columnId, Integer columnPos,
104             Integer columnCount, String path)
105         throws Exception {
106 
107         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
108             WebKeys.THEME_DISPLAY);
109 
110         if (portlet == null) {
111             portlet = PortletLocalServiceUtil.getPortletById(
112                 themeDisplay.getCompanyId(), portletId);
113         }
114 
115         if ((portlet != null) && (portlet.isInstanceable()) &&
116             (!portlet.isAddDefaultResource())) {
117 
118             String instanceId = portlet.getInstanceId();
119 
120             if (Validator.isNotNull(instanceId) &&
121                 Validator.isPassword(instanceId) &&
122                 (instanceId.length() == 4)) {
123 
124                 /*portletId +=
125                     PortletConstants.INSTANCE_SEPARATOR + instanceId;
126 
127                 portlet = PortletLocalServiceUtil.getPortletById(
128                     themeDisplay.getCompanyId(), portletId);*/
129             }
130             else {
131                 if (_log.isDebugEnabled()) {
132                     _log.debug(
133                         "Portlet " + portlet.getPortletId() +
134                             " is instanceable but does not have a " +
135                                 "valid instance id");
136                 }
137 
138                 portlet = null;
139             }
140         }
141 
142         if (portlet == null) {
143             return StringPool.BLANK;
144         }
145 
146         // Capture the current portlet's settings to reset them once the child
147         // portlet is rendered
148 
149         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
150 
151         PortletDisplay portletDisplayClone = PortletDisplayFactory.create();
152 
153         portletDisplay.copyTo(portletDisplayClone);
154 
155         PortletConfig portletConfig = (PortletConfig)request.getAttribute(
156             JavaConstants.JAVAX_PORTLET_CONFIG);
157 
158         try {
159             return PortalUtil.renderPortlet(
160                 servletContext, request, response, portlet, queryString,
161                 columnId, columnPos, columnCount, path, false);
162         }
163         finally {
164             portletDisplay.copyFrom(portletDisplayClone);
165 
166             portletDisplayClone.recycle();
167 
168             _defineObjects(
169                 request, portletConfig, renderRequest, renderResponse);
170         }
171     }
172 
173     public static String processTemplate(
174             ServletContext servletContext, HttpServletRequest request,
175             HttpServletResponse response, PageContext pageContext,
176             String velocityTemplateId, String velocityTemplateContent)
177         throws Exception {
178 
179         return processTemplate(
180             servletContext, request, response, pageContext, null,
181             velocityTemplateId, velocityTemplateContent);
182     }
183 
184     public static String processTemplate(
185             ServletContext servletContext, HttpServletRequest request,
186             HttpServletResponse response, PageContext pageContext,
187             String portletId, String velocityTemplateId,
188             String velocityTemplateContent)
189         throws Exception {
190 
191         if (Validator.isNull(velocityTemplateContent)) {
192             return StringPool.BLANK;
193         }
194 
195         TemplateProcessor processor = new TemplateProcessor(
196             servletContext, request, response, portletId);
197 
198         VelocityContext velocityContext =
199             VelocityEngineUtil.getWrappedStandardToolsContext();
200 
201         velocityContext.put("processor", processor);
202 
203         // Velocity variables
204 
205         VelocityVariables.insertVariables(velocityContext, request);
206 
207         // liferay:include tag library
208 
209         UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
210 
211         MethodWrapper methodWrapper = new MethodWrapper(
212             "com.liferay.taglib.util.VelocityTaglib", "init",
213             new Object[] {
214                 servletContext, request,
215                 new PipingServletResponse(response, unsyncStringWriter),
216                 pageContext
217             });
218 
219         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
220 
221         velocityContext.put("taglibLiferay", velocityTaglib);
222         velocityContext.put("theme", velocityTaglib);
223 
224         try {
225             VelocityEngineUtil.mergeTemplate(
226                 velocityTemplateId, velocityTemplateContent, velocityContext,
227                 unsyncStringWriter);
228         }
229         catch (Exception e) {
230             _log.error(e, e);
231 
232             throw e;
233         }
234 
235         String output = unsyncStringWriter.toString();
236 
237         Map<String, String> columnsMap = processor.getColumnsMap();
238 
239         Iterator<Map.Entry<String, String>> columnsMapItr =
240             columnsMap.entrySet().iterator();
241 
242         while (columnsMapItr.hasNext()) {
243             Map.Entry<String, String> entry = columnsMapItr.next();
244 
245             String key = entry.getKey();
246             String value = entry.getValue();
247 
248             output = StringUtil.replace(output, key, value);
249         }
250 
251         Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
252 
253         Map<String, String> contentsMap = new HashMap<String, String>(
254             portletsMap.size());
255 
256         for (Map.Entry<Portlet, Object[]> entry : portletsMap.entrySet()) {
257             Portlet portlet = entry.getKey();
258             Object[] value = entry.getValue();
259 
260             String queryString = (String)value[0];
261             String columnId = (String)value[1];
262             Integer columnPos = (Integer)value[2];
263             Integer columnCount = (Integer)value[3];
264 
265             String content = processPortlet(
266                 servletContext, request, response, portlet, queryString,
267                 columnId, columnPos, columnCount, null);
268 
269             contentsMap.put(portlet.getPortletId(), content);
270         }
271 
272         return StringUtil.replace(
273             output, "[$TEMPLATE_PORTLET_", "$]", contentsMap);
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 }