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