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.net;
29  
30  import java.io.Serializable;
31  import java.net.URISyntaxException;
32  import java.util.Locale;
33  
34  import org.apache.hc.core5.annotation.Contract;
35  import org.apache.hc.core5.annotation.ThreadingBehavior;
36  import org.apache.hc.core5.util.Args;
37  import org.apache.hc.core5.util.LangUtils;
38  import org.apache.hc.core5.util.TextUtils;
39  
40  /**
41   * Represents authority component of request URI.
42   *
43   * @since 5.0
44   */
45  @Contract(threading = ThreadingBehavior.IMMUTABLE)
46  public final class URIAuthority implements NamedEndpoint, Serializable {
47  
48      private final String userInfo;
49      private final String hostname;
50      private final int port;
51  
52      /**
53       * @throws IllegalArgumentException
54       *             If the port parameter is outside the specified range of valid port values, which is between 0 and
55       *             65535, inclusive. {@code -1} indicates the scheme default port.
56       */
57      private URIAuthority(final String userInfo, final String hostname, final int port, final boolean internal) {
58          super();
59          this.userInfo = userInfo;
60          this.hostname = hostname;
61          this.port = Ports.check(port);
62      }
63  
64      /**
65       * @throws IllegalArgumentException
66       *             If the port parameter is outside the specified range of valid port values, which is between 0 and
67       *             65535, inclusive. {@code -1} indicates the scheme default port.
68       */
69      public URIAuthority(final String userInfo, final String hostname, final int port) {
70          super();
71          Args.containsNoBlanks(hostname, "Host name");
72          if (userInfo != null) {
73              Args.containsNoBlanks(userInfo, "User info");
74          }
75          this.userInfo = userInfo;
76          this.hostname = hostname.toLowerCase(Locale.ROOT);
77          this.port = Ports.check(port);
78      }
79  
80      public URIAuthority(final String hostname, final int port) {
81          this(null, hostname, port);
82      }
83  
84      public URIAuthority(final NamedEndpoint namedEndpoint) {
85          this(null, namedEndpoint.getHostName(), namedEndpoint.getPort());
86      }
87  
88      /**
89       * Creates {@code URIHost} instance from string. Text may not contain any blanks.
90       */
91      public static URIAuthority create(final String s) throws URISyntaxException {
92          if (s == null) {
93              return null;
94          }
95          String userInfo = null;
96          String hostname = s;
97          int port = -1;
98          final int portIdx = hostname.lastIndexOf(":");
99          if (portIdx > 0) {
100             try {
101                 port = Integer.parseInt(hostname.substring(portIdx + 1));
102             } catch (final NumberFormatException ex) {
103                 throw new URISyntaxException(s, "invalid port");
104             }
105             hostname = hostname.substring(0, portIdx);
106         }
107         final int atIdx = hostname.lastIndexOf("@");
108         if (atIdx > 0) {
109             userInfo = hostname.substring(0, atIdx);
110             if (TextUtils.containsBlanks(userInfo)) {
111                 throw new URISyntaxException(s, "user info contains blanks");
112             }
113             hostname = hostname.substring(atIdx + 1);
114         }
115         if (TextUtils.containsBlanks(hostname)) {
116             throw new URISyntaxException(s, "hostname contains blanks");
117         }
118         return new URIAuthority(userInfo, hostname.toLowerCase(Locale.ROOT), port, true);
119     }
120 
121     public URIAuthority(final String hostname) {
122         this(null, hostname, -1);
123     }
124 
125     public String getUserInfo() {
126         return userInfo;
127     }
128 
129     @Override
130     public String getHostName() {
131         return hostname;
132     }
133 
134     @Override
135     public int getPort() {
136         return port;
137     }
138 
139     @Override
140     public String toString() {
141         final StringBuilder buffer = new StringBuilder();
142         if (userInfo != null) {
143             buffer.append(userInfo);
144             buffer.append("@");
145         }
146         buffer.append(hostname);
147         if (port != -1) {
148             buffer.append(":");
149             buffer.append(Integer.toString(port));
150         }
151         return buffer.toString();
152     }
153 
154     @Override
155     public boolean equals(final Object obj) {
156         if (this == obj) {
157             return true;
158         }
159         if (obj instanceof URIAuthority) {
160             final URIAuthority that = (URIAuthority) obj;
161             return LangUtils.equals(this.userInfo, that.userInfo) &&
162                     LangUtils.equals(this.hostname, that.hostname) &&
163                     this.port == that.port;
164         }
165         return false;
166     }
167 
168     @Override
169     public int hashCode() {
170         int hash = LangUtils.HASH_SEED;
171         hash = LangUtils.hashCode(hash, userInfo);
172         hash = LangUtils.hashCode(hash, hostname);
173         hash = LangUtils.hashCode(hash, port);
174         return hash;
175     }
176 
177 }