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             portletDisplayClone.recycle();
178 
179             _defineObjects(
180                 request, portletConfig, renderRequest, renderResponse);
181         }
182     }
183 
184     public static String processTemplate(
185             ServletContext servletContext, HttpServletRequest request,
186             HttpServletResponse response, PageContext pageContext,
187             String velocityTemplateId, String velocityTemplateContent)
188         throws Exception {
189 
190         return processTemplate(
191             servletContext, request, response, pageContext, null,
192             velocityTemplateId, velocityTemplateContent);
193     }
194 
195     public static String processTemplate(
196             ServletContext servletContext, HttpServletRequest request,
197             HttpServletResponse response, PageContext pageContext,
198             String portletId, String velocityTemplateId,
199             String velocityTemplateContent)
200         throws Exception {
201 
202         if (Validator.isNull(velocityTemplateContent)) {
203             return StringPool.BLANK;
204         }
205 
206         TemplateProcessor processor = new TemplateProcessor(
207             servletContext, request, response, portletId);
208 
209         VelocityContext velocityContext =
210             VelocityEngineUtil.getWrappedStandardToolsContext();
211 
212         velocityContext.put("processor", processor);
213 
214         // Velocity variables
215 
216         VelocityVariables.insertVariables(velocityContext, request);
217 
218         // liferay:include tag library
219 
220         StringServletResponse stringResponse = new StringServletResponse(
221             response);
222 
223         MethodWrapper methodWrapper = new MethodWrapper(
224             "com.liferay.taglib.util.VelocityTaglib", "init",
225             new Object[] {
226                 servletContext, request, stringResponse, pageContext
227             });
228 
229         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
230 
231         velocityContext.put("taglibLiferay", velocityTaglib);
232         velocityContext.put("theme", velocityTaglib);
233 
234         StringWriter stringWriter = new StringWriter();
235 
236         try {
237             VelocityEngineUtil.mergeTemplate(
238                 velocityTemplateId, velocityTemplateContent, velocityContext,
239                 stringWriter);
240         }
241         catch (Exception e) {
242             _log.error(e, e);
243 
244             throw e;
245         }
246 
247         String output = stringWriter.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 = LogFactoryUtil.getLog(RuntimePortletUtil.class);
360 
361 }