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