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