View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.commons.resourcehandler;
20  
21  
22  /**
23   * Utility methods needed in PackagedResource and PackagedResourceHandler. 
24   *
25   * @author Jakob Korherr
26   */
27  public class ResourceUtils
28  {
29      /**
30       * Checks if the user agent supports GZIP compression on basis of the "Accept-Encoding" header field. 
31       * Created according to RFC2616, section 14.3 Accept-Encoding.
32       *
33       * Some examples of Accept-Encoding:
34       *
35       *     Accept-Encoding: gzip, deflate
36       *     Accept-Encoding:
37       *     Accept-Encoding: *
38       *     Accept-Encoding: compress;q=0.5, gzip;q=1.0
39       *     Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0 
40       *
41       * @param acceptEncodingHeader
42       * @return
43       */
44      public static boolean isGZIPEncodingAccepted(String acceptEncodingHeader)
45      {
46          if (acceptEncodingHeader == null)
47          {
48              return false;
49          }
50          int gzipIndex = acceptEncodingHeader.indexOf("gzip");
51          if (gzipIndex != -1)
52          {
53              // "gzip" appears in the header
54              // --> check if banned via q=0
55              return !isEncodingQValueZero(acceptEncodingHeader, gzipIndex);
56          }
57  
58          // no "gzip" in header --> check for "*"
59          int starIndex = acceptEncodingHeader.indexOf('*');
60          if (starIndex != -1)
61          {
62              // "*" appears in the header
63              // --> check if banned via q=0
64              return !isEncodingQValueZero(acceptEncodingHeader, starIndex);
65          }
66  
67          // neither "gzip" nor "*" in header
68          return false;
69      }
70  
71      private static boolean isEncodingQValueZero(String acceptEncodingHeader, int startIndex)
72      {
73          // remove any precending definitions
74          String encodingSubstring = acceptEncodingHeader.substring(startIndex);
75  
76          // remove any subsequent definitions (separated via ,)
77          int commaIndex = encodingSubstring.indexOf(',');
78          if (commaIndex != -1)
79          {
80              encodingSubstring = encodingSubstring.substring(0, commaIndex);
81          }
82  
83          int qZeroIndex = encodingSubstring.indexOf("q=0");
84          if (qZeroIndex != -1)
85          {
86              String qZeroSubstring = encodingSubstring.substring(qZeroIndex).trim();
87              if (qZeroSubstring.matches("q=0(\\.(0){0,3})?"))
88              {
89                  // "q=0" or "q=0." or "q=0.0" or "q=0.00" or "q=0.000" found
90                  // NOTE that there MUST NOT be more than 3 digits after the decimal point (per RFC section 3.9)
91                  return true;
92              }
93              else
94              {
95                  // q=0.xyz" found with any of xyz being != 0
96                  return false;
97              }
98          }
99          else
100         {
101             // "q=0" not found
102             return false;
103         }
104     }
105     
106 }