001
014
015 package com.liferay.taglib.util;
016
017 import com.liferay.portal.kernel.freemarker.FreeMarkerContext;
018 import com.liferay.portal.kernel.freemarker.FreeMarkerEngineUtil;
019 import com.liferay.portal.kernel.freemarker.FreeMarkerVariablesUtil;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.servlet.PipingServletResponse;
024 import com.liferay.portal.kernel.servlet.PluginContextListener;
025 import com.liferay.portal.kernel.servlet.ServletContextPool;
026 import com.liferay.portal.kernel.util.GetterUtil;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.ThemeHelper;
029 import com.liferay.portal.kernel.util.UnsyncPrintWriterPool;
030 import com.liferay.portal.kernel.util.Validator;
031 import com.liferay.portal.kernel.util.WebKeys;
032 import com.liferay.portal.kernel.velocity.VelocityContext;
033 import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
034 import com.liferay.portal.kernel.velocity.VelocityVariablesUtil;
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 =
155 (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, 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, 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, boolean write)
196 throws Exception {
197
198
199
200
201
202
203
204 String servletContextName = GetterUtil.getString(
205 theme.getServletContextName());
206
207 if (ServletContextPool.get(servletContextName) == null) {
208
209
210
211
212 ServletContextPool.put(servletContextName, servletContext);
213 }
214
215 String portletId = getPortletId(request);
216
217 String resourcePath = theme.getResourcePath(
218 servletContext, portletId, path);
219
220 if (Validator.isNotNull(portletId) &&
221 !FreeMarkerEngineUtil.resourceExists(resourcePath) &&
222 portletId.contains(PortletConstants.INSTANCE_SEPARATOR)) {
223
224 String rootPortletId = PortletConstants.getRootPortletId(portletId);
225
226 resourcePath = theme.getResourcePath(
227 servletContext, rootPortletId, path);
228 }
229
230 if (Validator.isNotNull(portletId) &&
231 !FreeMarkerEngineUtil.resourceExists(resourcePath)) {
232
233 resourcePath = theme.getResourcePath(servletContext, null, path);
234 }
235
236 if (!FreeMarkerEngineUtil.resourceExists(resourcePath)) {
237 _log.error(resourcePath + " does not exist");
238
239 return null;
240 }
241
242 FreeMarkerContext freeMarkerContext =
243 FreeMarkerEngineUtil.getWrappedClassLoaderToolsContext();
244
245
246
247 FreeMarkerVariablesUtil.insertVariables(freeMarkerContext, request);
248
249
250
251 ServletContext themeServletContext = ServletContextPool.get(
252 servletContextName);
253
254 freeMarkerContext.put("themeServletContext", themeServletContext);
255
256
257
258 HttpServletResponse response =
259 (HttpServletResponse)pageContext.getResponse();
260
261 Writer writer = null;
262
263 if (write) {
264
265
266
267 writer = UnsyncPrintWriterPool.borrow(pageContext.getOut());
268 }
269 else {
270 writer = new UnsyncStringWriter();
271 }
272
273 VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
274 servletContext, request,
275 new PipingServletResponse(response, writer), pageContext);
276
277 request.setAttribute(WebKeys.VELOCITY_TAGLIB, velocityTaglib);
278
279 freeMarkerContext.put("taglibLiferay", velocityTaglib);
280 freeMarkerContext.put("theme", velocityTaglib);
281 freeMarkerContext.put("writer", writer);
282
283
284
285 TemplateHashModel portalTaglib =
286 FreeMarkerTaglibFactoryUtil.createTaglibFactory(servletContext);
287
288 freeMarkerContext.put("PortalJspTagLibs", portalTaglib);
289
290
291
292 TemplateHashModel themeTaglib =
293 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
294 themeServletContext);
295
296 freeMarkerContext.put("ThemeJspTaglibs", themeTaglib);
297
298
299
300 final Servlet servlet = (Servlet)pageContext.getPage();
301
302 GenericServlet genericServlet = null;
303
304 if (servlet instanceof GenericServlet) {
305 genericServlet = (GenericServlet)servlet;
306 }
307 else {
308 genericServlet = new GenericServlet() {
309
310 @Override
311 public void service(
312 ServletRequest servletRequest,
313 ServletResponse servletResponse)
314 throws IOException, ServletException {
315
316 servlet.service(servletRequest, servletResponse);
317 }
318
319 };
320
321 genericServlet.init(pageContext.getServletConfig());
322 }
323
324 ServletContextHashModel servletContextHashModel =
325 new ServletContextHashModel(
326 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
327
328 freeMarkerContext.put("Application", servletContextHashModel);
329
330 HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
331 request, response, ObjectWrapper.DEFAULT_WRAPPER);
332
333 freeMarkerContext.put("Request", httpRequestHashModel);
334
335
336
337 FreeMarkerEngineUtil.mergeTemplate(
338 resourcePath, freeMarkerContext, writer);
339
340 if (write) {
341 return null;
342 }
343 else {
344 return writer.toString();
345 }
346 }
347
348 protected static void doIncludeJSP(
349 ServletContext servletContext, HttpServletRequest request,
350 HttpServletResponse response, String path, Theme theme)
351 throws Exception {
352
353 insertTilesVariables(request);
354
355 if (theme.isWARFile()) {
356 ServletContext themeServletContext = servletContext.getContext(
357 theme.getContextPath());
358
359 if (themeServletContext == null) {
360 _log.error(
361 "Theme " + theme.getThemeId() + " cannot find its " +
362 "servlet context at " + theme.getServletContextName());
363 }
364 else {
365 RequestDispatcher requestDispatcher =
366 themeServletContext.getRequestDispatcher(path);
367
368 if (requestDispatcher == null) {
369 _log.error(
370 "Theme " + theme.getThemeId() + " does not have " +
371 path);
372 }
373 else {
374 requestDispatcher.include(request, response);
375 }
376 }
377 }
378 else {
379 RequestDispatcher requestDispatcher =
380 servletContext.getRequestDispatcher(path);
381
382 if (requestDispatcher == null) {
383 _log.error(
384 "Theme " + theme.getThemeId() + " does not have " + path);
385 }
386 else {
387 requestDispatcher.include(request, response);
388 }
389 }
390 }
391
392 protected static String doIncludeVM(
393 ServletContext servletContext, HttpServletRequest request,
394 PageContext pageContext, String page, Theme theme, boolean write)
395 throws Exception {
396
397
398
399
400
401
402
403 String servletContextName = GetterUtil.getString(
404 theme.getServletContextName());
405
406 if (ServletContextPool.get(servletContextName) == null) {
407
408
409
410
411 ServletContextPool.put(servletContextName, servletContext);
412 }
413
414 String portletId = getPortletId(request);
415
416 String resourcePath = theme.getResourcePath(
417 servletContext, portletId, page);
418
419 boolean checkResourceExists = true;
420
421 if (Validator.isNotNull(portletId)) {
422 if (portletId.contains(PortletConstants.INSTANCE_SEPARATOR) &&
423 (checkResourceExists = !VelocityEngineUtil.resourceExists(
424 resourcePath))) {
425
426 String rootPortletId = PortletConstants.getRootPortletId(
427 portletId);
428
429 resourcePath = theme.getResourcePath(
430 servletContext, rootPortletId, page);
431 }
432
433 if (checkResourceExists &&
434 (checkResourceExists = !VelocityEngineUtil.resourceExists(
435 resourcePath))) {
436
437 resourcePath = theme.getResourcePath(
438 servletContext, null, page);
439 }
440 }
441
442 if (checkResourceExists &&
443 !VelocityEngineUtil.resourceExists(resourcePath)) {
444
445 _log.error(resourcePath + " does not exist");
446
447 return null;
448 }
449
450 VelocityContext velocityContext =
451 VelocityEngineUtil.getWrappedClassLoaderToolsContext();
452
453
454
455 VelocityVariablesUtil.insertVariables(velocityContext, request);
456
457
458
459 velocityContext.put("pageContext", pageContext);
460
461
462
463 ServletContext themeServletContext = ServletContextPool.get(
464 servletContextName);
465
466 velocityContext.put("themeServletContext", themeServletContext);
467
468
469
470 HttpServletResponse response =
471 (HttpServletResponse)pageContext.getResponse();
472
473 Writer writer = null;
474
475 if (write) {
476 writer = pageContext.getOut();
477 }
478 else {
479 writer = new UnsyncStringWriter();
480 }
481
482 VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
483 servletContext, request,
484 new PipingServletResponse(response, writer), pageContext);
485
486 request.setAttribute(WebKeys.VELOCITY_TAGLIB, velocityTaglib);
487
488 velocityContext.put("taglibLiferay", velocityTaglib);
489 velocityContext.put("theme", velocityTaglib);
490 velocityContext.put("writer", writer);
491
492
493
494 VelocityEngineUtil.mergeTemplate(resourcePath, velocityContext, writer);
495
496 if (write) {
497 return null;
498 }
499 else {
500 return ((UnsyncStringWriter)writer).toString();
501 }
502 }
503
504 protected static void insertTilesVariables(HttpServletRequest request) {
505 ComponentContext componentContext =
506 (ComponentContext)request.getAttribute(
507 ComponentConstants.COMPONENT_CONTEXT);
508
509 if (componentContext == null) {
510 return;
511 }
512
513 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
514 WebKeys.THEME_DISPLAY);
515
516 String tilesTitle = (String)componentContext.getAttribute("title");
517 String tilesContent = (String)componentContext.getAttribute("content");
518 boolean tilesSelectable = GetterUtil.getBoolean(
519 (String)componentContext.getAttribute("selectable"));
520
521 themeDisplay.setTilesTitle(tilesTitle);
522 themeDisplay.setTilesContent(tilesContent);
523 themeDisplay.setTilesSelectable(tilesSelectable);
524 }
525
526 private static Log _log = LogFactoryUtil.getLog(ThemeUtil.class);
527
528 }