001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.taglib.util;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.log.LogUtil;
021    import com.liferay.portal.kernel.servlet.DirectServletContext;
022    import com.liferay.portal.kernel.servlet.PipingServletResponse;
023    import com.liferay.portal.kernel.servlet.TrackedServletRequest;
024    import com.liferay.portal.kernel.servlet.taglib.FileAvailabilityUtil;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
027    import com.liferay.portal.kernel.util.PropsKeys;
028    import com.liferay.portal.kernel.util.PropsUtil;
029    import com.liferay.portal.kernel.util.ServerDetector;
030    import com.liferay.portal.kernel.util.UnicodeProperties;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.util.WebKeys;
033    import com.liferay.portal.model.Group;
034    import com.liferay.portal.model.Portlet;
035    import com.liferay.portal.model.PortletApp;
036    import com.liferay.portal.model.Theme;
037    import com.liferay.portal.service.PortletLocalServiceUtil;
038    import com.liferay.portal.theme.ThemeDisplay;
039    import com.liferay.portal.util.CustomJspRegistryUtil;
040    import com.liferay.portal.util.PortalUtil;
041    
042    import java.lang.reflect.Constructor;
043    import java.lang.reflect.Method;
044    
045    import javax.servlet.RequestDispatcher;
046    import javax.servlet.ServletContext;
047    import javax.servlet.ServletRequest;
048    import javax.servlet.ServletResponse;
049    import javax.servlet.http.HttpServletRequest;
050    import javax.servlet.http.HttpServletResponse;
051    import javax.servlet.jsp.JspException;
052    
053    /**
054     * @author Brian Wing Shun Chan
055     * @author Shuyang Zhou
056     * @author Eduardo Lundgren
057     * @author Raymond Augé
058     */
059    public class IncludeTag extends AttributesTagSupport {
060    
061            @Override
062            public int doEndTag() throws JspException {
063                    try {
064                            ServletContext servletContext = getServletContext();
065                            HttpServletRequest request = getServletRequest();
066    
067                            String page = null;
068    
069                            if (_useCustomPage) {
070                                    page = getCustomPage(servletContext, request);
071                            }
072    
073                            if (Validator.isNull(page)) {
074                                    page = getPage();
075                            }
076    
077                            if (Validator.isNull(page)) {
078                                    page = getEndPage();
079                            }
080    
081                            callSetAttributes();
082    
083                            if (themeResourceExists(page)) {
084                                    _doIncludeTheme(page);
085    
086                                    return EVAL_PAGE;
087                            }
088                            else if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
089                                    return processEndTag();
090                            }
091                            else {
092                                    _doInclude(page);
093    
094                                    return EVAL_PAGE;
095                            }
096                    }
097                    catch (Exception e) {
098                            throw new JspException(e);
099                    }
100                    finally {
101                            clearDynamicAttributes();
102                            clearParams();
103                            clearProperties();
104    
105                            cleanUpSetAttributes();
106    
107                            if (!ServerDetector.isResin()) {
108                                    setPage(null);
109                                    setUseCustomPage(true);
110    
111                                    cleanUp();
112                            }
113                    }
114            }
115    
116            @Override
117            public int doStartTag() throws JspException {
118                    try {
119                            ServletContext servletContext = getServletContext();
120    
121                            String page = getStartPage();
122    
123                            callSetAttributes();
124    
125                            if (themeResourceExists(page)) {
126                                    _doIncludeTheme(page);
127    
128                                    return EVAL_BODY_INCLUDE;
129                            }
130                            else if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
131                                    return processStartTag();
132                            }
133                            else {
134                                    _doInclude(page);
135    
136                                    return EVAL_BODY_INCLUDE;
137                            }
138                    }
139                    catch (Exception e) {
140                            throw new JspException(e);
141                    }
142            }
143    
144            @Override
145            public ServletContext getServletContext() {
146                    ServletContext servletContext = super.getServletContext();
147    
148                    try {
149                            if (Validator.isNull(_portletId)) {
150                                    return servletContext;
151                            }
152    
153                            HttpServletRequest request = getServletRequest();
154    
155                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
156                                    WebKeys.THEME_DISPLAY);
157    
158                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
159                                    themeDisplay.getCompanyId(), _portletId);
160    
161                            if (portlet == null) {
162                                    return servletContext;
163                            }
164    
165                            PortletApp portletApp = portlet.getPortletApp();
166    
167                            if (!portletApp.isWARFile()) {
168                                    return servletContext;
169                            }
170    
171                            return PortalUtil.getServletContext(portlet, servletContext);
172                    }
173                    catch (SystemException se) {
174                            return servletContext;
175                    }
176            }
177    
178            public void runEndTag() throws JspException {
179                    doEndTag();
180            }
181    
182            public void runStartTag() throws JspException {
183                    doStartTag();
184            }
185    
186            public void runTag() throws JspException {
187                    doStartTag();
188                    doEndTag();
189            }
190    
191            public void setPage(String page) {
192                    _page = page;
193            }
194    
195            public void setPortletId(String portletId) {
196                    _portletId = portletId;
197            }
198    
199            public void setStrict(boolean strict) {
200                    _strict = strict;
201            }
202    
203            public void setUseCustomPage(boolean useCustomPage) {
204                    _useCustomPage = useCustomPage;
205            }
206    
207            protected void callSetAttributes() {
208                    if (_calledSetAttributes) {
209                            return;
210                    }
211    
212                    _calledSetAttributes = true;
213    
214                    HttpServletRequest request =
215                            (HttpServletRequest)pageContext.getRequest();
216    
217                    if (isCleanUpSetAttributes()) {
218                            _trackedRequest = new TrackedServletRequest(request);
219    
220                            request = _trackedRequest;
221                    }
222    
223                    setNamespacedAttribute(request, "bodyContent", getBodyContent());
224                    setNamespacedAttribute(
225                            request, "customAttributes", getCustomAttributes());
226                    setNamespacedAttribute(
227                            request, "dynamicAttributes", getDynamicAttributes());
228                    setNamespacedAttribute(
229                            request, "scopedAttributes", getScopedAttributes());
230    
231                    setAttributes(request);
232            }
233    
234            protected void cleanUp() {
235            }
236    
237            protected void cleanUpSetAttributes() {
238                    _calledSetAttributes = false;
239    
240                    if (isCleanUpSetAttributes()) {
241                            for (String name : _trackedRequest.getSetAttributes()) {
242                                    _trackedRequest.removeAttribute(name);
243                            }
244    
245                            _trackedRequest = null;
246                    }
247            }
248    
249            protected String getCustomPage(
250                    ServletContext servletContext, HttpServletRequest request) {
251    
252                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
253                            WebKeys.THEME_DISPLAY);
254    
255                    if (themeDisplay == null) {
256                            return null;
257                    }
258    
259                    Group group = themeDisplay.getScopeGroup();
260    
261                    UnicodeProperties typeSettingsProperties =
262                            group.getTypeSettingsProperties();
263    
264                    String customJspServletContextName = typeSettingsProperties.getProperty(
265                            "customJspServletContextName");
266    
267                    if (Validator.isNull(customJspServletContextName)) {
268                            return null;
269                    }
270    
271                    String page = getPage();
272    
273                    if (Validator.isNull(page)) {
274                            page = getEndPage();
275                    }
276    
277                    if (Validator.isNull(page)) {
278                            return null;
279                    }
280    
281                    String customPage = CustomJspRegistryUtil.getCustomJspFileName(
282                            customJspServletContextName, page);
283    
284                    if (FileAvailabilityUtil.isAvailable(servletContext, customPage)) {
285                            return customPage;
286                    }
287    
288                    return null;
289            }
290    
291            protected String getEndPage() {
292                    return null;
293            }
294    
295            protected String getPage() {
296                    return _page;
297            }
298    
299            protected String getStartPage() {
300                    return null;
301            }
302    
303            protected void include(String page) throws Exception {
304                    ServletContext servletContext = getServletContext();
305    
306                    if (_DIRECT_SERVLET_CONTEXT_ENABLED) {
307                            servletContext = new DirectServletContext(servletContext);
308                    }
309    
310                    RequestDispatcher requestDispatcher =
311                            servletContext.getRequestDispatcher(page);
312    
313                    HttpServletRequest request = getServletRequest();
314    
315                    request.setAttribute(
316                            WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT, _strict);
317                    request.setAttribute(WebKeys.SERVLET_PATH, page);
318    
319                    HttpServletResponse response = new PipingServletResponse(
320                            pageContext, isTrimNewLines());
321    
322                    if (!isWARFile(request)) {
323                            requestDispatcher.include(request, response);
324                    }
325                    else {
326                            ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
327    
328                            Class<?> clazz = classLoader.loadClass(_LIFERAY_REQUEST_DISPATCHER);
329    
330                            Constructor<?> constructor = clazz.getConstructor(
331                                    RequestDispatcher.class, String.class);
332    
333                            Object obj = constructor.newInstance(requestDispatcher, page);
334    
335                            Method method = clazz.getMethod(
336                                    "include", ServletRequest.class, ServletResponse.class,
337                                    boolean.class);
338    
339                            method.invoke(obj, request, response, true);
340                    }
341    
342                    request.removeAttribute(WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT);
343            }
344    
345            protected boolean isCleanUpSetAttributes() {
346                    return _CLEAN_UP_SET_ATTRIBUTES;
347            }
348    
349            protected boolean isTrimNewLines() {
350                    return _TRIM_NEW_LINES;
351            }
352    
353            protected boolean isWARFile(HttpServletRequest request)
354                    throws SystemException {
355    
356                    if (Validator.isNull(_portletId)) {
357                            return false;
358                    }
359    
360                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
361                            WebKeys.THEME_DISPLAY);
362    
363                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
364                            themeDisplay.getCompanyId(), _portletId);
365    
366                    if (portlet == null) {
367                            return false;
368                    }
369    
370                    PortletApp portletApp = portlet.getPortletApp();
371    
372                    return portletApp.isWARFile();
373            }
374    
375            protected int processEndTag() throws Exception {
376                    return EVAL_PAGE;
377            }
378    
379            protected int processStartTag() throws Exception {
380                    return EVAL_BODY_INCLUDE;
381            }
382    
383            protected void setAttributes(HttpServletRequest request) {
384            }
385    
386            protected void setCalledSetAttributes(boolean calledSetAttributes) {
387                    _calledSetAttributes = calledSetAttributes;
388            }
389    
390            protected boolean themeResourceExists(String page)
391                    throws Exception {
392    
393                    if ((page == null) || !_THEME_JSP_OVERRIDE_ENABLED || _strict) {
394                            return false;
395                    }
396    
397                    ServletContext servletContext = getServletContext();
398                    HttpServletRequest request = getServletRequest();
399    
400                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
401    
402                    String portletId = ThemeUtil.getPortletId(request);
403    
404                    boolean exists = theme.resourceExists(servletContext, portletId, page);
405    
406                    if (_log.isDebugEnabled() && exists) {
407                            String resourcePath = theme.getResourcePath(
408                                    servletContext, null, page);
409    
410                            _log.debug(resourcePath);
411                    }
412    
413                    return exists;
414            }
415    
416            private void _doInclude(String page) throws JspException {
417                    try {
418                            include(page);
419                    }
420                    catch (Exception e) {
421                            HttpServletRequest request = getServletRequest();
422    
423                            String currentURL = (String)request.getAttribute(
424                                    WebKeys.CURRENT_URL);
425    
426                            _log.error(
427                                    "Current URL " + currentURL + " generates exception: " +
428                                            e.getMessage());
429    
430                            LogUtil.log(_log, e);
431    
432                            if (e instanceof JspException) {
433                                    throw (JspException)e;
434                            }
435                    }
436            }
437    
438            private void _doIncludeTheme(String page) throws Exception {
439                    ServletContext servletContext = getServletContext();
440                    HttpServletRequest request = getServletRequest();
441                    HttpServletResponse response = getServletResponse();
442    
443                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
444    
445                    ThemeUtil.include(
446                            servletContext, request, response, pageContext, page, theme);
447            }
448    
449            private static final boolean _CLEAN_UP_SET_ATTRIBUTES = false;
450    
451            private static final boolean _DIRECT_SERVLET_CONTEXT_ENABLED =
452                    GetterUtil.getBoolean(
453                            PropsUtil.get(PropsKeys.DIRECT_SERVLET_CONTEXT_ENABLED));
454    
455            private static final String _LIFERAY_REQUEST_DISPATCHER =
456                    "com.liferay.portal.apache.bridges.struts.LiferayRequestDispatcher";
457    
458            private static final boolean _THEME_JSP_OVERRIDE_ENABLED =
459                    GetterUtil.getBoolean(
460                            PropsUtil.get(PropsKeys.THEME_JSP_OVERRIDE_ENABLED));
461    
462            private static final boolean _TRIM_NEW_LINES = false;
463    
464            private static Log _log = LogFactoryUtil.getLog(IncludeTag.class);
465    
466            private boolean _calledSetAttributes;
467            private String _page;
468            private String _portletId;
469            private boolean _strict;
470            private TrackedServletRequest _trackedRequest;
471            private boolean _useCustomPage = true;
472    
473    }