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    public final class GzipUtil
024    {
025        private static final float MIN_IE_VERSION = 7.0f;
026    
027        private static final String MSIE_6_COMPATIBLE_STRING = "SV1";
028    
029        /* defeat instantiation */
030        private GzipUtil() { }
031    
032        /**
033         * Determines if gzip compression is appropriate/possible based on the User Agent and 
034         * other limiting factors. IE versions < 6.1 are known to not work with gzip compression reliably. 
035         *
036         * @param request The current web request to check the headers of.
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    
044            if (encoding == null || encoding.indexOf("gzip") < 0)
045                return false;
046    
047            // Handle IE specific hacks
048    
049            String userAgent = request.getHeader("User-Agent");
050            int ieIndex = (userAgent != null) ? userAgent.indexOf("MSIE") : -1;
051            if (ieIndex > -1)
052            {
053                float version = -1;
054    
055                try
056                {
057                    version = Float.parseFloat(userAgent.substring(ieIndex + 4, ieIndex + 8));
058                } catch (NumberFormatException nf) {nf.printStackTrace();}
059    
060                if (version >= MIN_IE_VERSION)
061                    return true;
062    
063                if (userAgent.indexOf(MSIE_6_COMPATIBLE_STRING) > -1)
064                    return true;
065    
066                // else false
067    
068                return false;
069            }
070    
071            return true;
072        }
073    
074        /**
075         * Based on the given type of content, determines if compression is appropriate. The biggest
076         * thing it does is make sure that image content isn't compressed as that kind of content
077         * is already compressed fairly well.
078         *
079         * @param contentType
080         *          The content type to check. (ie "text/javascript","text/html", etc..)
081         *
082         * @return True if compression is appropriate for the content specified, false otherwise.
083         */
084        public static boolean shouldCompressContentType(String contentType)
085        {
086            if (contentType == null)
087                return false;
088    
089            return contentType.indexOf("javascript") > -1
090                   || contentType.indexOf("css") > -1
091                   || contentType.indexOf("html") > -1
092                   || contentType.indexOf("text") > -1;
093        }
094    }