View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the
    6    * License.  You may obtain a copy of the License at:
    7    *
    8    *    http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.handler.codec.http;
    17
    18  import java.util.regex.Matcher;
    19  import java.util.regex.Pattern;
    20
    21  /**
    22   * The version of HTTP or its derived protocols, such as
    23   * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
    24   * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>.
    25   *
    26   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    27   * @author Andy Taylor (andy.taylor@jboss.org)
    28   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
    29   * @version $Rev: 2089 $, $Date: 2010-01-27 11:39:28 +0900 (Wed, 27 Jan 2010) $
    30   *
    31   * @apiviz.exclude
    32   */
    33  public class HttpVersion implements Comparable<HttpVersion> {
    34
    35      private static final Pattern VERSION_PATTERN =
    36          Pattern.compile("(\\S+)/(\\d+)\\.(\\d+)");
    37
    38      /**
    39       * HTTP/1.0
    40       */
    41      public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false);
    42
    43      /**
    44       * HTTP/1.1
    45       */
    46      public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true);
    47
    48      /**
    49       * Returns an existing or new {@link HttpVersion} instance which matches to
    50       * the specified protocol version string.  If the specified {@code text} is
    51       * equal to {@code "HTTP/1.0"}, {@link #HTTP_1_0} will be returned.  If the
    52       * specified {@code text} is equal to {@code "HTTP/1.1"}, {@link #HTTP_1_1}
    53       * will be returned.  Otherwise, a new {@link HttpVersion} instance will be
    54       * returned.
    55       */
    56      public static HttpVersion valueOf(String text) {
    57          if (text == null) {
    58              throw new NullPointerException("text");
    59          }
    60
    61          text = text.trim().toUpperCase();
    62          if (text.equals("HTTP/1.1")) {
    63              return HTTP_1_1;
    64          }
    65          if (text.equals("HTTP/1.0")) {
    66              return HTTP_1_0;
    67          }
    68          return new HttpVersion(text, true);
    69      }
    70
    71      private final String protocolName;
    72      private final int majorVersion;
    73      private final int minorVersion;
    74      private final String text;
    75      private final boolean keepAliveDefault;
    76
    77      /**
    78       * @deprecated Use {@link #HttpVersion(String, boolean)} instead.
    79       */
    80      @Deprecated
    81      public HttpVersion(String text) {
    82          this(text, true);
    83      }
    84
    85      /**
    86       * Creates a new HTTP version with the specified version string.  You will
    87       * not need to create a new instance unless you are implementing a protocol
    88       * derived from HTTP, such as
    89       * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
    90       * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>.
    91       *
    92       * @param keepAliveDefault
    93       *        {@code true} if and only if the connection is kept alive unless
    94       *        the {@code "Connection"} header is set to {@code "close"} explicitly.
    95       */
    96      public HttpVersion(String text, boolean keepAliveDefault) {
    97          if (text == null) {
    98              throw new NullPointerException("text");
    99          }
    100
    101         text = text.trim().toUpperCase();
    102         if (text.length() == 0) {
    103             throw new IllegalArgumentException("empty text");
    104         }
    105
    106         Matcher m = VERSION_PATTERN.matcher(text);
    107         if (!m.matches()) {
    108             throw new IllegalArgumentException("invalid version format: " + text);
    109         }
    110
    111         protocolName = m.group(1);
    112         majorVersion = Integer.parseInt(m.group(2));
    113         minorVersion = Integer.parseInt(m.group(3));
    114         this.text = protocolName + '/' + majorVersion + '.' + minorVersion;
    115         this.keepAliveDefault = keepAliveDefault;
    116     }
    117
    118     /**
    119      * @deprecated Use {@link #HttpVersion(String, int, int, boolean)} instead.
    120      */
    121     @Deprecated
    122     public HttpVersion(
    123             String protocolName, int majorVersion, int minorVersion) {
    124         this(protocolName, majorVersion, minorVersion, true);
    125     }
    126
    127     /**
    128      * Creates a new HTTP version with the specified protocol name and version
    129      * numbers.  You will not need to create a new instance unless you are
    130      * implementing a protocol derived from HTTP, such as
    131      * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
    132      * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>
    133      *
    134      * @param keepAliveDefault
    135      *        {@code true} if and only if the connection is kept alive unless
    136      *        the {@code "Connection"} header is set to {@code "close"} explicitly.
    137      */
    138     public HttpVersion(
    139             String protocolName, int majorVersion, int minorVersion,
    140             boolean keepAliveDefault) {
    141         if (protocolName == null) {
    142             throw new NullPointerException("protocolName");
    143         }
    144
    145         protocolName = protocolName.trim().toUpperCase();
    146         if (protocolName.length() == 0) {
    147             throw new IllegalArgumentException("empty protocolName");
    148         }
    149
    150         for (int i = 0; i < protocolName.length(); i ++) {
    151             if (Character.isISOControl(protocolName.charAt(i)) ||
    152                 Character.isWhitespace(protocolName.charAt(i))) {
    153                 throw new IllegalArgumentException("invalid character in protocolName");
    154             }
    155         }
    156
    157         if (majorVersion < 0) {
    158             throw new IllegalArgumentException("negative majorVersion");
    159         }
    160         if (minorVersion < 0) {
    161             throw new IllegalArgumentException("negative minorVersion");
    162         }
    163
    164         this.protocolName = protocolName;
    165         this.majorVersion = majorVersion;
    166         this.minorVersion = minorVersion;
    167         text = protocolName + '/' + majorVersion + '.' + minorVersion;
    168         this.keepAliveDefault = keepAliveDefault;
    169     }
    170
    171     /**
    172      * Returns the name of the protocol such as {@code "HTTP"} in {@code "HTTP/1.0"}.
    173      */
    174     public String getProtocolName() {
    175         return protocolName;
    176     }
    177
    178     /**
    179      * Returns the name of the protocol such as {@code 1} in {@code "HTTP/1.0"}.
    180      */
    181     public int getMajorVersion() {
    182         return majorVersion;
    183     }
    184
    185     /**
    186      * Returns the name of the protocol such as {@code 0} in {@code "HTTP/1.0"}.
    187      */
    188     public int getMinorVersion() {
    189         return minorVersion;
    190     }
    191
    192     /**
    193      * Returns the full protocol version text such as {@code "HTTP/1.0"}.
    194      */
    195     public String getText() {
    196         return text;
    197     }
    198
    199     /**
    200      * Returns {@code true} if and only if the connection is kept alive unless
    201      * the {@code "Connection"} header is set to {@code "close"} explicitly.
    202      */
    203     public boolean isKeepAliveDefault() {
    204         return keepAliveDefault;
    205     }
    206
    207     /**
    208      * Returns the full protocol version text such as {@code "HTTP/1.0"}.
    209      */
    210     @Override
    211     public String toString() {
    212         return getText();
    213     }
    214
    215     @Override
    216     public int hashCode() {
    217         return (getProtocolName().hashCode() * 31 + getMajorVersion()) * 31 +
    218                getMinorVersion();
    219     }
    220
    221     @Override
    222     public boolean equals(Object o) {
    223         if (!(o instanceof HttpVersion)) {
    224             return false;
    225         }
    226
    227         HttpVersion that = (HttpVersion) o;
    228         return getMinorVersion() == that.getMinorVersion() &&
    229                getMajorVersion() == that.getMajorVersion() &&
    230                getProtocolName().equals(that.getProtocolName());
    231     }
    232
    233     public int compareTo(HttpVersion o) {
    234         int v = getProtocolName().compareTo(o.getProtocolName());
    235         if (v != 0) {
    236             return v;
    237         }
    238
    239         v = getMajorVersion() - o.getMajorVersion();
    240         if (v != 0) {
    241             return v;
    242         }
    243
    244         return getMinorVersion() - o.getMinorVersion();
    245     }
    246 }