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