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