001
014
015 package com.liferay.taglib.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.PipingServletResponse;
021 import com.liferay.portal.kernel.servlet.PluginContextListener;
022 import com.liferay.portal.kernel.servlet.ServletContextPool;
023 import com.liferay.portal.kernel.template.Template;
024 import com.liferay.portal.kernel.template.TemplateContextType;
025 import com.liferay.portal.kernel.template.TemplateManager;
026 import com.liferay.portal.kernel.template.TemplateManagerUtil;
027 import com.liferay.portal.kernel.template.TemplateResource;
028 import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
029 import com.liferay.portal.kernel.templateparser.TemplateContext;
030 import com.liferay.portal.kernel.util.GetterUtil;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.ThemeHelper;
033 import com.liferay.portal.kernel.util.UnsyncPrintWriterPool;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.util.WebKeys;
036 import com.liferay.portal.model.PortletConstants;
037 import com.liferay.portal.model.Theme;
038 import com.liferay.portal.theme.PortletDisplay;
039 import com.liferay.portal.theme.ThemeDisplay;
040 import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
041
042 import freemarker.ext.servlet.HttpRequestHashModel;
043 import freemarker.ext.servlet.ServletContextHashModel;
044
045 import freemarker.template.ObjectWrapper;
046 import freemarker.template.TemplateHashModel;
047
048 import java.io.IOException;
049 import java.io.Writer;
050
051 import javax.servlet.GenericServlet;
052 import javax.servlet.RequestDispatcher;
053 import javax.servlet.Servlet;
054 import javax.servlet.ServletContext;
055 import javax.servlet.ServletException;
056 import javax.servlet.ServletRequest;
057 import javax.servlet.ServletResponse;
058 import javax.servlet.http.HttpServletRequest;
059 import javax.servlet.http.HttpServletResponse;
060 import javax.servlet.jsp.PageContext;
061
062 import org.apache.struts.taglib.tiles.ComponentConstants;
063 import org.apache.struts.tiles.ComponentContext;
064
065
072 public class ThemeUtil {
073
074 public static String getPortletId(HttpServletRequest request) {
075 String portletId = null;
076
077 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
078 WebKeys.THEME_DISPLAY);
079
080 if (themeDisplay != null) {
081 PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
082
083 portletId = portletDisplay.getId();
084 }
085
086 return portletId;
087 }
088
089 public static void include(
090 ServletContext servletContext, HttpServletRequest request,
091 HttpServletResponse response, PageContext pageContext, String path,
092 Theme theme)
093 throws Exception {
094
095 String extension = theme.getTemplateExtension();
096
097 if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_FTL)) {
098 includeFTL(servletContext, request, pageContext, path, theme, true);
099 }
100 else if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_VM)) {
101 includeVM(servletContext, request, pageContext, path, theme, true);
102 }
103 else {
104 path = theme.getTemplatesPath() + StringPool.SLASH + path;
105
106 includeJSP(servletContext, request, response, path, theme);
107 }
108 }
109
110 public static String includeFTL(
111 ServletContext servletContext, HttpServletRequest request,
112 PageContext pageContext, String path, Theme theme, boolean write)
113 throws Exception {
114
115 return doDispatch(
116 servletContext, request, null, pageContext, path, theme, write,
117 ThemeHelper.TEMPLATE_EXTENSION_FTL);
118 }
119
120 public static void includeJSP(
121 ServletContext servletContext, HttpServletRequest request,
122 HttpServletResponse response, String path, Theme theme)
123 throws Exception {
124
125 doDispatch(
126 servletContext, request, response, null, path, theme, true,
127 ThemeHelper.TEMPLATE_EXTENSION_JSP);
128 }
129
130 public static String includeVM(
131 ServletContext servletContext, HttpServletRequest request,
132 PageContext pageContext, String path, Theme theme, boolean write)
133 throws Exception {
134
135 return doDispatch(
136 servletContext, request, null, pageContext, path, theme, write,
137 ThemeHelper.TEMPLATE_EXTENSION_VM);
138 }
139
140 protected static String doDispatch(
141 ServletContext servletContext, HttpServletRequest request,
142 HttpServletResponse response, PageContext pageContext, String path,
143 Theme theme, boolean write, String extension)
144 throws Exception {
145
146 String pluginServletContextName = GetterUtil.getString(
147 theme.getServletContextName());
148
149 ServletContext pluginServletContext = ServletContextPool.get(
150 pluginServletContextName);
151
152 ClassLoader pluginClassLoader = null;
153
154 if (pluginServletContext != null) {
155 pluginClassLoader =
156 (ClassLoader)pluginServletContext.getAttribute(
157 PluginContextListener.PLUGIN_CLASS_LOADER);
158 }
159
160 Thread currentThread = Thread.currentThread();
161
162 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
163
164 TemplateContextType templateContextType = TemplateContextType.STANDARD;
165
166 if ((pluginClassLoader != null) &&
167 (pluginClassLoader != contextClassLoader)) {
168
169 currentThread.setContextClassLoader(pluginClassLoader);
170
171 templateContextType = TemplateContextType.CLASS_LOADER;
172 }
173
174 try {
175 if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_FTL)) {
176 return doIncludeFTL(
177 servletContext, request, pageContext, path, theme,
178 templateContextType, write);
179 }
180 else if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_JSP)) {
181 doIncludeJSP(servletContext, request, response, path, theme);
182 }
183 else if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_VM)) {
184 return doIncludeVM(
185 servletContext, request, pageContext, path, theme,
186 templateContextType, write);
187 }
188
189 return null;
190 }
191 finally {
192 if ((pluginClassLoader != null) &&
193 (pluginClassLoader != contextClassLoader)) {
194
195 currentThread.setContextClassLoader(contextClassLoader);
196 }
197 }
198 }
199
200 protected static String doIncludeFTL(
201 ServletContext servletContext, HttpServletRequest request,
202 PageContext pageContext, String path, Theme theme,
203 TemplateContextType templateContextType, boolean write)
204 throws Exception {
205
206
207
208
209
210
211
212 String servletContextName = GetterUtil.getString(
213 theme.getServletContextName());
214
215 if (ServletContextPool.get(servletContextName) == null) {
216
217
218
219
220 ServletContextPool.put(servletContextName, servletContext);
221 }
222
223 String portletId = getPortletId(request);
224
225 String resourcePath = theme.getResourcePath(
226 servletContext, portletId, path);
227
228 if (Validator.isNotNull(portletId) &&
229 PortletConstants.hasInstanceId(portletId) &&
230 !TemplateResourceLoaderUtil.hasTemplateResource(
231 TemplateManager.FREEMARKER, resourcePath)) {
232
233 String rootPortletId = PortletConstants.getRootPortletId(portletId);
234
235 resourcePath = theme.getResourcePath(
236 servletContext, rootPortletId, path);
237 }
238
239 if (Validator.isNotNull(portletId) &&
240 !TemplateResourceLoaderUtil.hasTemplateResource(
241 TemplateManager.FREEMARKER, resourcePath)) {
242
243 resourcePath = theme.getResourcePath(servletContext, null, path);
244 }
245
246 if (!TemplateResourceLoaderUtil.hasTemplateResource(
247 TemplateManager.FREEMARKER, resourcePath)) {
248
249 _log.error(resourcePath + " does not exist");
250
251 return null;
252 }
253
254 TemplateResource templateResource =
255 TemplateResourceLoaderUtil.getTemplateResource(
256 TemplateManager.FREEMARKER, resourcePath);
257
258 Template template = TemplateManagerUtil.getTemplate(
259 TemplateManager.FREEMARKER, templateResource,
260 TemplateContextType.STANDARD);
261
262
263
264 template.prepare(request);
265
266
267
268 ServletContext themeServletContext = ServletContextPool.get(
269 servletContextName);
270
271 template.put("themeServletContext", themeServletContext);
272
273
274
275 HttpServletResponse response =
276 (HttpServletResponse)pageContext.getResponse();
277
278 Writer writer = null;
279
280 if (write) {
281
282
283
284 writer = UnsyncPrintWriterPool.borrow(pageContext.getOut());
285 }
286 else {
287 writer = new UnsyncStringWriter();
288 }
289
290 VelocityTaglib velocityTaglib = new VelocityTaglib(
291 servletContext, request,
292 new PipingServletResponse(response, writer), pageContext, template);
293
294 template.put(TemplateContext.WRITER, writer);
295 template.put("taglibLiferay", velocityTaglib);
296 template.put("theme", velocityTaglib);
297
298
299
300 TemplateHashModel portalTaglib =
301 FreeMarkerTaglibFactoryUtil.createTaglibFactory(servletContext);
302
303 template.put("PortalJspTagLibs", portalTaglib);
304
305
306
307 TemplateHashModel themeTaglib =
308 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
309 themeServletContext);
310
311 template.put("ThemeJspTaglibs", themeTaglib);
312
313
314
315 final Servlet servlet = (Servlet)pageContext.getPage();
316
317 GenericServlet genericServlet = null;
318
319 if (servlet instanceof GenericServlet) {
320 genericServlet = (GenericServlet) servlet;
321 }
322 else {
323 genericServlet = new GenericServlet() {
324
325 @Override
326 public void service(
327 ServletRequest servletRequest,
328 ServletResponse servletResponse)
329 throws IOException, ServletException {
330
331 servlet.service(servletRequest, servletResponse);
332 }
333
334 };
335
336 genericServlet.init(pageContext.getServletConfig());
337 }
338
339 ServletContextHashModel servletContextHashModel =
340 new ServletContextHashModel(
341 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
342
343 template.put("Application", servletContextHashModel);
344
345 HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
346 request, response, ObjectWrapper.DEFAULT_WRAPPER);
347
348 template.put("Request", httpRequestHashModel);
349
350
351
352 template.processTemplate(writer);
353
354 if (write) {
355 return null;
356 }
357 else {
358 return writer.toString();
359 }
360 }
361
362 protected static void doIncludeJSP(
363 ServletContext servletContext, HttpServletRequest request,
364 HttpServletResponse response, String path, Theme theme)
365 throws Exception {
366
367 insertTilesVariables(request);
368
369 if (theme.isWARFile()) {
370 ServletContext themeServletContext = servletContext.getContext(
371 theme.getContextPath());
372
373 if (themeServletContext == null) {
374 _log.error(
375 "Theme " + theme.getThemeId() + " cannot find its " +
376 "servlet context at " + theme.getServletContextName());
377 }
378 else {
379 RequestDispatcher requestDispatcher =
380 themeServletContext.getRequestDispatcher(path);
381
382 if (requestDispatcher == null) {
383 _log.error(
384 "Theme " + theme.getThemeId() + " does not have " +
385 path);
386 }
387 else {
388 requestDispatcher.include(request, response);
389 }
390 }
391 }
392 else {
393 RequestDispatcher requestDispatcher =
394 servletContext.getRequestDispatcher(path);
395
396 if (requestDispatcher == null) {
397 _log.error(
398 "Theme " + theme.getThemeId() + " does not have " + path);
399 }
400 else {
401 requestDispatcher.include(request, response);
402 }
403 }
404 }
405
406 protected static String doIncludeVM(
407 ServletContext servletContext, HttpServletRequest request,
408 PageContext pageContext, String page, Theme theme,
409 TemplateContextType templateContextType, boolean write)
410 throws Exception {
411
412
413
414
415
416
417
418 String servletContextName = GetterUtil.getString(
419 theme.getServletContextName());
420
421 if (ServletContextPool.get(servletContextName) == null) {
422
423
424
425
426 ServletContextPool.put(servletContextName, servletContext);
427 }
428
429 String portletId = getPortletId(request);
430
431 String resourcePath = theme.getResourcePath(
432 servletContext, portletId, page);
433
434 boolean checkResourceExists = true;
435
436 if (Validator.isNotNull(portletId)) {
437 if (PortletConstants.hasInstanceId(portletId) &&
438 (checkResourceExists = !
439 TemplateResourceLoaderUtil.hasTemplateResource(
440 TemplateManager.VELOCITY, resourcePath))) {
441
442 String rootPortletId = PortletConstants.getRootPortletId(
443 portletId);
444
445 resourcePath = theme.getResourcePath(
446 servletContext, rootPortletId, page);
447 }
448
449 if (checkResourceExists &&
450 (checkResourceExists = !
451 TemplateResourceLoaderUtil.hasTemplateResource(
452 TemplateManager.VELOCITY, resourcePath))) {
453
454 resourcePath = theme.getResourcePath(
455 servletContext, null, page);
456 }
457 }
458
459 if (checkResourceExists &&
460 !TemplateResourceLoaderUtil.hasTemplateResource(
461 TemplateManager.VELOCITY, resourcePath)) {
462
463 _log.error(resourcePath + " does not exist");
464
465 return null;
466 }
467
468 TemplateResource templateResource =
469 TemplateResourceLoaderUtil.getTemplateResource(
470 TemplateManager.VELOCITY, resourcePath);
471
472 if (templateResource == null) {
473 throw new Exception(
474 "Unable to load template resource " + resourcePath);
475 }
476
477 Template template = TemplateManagerUtil.getTemplate(
478 TemplateManager.VELOCITY, templateResource,
479 TemplateContextType.STANDARD);
480
481
482
483 template.prepare(request);
484
485
486
487 template.put("pageContext", pageContext);
488
489
490
491 ServletContext themeServletContext = ServletContextPool.get(
492 servletContextName);
493
494 template.put("themeServletContext", themeServletContext);
495
496
497
498 HttpServletResponse response =
499 (HttpServletResponse)pageContext.getResponse();
500
501 Writer writer = null;
502
503 if (write) {
504 writer = pageContext.getOut();
505 }
506 else {
507 writer = new UnsyncStringWriter();
508 }
509
510 VelocityTaglib velocityTaglib = new VelocityTaglib(
511 servletContext, request,
512 new PipingServletResponse(response, writer), pageContext, template);
513
514 template.put(TemplateContext.WRITER, writer);
515 template.put("taglibLiferay", velocityTaglib);
516 template.put("theme", velocityTaglib);
517
518
519
520 template.processTemplate(writer);
521
522 if (write) {
523 return null;
524 }
525 else {
526 return ((UnsyncStringWriter)writer).toString();
527 }
528 }
529
530 protected static void insertTilesVariables(HttpServletRequest request) {
531 ComponentContext componentContext =
532 (ComponentContext)request.getAttribute(
533 ComponentConstants.COMPONENT_CONTEXT);
534
535 if (componentContext == null) {
536 return;
537 }
538
539 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
540 WebKeys.THEME_DISPLAY);
541
542 String tilesTitle = (String)componentContext.getAttribute("title");
543 String tilesContent = (String)componentContext.getAttribute("content");
544 boolean tilesSelectable = GetterUtil.getBoolean(
545 (String)componentContext.getAttribute("selectable"));
546
547 themeDisplay.setTilesTitle(tilesTitle);
548 themeDisplay.setTilesContent(tilesContent);
549 themeDisplay.setTilesSelectable(tilesSelectable);
550 }
551
552 private static Log _log = LogFactoryUtil.getLog(ThemeUtil.class);
553
554 }