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 28 package org.apache.hc.core5.http; 29 30 import java.io.Serializable; 31 import java.net.InetAddress; 32 import java.net.URI; 33 import java.net.URISyntaxException; 34 import java.util.Locale; 35 36 import org.apache.hc.core5.annotation.Contract; 37 import org.apache.hc.core5.annotation.ThreadingBehavior; 38 import org.apache.hc.core5.net.Host; 39 import org.apache.hc.core5.net.NamedEndpoint; 40 import org.apache.hc.core5.net.URIAuthority; 41 import org.apache.hc.core5.util.Args; 42 import org.apache.hc.core5.util.LangUtils; 43 import org.apache.hc.core5.util.TextUtils; 44 45 /** 46 * Component that holds all details needed to describe an HTTP connection 47 * to a host. This includes remote host name, port and protocol scheme. 48 * 49 * @see org.apache.hc.core5.net.Host 50 * 51 * @since 4.0 52 * @since 5.0 For constructors that take a scheme as an argument, that argument is now the first one. 53 */ 54 @Contract(threading = ThreadingBehavior.IMMUTABLE) 55 public final class HttpHost implements NamedEndpoint, Serializable { 56 57 private static final long serialVersionUID = -7529410654042457626L; 58 59 /** The default scheme is "http". */ 60 public static final URIScheme DEFAULT_SCHEME = URIScheme.HTTP; 61 62 private final String schemeName; 63 private final Host host; 64 private final InetAddress address; 65 66 /** 67 * Creates a new {@link HttpHost HttpHost}, specifying all values. 68 * Constructor for HttpHost. 69 * @param scheme the name of the scheme. 70 * {@code null} indicates the 71 * {@link #DEFAULT_SCHEME default scheme} 72 * @param address the inet address. Can be {@code null} 73 * @param hostname the hostname (IP or DNS name) 74 * @param port the port number. 75 * {@code -1} indicates the scheme default port. 76 * 77 * @throws IllegalArgumentException 78 * If the port parameter is outside the specified range of valid port values, which is between 0 and 79 * 65535, inclusive. {@code -1} indicates the scheme default port. 80 * 81 * @since 5.0 82 */ 83 public HttpHost(final String scheme, final InetAddress address, final String hostname, final int port) { 84 Args.containsNoBlanks(hostname, "Host name"); 85 this.host = new Host(hostname, port); 86 this.schemeName = scheme != null ? scheme.toLowerCase(Locale.ROOT) : DEFAULT_SCHEME.id; 87 this.address = address; 88 } 89 90 /** 91 * Creates {@code HttpHost} instance with the given scheme, hostname and port. 92 * @param scheme the name of the scheme. 93 * {@code null} indicates the 94 * {@link #DEFAULT_SCHEME default scheme} 95 * @param hostname the hostname (IP or DNS name) 96 * @param port the port number. 97 * {@code -1} indicates the scheme default port. 98 * 99 * @throws IllegalArgumentException 100 * If the port parameter is outside the specified range of valid port values, which is between 0 and 101 * 65535, inclusive. {@code -1} indicates the scheme default port. 102 */ 103 public HttpHost(final String scheme, final String hostname, final int port) { 104 this(scheme, null, hostname, port); 105 } 106 107 /** 108 * Creates {@code HttpHost} instance with the default scheme and the given hostname and port. 109 * 110 * @param hostname the hostname (IP or DNS name) 111 * @param port the port number. 112 * {@code -1} indicates the scheme default port. 113 * 114 * @throws IllegalArgumentException 115 * If the port parameter is outside the specified range of valid port values, which is between 0 and 116 * 65535, inclusive. {@code -1} indicates the scheme default port. 117 */ 118 public HttpHost(final String hostname, final int port) { 119 this(null, hostname, port); 120 } 121 122 /** 123 * Creates {@code HttpHost} instance with the given hostname and scheme and the default port for that scheme. 124 * @param scheme the name of the scheme. 125 * {@code null} indicates the 126 * {@link #DEFAULT_SCHEME default scheme} 127 * @param hostname the hostname (IP or DNS name) 128 * 129 * @throws IllegalArgumentException 130 * If the port parameter is outside the specified range of valid port values, which is between 0 and 131 * 65535, inclusive. {@code -1} indicates the scheme default port. 132 */ 133 public HttpHost(final String scheme, final String hostname) { 134 this(scheme, hostname, -1); 135 } 136 137 /** 138 * Creates {@code HttpHost} instance from a string. Text may not contain any blanks. 139 * 140 * @since 4.4 141 */ 142 public static HttpHost create(final String s) throws URISyntaxException { 143 Args.notEmpty(s, "HTTP Host"); 144 String text = s; 145 String scheme = null; 146 final int schemeIdx = text.indexOf("://"); 147 if (schemeIdx > 0) { 148 scheme = text.substring(0, schemeIdx); 149 if (TextUtils.containsBlanks(scheme)) { 150 throw new URISyntaxException(s, "scheme contains blanks"); 151 } 152 text = text.substring(schemeIdx + 3); 153 } 154 final Host host = Host.create(text); 155 return new HttpHost(scheme, host); 156 } 157 158 /** 159 * Creates an {@code HttpHost} instance from the scheme, host, and port from the given URI. Other URI elements are ignored. 160 * 161 * @param uri scheme, host, and port. 162 * @return a new HttpHost 163 * 164 * @since 5.0 165 */ 166 public static HttpHost create(final URI uri) { 167 final String scheme = uri.getScheme(); 168 return new HttpHost(scheme != null ? scheme : URIScheme.HTTP.getId(), uri.getHost(), uri.getPort()); 169 } 170 171 /** 172 * Creates {@code HttpHost} instance with the default scheme and port and the given hostname. 173 * 174 * @param hostname the hostname (IP or DNS name) 175 * 176 * @throws IllegalArgumentException 177 * If the port parameter is outside the specified range of valid port values, which is between 0 and 178 * 65535, inclusive. {@code -1} indicates the scheme default port. 179 */ 180 public HttpHost(final String hostname) { 181 this(null, hostname, -1); 182 } 183 184 /** 185 * Creates {@code HttpHost} instance with the given scheme, inet address and port. 186 * @param scheme the name of the scheme. 187 * {@code null} indicates the 188 * {@link #DEFAULT_SCHEME default scheme} 189 * @param address the inet address. 190 * @param port the port number. 191 * {@code -1} indicates the scheme default port. 192 * 193 * @throws IllegalArgumentException 194 * If the port parameter is outside the specified range of valid port values, which is between 0 and 195 * 65535, inclusive. {@code -1} indicates the scheme default port. 196 * 197 * @since 5.0 198 */ 199 public HttpHost(final String scheme, final InetAddress address, final int port) { 200 this(scheme, Args.notNull(address,"Inet address"), address.getHostName(), port); 201 } 202 203 /** 204 * Creates {@code HttpHost} instance with the default scheme and the given inet address 205 * and port. 206 * 207 * @param address the inet address. 208 * @param port the port number. 209 * {@code -1} indicates the scheme default port. 210 * 211 * @throws IllegalArgumentException 212 * If the port parameter is outside the specified range of valid port values, which is between 0 and 213 * 65535, inclusive. {@code -1} indicates the scheme default port. 214 * 215 * @since 4.3 216 */ 217 public HttpHost(final InetAddress address, final int port) { 218 this(null, address, port); 219 } 220 221 /** 222 * Creates {@code HttpHost} instance with the default scheme and port and the given inet 223 * address. 224 * 225 * @param address the inet address. 226 * 227 * @throws IllegalArgumentException 228 * If the port parameter is outside the specified range of valid port values, which is between 0 and 229 * 65535, inclusive. {@code -1} indicates the scheme default port. 230 * 231 * @since 4.3 232 */ 233 public HttpHost(final InetAddress address) { 234 this(null, address, -1); 235 } 236 237 /** 238 * @throws IllegalArgumentException 239 * If the port parameter is outside the specified range of valid port values, which is between 0 and 240 * 65535, inclusive. {@code -1} indicates the scheme default port. 241 * 242 * @since 5.0 243 */ 244 public HttpHost(final String scheme, final NamedEndpoint namedEndpoint) { 245 this(scheme, Args.notNull(namedEndpoint, "Named endpoint").getHostName(), namedEndpoint.getPort()); 246 } 247 248 /** 249 * @throws IllegalArgumentException 250 * If the port parameter is outside the specified range of valid port values, which is between 0 and 251 * 65535, inclusive. {@code -1} indicates the scheme default port. 252 * 253 * @since 5.0 254 */ 255 public HttpHost(final URIAuthority authority) { 256 this(null, authority); 257 } 258 259 /** 260 * Returns the host name. 261 * 262 * @return the host name (IP or DNS name) 263 */ 264 @Override 265 public String getHostName() { 266 return this.host.getHostName(); 267 } 268 269 /** 270 * Returns the port. 271 * 272 * @return the host port, or {@code -1} if not set 273 */ 274 @Override 275 public int getPort() { 276 return this.host.getPort(); 277 } 278 279 /** 280 * Returns the scheme name. 281 * 282 * @return the scheme name 283 */ 284 public String getSchemeName() { 285 return this.schemeName; 286 } 287 288 /** 289 * Returns the inet address if explicitly set by a constructor, 290 * {@code null} otherwise. 291 * @return the inet address 292 * 293 * @since 4.3 294 */ 295 public InetAddress getAddress() { 296 return this.address; 297 } 298 299 /** 300 * Return the host URI, as a string. 301 * 302 * @return the host URI 303 */ 304 public String toURI() { 305 final StringBuilder buffer = new StringBuilder(); 306 buffer.append(this.schemeName); 307 buffer.append("://"); 308 buffer.append(this.host.toString()); 309 return buffer.toString(); 310 } 311 312 313 /** 314 * Obtains the host string, without scheme prefix. 315 * 316 * @return the host string, for example {@code localhost:8080} 317 */ 318 public String toHostString() { 319 return this.host.toString(); 320 } 321 322 323 @Override 324 public String toString() { 325 return toURI(); 326 } 327 328 329 @Override 330 public boolean equals(final Object obj) { 331 if (this == obj) { 332 return true; 333 } 334 if (obj instanceof HttpHost) { 335 final HttpHost../../../../../org/apache/hc/core5/http/HttpHost.html#HttpHost">HttpHost that = (HttpHost) obj; 336 return this.schemeName.equals(that.schemeName) && 337 this.host.equals(that.host) && 338 LangUtils.equals(this.address, that.address); 339 } 340 return false; 341 } 342 343 /** 344 * @see java.lang.Object#hashCode() 345 */ 346 @Override 347 public int hashCode() { 348 int hash = LangUtils.HASH_SEED; 349 hash = LangUtils.hashCode(hash, this.schemeName); 350 hash = LangUtils.hashCode(hash, this.host); 351 hash = LangUtils.hashCode(hash, this.address); 352 return hash; 353 } 354 355 }