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