| /* |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| */ |
| |
| package org.apache.hc.core5.http; |
| |
| import java.io.Serializable; |
| import java.net.InetAddress; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.Locale; |
| import java.util.Objects; |
| |
| import org.apache.hc.core5.annotation.Contract; |
| import org.apache.hc.core5.annotation.ThreadingBehavior; |
| import org.apache.hc.core5.net.NamedEndpoint; |
| import org.apache.hc.core5.net.Ports; |
| import org.apache.hc.core5.net.URIAuthority; |
| import org.apache.hc.core5.util.Args; |
| import org.apache.hc.core5.util.TextUtils; |
| |
| /** |
| * Component that holds all details needed to describe an HTTP connection |
| * to a host. This includes remote host name, port and protocol scheme. |
| * |
| * @see org.apache.hc.core5.net.Host |
| * |
| * @since 4.0 |
| * @since 5.0 For constructors that take a scheme as an argument, that argument is now the first one. |
| */ |
| @Contract(threading = ThreadingBehavior.IMMUTABLE) |
| public final class HttpHost implements NamedEndpoint, Serializable { |
| |
| private static final long serialVersionUID = -7529410654042457626L; |
| |
| /** The default scheme is "http". */ |
| public static final URIScheme DEFAULT_SCHEME = URIScheme.HTTP; |
| |
| /** The host to use. */ |
| private final String hostname; |
| |
| /** The lowercase host, for {@link #equals} and {@link #hashCode}. */ |
| private final String lcHostname; |
| |
| /** The port to use, defaults to -1 if not set. */ |
| private final int port; |
| |
| /** The scheme (lowercased) */ |
| private final String schemeName; |
| |
| private final InetAddress address; |
| |
| /** |
| * Creates a new {@link HttpHost HttpHost}, specifying all values. |
| * Constructor for HttpHost. |
| * @param scheme the name of the scheme. |
| * {@code null} indicates the |
| * {@link #DEFAULT_SCHEME default scheme} |
| * @param address the inet address. Can be {@code null} |
| * @param hostname the hostname (IP or DNS name) |
| * @param port the port number. |
| * {@code -1} indicates the scheme default port. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 5.0 |
| */ |
| public HttpHost(final String scheme, final InetAddress address, final String hostname, final int port) { |
| this.hostname = Args.containsNoBlanks(hostname, "Host name"); |
| this.port = Ports.checkWithDefault(port); |
| this.lcHostname = hostname.toLowerCase(Locale.ROOT); |
| if (scheme != null) { |
| this.schemeName = scheme.toLowerCase(Locale.ROOT); |
| } else { |
| this.schemeName = DEFAULT_SCHEME.id; |
| } |
| this.address = address; |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the given scheme, hostname and port. |
| * @param scheme the name of the scheme. |
| * {@code null} indicates the |
| * {@link #DEFAULT_SCHEME default scheme} |
| * @param hostname the hostname (IP or DNS name) |
| * @param port the port number. |
| * {@code -1} indicates the scheme default port. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| */ |
| public HttpHost(final String scheme, final String hostname, final int port) { |
| this(scheme, null, hostname, port); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the default scheme and the given hostname and port. |
| * |
| * @param hostname the hostname (IP or DNS name) |
| * @param port the port number. |
| * {@code -1} indicates the scheme default port. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| */ |
| public HttpHost(final String hostname, final int port) { |
| this(null, hostname, port); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the given hostname and scheme and the default port for that scheme. |
| * @param scheme the name of the scheme. |
| * {@code null} indicates the |
| * {@link #DEFAULT_SCHEME default scheme} |
| * @param hostname the hostname (IP or DNS name) |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| */ |
| public HttpHost(final String scheme, final String hostname) { |
| this(scheme, hostname, -1); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance from a string. Text may not contain any blanks. |
| * |
| * @since 4.4 |
| */ |
| public static HttpHost create(final String s) throws URISyntaxException { |
| Args.notEmpty(s, "HTTP Host"); |
| String text = s; |
| String scheme = null; |
| final int schemeIdx = text.indexOf("://"); |
| if (schemeIdx > 0) { |
| scheme = text.substring(0, schemeIdx); |
| if (TextUtils.containsBlanks(scheme)) { |
| throw new URISyntaxException(s, "scheme contains blanks"); |
| } |
| text = text.substring(schemeIdx + 3); |
| } |
| int port = -1; |
| final int portIdx = text.lastIndexOf(":"); |
| if (portIdx > 0) { |
| try { |
| port = Integer.parseInt(text.substring(portIdx + 1)); |
| } catch (final NumberFormatException ex) { |
| throw new URISyntaxException(s, "invalid port"); |
| } |
| text = text.substring(0, portIdx); |
| } |
| if (TextUtils.containsBlanks(text)) { |
| throw new URISyntaxException(s, "hostname contains blanks"); |
| } |
| return new HttpHost(scheme, null, text, port); |
| } |
| |
| /** |
| * Creates an {@code HttpHost} instance from the scheme, host, and port from the given URI. Other URI elements are ignored. |
| * |
| * @param uri scheme, host, and port. |
| * @return a new HttpHost |
| * |
| * @since 5.0 |
| */ |
| public static HttpHost create(final URI uri) { |
| final String scheme = uri.getScheme(); |
| return new HttpHost(scheme != null ? scheme : URIScheme.HTTP.getId(), uri.getHost(), uri.getPort()); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the default scheme and port and the given hostname. |
| * |
| * @param hostname the hostname (IP or DNS name) |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| */ |
| public HttpHost(final String hostname) { |
| this(null, hostname, -1); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the given scheme, inet address and port. |
| * @param scheme the name of the scheme. |
| * {@code null} indicates the |
| * {@link #DEFAULT_SCHEME default scheme} |
| * @param address the inet address. |
| * @param port the port number. |
| * {@code -1} indicates the scheme default port. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 5.0 |
| */ |
| public HttpHost(final String scheme, final InetAddress address, final int port) { |
| this(scheme, Args.notNull(address,"Inet address"), address.getHostName(), port); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the default scheme and the given inet address |
| * and port. |
| * |
| * @param address the inet address. |
| * @param port the port number. |
| * {@code -1} indicates the scheme default port. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 4.3 |
| */ |
| public HttpHost(final InetAddress address, final int port) { |
| this(null, address, port); |
| } |
| |
| /** |
| * Creates {@code HttpHost} instance with the default scheme and port and the given inet |
| * address. |
| * |
| * @param address the inet address. |
| * |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 4.3 |
| */ |
| public HttpHost(final InetAddress address) { |
| this(null, address, -1); |
| } |
| |
| /** |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 5.0 |
| */ |
| public HttpHost(final String scheme, final NamedEndpoint namedEndpoint) { |
| this(scheme, Args.notNull(namedEndpoint, "Named endpoint").getHostName(), namedEndpoint.getPort()); |
| } |
| |
| /** |
| * @throws IllegalArgumentException |
| * If the port parameter is outside the specified range of valid port values, which is between 0 and |
| * 65535, inclusive. {@code -1} indicates the scheme default port. |
| * |
| * @since 5.0 |
| */ |
| public HttpHost(final URIAuthority authority) { |
| this(null, authority); |
| } |
| |
| /** |
| * Returns the host name. |
| * |
| * @return the host name (IP or DNS name) |
| */ |
| @Override |
| public String getHostName() { |
| return this.hostname; |
| } |
| |
| /** |
| * Returns the port. |
| * |
| * @return the host port, or {@code -1} if not set |
| */ |
| @Override |
| public int getPort() { |
| return this.port; |
| } |
| |
| /** |
| * Returns the scheme name. |
| * |
| * @return the scheme name |
| */ |
| public String getSchemeName() { |
| return this.schemeName; |
| } |
| |
| /** |
| * Returns the inet address if explicitly set by a constructor, |
| * {@code null} otherwise. |
| * @return the inet address |
| * |
| * @since 4.3 |
| */ |
| public InetAddress getAddress() { |
| return this.address; |
| } |
| |
| /** |
| * Return the host URI, as a string. |
| * |
| * @return the host URI |
| */ |
| public String toURI() { |
| final StringBuilder buffer = new StringBuilder(); |
| buffer.append(this.schemeName); |
| buffer.append("://"); |
| buffer.append(this.hostname); |
| if (this.port != -1) { |
| buffer.append(':'); |
| buffer.append(Integer.toString(this.port)); |
| } |
| return buffer.toString(); |
| } |
| |
| |
| /** |
| * Obtains the host string, without scheme prefix. |
| * |
| * @return the host string, for example {@code localhost:8080} |
| */ |
| public String toHostString() { |
| if (this.port != -1) { |
| //the highest port number is 65535, which is length 6 with the addition of the colon |
| final StringBuilder buffer = new StringBuilder(this.hostname.length() + 6); |
| buffer.append(this.hostname); |
| buffer.append(":"); |
| buffer.append(Integer.toString(this.port)); |
| return buffer.toString(); |
| } |
| return this.hostname; |
| } |
| |
| |
| @Override |
| public String toString() { |
| return toURI(); |
| } |
| |
| |
| @Override |
| public boolean equals(final Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof HttpHost) { |
| final HttpHost that = (HttpHost) obj; |
| return this.lcHostname.equals(that.lcHostname) |
| && this.port == that.port |
| && this.schemeName.equals(that.schemeName) |
| && Objects.equals(this.address, that.address); |
| } |
| return false; |
| } |
| |
| /** |
| * @see java.lang.Object#hashCode() |
| */ |
| @Override |
| public int hashCode() { |
| return Objects.hash(lcHostname, port, schemeName, address); |
| } |
| |
| } |