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