Home | History | Annotate | Download | only in http
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/ProtocolVersion.java $
      3  * $Revision: 609106 $
      4  * $Date: 2008-01-05 01:15:42 -0800 (Sat, 05 Jan 2008) $
      5  *
      6  * ====================================================================
      7  * Licensed to the Apache Software Foundation (ASF) under one
      8  * or more contributor license agreements.  See the NOTICE file
      9  * distributed with this work for additional information
     10  * regarding copyright ownership.  The ASF licenses this file
     11  * to you under the Apache License, Version 2.0 (the
     12  * "License"); you may not use this file except in compliance
     13  * with the License.  You may obtain a copy of the License at
     14  *
     15  *   http://www.apache.org/licenses/LICENSE-2.0
     16  *
     17  * Unless required by applicable law or agreed to in writing,
     18  * software distributed under the License is distributed on an
     19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     20  * KIND, either express or implied.  See the License for the
     21  * specific language governing permissions and limitations
     22  * under the License.
     23  * ====================================================================
     24  *
     25  * This software consists of voluntary contributions made by many
     26  * individuals on behalf of the Apache Software Foundation.  For more
     27  * information on the Apache Software Foundation, please see
     28  * <http://www.apache.org/>.
     29  *
     30  */
     31 
     32 package org.apache.http;
     33 
     34 import java.io.Serializable;
     35 import org.apache.http.util.CharArrayBuffer;
     36 
     37 
     38 /**
     39  * Represents a protocol version, as specified in RFC 2616.
     40  * RFC 2616 specifies only HTTP versions, like "HTTP/1.1" and "HTTP/1.0".
     41  * RFC 3261 specifies a message format that is identical to HTTP except
     42  * for the protocol name. It defines a protocol version "SIP/2.0".
     43  * There are some nitty-gritty differences between the interpretation
     44  * of versions in HTTP and SIP. In those cases, HTTP takes precedence.
     45  * <p>
     46  * This class defines a protocol version as a combination of
     47  * protocol name, major version number, and minor version number.
     48  * Note that {@link #equals} and {@link #hashCode} are defined as
     49  * final here, they cannot be overridden in derived classes.
     50  *
     51  * @author <a href="mailto:oleg (at) ural.ru">Oleg Kalnichevski</a>
     52  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
     53  *
     54  * @version $Revision: 609106 $
     55  */
     56 public class ProtocolVersion implements Serializable, Cloneable {
     57 
     58     private static final long serialVersionUID = 8950662842175091068L;
     59 
     60 
     61     /** Name of the protocol. */
     62     protected final String protocol;
     63 
     64     /** Major version number of the protocol */
     65     protected final int major;
     66 
     67     /** Minor version number of the protocol */
     68     protected final int minor;
     69 
     70 
     71     /**
     72      * Create a protocol version designator.
     73      *
     74      * @param protocol   the name of the protocol, for example "HTTP"
     75      * @param major      the major version number of the protocol
     76      * @param minor      the minor version number of the protocol
     77      */
     78     public ProtocolVersion(String protocol, int major, int minor) {
     79         if (protocol == null) {
     80             throw new IllegalArgumentException
     81                 ("Protocol name must not be null.");
     82         }
     83         if (major < 0) {
     84             throw new IllegalArgumentException
     85                 ("Protocol major version number must not be negative.");
     86         }
     87         if (minor < 0) {
     88             throw new IllegalArgumentException
     89                 ("Protocol minor version number may not be negative");
     90         }
     91         this.protocol = protocol;
     92         this.major = major;
     93         this.minor = minor;
     94     }
     95 
     96     /**
     97      * Returns the name of the protocol.
     98      *
     99      * @return the protocol name
    100      */
    101     public final String getProtocol() {
    102         return protocol;
    103     }
    104 
    105     /**
    106      * Returns the major version number of the protocol.
    107      *
    108      * @return the major version number.
    109      */
    110     public final int getMajor() {
    111         return major;
    112     }
    113 
    114     /**
    115      * Returns the minor version number of the HTTP protocol.
    116      *
    117      * @return the minor version number.
    118      */
    119     public final int getMinor() {
    120         return minor;
    121     }
    122 
    123 
    124     /**
    125      * Obtains a specific version of this protocol.
    126      * This can be used by derived classes to instantiate themselves instead
    127      * of the base class, and to define constants for commonly used versions.
    128      * <br/>
    129      * The default implementation in this class returns <code>this</code>
    130      * if the version matches, and creates a new {@link ProtocolVersion}
    131      * otherwise.
    132      *
    133      * @param major     the major version
    134      * @param minor     the minor version
    135      *
    136      * @return  a protocol version with the same protocol name
    137      *          and the argument version
    138      */
    139     public ProtocolVersion forVersion(int major, int minor) {
    140 
    141         if ((major == this.major) && (minor == this.minor)) {
    142             return this;
    143         }
    144 
    145         // argument checking is done in the constructor
    146         return new ProtocolVersion(this.protocol, major, minor);
    147     }
    148 
    149 
    150     /**
    151      * Obtains a hash code consistent with {@link #equals}.
    152      *
    153      * @return  the hashcode of this protocol version
    154      */
    155     public final int hashCode() {
    156         return this.protocol.hashCode() ^ (this.major * 100000) ^ this.minor;
    157     }
    158 
    159 
    160     /**
    161      * Checks equality of this protocol version with an object.
    162      * The object is equal if it is a protocl version with the same
    163      * protocol name, major version number, and minor version number.
    164      * The specific class of the object is <i>not</i> relevant,
    165      * instances of derived classes with identical attributes are
    166      * equal to instances of the base class and vice versa.
    167      *
    168      * @param obj       the object to compare with
    169      *
    170      * @return  <code>true</code> if the argument is the same protocol version,
    171      *          <code>false</code> otherwise
    172      */
    173     public final boolean equals(Object obj) {
    174         if (this == obj) {
    175             return true;
    176         }
    177         if (!(obj instanceof ProtocolVersion)) {
    178             return false;
    179         }
    180         ProtocolVersion that = (ProtocolVersion) obj;
    181 
    182         return ((this.protocol.equals(that.protocol)) &&
    183                 (this.major == that.major) &&
    184                 (this.minor == that.minor));
    185     }
    186 
    187 
    188     /**
    189      * Checks whether this protocol can be compared to another one.
    190      * Only protocol versions with the same protocol name can be
    191      * {@link #compareToVersion compared}.
    192      *
    193      * @param that      the protocol version to consider
    194      *
    195      * @return  <code>true</code> if {@link #compareToVersion compareToVersion}
    196      *          can be called with the argument, <code>false</code> otherwise
    197      */
    198     public boolean isComparable(ProtocolVersion that) {
    199         return (that != null) && this.protocol.equals(that.protocol);
    200     }
    201 
    202 
    203     /**
    204      * Compares this protocol version with another one.
    205      * Only protocol versions with the same protocol name can be compared.
    206      * This method does <i>not</i> define a total ordering, as it would be
    207      * required for {@link java.lang.Comparable}.
    208      *
    209      * @param that      the protocl version to compare with
    210      *
    211      * @return   a negative integer, zero, or a positive integer
    212      *           as this version is less than, equal to, or greater than
    213      *           the argument version.
    214      *
    215      * @throws IllegalArgumentException
    216      *         if the argument has a different protocol name than this object,
    217      *         or if the argument is <code>null</code>
    218      */
    219     public int compareToVersion(ProtocolVersion that) {
    220         if (that == null) {
    221             throw new IllegalArgumentException
    222                 ("Protocol version must not be null.");
    223         }
    224         if (!this.protocol.equals(that.protocol)) {
    225             throw new IllegalArgumentException
    226                 ("Versions for different protocols cannot be compared. " +
    227                  this + " " + that);
    228         }
    229 
    230         int delta = getMajor() - that.getMajor();
    231         if (delta == 0) {
    232             delta = getMinor() - that.getMinor();
    233         }
    234         return delta;
    235     }
    236 
    237 
    238     /**
    239      * Tests if this protocol version is greater or equal to the given one.
    240      *
    241      * @param version   the version against which to check this version
    242      *
    243      * @return  <code>true</code> if this protocol version is
    244      *          {@link #isComparable comparable} to the argument
    245      *          and {@link #compareToVersion compares} as greater or equal,
    246      *          <code>false</code> otherwise
    247      */
    248     public final boolean greaterEquals(ProtocolVersion version) {
    249         return isComparable(version) && (compareToVersion(version) >= 0);
    250     }
    251 
    252 
    253     /**
    254      * Tests if this protocol version is less or equal to the given one.
    255      *
    256      * @param version   the version against which to check this version
    257      *
    258      * @return  <code>true</code> if this protocol version is
    259      *          {@link #isComparable comparable} to the argument
    260      *          and {@link #compareToVersion compares} as less or equal,
    261      *          <code>false</code> otherwise
    262      */
    263     public final boolean lessEquals(ProtocolVersion version) {
    264         return isComparable(version) && (compareToVersion(version) <= 0);
    265     }
    266 
    267 
    268     /**
    269      * Converts this protocol version to a string.
    270      *
    271      * @return  a protocol version string, like "HTTP/1.1"
    272      */
    273     public String toString() {
    274         CharArrayBuffer buffer = new CharArrayBuffer(16);
    275         buffer.append(this.protocol);
    276         buffer.append('/');
    277         buffer.append(Integer.toString(this.major));
    278         buffer.append('.');
    279         buffer.append(Integer.toString(this.minor));
    280         return buffer.toString();
    281     }
    282 
    283     public Object clone() throws CloneNotSupportedException {
    284         return super.clone();
    285     }
    286 
    287 }
    288