001
014
015 package com.liferay.portlet.layoutconfiguration.util;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.servlet.PipingPageContext;
021 import com.liferay.portal.kernel.servlet.PipingServletResponse;
022 import com.liferay.portal.kernel.servlet.PluginContextListener;
023 import com.liferay.portal.kernel.servlet.ServletContextPool;
024 import com.liferay.portal.kernel.util.GetterUtil;
025 import com.liferay.portal.kernel.util.JavaConstants;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.kernel.velocity.VelocityContext;
031 import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
032 import com.liferay.portal.kernel.velocity.VelocityVariablesUtil;
033 import com.liferay.portal.model.LayoutTemplate;
034 import com.liferay.portal.model.LayoutTemplateConstants;
035 import com.liferay.portal.model.Portlet;
036 import com.liferay.portal.model.PortletConstants;
037 import com.liferay.portal.security.lang.PortalSecurityManagerThreadLocal;
038 import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
039 import com.liferay.portal.security.pacl.PACLPolicy;
040 import com.liferay.portal.security.pacl.PACLPolicyManager;
041 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
042 import com.liferay.portal.service.PortletLocalServiceUtil;
043 import com.liferay.portal.theme.PortletDisplay;
044 import com.liferay.portal.theme.PortletDisplayFactory;
045 import com.liferay.portal.theme.ThemeDisplay;
046 import com.liferay.portal.util.PortalUtil;
047 import com.liferay.portal.util.WebKeys;
048 import com.liferay.portlet.layoutconfiguration.util.velocity.CustomizationSettingsProcessor;
049 import com.liferay.portlet.layoutconfiguration.util.velocity.TemplateProcessor;
050 import com.liferay.portlet.layoutconfiguration.util.xml.ActionURLLogic;
051 import com.liferay.portlet.layoutconfiguration.util.xml.PortletLogic;
052 import com.liferay.portlet.layoutconfiguration.util.xml.RenderURLLogic;
053 import com.liferay.portlet.layoutconfiguration.util.xml.RuntimeLogic;
054 import com.liferay.taglib.util.VelocityTaglib;
055
056 import java.lang.reflect.Constructor;
057
058 import java.util.HashMap;
059 import java.util.Map;
060
061 import javax.portlet.PortletConfig;
062 import javax.portlet.PortletRequest;
063 import javax.portlet.RenderRequest;
064 import javax.portlet.RenderResponse;
065
066 import javax.servlet.ServletContext;
067 import javax.servlet.http.HttpServletRequest;
068 import javax.servlet.http.HttpServletResponse;
069 import javax.servlet.jsp.JspWriter;
070 import javax.servlet.jsp.PageContext;
071
072
077 public class RuntimePortletImpl implements RuntimePortlet {
078
079 public String processCustomizationSettings(
080 ServletContext servletContext, HttpServletRequest request,
081 HttpServletResponse response, PageContext pageContext,
082 String velocityTemplateId, String velocityTemplateContent)
083 throws Exception {
084
085 return doDispatch(
086 servletContext, request, response, pageContext, null, null,
087 velocityTemplateId, velocityTemplateContent, false);
088 }
089
090 public String processPortlet(
091 ServletContext servletContext, HttpServletRequest request,
092 HttpServletResponse response, Portlet portlet, String queryString,
093 String columnId, Integer columnPos, Integer columnCount,
094 String path, boolean writeOutput)
095 throws Exception {
096
097 return processPortlet(
098 servletContext, request, response, null, null, portlet,
099 portlet.getPortletId(), queryString, columnId, columnPos,
100 columnCount, path, writeOutput);
101 }
102
103 public String processPortlet(
104 ServletContext servletContext, HttpServletRequest request,
105 HttpServletResponse response, RenderRequest renderRequest,
106 RenderResponse renderResponse, Portlet portlet, String portletId,
107 String queryString, String columnId, Integer columnPos,
108 Integer columnCount, String path, boolean writeOutput)
109 throws Exception {
110
111 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
112 WebKeys.THEME_DISPLAY);
113
114 if (portlet == null) {
115 portlet = PortletLocalServiceUtil.getPortletById(
116 themeDisplay.getCompanyId(), portletId);
117 }
118
119 if ((portlet != null) && portlet.isInstanceable() &&
120 !portlet.isAddDefaultResource()) {
121
122 String instanceId = portlet.getInstanceId();
123
124 if (Validator.isNotNull(instanceId) &&
125 Validator.isPassword(instanceId) &&
126 (instanceId.length() >= 4)) {
127
128
132 }
133 else {
134 if (_log.isDebugEnabled()) {
135 _log.debug(
136 "Portlet " + portlet.getPortletId() +
137 " is instanceable but does not have a " +
138 "valid instance id");
139 }
140
141 portlet = null;
142 }
143 }
144
145 if (portlet == null) {
146 return StringPool.BLANK;
147 }
148
149
150
151
152 PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
153
154 PortletDisplay portletDisplayClone = PortletDisplayFactory.create();
155
156 portletDisplay.copyTo(portletDisplayClone);
157
158 PortletConfig portletConfig = (PortletConfig)request.getAttribute(
159 JavaConstants.JAVAX_PORTLET_CONFIG);
160
161 String lifecycle = (String)request.getAttribute(
162 PortletRequest.LIFECYCLE_PHASE);
163
164 try {
165 return PortalUtil.renderPortlet(
166 servletContext, request, response, portlet, queryString,
167 columnId, columnPos, columnCount, path, writeOutput);
168 }
169 finally {
170 portletDisplay.copyFrom(portletDisplayClone);
171
172 portletDisplayClone.recycle();
173
174 _defineObjects(
175 request, portletConfig, renderRequest, renderResponse);
176
177 if (lifecycle != null) {
178 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
179 }
180 }
181 }
182
183 public String processPortlet(
184 ServletContext servletContext, HttpServletRequest request,
185 HttpServletResponse response, RenderRequest renderRequest,
186 RenderResponse renderResponse, String portletId, String queryString,
187 boolean writeOutput)
188 throws Exception {
189
190 return processPortlet(
191 servletContext, request, response, renderRequest, renderResponse,
192 portletId, queryString, null, null, null, writeOutput);
193 }
194
195 public String processPortlet(
196 ServletContext servletContext, HttpServletRequest request,
197 HttpServletResponse response, RenderRequest renderRequest,
198 RenderResponse renderResponse, String portletId, String queryString,
199 String columnId, Integer columnPos, Integer columnCount,
200 boolean writeOutput)
201 throws Exception {
202
203 return processPortlet(
204 servletContext, request, response, renderRequest, renderResponse,
205 null, portletId, queryString, columnId, columnPos, columnCount,
206 null, writeOutput);
207 }
208
209 public void processTemplate(
210 ServletContext servletContext, HttpServletRequest request,
211 HttpServletResponse response, PageContext pageContext,
212 JspWriter jspWriter, String velocityTemplateId,
213 String velocityTemplateContent)
214 throws Exception {
215
216 processTemplate(
217 servletContext, request, response, pageContext, jspWriter, null,
218 velocityTemplateId, velocityTemplateContent);
219 }
220
221 public void processTemplate(
222 ServletContext servletContext, HttpServletRequest request,
223 HttpServletResponse response, PageContext pageContext,
224 JspWriter jspWriter, String portletId, String velocityTemplateId,
225 String velocityTemplateContent)
226 throws Exception {
227
228 doDispatch(
229 servletContext, request, response, pageContext, jspWriter,
230 portletId, velocityTemplateId, velocityTemplateContent, true);
231 }
232
233 public String processXML(
234 HttpServletRequest request, String content,
235 RuntimeLogic runtimeLogic)
236 throws Exception {
237
238 if (Validator.isNull(content)) {
239 return StringPool.BLANK;
240 }
241
242 int index = content.indexOf(runtimeLogic.getOpenTag());
243
244 if (index == -1) {
245 return content;
246 }
247
248 Portlet renderPortlet = (Portlet)request.getAttribute(
249 WebKeys.RENDER_PORTLET);
250
251 Boolean renderPortletResource = (Boolean)request.getAttribute(
252 WebKeys.RENDER_PORTLET_RESOURCE);
253
254 String outerPortletId = (String)request.getAttribute(
255 WebKeys.OUTER_PORTLET_ID);
256
257 if (outerPortletId == null) {
258 request.setAttribute(
259 WebKeys.OUTER_PORTLET_ID, renderPortlet.getPortletId());
260 }
261
262 try {
263 request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
264
265 StringBundler sb = new StringBundler();
266
267 int x = 0;
268 int y = index;
269
270 while (y != -1) {
271 sb.append(content.substring(x, y));
272
273 int close1 = content.indexOf(runtimeLogic.getClose1Tag(), y);
274 int close2 = content.indexOf(runtimeLogic.getClose2Tag(), y);
275
276 if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
277 x = close1 + runtimeLogic.getClose1Tag().length();
278 }
279 else {
280 x = close2 + runtimeLogic.getClose2Tag().length();
281 }
282
283 sb.append(runtimeLogic.processXML(content.substring(y, x)));
284
285 y = content.indexOf(runtimeLogic.getOpenTag(), x);
286 }
287
288 if (y == -1) {
289 sb.append(content.substring(x));
290 }
291
292 return sb.toString();
293 }
294 finally {
295 if (outerPortletId == null) {
296 request.removeAttribute(WebKeys.OUTER_PORTLET_ID);
297 }
298
299 request.setAttribute(WebKeys.RENDER_PORTLET, renderPortlet);
300
301 if (renderPortletResource == null) {
302 request.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
303 }
304 else {
305 request.setAttribute(
306 WebKeys.RENDER_PORTLET_RESOURCE, renderPortletResource);
307 }
308 }
309 }
310
311 public String processXML(
312 ServletContext servletContext, HttpServletRequest request,
313 HttpServletResponse response, RenderRequest renderRequest,
314 RenderResponse renderResponse, String content)
315 throws Exception {
316
317 RuntimeLogic portletLogic = new PortletLogic
318 (servletContext, request, response, renderRequest, renderResponse);
319 RuntimeLogic actionURLLogic = new ActionURLLogic(renderResponse);
320 RuntimeLogic renderURLLogic = new RenderURLLogic(renderResponse);
321
322 content = RuntimePortletUtil.processXML(request, content, portletLogic);
323 content = RuntimePortletUtil.processXML(
324 request, content, actionURLLogic);
325 content = RuntimePortletUtil.processXML(
326 request, content, renderURLLogic);
327
328 return content;
329 }
330
331 protected Object buildVelocityTaglib(
332 HttpServletRequest request, HttpServletResponse response,
333 PageContext pageContext)
334 throws Exception {
335
336
337
338
339 Class<?> clazz = Class.forName(VelocityTaglib.class.getName());
340
341 Constructor<?> constructor = clazz.getConstructor(
342 ServletContext.class, HttpServletRequest.class,
343 HttpServletResponse.class, PageContext.class);
344
345 return constructor.newInstance(
346 pageContext.getServletContext(), request, response, pageContext);
347 }
348
349 protected String doDispatch(
350 ServletContext servletContext, HttpServletRequest request,
351 HttpServletResponse response, PageContext pageContext,
352 JspWriter jspWriter, String portletId, String velocityTemplateId,
353 String velocityTemplateContent, boolean processTemplate)
354 throws Exception {
355
356 if (Validator.isNull(velocityTemplateContent)) {
357 return null;
358 }
359
360 LayoutTemplate layoutTemplate = getLayoutTemplate(velocityTemplateId);
361
362 String pluginServletContextName = GetterUtil.getString(
363 layoutTemplate.getServletContextName());
364
365 ServletContext pluginServletContext = ServletContextPool.get(
366 pluginServletContextName);
367
368 ClassLoader pluginClassLoader = null;
369
370 if (pluginServletContext != null) {
371 pluginClassLoader =
372 (ClassLoader)pluginServletContext.getAttribute(
373 PluginContextListener.PLUGIN_CLASS_LOADER);
374 }
375
376 ClassLoader contextClassLoader =
377 PACLClassLoaderUtil.getContextClassLoader();
378
379 PACLPolicy contextClassLoaderPACLPolicy =
380 PACLPolicyManager.getPACLPolicy(contextClassLoader);
381 PACLPolicy pluginClassLoaderPACLPolicy =
382 PACLPolicyManager.getPACLPolicy(pluginClassLoader);
383
384 try {
385 if ((pluginClassLoader != null) &&
386 (pluginClassLoader != contextClassLoader)) {
387
388 PACLClassLoaderUtil.setContextClassLoader(pluginClassLoader);
389 PortalSecurityManagerThreadLocal.setPACLPolicy(
390 pluginClassLoaderPACLPolicy);
391 }
392
393 if (processTemplate) {
394 doProcessTemplate(
395 servletContext, request, response, pageContext, jspWriter,
396 portletId, velocityTemplateId, velocityTemplateContent);
397 }
398 else {
399 return doProcessCustomizationSettings(
400 servletContext, request, response, pageContext,
401 velocityTemplateId, velocityTemplateContent);
402 }
403
404 return null;
405 }
406 finally {
407 if ((pluginClassLoader != null) &&
408 (pluginClassLoader != contextClassLoader)) {
409
410 PortalSecurityManagerThreadLocal.setPACLPolicy(
411 contextClassLoaderPACLPolicy);
412 PACLClassLoaderUtil.setContextClassLoader(contextClassLoader);
413 }
414 }
415 }
416
417 protected String doProcessCustomizationSettings(
418 ServletContext servletContext, HttpServletRequest request,
419 HttpServletResponse response, PageContext pageContext,
420 String velocityTemplateId, String velocityTemplateContent)
421 throws Exception {
422
423 if (Validator.isNull(velocityTemplateContent)) {
424 return StringPool.BLANK;
425 }
426
427 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
428
429 CustomizationSettingsProcessor processor =
430 new CustomizationSettingsProcessor(
431 request, new PipingPageContext(pageContext, unsyncStringWriter),
432 unsyncStringWriter);
433
434 VelocityContext velocityContext =
435 VelocityEngineUtil.getWrappedClassLoaderToolsContext();
436
437 velocityContext.put("processor", processor);
438
439
440
441 VelocityVariablesUtil.insertVariables(velocityContext, request);
442
443
444
445 Object velocityTaglib = buildVelocityTaglib(
446 request, response, pageContext);
447
448 velocityContext.put("taglibLiferay", velocityTaglib);
449 velocityContext.put("theme", velocityTaglib);
450
451 try {
452 VelocityEngineUtil.mergeTemplate(
453 velocityTemplateId, velocityTemplateContent, velocityContext,
454 unsyncStringWriter);
455 }
456 catch (Exception e) {
457 _log.error(e, e);
458
459 throw e;
460 }
461
462 return unsyncStringWriter.toString();
463 }
464
465 protected void doProcessTemplate(
466 ServletContext servletContext, HttpServletRequest request,
467 HttpServletResponse response, PageContext pageContext,
468 JspWriter jspWriter, String portletId, String velocityTemplateId,
469 String velocityTemplateContent)
470 throws Exception {
471
472 if (Validator.isNull(velocityTemplateContent)) {
473 return;
474 }
475
476 TemplateProcessor processor = new TemplateProcessor(
477 servletContext, request, response, portletId);
478
479 VelocityContext velocityContext =
480 VelocityEngineUtil.getWrappedClassLoaderToolsContext();
481
482 velocityContext.put("processor", processor);
483
484
485
486 VelocityVariablesUtil.insertVariables(velocityContext, request);
487
488
489
490 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
491
492 Object velocityTaglib = buildVelocityTaglib(
493 request, response, pageContext);
494
495 velocityContext.put("taglibLiferay", velocityTaglib);
496 velocityContext.put("theme", velocityTaglib);
497
498 try {
499 VelocityEngineUtil.mergeTemplate(
500 velocityTemplateId, velocityTemplateContent, velocityContext,
501 unsyncStringWriter);
502 }
503 catch (Exception e) {
504 _log.error(e, e);
505
506 throw e;
507 }
508
509 String output = unsyncStringWriter.toString();
510
511 Map<Portlet, Object[]> portletsMap = processor.getPortletsMap();
512
513 Map<String, StringBundler> contentsMap =
514 new HashMap<String, StringBundler>(portletsMap.size());
515
516 for (Map.Entry<Portlet, Object[]> entry : portletsMap.entrySet()) {
517 Portlet portlet = entry.getKey();
518 Object[] value = entry.getValue();
519
520 String queryString = (String)value[0];
521 String columnId = (String)value[1];
522 Integer columnPos = (Integer)value[2];
523 Integer columnCount = (Integer)value[3];
524
525 UnsyncStringWriter portletUnsyncStringWriter =
526 new UnsyncStringWriter();
527
528 PipingServletResponse pipingServletResponse =
529 new PipingServletResponse(response, portletUnsyncStringWriter);
530
531 processPortlet(
532 servletContext, request, pipingServletResponse, portlet,
533 queryString, columnId, columnPos, columnCount, null, true);
534
535 contentsMap.put(
536 portlet.getPortletId(),
537 portletUnsyncStringWriter.getStringBundler());
538 }
539
540 StringBundler sb = StringUtil.replaceWithStringBundler(
541 output, "[$TEMPLATE_PORTLET_", "$]", contentsMap);
542
543 sb.writeTo(jspWriter);
544 }
545
546 protected LayoutTemplate getLayoutTemplate(String velocityTemplateId) {
547 String separator = LayoutTemplateConstants.CUSTOM_SEPARATOR;
548 boolean standard = false;
549
550 if (velocityTemplateId.contains(
551 LayoutTemplateConstants.STANDARD_SEPARATOR)) {
552
553 separator = LayoutTemplateConstants.STANDARD_SEPARATOR;
554 standard = true;
555 }
556
557 String layoutTemplateId = null;
558
559 String themeId = null;
560
561 int pos = velocityTemplateId.indexOf(separator);
562
563 if (pos != -1) {
564 layoutTemplateId = velocityTemplateId.substring(
565 pos + separator.length());
566
567 themeId = velocityTemplateId.substring(0, pos);
568 }
569
570 pos = layoutTemplateId.indexOf(PortletConstants.INSTANCE_SEPARATOR);
571
572 if (pos != -1) {
573 layoutTemplateId = layoutTemplateId.substring(
574 pos + PortletConstants.INSTANCE_SEPARATOR.length() + 1);
575
576 pos = layoutTemplateId.indexOf(StringPool.UNDERLINE);
577
578 layoutTemplateId = layoutTemplateId.substring(pos + 1);
579 }
580
581 return LayoutTemplateLocalServiceUtil.getLayoutTemplate(
582 layoutTemplateId, standard, themeId);
583 }
584
585 private static void _defineObjects(
586 HttpServletRequest request, PortletConfig portletConfig,
587 RenderRequest renderRequest, RenderResponse renderResponse) {
588
589 if (portletConfig != null) {
590 request.setAttribute(
591 JavaConstants.JAVAX_PORTLET_CONFIG, portletConfig);
592 }
593
594 if (renderRequest != null) {
595 request.setAttribute(
596 JavaConstants.JAVAX_PORTLET_REQUEST, renderRequest);
597 }
598
599 if (renderResponse != null) {
600 request.setAttribute(
601 JavaConstants.JAVAX_PORTLET_RESPONSE, renderResponse);
602 }
603 }
604
605 private static Log _log = LogFactoryUtil.getLog(RuntimePortletUtil.class);
606
607 }