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