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