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