001
014
015 package com.liferay.taglib.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.log.LogUtil;
020 import com.liferay.portal.kernel.portlet.PortletBag;
021 import com.liferay.portal.kernel.portlet.PortletBagPool;
022 import com.liferay.portal.kernel.servlet.DirectRequestDispatcherFactoryUtil;
023 import com.liferay.portal.kernel.servlet.TrackedServletRequest;
024 import com.liferay.portal.kernel.servlet.taglib.TagDynamicIdFactory;
025 import com.liferay.portal.kernel.servlet.taglib.TagDynamicIdFactoryRegistry;
026 import com.liferay.portal.kernel.servlet.taglib.TagDynamicIncludeUtil;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.PropsKeys;
029 import com.liferay.portal.kernel.util.PropsUtil;
030 import com.liferay.portal.kernel.util.ServerDetector;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.UnicodeProperties;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.util.WebKeys;
036 import com.liferay.portal.model.Group;
037 import com.liferay.portal.model.PortletConstants;
038 import com.liferay.portal.model.Theme;
039 import com.liferay.portal.theme.ThemeDisplay;
040 import com.liferay.portal.util.CustomJspRegistryUtil;
041 import com.liferay.portlet.exportimport.staging.StagingUtil;
042 import com.liferay.taglib.FileAvailabilityUtil;
043 import com.liferay.taglib.servlet.JspWriterHttpServletResponse;
044 import com.liferay.taglib.servlet.PipingServletResponse;
045
046 import javax.servlet.RequestDispatcher;
047 import javax.servlet.ServletContext;
048 import javax.servlet.http.HttpServletRequest;
049 import javax.servlet.http.HttpServletResponse;
050 import javax.servlet.jsp.JspException;
051 import javax.servlet.jsp.tagext.BodyContent;
052
053
059 public class IncludeTag extends AttributesTagSupport {
060
061 @Override
062 public int doEndTag() throws JspException {
063 try {
064 String page = getPage();
065
066 if (Validator.isNull(page)) {
067 page = getEndPage();
068 }
069
070 callSetAttributes();
071
072 if (themeResourceExists(page)) {
073 doIncludeTheme(page);
074
075 return EVAL_PAGE;
076 }
077
078 if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
079 logUnavailablePage(page);
080
081 return processEndTag();
082 }
083
084 doInclude(page, false);
085
086 return EVAL_PAGE;
087 }
088 catch (Exception e) {
089 throw new JspException(e);
090 }
091 finally {
092 clearDynamicAttributes();
093 clearParams();
094 clearProperties();
095
096 cleanUpSetAttributes();
097
098 if (!ServerDetector.isResin()) {
099 setPage(null);
100 setUseCustomPage(true);
101
102 cleanUp();
103 }
104 }
105 }
106
107 @Override
108 public int doStartTag() throws JspException {
109 try {
110 String page = getStartPage();
111
112 callSetAttributes();
113
114 if (themeResourceExists(page)) {
115 doIncludeTheme(page);
116
117 return EVAL_BODY_INCLUDE;
118 }
119
120 if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
121 logUnavailablePage(page);
122
123 return processStartTag();
124 }
125
126 doInclude(page, true);
127
128 return EVAL_BODY_INCLUDE;
129 }
130 catch (Exception e) {
131 throw new JspException(e);
132 }
133 }
134
135 public void runTag() throws JspException {
136 doStartTag();
137 doEndTag();
138 }
139
140 public void setPage(String page) {
141 _page = page;
142 }
143
144 public void setPortletId(String portletId) {
145 if (Validator.isNotNull(portletId)) {
146 String rootPortletId = PortletConstants.getRootPortletId(portletId);
147
148 PortletBag portletBag = PortletBagPool.get(rootPortletId);
149
150 servletContext = portletBag.getServletContext();
151 }
152 }
153
154 public void setStrict(boolean strict) {
155 _strict = strict;
156 }
157
158 public void setUseCustomPage(boolean useCustomPage) {
159 _useCustomPage = useCustomPage;
160 }
161
162 protected void callSetAttributes() {
163 HttpServletRequest request = getOriginalServletRequest();
164
165 if (isCleanUpSetAttributes()) {
166 _trackedRequest = new TrackedServletRequest(request);
167
168 request = _trackedRequest;
169 }
170
171 setNamespacedAttribute(request, "bodyContent", getBodyContentWrapper());
172 setNamespacedAttribute(
173 request, "dynamicAttributes", getDynamicAttributes());
174 setNamespacedAttribute(
175 request, "scopedAttributes", getScopedAttributes());
176
177 setAttributes(request);
178 }
179
180 protected void cleanUp() {
181 }
182
183 protected void cleanUpSetAttributes() {
184 if (isCleanUpSetAttributes() && (_trackedRequest != null)) {
185 for (String name : _trackedRequest.getSetAttributes()) {
186 _trackedRequest.removeAttribute(name);
187 }
188
189 _trackedRequest = null;
190 }
191 }
192
193 protected void doInclude(
194 String page, boolean dynamicIncludeAscendingPriority)
195 throws JspException {
196
197 try {
198 include(page, dynamicIncludeAscendingPriority);
199 }
200 catch (Exception e) {
201 String currentURL = (String)request.getAttribute(
202 WebKeys.CURRENT_URL);
203
204 String message =
205 "Current URL " + currentURL + " generates exception: " +
206 e.getMessage();
207
208 LogUtil.log(_log, e, message);
209
210 if (e instanceof JspException) {
211 throw (JspException)e;
212 }
213 }
214 }
215
216 protected void doIncludeTheme(String page) throws Exception {
217 HttpServletResponse response =
218 (HttpServletResponse)pageContext.getResponse();
219
220 Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
221
222 ThemeUtil.include(servletContext, request, response, page, theme);
223 }
224
225 protected Object getBodyContentWrapper() {
226 final BodyContent bodyContent = getBodyContent();
227
228 if (bodyContent == null) {
229 return null;
230 }
231
232 return new Object() {
233
234 @Override
235 public String toString() {
236 return bodyContent.getString();
237 }
238
239 };
240 }
241
242 protected String getCustomPage(
243 ServletContext servletContext, HttpServletRequest request,
244 String page) {
245
246 if (Validator.isNull(page)) {
247 return null;
248 }
249
250 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
251 WebKeys.THEME_DISPLAY);
252
253 if (themeDisplay == null) {
254 return null;
255 }
256
257 Group group = null;
258
259 try {
260 group = StagingUtil.getLiveGroup(themeDisplay.getScopeGroupId());
261 }
262 catch (Exception e) {
263 return null;
264 }
265
266 UnicodeProperties typeSettingsProperties =
267 group.getTypeSettingsProperties();
268
269 String customJspServletContextName = typeSettingsProperties.getProperty(
270 "customJspServletContextName");
271
272 if (Validator.isNull(customJspServletContextName)) {
273 return null;
274 }
275
276 String customPage = CustomJspRegistryUtil.getCustomJspFileName(
277 customJspServletContextName, page);
278
279 if (FileAvailabilityUtil.isAvailable(servletContext, customPage)) {
280 return customPage;
281 }
282
283 return null;
284 }
285
286 protected String getEndPage() {
287 return null;
288 }
289
290 protected HttpServletRequest getOriginalServletRequest() {
291 return (HttpServletRequest)pageContext.getRequest();
292 }
293
294 protected String getPage() {
295 return _page;
296 }
297
298 protected RequestDispatcher getRequestDispatcher(String page) {
299 return DirectRequestDispatcherFactoryUtil.getRequestDispatcher(
300 servletContext, page);
301 }
302
303 protected String getStartPage() {
304 return null;
305 }
306
307 protected void include(String page, boolean doStartTag) throws Exception {
308 JspWriterHttpServletResponse jspWriterHttpServletResponse = null;
309
310 Class<?> clazz = getClass();
311
312 String tagClassName = clazz.getName();
313
314 String tagDynamicId = null;
315
316 String tagPointPrefix = null;
317
318 if (doStartTag) {
319 tagPointPrefix = "doStartTag#";
320 }
321 else {
322 tagPointPrefix = "doEndTag#";
323 }
324
325 TagDynamicIdFactory tagDynamicIdFactory =
326 TagDynamicIdFactoryRegistry.getTagDynamicIdFactory(tagClassName);
327
328 if (tagDynamicIdFactory != null) {
329 jspWriterHttpServletResponse = new JspWriterHttpServletResponse(
330 pageContext);
331
332 tagDynamicId = tagDynamicIdFactory.getTagDynamicId(
333 request, jspWriterHttpServletResponse, this);
334
335 TagDynamicIncludeUtil.include(
336 request, jspWriterHttpServletResponse, tagClassName,
337 tagDynamicId, tagPointPrefix + "before", doStartTag);
338 }
339
340 if (_useCustomPage) {
341 String customPage = getCustomPage(servletContext, request, page);
342
343 if (Validator.isNotNull(customPage)) {
344 page = customPage;
345 }
346 }
347
348 RequestDispatcher requestDispatcher = getRequestDispatcher(page);
349
350 request.setAttribute(
351 WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT, _strict);
352
353 HttpServletResponse response = new PipingServletResponse(pageContext);
354
355 requestDispatcher.include(request, response);
356
357 request.removeAttribute(WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT);
358
359 if (tagDynamicIdFactory != null) {
360 TagDynamicIncludeUtil.include(
361 request, jspWriterHttpServletResponse, tagClassName,
362 tagDynamicId, tagPointPrefix + "after", doStartTag);
363 }
364 }
365
366 protected boolean isCleanUpSetAttributes() {
367 return _CLEAN_UP_SET_ATTRIBUTES;
368 }
369
370 protected boolean isPortalPage(String page) {
371 if (page.startsWith("/html/taglib/") &&
372 (page.endsWith("/end.jsp") || page.endsWith("/page.jsp") ||
373 page.endsWith("/start.jsp"))) {
374
375 return true;
376 }
377
378 return false;
379 }
380
381 protected boolean isUseCustomPage() {
382 return _useCustomPage;
383 }
384
385 protected void logUnavailablePage(String page) {
386 if ((page == null) || !_log.isWarnEnabled()) {
387 return;
388 }
389
390 String contextPath = servletContext.getContextPath();
391
392 if (contextPath.equals(StringPool.BLANK)) {
393 contextPath = StringPool.SLASH;
394 }
395
396 StringBundler sb = new StringBundler(13);
397
398 sb.append("Unable to find ");
399 sb.append(page);
400 sb.append(" in the context ");
401 sb.append(contextPath);
402 sb.append(".");
403
404 if (isPortalPage(page)) {
405 if (contextPath.equals(StringPool.SLASH)) {
406 sb = null;
407 }
408 else {
409 sb.append(" You must not use a taglib from a module and ");
410 sb.append("set the attribute \"servletContext\". Inline the ");
411 sb.append("content directly where the taglib is invoked.");
412 }
413 }
414 else if (contextPath.equals(StringPool.SLASH)) {
415 Class<?> clazz = getClass();
416
417 if (clazz.equals(IncludeTag.class)) {
418 sb.append(" You must set the attribute \"servletContext\" ");
419 sb.append("with the value \"<%= application %>\" when ");
420 sb.append("invoking a taglib from a module.");
421 }
422 else {
423 sb.append(" You must not use a taglib from a module and ");
424 sb.append("set the attribute \"file\". Inline the content ");
425 sb.append("directly where the taglib is invoked.");
426 }
427 }
428
429 if (sb != null) {
430 _log.warn(sb.toString());
431 }
432 }
433
434 protected int processEndTag() throws Exception {
435 return EVAL_PAGE;
436 }
437
438 protected int processStartTag() throws Exception {
439 return EVAL_BODY_INCLUDE;
440 }
441
442 protected void setAttributes(HttpServletRequest request) {
443 }
444
445 protected boolean themeResourceExists(String page) throws Exception {
446 if ((page == null) || !_THEME_JSP_OVERRIDE_ENABLED || _strict) {
447 return false;
448 }
449
450 Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
451
452 if (theme == null) {
453 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
454 WebKeys.THEME_DISPLAY);
455
456 if (themeDisplay != null) {
457 theme = themeDisplay.getTheme();
458 }
459 }
460
461 if (theme == null) {
462 return false;
463 }
464
465 String portletId = ThemeUtil.getPortletId(request);
466
467 boolean exists = theme.resourceExists(servletContext, portletId, page);
468
469 if (_log.isDebugEnabled() && exists) {
470 String resourcePath = theme.getResourcePath(
471 servletContext, null, page);
472
473 _log.debug(resourcePath);
474 }
475
476 return exists;
477 }
478
479 private static final boolean _CLEAN_UP_SET_ATTRIBUTES = false;
480
481 private static final boolean _THEME_JSP_OVERRIDE_ENABLED =
482 GetterUtil.getBoolean(
483 PropsUtil.get(PropsKeys.THEME_JSP_OVERRIDE_ENABLED));
484
485 private static final Log _log = LogFactoryUtil.getLog(IncludeTag.class);
486
487 private String _page;
488 private boolean _strict;
489 private TrackedServletRequest _trackedRequest;
490 private boolean _useCustomPage = true;
491
492 }