001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    package org.apache.tapestry.util.io;
015    
016    import org.apache.tapestry.web.WebRequest;
017    
018    
019    /**
020     * Encapsulates logic related to various gzip compression schemes and their rules
021     * as they apply to different browsers.
022     *
023     * @author jkuhnert
024     */
025    public final class GzipUtil
026    {
027        private static final float MIN_IE_VERSION = 7.0f;
028    
029        private static final String MSIE_6_COMPATIBLE_STRING = "SV1";
030    
031        /* defeat instantiation */
032        private GzipUtil() { }
033    
034        /**
035         * Determines if gzip compression is appropriate/possible based on the User Agent and 
036         * other limiting factors. IE versions < 6.1 are known to not work with gzip compression reliably. 
037         *
038         * @return True, if this request can be served in gzip format. False otherwise.
039         */
040        public static boolean isGzipCapable(WebRequest request)
041        {
042            String encoding = request.getHeader("Accept-Encoding");
043            if (encoding == null || encoding.indexOf("gzip") < 0)
044                return false;
045    
046            // Handle IE specific hacks
047    
048            String userAgent = request.getHeader("User-Agent");
049            int ieIndex = (userAgent != null) ? userAgent.indexOf("MSIE") : -1;
050            if (ieIndex > -1) {
051    
052                float version = -1;
053    
054                try {
055                    version = Float.parseFloat(userAgent.substring(ieIndex + 4, ieIndex + 8));
056                } catch (NumberFormatException nf) {nf.printStackTrace();}
057    
058                if (version >= MIN_IE_VERSION)
059                    return true;
060    
061                if (userAgent.indexOf(MSIE_6_COMPATIBLE_STRING) > -1)
062                    return true;
063    
064                // else false
065    
066                return false;
067            }
068    
069            return true;
070        }
071    
072        /**
073         * Based on the given type of content, determines if compression is appropriate. The biggest
074         * thing it does is make sure that image content isn't compressed as that kind of content
075         * is already compressed fairly well.
076         *
077         * @param contentType
078         *          The content type to check. (ie "text/javascript","text/html", etc..)
079         *
080         * @return True if compression is appropriate for the content specified, false otherwise.
081         */
082        public static boolean shouldCompressContentType(String contentType)
083        {
084            if (contentType == null)
085                return false;
086    
087            return contentType.indexOf("javascript") > -1
088                   || contentType.indexOf("css") > -1
089                   || contentType.indexOf("html") > -1
090                   || contentType.indexOf("text") > -1;
091        }
092    }