1   /**
2    * Copyright (c) 2000-2008 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 stringServletRes = new StringServletResponse(res);
215 
216         MethodWrapper methodWrapper = new MethodWrapper(
217             "com.liferay.taglib.util.VelocityTaglib", "init",
218             new Object[] {ctx, req, stringServletRes, pageContext});
219 
220         Object velocityTaglib = MethodInvoker.invoke(methodWrapper);
221 
222         vc.put("taglibLiferay", velocityTaglib);
223         vc.put("theme", velocityTaglib);
224 
225         StringWriter sw = new StringWriter();
226 
227         try {
228             Velocity.evaluate(
229                 vc, sw, RuntimePortletUtil.class.getName(), content);
230         }
231         catch (Exception e) {
232             _log.error(e, e);
233 
234             throw e;
235         }
236 
237         String output = sw.toString();
238 
239         Map<String, String> columnsMap = processor.getColumnsMap();
240 
241         Iterator<Map.Entry<String, String>> columnsMapItr =
242             columnsMap.entrySet().iterator();
243 
244         while (columnsMapItr.hasNext()) {
245             Map.Entry<String, String> entry = columnsMapItr.next();
246 
247             String key = entry.getKey();
248             String value = entry.getValue();
249 
250             output = StringUtil.replace(output, key, value);
251         }
252 
253         Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
254 
255         Iterator<Map.Entry<Portlet, Object[]>> portletsMapItr =
256             portletsMap.entrySet().iterator();
257 
258         while (portletsMapItr.hasNext()) {
259             Map.Entry<Portlet, Object[]> entry = portletsMapItr.next();
260 
261             Portlet portlet = entry.getKey();
262             Object[] value = entry.getValue();
263 
264             String queryString = (String)value[0];
265             String columnId = (String)value[1];
266             Integer columnPos = (Integer)value[2];
267             Integer columnCount = (Integer)value[3];
268 
269             StringMaker sm = new StringMaker();
270 
271             processPortlet(
272                 sm, ctx, req, res, portlet, queryString, columnId, columnPos,
273                 columnCount, null);
274 
275             output = StringUtil.replace(
276                 output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]",
277                 sm.toString());
278         }
279 
280         return output;
281     }
282 
283     public static String processXML(
284             HttpServletRequest req, String content, RuntimeLogic runtimeLogic)
285         throws Exception {
286 
287         if (Validator.isNull(content)) {
288             return StringPool.BLANK;
289         }
290 
291         try {
292             req.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
293 
294             StringMaker sm = new StringMaker();
295 
296             int x = 0;
297             int y = content.indexOf(runtimeLogic.getOpenTag());
298 
299             while (y != -1) {
300                 sm.append(content.substring(x, y));
301 
302                 int close1 = content.indexOf(runtimeLogic.getClose1Tag(), y);
303                 int close2 = content.indexOf(runtimeLogic.getClose2Tag(), y);
304 
305                 if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
306                     x = close1 + runtimeLogic.getClose1Tag().length();
307                 }
308                 else {
309                     x = close2 + runtimeLogic.getClose2Tag().length();
310                 }
311 
312                 runtimeLogic.processXML(sm, content.substring(y, x));
313 
314                 y = content.indexOf(runtimeLogic.getOpenTag(), x);
315             }
316 
317             if (y == -1) {
318                 sm.append(content.substring(x, content.length()));
319             }
320 
321             return sm.toString();
322         }
323         finally {
324             req.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
325         }
326     }
327 
328     private static void _defineObjects(
329         HttpServletRequest req, PortletConfig portletConfig,
330         RenderRequest renderRequest, RenderResponse renderResponse) {
331 
332         if (portletConfig != null) {
333             req.setAttribute(JavaConstants.JAVAX_PORTLET_CONFIG, portletConfig);
334         }
335 
336         if (renderRequest != null) {
337             req.setAttribute(
338                 JavaConstants.JAVAX_PORTLET_REQUEST, renderRequest);
339         }
340 
341         if (renderResponse != null) {
342             req.setAttribute(
343                 JavaConstants.JAVAX_PORTLET_RESPONSE, renderResponse);
344         }
345     }
346 
347     private static Log _log = LogFactory.getLog(RuntimePortletUtil.class);
348 
349 }