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.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 =
166                            (HttpServletRequest)pageContext.getRequest();
167    
168                    if (isCleanUpSetAttributes()) {
169                            _trackedRequest = new TrackedServletRequest(request);
170    
171                            request = _trackedRequest;
172                    }
173    
174                    setNamespacedAttribute(request, "bodyContent", getBodyContent());
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                    _calledSetAttributes = false;
188    
189                    if (isCleanUpSetAttributes()) {
190                            for (String name : _trackedRequest.getSetAttributes()) {
191                                    _trackedRequest.removeAttribute(name);
192                            }
193    
194                            _trackedRequest = null;
195                    }
196            }
197    
198            protected void doInclude(String page) throws JspException {
199                    try {
200                            include(page);
201                    }
202                    catch (Exception e) {
203                            String currentURL = (String)request.getAttribute(
204                                    WebKeys.CURRENT_URL);
205    
206                            _log.error(
207                                    "Current URL " + currentURL + " generates exception: " +
208                                            e.getMessage());
209    
210                            LogUtil.log(_log, e);
211    
212                            if (e instanceof JspException) {
213                                    throw (JspException)e;
214                            }
215                    }
216            }
217    
218            protected void doIncludeTheme(String page) throws Exception {
219                    HttpServletResponse response =
220                            (HttpServletResponse)pageContext.getResponse();
221    
222                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
223    
224                    ThemeUtil.include(
225                            servletContext, request, response, pageContext, page, theme);
226            }
227    
228            protected String getCustomPage(
229                    ServletContext servletContext, HttpServletRequest request) {
230    
231                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
232                            WebKeys.THEME_DISPLAY);
233    
234                    if (themeDisplay == null) {
235                            return null;
236                    }
237    
238                    Group group = themeDisplay.getScopeGroup();
239    
240                    UnicodeProperties typeSettingsProperties =
241                            group.getTypeSettingsProperties();
242    
243                    String customJspServletContextName = typeSettingsProperties.getProperty(
244                            "customJspServletContextName");
245    
246                    if (Validator.isNull(customJspServletContextName)) {
247                            return null;
248                    }
249    
250                    String page = getPage();
251    
252                    if (Validator.isNull(page)) {
253                            page = getEndPage();
254                    }
255    
256                    if (Validator.isNull(page)) {
257                            return null;
258                    }
259    
260                    String customPage = CustomJspRegistryUtil.getCustomJspFileName(
261                            customJspServletContextName, page);
262    
263                    if (FileAvailabilityUtil.isAvailable(servletContext, customPage)) {
264                            return customPage;
265                    }
266    
267                    return null;
268            }
269    
270            protected String getEndPage() {
271                    return null;
272            }
273    
274            protected String getPage() {
275                    return _page;
276            }
277    
278            protected String getStartPage() {
279                    return null;
280            }
281    
282            protected void include(String page) throws Exception {
283                    RequestDispatcher requestDispatcher =
284                            DirectRequestDispatcherFactoryUtil.getRequestDispatcher(
285                                    servletContext, page);
286    
287                    request.setAttribute(
288                            WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT, _strict);
289    
290                    HttpServletResponse response = new PipingServletResponse(pageContext);
291    
292                    requestDispatcher.include(request, response);
293    
294                    request.removeAttribute(WebKeys.SERVLET_CONTEXT_INCLUDE_FILTER_STRICT);
295            }
296    
297            protected boolean isCleanUpSetAttributes() {
298                    return _CLEAN_UP_SET_ATTRIBUTES;
299            }
300    
301            protected boolean isUseCustomPage() {
302                    return _useCustomPage;
303            }
304    
305            protected int processEndTag() throws Exception {
306                    return EVAL_PAGE;
307            }
308    
309            protected int processStartTag() throws Exception {
310                    return EVAL_BODY_INCLUDE;
311            }
312    
313            protected void setAttributes(HttpServletRequest request) {
314            }
315    
316            protected void setCalledSetAttributes(boolean calledSetAttributes) {
317                    _calledSetAttributes = calledSetAttributes;
318            }
319    
320            protected boolean themeResourceExists(String page) throws Exception {
321                    if ((page == null) || !_THEME_JSP_OVERRIDE_ENABLED || _strict) {
322                            return false;
323                    }
324    
325                    Theme theme = (Theme)request.getAttribute(WebKeys.THEME);
326    
327                    if (theme == null) {
328                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
329                                    WebKeys.THEME_DISPLAY);
330    
331                            if (themeDisplay != null) {
332                                    theme = themeDisplay.getTheme();
333                            }
334                    }
335    
336                    if (theme == null) {
337                            return false;
338                    }
339    
340                    String portletId = ThemeUtil.getPortletId(request);
341    
342                    boolean exists = theme.resourceExists(servletContext, portletId, page);
343    
344                    if (_log.isDebugEnabled() && exists) {
345                            String resourcePath = theme.getResourcePath(
346                                    servletContext, null, page);
347    
348                            _log.debug(resourcePath);
349                    }
350    
351                    return exists;
352            }
353    
354            private static final boolean _CLEAN_UP_SET_ATTRIBUTES = false;
355    
356            private static final boolean _THEME_JSP_OVERRIDE_ENABLED =
357                    GetterUtil.getBoolean(
358                            PropsUtil.get(PropsKeys.THEME_JSP_OVERRIDE_ENABLED));
359    
360            private static Log _log = LogFactoryUtil.getLog(IncludeTag.class);
361    
362            private boolean _calledSetAttributes;
363            private String _page;
364            private boolean _strict;
365            private TrackedServletRequest _trackedRequest;
366            private boolean _useCustomPage = true;
367    
368    }