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.Objects;
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  import org.apache.hc.core5.util.Tokenizer;
40  
41  /**
42   * Represents authority component of request {@link java.net.URI}.
43   *
44   * @since 5.0
45   */
46  @Contract(threading = ThreadingBehavior.IMMUTABLE)
47  public final class URIAuthority implements NamedEndpoint, Serializable {
48  
49      private static final long serialVersionUID = 1L;
50      private final String userInfo;
51      private final Host host;
52  
53      static URIAuthority parse(final CharSequence s, final Tokenizer.Cursor cursor) throws URISyntaxException {
54          final Tokenizer tokenizer = Tokenizer.INSTANCE;
55          String userInfo = null;
56          final int initPos = cursor.getPos();
57          final String token = tokenizer.parseContent(s, cursor, URISupport.HOST_SEPARATORS);
58          if (!cursor.atEnd() && s.charAt(cursor.getPos()) == '@') {
59              cursor.updatePos(cursor.getPos() + 1);
60              if (!TextUtils.isBlank(token)) {
61                  userInfo = token;
62              }
63          } else {
64              //Rewind
65              cursor.updatePos(initPos);
66          }
67          final Host host = Host.parse(s, cursor);
68          return new URIAuthority(userInfo, host);
69      }
70  
71      static URIAuthority parse(final CharSequence s) throws URISyntaxException {
72          final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
73          return parse(s, cursor);
74      }
75  
76      static void format(final StringBuilder buf, final URIAuthority uriAuthority) {
77          if (uriAuthority.getUserInfo() != null) {
78              buf.append(uriAuthority.getUserInfo());
79              buf.append("@");
80          }
81          Host.format(buf, uriAuthority);
82      }
83  
84      static String format(final URIAuthority uriAuthority) {
85          final StringBuilder buf = new StringBuilder();
86          format(buf, uriAuthority);
87          return buf.toString();
88      }
89  
90      /**
91       * Constructs a new instance.
92       *
93       * @throws IllegalArgumentException
94       *             If the port parameter is outside the specified range of valid port values, which is between 0 and
95       *             65535, inclusive. {@code -1} indicates the scheme default port.
96       */
97      public URIAuthority(final String userInfo, final String hostname, final int port) {
98          super();
99          this.userInfo = userInfo;
100         this.host = new Host(hostname, port);
101     }
102 
103     public URIAuthority(final String hostname, final int port) {
104         this(null, hostname, port);
105     }
106 
107     /**
108      * @since 5.2
109      */
110     public URIAuthority(final String userInfo, final Host host) {
111         super();
112         Args.notNull(host, "Host");
113         this.userInfo = userInfo;
114         this.host = host;
115     }
116 
117     /**
118      * @since 5.2
119      */
120     public URIAuthority(final Host host) {
121         this(null, host);
122     }
123 
124     /**
125      * @since 5.2
126      */
127     public URIAuthority(final String userInfo, final NamedEndpoint endpoint) {
128         super();
129         Args.notNull(endpoint, "Endpoint");
130         this.userInfo = userInfo;
131         this.host = new Host(endpoint.getHostName(), endpoint.getPort());
132     }
133 
134     public URIAuthority(final NamedEndpoint namedEndpoint) {
135         this(null, namedEndpoint);
136     }
137 
138     /**
139      * Creates a {@code URIAuthority} instance from a string. Text may not contain any blanks.
140      */
141     public static URIAuthority create(final String s) throws URISyntaxException {
142         if (TextUtils.isBlank(s)) {
143             return null;
144         }
145         final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
146         final URIAuthority uriAuthority = parse(s, cursor);
147         if (!cursor.atEnd()) {
148             throw URISupport.createException(s, cursor, "Unexpected content");
149         }
150         return uriAuthority;
151     }
152 
153     public URIAuthority(final String hostname) {
154         this(null, hostname, -1);
155     }
156 
157     public String getUserInfo() {
158         return userInfo;
159     }
160 
161     @Override
162     public String getHostName() {
163         return host.getHostName();
164     }
165 
166     @Override
167     public int getPort() {
168         return host.getPort();
169     }
170 
171     @Override
172     public String toString() {
173         return format(this);
174     }
175 
176     @Override
177     public boolean equals(final Object obj) {
178         if (this == obj) {
179             return true;
180         }
181         if (obj instanceof URIAuthority) {
182             final URIAuthority that = (URIAuthority) obj;
183             return Objects.equals(this.userInfo, that.userInfo) &&
184                     Objects.equals(this.host, that.host);
185         }
186         return false;
187     }
188 
189     @Override
190     public int hashCode() {
191         int hash = LangUtils.HASH_SEED;
192         hash = LangUtils.hashCode(hash, userInfo);
193         hash = LangUtils.hashCode(hash, host);
194         return hash;
195     }
196 
197 }