View Javadoc
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 }