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