1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 package org.apache.http.conn.scheme; 28 29 import java.util.Locale; 30 31 import org.apache.http.annotation.Contract; 32 import org.apache.http.annotation.ThreadingBehavior; 33 import org.apache.http.util.Args; 34 import org.apache.http.util.LangUtils; 35 36 /** 37 * Encapsulates specifics of a protocol scheme such as "http" or "https". Schemes are identified 38 * by lowercase names. Supported schemes are typically collected in a {@link SchemeRegistry 39 * SchemeRegistry}. 40 * <p> 41 * For example, to configure support for "https://" URLs, you could write code like the following: 42 * </p> 43 * <pre> 44 * Scheme https = new Scheme("https", 443, new MySecureSocketFactory()); 45 * SchemeRegistry registry = new SchemeRegistry(); 46 * registry.register(https); 47 * </pre> 48 * 49 * @since 4.0 50 * 51 * @deprecated (4.3) use {@link org.apache.http.conn.SchemePortResolver} for default port 52 * resolution and {@link org.apache.http.config.Registry} for socket factory lookups. 53 */ 54 @Contract(threading = ThreadingBehavior.IMMUTABLE) 55 @Deprecated 56 public final class Scheme { 57 58 /** The name of this scheme, in lowercase. (e.g. http, https) */ 59 private final String name; 60 61 /** The socket factory for this scheme */ 62 private final SchemeSocketFactory socketFactory; 63 64 /** The default port for this scheme */ 65 private final int defaultPort; 66 67 /** Indicates whether this scheme allows for layered connections */ 68 private final boolean layered; 69 70 /** A string representation, for {@link #toString toString}. */ 71 private String stringRep; 72 /* 73 * This is used to cache the result of the toString() method 74 * Since the method always generates the same value, there's no 75 * need to synchronize, and it does not affect immutability. 76 */ 77 78 /** 79 * Creates a new scheme. 80 * Whether the created scheme allows for layered connections 81 * depends on the class of {@code factory}. 82 * 83 * @param name the scheme name, for example "http". 84 * The name will be converted to lowercase. 85 * @param port the default port for this scheme 86 * @param factory the factory for creating sockets for communication 87 * with this scheme 88 * 89 * @since 4.1 90 */ 91 public Scheme(final String name, final int port, final SchemeSocketFactory factory) { 92 Args.notNull(name, "Scheme name"); 93 Args.check(port > 0 && port <= 0xffff, "Port is invalid"); 94 Args.notNull(factory, "Socket factory"); 95 this.name = name.toLowerCase(Locale.ENGLISH); 96 this.defaultPort = port; 97 if (factory instanceof SchemeLayeredSocketFactory) { 98 this.layered = true; 99 this.socketFactory = factory; 100 } else if (factory instanceof LayeredSchemeSocketFactory) { 101 this.layered = true; 102 this.socketFactory = new SchemeLayeredSocketFactoryAdaptor2((LayeredSchemeSocketFactory) factory); 103 } else { 104 this.layered = false; 105 this.socketFactory = factory; 106 } 107 } 108 109 /** 110 * Creates a new scheme. 111 * Whether the created scheme allows for layered connections 112 * depends on the class of {@code factory}. 113 * 114 * @param name the scheme name, for example "http". 115 * The name will be converted to lowercase. 116 * @param factory the factory for creating sockets for communication 117 * with this scheme 118 * @param port the default port for this scheme 119 * 120 * @deprecated (4.1) Use {@link #Scheme(String, int, SchemeSocketFactory)} 121 */ 122 @Deprecated 123 public Scheme(final String name, 124 final SocketFactory factory, 125 final int port) { 126 127 Args.notNull(name, "Scheme name"); 128 Args.notNull(factory, "Socket factory"); 129 Args.check(port > 0 && port <= 0xffff, "Port is invalid"); 130 131 this.name = name.toLowerCase(Locale.ENGLISH); 132 if (factory instanceof LayeredSocketFactory) { 133 this.socketFactory = new SchemeLayeredSocketFactoryAdaptor( 134 (LayeredSocketFactory) factory); 135 this.layered = true; 136 } else { 137 this.socketFactory = new SchemeSocketFactoryAdaptor(factory); 138 this.layered = false; 139 } 140 this.defaultPort = port; 141 } 142 143 /** 144 * Obtains the default port. 145 * 146 * @return the default port for this scheme 147 */ 148 public int getDefaultPort() { 149 return defaultPort; 150 } 151 152 153 /** 154 * Obtains the socket factory. 155 * If this scheme is {@link #isLayered layered}, the factory implements 156 * {@link LayeredSocketFactory LayeredSocketFactory}. 157 * 158 * @return the socket factory for this scheme 159 * 160 * @deprecated (4.1) Use {@link #getSchemeSocketFactory()} 161 */ 162 @Deprecated 163 public SocketFactory getSocketFactory() { 164 if (this.socketFactory instanceof SchemeSocketFactoryAdaptor) { 165 return ((SchemeSocketFactoryAdaptor) this.socketFactory).getFactory(); 166 } 167 return this.layered 168 ? new LayeredSocketFactoryAdaptor( 169 (LayeredSchemeSocketFactory) this.socketFactory) 170 : new SocketFactoryAdaptor(this.socketFactory); 171 } 172 173 /** 174 * Obtains the socket factory. 175 * If this scheme is {@link #isLayered layered}, the factory implements 176 * {@link LayeredSocketFactory LayeredSchemeSocketFactory}. 177 * 178 * @return the socket factory for this scheme 179 * 180 * @since 4.1 181 */ 182 public SchemeSocketFactory getSchemeSocketFactory() { 183 return this.socketFactory; 184 } 185 186 /** 187 * Obtains the scheme name. 188 * 189 * @return the name of this scheme, in lowercase 190 */ 191 public String getName() { 192 return name; 193 } 194 195 /** 196 * Indicates whether this scheme allows for layered connections. 197 * 198 * @return {@code true} if layered connections are possible, 199 * {@code false} otherwise 200 */ 201 public boolean isLayered() { 202 return layered; 203 } 204 205 /** 206 * Resolves the correct port for this scheme. 207 * Returns the given port if it is valid, the default port otherwise. 208 * 209 * @param port the port to be resolved, 210 * a negative number to obtain the default port 211 * 212 * @return the given port or the defaultPort 213 */ 214 public int resolvePort(final int port) { 215 return port <= 0 ? defaultPort : port; 216 } 217 218 /** 219 * Return a string representation of this object. 220 * 221 * @return a human-readable string description of this scheme 222 */ 223 @Override 224 public String toString() { 225 if (stringRep == null) { 226 final StringBuilder buffer = new StringBuilder(); 227 buffer.append(this.name); 228 buffer.append(':'); 229 buffer.append(Integer.toString(this.defaultPort)); 230 stringRep = buffer.toString(); 231 } 232 return stringRep; 233 } 234 235 @Override 236 public boolean equals(final Object obj) { 237 if (this == obj) { 238 return true; 239 } 240 if (obj instanceof Scheme) { 241 final Scheme="../../../../../org/apache/http/conn/scheme/Scheme.html#Scheme">Scheme that = (Scheme) obj; 242 return this.name.equals(that.name) 243 && this.defaultPort == that.defaultPort 244 && this.layered == that.layered; 245 } 246 return false; 247 } 248 249 @Override 250 public int hashCode() { 251 int hash = LangUtils.HASH_SEED; 252 hash = LangUtils.hashCode(hash, this.defaultPort); 253 hash = LangUtils.hashCode(hash, this.name); 254 hash = LangUtils.hashCode(hash, this.layered); 255 return hash; 256 } 257 258 }