001    /**
002     * Copyright (c) 2000-2010 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.portal.servlet.filters.gzip;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.LiferayWindowState;
020    import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
021    import com.liferay.portal.kernel.util.HttpUtil;
022    import com.liferay.portal.kernel.util.JavaConstants;
023    import com.liferay.portal.kernel.util.ParamUtil;
024    import com.liferay.portal.kernel.util.ServerDetector;
025    import com.liferay.portal.servlet.filters.BasePortalFilter;
026    
027    import javax.servlet.FilterChain;
028    import javax.servlet.http.HttpServletRequest;
029    import javax.servlet.http.HttpServletResponse;
030    
031    /**
032     * @author Brian Wing Shun Chan
033     * @author Raymond Augé
034     */
035    public class GZipFilter extends BasePortalFilter {
036    
037            public static final String SKIP_FILTER =
038                    GZipFilter.class.getName() + "SKIP_FILTER";
039    
040            public GZipFilter() {
041    
042                    // The compression filter will work on JBoss, Jetty, JOnAS, OC4J, and
043                    // Tomcat, but may break on other servers
044    
045                    if (super.isFilterEnabled()) {
046                            if (ServerDetector.isJBoss() || ServerDetector.isJetty() ||
047                                    ServerDetector.isJOnAS() || ServerDetector.isOC4J() ||
048                                    ServerDetector.isTomcat()) {
049    
050                                    _filterEnabled = true;
051                            }
052                            else {
053                                    _filterEnabled = false;
054                            }
055                    }
056            }
057    
058            protected boolean isAlreadyFiltered(HttpServletRequest request) {
059                    if (request.getAttribute(SKIP_FILTER) != null) {
060                            return true;
061                    }
062                    else {
063                            return false;
064                    }
065            }
066    
067            protected boolean isCompress(HttpServletRequest request) {
068                    if (!ParamUtil.get(request, _COMPRESS, true)) {
069                            return false;
070                    }
071                    else {
072    
073                            // Modifying binary content through a servlet filter under certain
074                            // conditions is bad on performance the user will not start
075                            // downloading the content until the entire content is modified.
076    
077                            String lifecycle = ParamUtil.getString(request, "p_p_lifecycle");
078    
079                            if ((lifecycle.equals("1") &&
080                                     LiferayWindowState.isExclusive(request)) ||
081                                    lifecycle.equals("2")) {
082    
083                                    return false;
084                            }
085                            else {
086                                    return true;
087                            }
088                    }
089            }
090    
091            protected boolean isFilterEnabled() {
092                    return _filterEnabled;
093            }
094    
095            protected boolean isInclude(HttpServletRequest request) {
096                    String uri = (String)request.getAttribute(
097                            JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI);
098    
099                    if (uri == null) {
100                            return false;
101                    }
102                    else {
103                            return true;
104                    }
105            }
106    
107            protected void processFilter(
108                            HttpServletRequest request, HttpServletResponse response,
109                            FilterChain filterChain)
110                    throws Exception {
111    
112                    if (isCompress(request) && !isInclude(request) &&
113                            BrowserSnifferUtil.acceptsGzip(request) &&
114                            !isAlreadyFiltered(request)) {
115    
116                            if (_log.isDebugEnabled()) {
117                                    String completeURL = HttpUtil.getCompleteURL(request);
118    
119                                    _log.debug("Compressing " + completeURL);
120                            }
121    
122                            request.setAttribute(SKIP_FILTER, Boolean.TRUE);
123    
124                            GZipResponse gZipResponse = new GZipResponse(response);
125    
126                            processFilter(GZipFilter.class, request, gZipResponse, filterChain);
127    
128                            gZipResponse.finishResponse();
129                    }
130                    else {
131                            if (_log.isDebugEnabled()) {
132                                    String completeURL = HttpUtil.getCompleteURL(request);
133    
134                                    _log.debug("Not compressing " + completeURL);
135                            }
136    
137                            processFilter(
138                                    GZipFilter.class, request, response, filterChain);
139                    }
140            }
141    
142            private static final String _COMPRESS = "compress";
143    
144            private static Log _log = LogFactoryUtil.getLog(GZipFilter.class);
145    
146            private boolean _filterEnabled;
147    
148    }