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