1/* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/scheme/Scheme.java $ 3 * $Revision: 652950 $ 4 * $Date: 2008-05-02 16:49:48 -0700 (Fri, 02 May 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 */ 31package org.apache.http.conn.scheme; 32 33import java.util.Locale; 34 35import org.apache.http.util.LangUtils; 36 37/** 38 * Encapsulates specifics of a protocol scheme such as "http" or "https". 39 * Schemes are identified by lowercase names. 40 * Supported schemes are typically collected in a 41 * {@link SchemeRegistry SchemeRegistry}. 42 * 43 * <p> 44 * For example, to configure support for "https://" URLs, 45 * you could write code like the following: 46 * </p> 47 * <pre> 48 * Scheme https = new Scheme("https", new MySecureSocketFactory(), 443); 49 * SchemeRegistry.DEFAULT.register(https); 50 * </pre> 51 * 52 * @author <a href="mailto:rolandw at apache.org">Roland Weber</a> 53 * @author Michael Becke 54 * @author Jeff Dever 55 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 56 */ 57public final class Scheme { 58 59 /** The name of this scheme, in lowercase. (e.g. http, https) */ 60 private final String name; 61 62 /** The socket factory for this scheme */ 63 private final SocketFactory socketFactory; 64 65 /** The default port for this scheme */ 66 private final int defaultPort; 67 68 /** Indicates whether this scheme allows for layered connections */ 69 private final boolean layered; 70 71 72 /** A string representation, for {@link #toString toString}. */ 73 private String stringRep; 74 75 76 /** 77 * Creates a new scheme. 78 * Whether the created scheme allows for layered connections 79 * depends on the class of <code>factory</code>. 80 * 81 * @param name the scheme name, for example "http". 82 * The name will be converted to lowercase. 83 * @param factory the factory for creating sockets for communication 84 * with this scheme 85 * @param port the default port for this scheme 86 */ 87 public Scheme(final String name, 88 final SocketFactory factory, 89 final int port) { 90 91 if (name == null) { 92 throw new IllegalArgumentException 93 ("Scheme name may not be null"); 94 } 95 if (factory == null) { 96 throw new IllegalArgumentException 97 ("Socket factory may not be null"); 98 } 99 if ((port <= 0) || (port > 0xffff)) { 100 throw new IllegalArgumentException 101 ("Port is invalid: " + port); 102 } 103 104 this.name = name.toLowerCase(Locale.ENGLISH); 105 this.socketFactory = factory; 106 this.defaultPort = port; 107 this.layered = (factory instanceof LayeredSocketFactory); 108 } 109 110 111 /** 112 * Obtains the default port. 113 * 114 * @return the default port for this scheme 115 */ 116 public final int getDefaultPort() { 117 return defaultPort; 118 } 119 120 121 /** 122 * Obtains the socket factory. 123 * If this scheme is {@link #isLayered layered}, the factory implements 124 * {@link LayeredSocketFactory LayeredSocketFactory}. 125 * 126 * @return the socket factory for this scheme 127 */ 128 public final SocketFactory getSocketFactory() { 129 return socketFactory; 130 } 131 132 133 /** 134 * Obtains the scheme name. 135 * 136 * @return the name of this scheme, in lowercase 137 */ 138 public final String getName() { 139 return name; 140 } 141 142 143 /** 144 * Indicates whether this scheme allows for layered connections. 145 * 146 * @return <code>true</code> if layered connections are possible, 147 * <code>false</code> otherwise 148 */ 149 public final boolean isLayered() { 150 return layered; 151 } 152 153 154 /** 155 * Resolves the correct port for this scheme. 156 * Returns the given port if it is valid, the default port otherwise. 157 * 158 * @param port the port to be resolved, 159 * a negative number to obtain the default port 160 * 161 * @return the given port or the defaultPort 162 */ 163 public final int resolvePort(int port) { 164 return ((port <= 0) || (port > 0xffff)) ? defaultPort : port; 165 } 166 167 168 /** 169 * Return a string representation of this object. 170 * 171 * @return a human-readable string description of this scheme 172 */ 173 @Override 174 public final String toString() { 175 if (stringRep == null) { 176 StringBuilder buffer = new StringBuilder(); 177 buffer.append(this.name); 178 buffer.append(':'); 179 buffer.append(Integer.toString(this.defaultPort)); 180 stringRep = buffer.toString(); 181 } 182 return stringRep; 183 } 184 185 186 /** 187 * Compares this scheme to an object. 188 * 189 * @param obj the object to compare with 190 * 191 * @return <code>true</code> iff the argument is equal to this scheme 192 */ 193 @Override 194 public final boolean equals(Object obj) { 195 if (obj == null) return false; 196 if (this == obj) return true; 197 if (!(obj instanceof Scheme)) return false; 198 199 Scheme s = (Scheme) obj; 200 return (name.equals(s.name) && 201 defaultPort == s.defaultPort && 202 layered == s.layered && 203 socketFactory.equals(s.socketFactory) 204 ); 205 } // equals 206 207 208 /** 209 * Obtains a hash code for this scheme. 210 * 211 * @return the hash code 212 */ 213 @Override 214 public int hashCode() { 215 int hash = LangUtils.HASH_SEED; 216 hash = LangUtils.hashCode(hash, this.defaultPort); 217 hash = LangUtils.hashCode(hash, this.name); 218 hash = LangUtils.hashCode(hash, this.layered); 219 hash = LangUtils.hashCode(hash, this.socketFactory); 220 return hash; 221 } 222 223} // class Scheme 224