001    /**
002     * Copyright (c) 2000-2013 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.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.PipingServletResponse;
024    import com.liferay.portal.kernel.servlet.TrackedServletRequest;
025    import com.liferay.portal.kernel.servlet.taglib.FileAvailabilityUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
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.PortletConstants;
035    import com.liferay.portal.model.Theme;
036    import com.liferay.portal.theme.ThemeDisplay;
037    import com.liferay.portal.util.CustomJspRegistryUtil;
038    
039    import javax.servlet.RequestDispatcher;
040    import javax.servlet.ServletContext;
041    import javax.servlet.http.HttpServletRequest;
042    import javax.servlet.http.HttpServletResponse;
043    import javax.servlet.jsp.JspException;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Shuyang Zhou
048     * @author Eduardo Lundgren
049     * @author Raymond Augé
050     */
051    public class IncludeTag extends AttributesTagSupport {
052    
053            @Override
054            public int doEndTag() throws JspException {
055                    try {
056                            String page = null;
057    
058                            if (_useCustomPage) {
059                                    page = getCustomPage(servletContext, request);
060                            }
061    
062                            if (Validator.isNull(page)) {
063                                    page = getPage();
064                            }
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                            else if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
078                                    return processEndTag();
079                            }
080                            else {
081                                    doInclude(page);
082    
083                                    return EVAL_PAGE;
084                            }
085                    }
086                    catch (Exception e) {
087                            throw new JspException(e);
088                    }
089                    finally {
090                            clearDynamicAttributes();
091                            clearParams();
092                            clearProperties();
093    
094                            cleanUpSetAttributes();
095    
096                            if (!ServerDetector.isResin()) {
097                                    setPage(null);
098                                    setUseCustomPage(true);
099    
100                                    cleanUp();
101                            }
102                    }
103            }
104    
105            @Override
106            public int doStartTag() throws JspException {
107                    try {
108                            String page = getStartPage();
109    
110                            callSetAttributes();
111    
112                            if (themeResourceExists(page)) {
113                                    doIncludeTheme(page);
114    
115                                    return EVAL_BODY_INCLUDE;
116                            }
117                            else if (!FileAvailabilityUtil.isAvailable(servletContext, page)) {
118                                    return processStartTag();
119                            }
120                            else {
121                                    doInclude(page);
122    
123                                    return EVAL_BODY_INCLUDE;
124                            }
125                    }
126                    catch (Exception e) {
127                            throw new JspException(e);
128                    }
129            }
130    
131            public void runTag() throws JspException {
132                    doStartTag();
133                    doEndTag();
134            }
135    
136            public void setPage(String page) {
137                    _page = page;
138            }
139    
140            public void setPortletId(String portletId) {
141                    if (Validator.isNotNull(portletId)) {
142                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
143    
144                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
145    
146                            servletContext = portletBag.getServletContext();
147                    }
148            }
149    
150            public void setStrict(boolean strict) {
151                    _strict = strict;
152            }
153    
154            public void setUseCustomPage(boolean useCustomPage) {
155                    _useCustomPage = useCustomPage;
156            }
157    
158            protected void callSetAttributes() {
159                    if (_calledSetAttributes) {
160                            return;
161                    }
162    
163                    _calledSetAttributes = true;
164    
165                    HttpServletRequest request = getOriginalServletRequest();
166    
167                    if (isCleanUpSetAttributes()) {
168                            _trackedRequest = new TrackedServletRequest(request);
169    
170                            request = _trackedRequest;
171                    }
172    
173                    setNamespacedAttribute(request, "bodyContent", getBodyContent());
174                    setNamespacedAttribute(
175                            request, "dynamicAttributes", getDynamicAttributes());
176                    setNamespacedAttribute(
177                            request, "scopedAttributes", getScopedAttributes());
178    
179                    setAttributes(request);
180            }
181    
182            protected void cleanUp() {
183            }
184    
185            protected void cleanUpSetAttributes() {
186                    _calledSetAttributes = false;
187    
188                    if (isCleanUpSetAttributes()) {
189                            for (String name : _trackedRequest.getSetAttributes()) {
190                                    _trackedRequest.removeAttribute(name);
191                            }
192    
193                            _trackedRequest = null;
194                    }
195            }
196    
197            protected void doInclude(String page) throws JspException {
198                    try {
199                            include(page);
200                    }
201                    catch (Exception e) {
202                            String currentURL = (String)request.getAttribute(
203                                    WebKeys.CURRENT_URL);
204    
205                            _log.error(
206                                    "Current URL " + currentURL + " generates exception: " +
207                                            e.getMessage());
208    
209                            LogUtil.log(_log, e);
210    
211                            if (e instanceof JspException) {
212                                    throw (JspException)e;
213                            }
214                    }
215            }
216    
217            protected void doIncludeTheme(String page) throws Exception {
218                    HttpServletResponse response =
219                            (HttpServletResponse)pageContext.getResponse();
220    
221                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
222    
223                    ThemeUtil.include(
224                            servletContext, request, response, pageContext, page, theme);
225            }
226    
227            protected String getCustomPage(
228                    ServletContext servletContext, HttpServletRequest request) {
229    
230                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
231                            WebKeys.THEME_DISPLAY);
232    
233                    if (themeDisplay == null) {
234                            return null;
235                    }
236    
237                    Group group = themeDisplay.getScopeGroup();
238    
239                    UnicodeProperties typeSettingsProperties =
240                            group.getTypeSettingsProperties();
241    
242                    String customJspServletContextName = typeSettingsProperties.getProperty(
243                            "customJspServletContextName");
244    
245                    if (Validator.isNull(customJspServletContextName)) {
246                            return null;
247                    }
248    
249                    String page = getPage();
250    
251                    if (Validator.isNull(page)) {
252                            page = getEndPage();
253                    }
254    
255                    if (Validator.isNull(page)) {
256                            return null;
257                    }
258    
259                    String customPage = CustomJspRegistryUtil.getCustomJspFileName(
260                            customJspServletContextName, page);
261    
262                    if (FileAvailabilityUtil.isAvailable(servletContext, customPage)) {
263                            return customPage;
264                    }
265    
266                    return null;
267            }
268    
269            protected String getEndPage() {
270                    return null;
271            }
272    
273            protected HttpServletRequest getOriginalServletRequest() {
274                    return (HttpServletRequest)pageContext.getRequest();
275            }
276    
277            protected String getPage() {
278                    return _page;
279            }
280    
281            protected String getStartPage() {
282                    return null;
283            }
284    
285            protected void include(String page) throws Exception {
286                    RequestDispatcher requestDispatcher =
287                            DirectRequestDispatcherFactoryUtil.getRequestDispatcher(
288                                    servletContext, page);
289    
290                    request.setAttribute(
291                            WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT, _strict);
292    
293                    HttpServletResponse response = new PipingServletResponse(pageContext);
294    
295                    requestDispatcher.include(request, response);
296    
297                    request.removeAttribute(WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT);
298            }
299    
300            protected boolean isCleanUpSetAttributes() {
301                    return _CLEAN_UP_SET_ATTRIBUTES;
302            }
303    
304            protected boolean isUseCustomPage() {
305                    return _useCustomPage;
306            }
307    
308            protected int processEndTag() throws Exception {
309                    return EVAL_PAGE;
310            }
311    
312            protected int processStartTag() throws Exception {
313                    return EVAL_BODY_INCLUDE;
314            }
315    
316            protected void setAttributes(HttpServletRequest request) {
317            }
318    
319            protected void setCalledSetAttributes(boolean calledSetAttributes) {
320                    _calledSetAttributes = calledSetAttributes;
321            }
322    
323            protected boolean themeResourceExists(String page) throws Exception {
324                    if ((page == null) || !_THEME_JSP_OVERRIDE_ENABLED || _strict) {
325                            return false;
326                    }
327    
328                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
329    
330                    if (theme == null) {
331                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
332                                    WebKeys.THEME_DISPLAY);
333    
334                            if (themeDisplay != null) {
335                                    theme = themeDisplay.getTheme();
336                            }
337                    }
338    
339                    if (theme == null) {
340                            return false;
341                    }
342    
343                    String portletId = ThemeUtil.getPortletId(request);
344    
345                    boolean exists = theme.resourceExists(servletContext, portletId, page);
346    
347                    if (_log.isDebugEnabled() && exists) {
348                            String resourcePath = theme.getResourcePath(
349                                    servletContext, null, page);
350    
351                            _log.debug(resourcePath);
352                    }
353    
354                    return exists;
355            }
356    
357            private static final boolean _CLEAN_UP_SET_ATTRIBUTES = false;
358    
359            private static final boolean _THEME_JSP_OVERRIDE_ENABLED =
360                    GetterUtil.getBoolean(
361                            PropsUtil.get(PropsKeys.THEME_JSP_OVERRIDE_ENABLED));
362    
363            private static Log _log = LogFactoryUtil.getLog(IncludeTag.class);
364    
365            private boolean _calledSetAttributes;
366            private String _page;
367            private boolean _strict;
368            private TrackedServletRequest _trackedRequest;
369            private boolean _useCustomPage = true;
370    
371    }