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