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.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   */
59  public class RuntimePortletUtil {
60  
61      public static String processPortlet(
62              ServletContext servletContext, HttpServletRequest request,
63              HttpServletResponse response, RenderRequest renderRequest,
64              RenderResponse renderResponse, String portletId, String queryString)
65          throws Exception {
66  
67          return processPortlet(
68              servletContext, request, response, renderRequest, renderResponse,
69              portletId, queryString, null, null, null);
70      }
71  
72      public static String processPortlet(
73              ServletContext servletContext, HttpServletRequest request,
74              HttpServletResponse response, RenderRequest renderRequest,
75              RenderResponse renderResponse, String portletId, String queryString,
76              String columnId, Integer columnPos, Integer columnCount)
77          throws Exception {
78  
79          return processPortlet(
80              servletContext, request, response, renderRequest, renderResponse,
81              null, portletId, queryString, columnId, columnPos, columnCount,
82              null);
83      }
84  
85      public static String processPortlet(
86              ServletContext servletContext, HttpServletRequest request,
87              HttpServletResponse response, Portlet portlet, String queryString,
88              String columnId, Integer columnPos, Integer columnCount,
89              String path)
90          throws Exception {
91  
92          return processPortlet(
93              servletContext, request, response, null, null, portlet,
94              portlet.getPortletId(), queryString, columnId, columnPos,
95              columnCount, path);
96      }
97  
98      public static String processPortlet(
99              ServletContext servletContext, HttpServletRequest request,
100             HttpServletResponse response, RenderRequest renderRequest,
101             RenderResponse renderResponse, Portlet portlet, String portletId,
102             String queryString, String columnId, Integer columnPos,
103             Integer columnCount, String path)
104         throws Exception {
105 
106         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
107             WebKeys.THEME_DISPLAY);
108 
109         if (portlet == null) {
110             portlet = PortletLocalServiceUtil.getPortletById(
111                 themeDisplay.getCompanyId(), portletId);
112         }
113 
114         if ((portlet != null) && (portlet.isInstanceable()) &&
115             (!portlet.isAddDefaultResource())) {
116 
117             String instanceId = portlet.getInstanceId();
118 
119             if (Validator.isNotNull(instanceId) &&
120                 Validator.isPassword(instanceId) &&
121                 (instanceId.length() == 4)) {
122 
123                 /*portletId +=
124                     PortletConstants.INSTANCE_SEPARATOR + instanceId;
125 
126                 portlet = PortletLocalServiceUtil.getPortletById(
127                     themeDisplay.getCompanyId(), portletId);*/
128             }
129             else {
130                 if (_log.isDebugEnabled()) {
131                     _log.debug(
132                         "Portlet " + portlet.getPortletId() +
133                             " is instanceable but does not have a " +
134                                 "valid instance id");
135                 }
136 
137                 portlet = null;
138             }
139         }
140 
141         if (portlet == null) {
142             return StringPool.BLANK;
143         }
144 
145         // Capture the current portlet's settings to reset them once the child
146         // portlet is rendered
147 
148         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
149 
150         PortletDisplay portletDisplayClone = PortletDisplayFactory.create();
151 
152         portletDisplay.copyTo(portletDisplayClone);
153 
154         PortletConfig portletConfig = (PortletConfig)request.getAttribute(
155             JavaConstants.JAVAX_PORTLET_CONFIG);
156 
157         try {
158             return PortalUtil.renderPortlet(
159                 servletContext, request, response, portlet, queryString,
160                 columnId, columnPos, columnCount, path, false);
161         }
162         finally {
163             portletDisplay.copyFrom(portletDisplayClone);
164 
165             portletDisplayClone.recycle();
166 
167             _defineObjects(
168                 request, portletConfig, renderRequest, renderResponse);
169         }
170     }
171 
172     public static String processTemplate(
173             ServletContext servletContext, HttpServletRequest request,
174             HttpServletResponse response, PageContext pageContext,
175             String velocityTemplateId, String velocityTemplateContent)
176         throws Exception {
177 
178         return processTemplate(
179             servletContext, request, response, pageContext, null,
180             velocityTemplateId, velocityTemplateContent);
181     }
182 
183     public static String processTemplate(
184             ServletContext servletContext, HttpServletRequest request,
185             HttpServletResponse response, PageContext pageContext,
186             String portletId, String velocityTemplateId,
187             String velocityTemplateContent)
188         throws Exception {
189 
190         if (Validator.isNull(velocityTemplateContent)) {
191             return StringPool.BLANK;
192         }
193 
194         TemplateProcessor processor = new TemplateProcessor(
195             servletContext, request, response, portletId);
196 
197         VelocityContext velocityContext =
198             VelocityEngineUtil.getWrappedStandardToolsContext();
199 
200         velocityContext.put("processor", processor);
201 
202         // Velocity variables
203 
204         VelocityVariables.insertVariables(velocityContext, request);
205 
206         // liferay:include tag library
207 
208         StringServletResponse stringResponse = new StringServletResponse(
209             response);
210 
211         MethodWrapper methodWrapper = new MethodWrapper(
212             "com.liferay.taglib.util.VelocityTaglib", "init",
213             new Object[] {
214                 servletContext, request, stringResponse, pageContext
215             });
216 
217         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
218 
219         velocityContext.put("taglibLiferay", velocityTaglib);
220         velocityContext.put("theme", velocityTaglib);
221 
222         UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
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 }