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.TemplateConstants;
025 import com.liferay.portal.kernel.template.TemplateContextType;
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 = (ClassLoader)pluginServletContext.getAttribute(
156 PluginContextListener.PLUGIN_CLASS_LOADER);
157 }
158
159 Thread currentThread = Thread.currentThread();
160
161 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
162
163 if ((pluginClassLoader != null) &&
164 (pluginClassLoader != contextClassLoader)) {
165
166 currentThread.setContextClassLoader(pluginClassLoader);
167 }
168
169 try {
170 if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_FTL)) {
171 return doIncludeFTL(
172 servletContext, request, pageContext, path, theme,
173 TemplateContextType.STANDARD, write);
174 }
175 else if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_JSP)) {
176 doIncludeJSP(servletContext, request, response, path, theme);
177 }
178 else if (extension.equals(ThemeHelper.TEMPLATE_EXTENSION_VM)) {
179 return doIncludeVM(
180 servletContext, request, pageContext, path, theme,
181 TemplateContextType.STANDARD, write);
182 }
183
184 return null;
185 }
186 finally {
187 if ((pluginClassLoader != null) &&
188 (pluginClassLoader != contextClassLoader)) {
189
190 currentThread.setContextClassLoader(contextClassLoader);
191 }
192 }
193 }
194
195 protected static String doIncludeFTL(
196 ServletContext servletContext, HttpServletRequest request,
197 PageContext pageContext, String path, Theme theme,
198 TemplateContextType templateContextType, boolean write)
199 throws Exception {
200
201
202
203
204
205
206
207 String servletContextName = GetterUtil.getString(
208 theme.getServletContextName());
209
210 if (ServletContextPool.get(servletContextName) == null) {
211
212
213
214
215 ServletContextPool.put(servletContextName, servletContext);
216 }
217
218 String portletId = getPortletId(request);
219
220 String resourcePath = theme.getResourcePath(
221 servletContext, portletId, path);
222
223 if (Validator.isNotNull(portletId) &&
224 PortletConstants.hasInstanceId(portletId) &&
225 !TemplateResourceLoaderUtil.hasTemplateResource(
226 TemplateConstants.LANG_TYPE_FTL, resourcePath)) {
227
228 String rootPortletId = PortletConstants.getRootPortletId(portletId);
229
230 resourcePath = theme.getResourcePath(
231 servletContext, rootPortletId, path);
232 }
233
234 if (Validator.isNotNull(portletId) &&
235 !TemplateResourceLoaderUtil.hasTemplateResource(
236 TemplateConstants.LANG_TYPE_FTL, resourcePath)) {
237
238 resourcePath = theme.getResourcePath(servletContext, null, path);
239 }
240
241 if (!TemplateResourceLoaderUtil.hasTemplateResource(
242 TemplateConstants.LANG_TYPE_FTL, resourcePath)) {
243
244 _log.error(resourcePath + " does not exist");
245
246 return null;
247 }
248
249 TemplateResource templateResource =
250 TemplateResourceLoaderUtil.getTemplateResource(
251 TemplateConstants.LANG_TYPE_FTL, resourcePath);
252
253 Template template = TemplateManagerUtil.getTemplate(
254 TemplateConstants.LANG_TYPE_FTL, templateResource,
255 templateContextType);
256
257
258
259 template.prepare(request);
260
261
262
263 ServletContext themeServletContext = ServletContextPool.get(
264 servletContextName);
265
266 template.put("themeServletContext", themeServletContext);
267
268
269
270 HttpServletResponse response =
271 (HttpServletResponse)pageContext.getResponse();
272
273 Writer writer = null;
274
275 if (write) {
276
277
278
279 writer = UnsyncPrintWriterPool.borrow(pageContext.getOut());
280 }
281 else {
282 writer = new UnsyncStringWriter();
283 }
284
285 VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
286 servletContext, request,
287 new PipingServletResponse(response, writer), pageContext, template);
288
289 template.put(TemplateContext.WRITER, writer);
290 template.put("taglibLiferay", velocityTaglib);
291 template.put("theme", velocityTaglib);
292
293
294
295 TemplateHashModel portalTaglib =
296 FreeMarkerTaglibFactoryUtil.createTaglibFactory(servletContext);
297
298 template.put("PortalJspTagLibs", portalTaglib);
299
300
301
302 TemplateHashModel themeTaglib =
303 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
304 themeServletContext);
305
306 template.put("ThemeJspTaglibs", themeTaglib);
307
308
309
310 final Servlet servlet = (Servlet)pageContext.getPage();
311
312 GenericServlet genericServlet = null;
313
314 if (servlet instanceof GenericServlet) {
315 genericServlet = (GenericServlet)servlet;
316 }
317 else {
318 genericServlet = new GenericServlet() {
319
320 @Override
321 public void service(
322 ServletRequest servletRequest,
323 ServletResponse servletResponse)
324 throws IOException, ServletException {
325
326 servlet.service(servletRequest, servletResponse);
327 }
328
329 };
330
331 genericServlet.init(pageContext.getServletConfig());
332 }
333
334 ServletContextHashModel servletContextHashModel =
335 new ServletContextHashModel(
336 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
337
338 template.put("Application", servletContextHashModel);
339
340 HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
341 request, response, ObjectWrapper.DEFAULT_WRAPPER);
342
343 template.put("Request", httpRequestHashModel);
344
345
346
347 template.processTemplate(writer);
348
349 if (write) {
350 return null;
351 }
352 else {
353 return writer.toString();
354 }
355 }
356
357 protected static void doIncludeJSP(
358 ServletContext servletContext, HttpServletRequest request,
359 HttpServletResponse response, String path, Theme theme)
360 throws Exception {
361
362 insertTilesVariables(request);
363
364 if (theme.isWARFile()) {
365 ServletContext themeServletContext = servletContext.getContext(
366 theme.getContextPath());
367
368 if (themeServletContext == null) {
369 _log.error(
370 "Theme " + theme.getThemeId() + " cannot find its " +
371 "servlet context at " + theme.getServletContextName());
372 }
373 else {
374 RequestDispatcher requestDispatcher =
375 themeServletContext.getRequestDispatcher(path);
376
377 if (requestDispatcher == null) {
378 _log.error(
379 "Theme " + theme.getThemeId() + " does not have " +
380 path);
381 }
382 else {
383 requestDispatcher.include(request, response);
384 }
385 }
386 }
387 else {
388 RequestDispatcher requestDispatcher =
389 servletContext.getRequestDispatcher(path);
390
391 if (requestDispatcher == null) {
392 _log.error(
393 "Theme " + theme.getThemeId() + " does not have " + path);
394 }
395 else {
396 requestDispatcher.include(request, response);
397 }
398 }
399 }
400
401 protected static String doIncludeVM(
402 ServletContext servletContext, HttpServletRequest request,
403 PageContext pageContext, String page, Theme theme,
404 TemplateContextType templateContextType, boolean write)
405 throws Exception {
406
407
408
409
410
411
412
413 String servletContextName = GetterUtil.getString(
414 theme.getServletContextName());
415
416 if (ServletContextPool.get(servletContextName) == null) {
417
418
419
420
421 ServletContextPool.put(servletContextName, servletContext);
422 }
423
424 String portletId = getPortletId(request);
425
426 String resourcePath = theme.getResourcePath(
427 servletContext, portletId, page);
428
429 boolean checkResourceExists = true;
430
431 if (Validator.isNotNull(portletId)) {
432 if (PortletConstants.hasInstanceId(portletId) &&
433 (checkResourceExists = !
434 TemplateResourceLoaderUtil.hasTemplateResource(
435 TemplateConstants.LANG_TYPE_VM, resourcePath))) {
436
437 String rootPortletId = PortletConstants.getRootPortletId(
438 portletId);
439
440 resourcePath = theme.getResourcePath(
441 servletContext, rootPortletId, page);
442 }
443
444 if (checkResourceExists &&
445 (checkResourceExists = !
446 TemplateResourceLoaderUtil.hasTemplateResource(
447 TemplateConstants.LANG_TYPE_VM, resourcePath))) {
448
449 resourcePath = theme.getResourcePath(
450 servletContext, null, page);
451 }
452 }
453
454 if (checkResourceExists &&
455 !TemplateResourceLoaderUtil.hasTemplateResource(
456 TemplateConstants.LANG_TYPE_VM, resourcePath)) {
457
458 _log.error(resourcePath + " does not exist");
459
460 return null;
461 }
462
463 TemplateResource templateResource =
464 TemplateResourceLoaderUtil.getTemplateResource(
465 TemplateConstants.LANG_TYPE_VM, resourcePath);
466
467 if (templateResource == null) {
468 throw new Exception(
469 "Unable to load template resource " + resourcePath);
470 }
471
472 Template template = TemplateManagerUtil.getTemplate(
473 TemplateConstants.LANG_TYPE_VM, templateResource,
474 templateContextType);
475
476
477
478 template.prepare(request);
479
480
481
482 template.put("pageContext", pageContext);
483
484
485
486 ServletContext themeServletContext = ServletContextPool.get(
487 servletContextName);
488
489 template.put("themeServletContext", themeServletContext);
490
491
492
493 HttpServletResponse response =
494 (HttpServletResponse)pageContext.getResponse();
495
496 Writer writer = null;
497
498 if (write) {
499 writer = pageContext.getOut();
500 }
501 else {
502 writer = new UnsyncStringWriter();
503 }
504
505 VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
506 servletContext, request,
507 new PipingServletResponse(response, writer), pageContext, template);
508
509 template.put(TemplateContext.WRITER, writer);
510 template.put("taglibLiferay", velocityTaglib);
511 template.put("theme", velocityTaglib);
512
513
514
515 template.processTemplate(writer);
516
517 if (write) {
518 return null;
519 }
520 else {
521 return ((UnsyncStringWriter)writer).toString();
522 }
523 }
524
525 protected static void insertTilesVariables(HttpServletRequest request) {
526 ComponentContext componentContext =
527 (ComponentContext)request.getAttribute(
528 ComponentConstants.COMPONENT_CONTEXT);
529
530 if (componentContext == null) {
531 return;
532 }
533
534 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
535 WebKeys.THEME_DISPLAY);
536
537 String tilesTitle = (String)componentContext.getAttribute("title");
538 String tilesContent = (String)componentContext.getAttribute("content");
539 boolean tilesSelectable = GetterUtil.getBoolean(
540 (String)componentContext.getAttribute("selectable"));
541
542 themeDisplay.setTilesTitle(tilesTitle);
543 themeDisplay.setTilesContent(tilesContent);
544 themeDisplay.setTilesSelectable(tilesSelectable);
545 }
546
547 private static Log _log = LogFactoryUtil.getLog(ThemeUtil.class);
548
549 }