1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.BitSet;
33 import java.util.Locale;
34
35 import org.apache.hc.core5.annotation.Contract;
36 import org.apache.hc.core5.annotation.ThreadingBehavior;
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
43
44
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 String hostname;
52 private final int port;
53
54 private static final BitSet HOST_SEPARATORS = new BitSet(256);
55 private static final BitSet PORT_SEPARATORS = new BitSet(256);
56 private static final BitSet TERMINATORS = new BitSet(256);
57
58 static {
59 TERMINATORS.set('/');
60 TERMINATORS.set('#');
61 TERMINATORS.set('?');
62 HOST_SEPARATORS.or(TERMINATORS);
63 HOST_SEPARATORS.set('@');
64 PORT_SEPARATORS.or(TERMINATORS);
65 PORT_SEPARATORS.set(':');
66 }
67
68 static URISyntaxException createException(
69 final CharSequence input, final Tokenizer.Cursor cursor, final String reason) {
70 return new URISyntaxException(
71 input.subSequence(cursor.getLowerBound(), cursor.getUpperBound()).toString(),
72 reason,
73 cursor.getPos());
74 }
75
76 static URIAuthority parse(final CharSequence s, final Tokenizer.Cursor cursor) throws URISyntaxException {
77 final Tokenizer tokenizer = Tokenizer.INSTANCE;
78 String userInfo = null;
79 final int initPos = cursor.getPos();
80 final String token = tokenizer.parseContent(s, cursor, HOST_SEPARATORS);
81 if (!cursor.atEnd() && s.charAt(cursor.getPos()) == '@') {
82 cursor.updatePos(cursor.getPos() + 1);
83 if (!TextUtils.isBlank(token)) {
84 userInfo = token;
85 }
86 } else {
87
88 cursor.updatePos(initPos);
89 }
90 final String hostName = tokenizer.parseContent(s, cursor, PORT_SEPARATORS);
91 String portText = null;
92 if (!cursor.atEnd() && s.charAt(cursor.getPos()) == ':') {
93 cursor.updatePos(cursor.getPos() + 1);
94 portText = tokenizer.parseContent(s, cursor, TERMINATORS);
95 }
96 final int port;
97 if (!TextUtils.isBlank(portText)) {
98 try {
99 port = Integer.parseInt(portText);
100 } catch (final NumberFormatException ex) {
101 throw createException(s, cursor, "Authority port is invalid");
102 }
103 } else {
104 port = -1;
105 }
106 return new URIAuthority(userInfo, hostName.toLowerCase(Locale.ROOT), port, true);
107 }
108
109 static URIAuthority parse(final CharSequence s) throws URISyntaxException {
110 final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
111 return parse(s, cursor);
112 }
113
114 static void format(final StringBuilder buf, final URIAuthority uriAuthority) {
115 if (uriAuthority.userInfo != null) {
116 buf.append(uriAuthority.userInfo);
117 buf.append("@");
118 }
119 buf.append(uriAuthority.hostname);
120 if (uriAuthority.port != -1) {
121 buf.append(":");
122 buf.append(uriAuthority.port);
123 }
124 }
125
126 static String format(final URIAuthority uriAuthority) {
127 final StringBuilder buf = new StringBuilder();
128 format(buf, uriAuthority);
129 return buf.toString();
130 }
131
132
133
134
135
136
137 private URIAuthority(final String userInfo, final String hostname, final int port, final boolean internal) {
138 super();
139 this.userInfo = userInfo;
140 this.hostname = hostname;
141 this.port = Ports.checkWithDefault(port);
142 }
143
144
145
146
147
148
149 public URIAuthority(final String userInfo, final String hostname, final int port) {
150 super();
151 this.userInfo = userInfo;
152 this.hostname = hostname != null ? hostname.toLowerCase(Locale.ROOT) : null;
153 this.port = Ports.checkWithDefault(port);
154 }
155
156 public URIAuthority(final String hostname, final int port) {
157 this(null, hostname, port);
158 }
159
160 public URIAuthority(final NamedEndpoint namedEndpoint) {
161 this(null, namedEndpoint.getHostName(), namedEndpoint.getPort());
162 }
163
164
165
166
167 public static URIAuthority create(final String s) throws URISyntaxException {
168 if (TextUtils.isBlank(s)) {
169 return null;
170 }
171 final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
172 final URIAuthority uriAuthority = parse(s, cursor);
173 if (!cursor.atEnd()) {
174 throw createException(s, cursor, "Unexpected content");
175 }
176 return uriAuthority;
177 }
178
179 public URIAuthority(final String hostname) {
180 this(null, hostname, -1);
181 }
182
183 public String getUserInfo() {
184 return userInfo;
185 }
186
187 @Override
188 public String getHostName() {
189 return hostname;
190 }
191
192 @Override
193 public int getPort() {
194 return port;
195 }
196
197 @Override
198 public String toString() {
199 return format(this);
200 }
201
202 @Override
203 public boolean equals(final Object obj) {
204 if (this == obj) {
205 return true;
206 }
207 if (obj instanceof URIAuthority) {
208 final URIAuthority./../../../org/apache/hc/core5/net/URIAuthority.html#URIAuthority">URIAuthority that = (URIAuthority) obj;
209 return LangUtils.equals(this.userInfo, that.userInfo) &&
210 LangUtils.equals(this.hostname, that.hostname) &&
211 this.port == that.port;
212 }
213 return false;
214 }
215
216 @Override
217 public int hashCode() {
218 int hash = LangUtils.HASH_SEED;
219 hash = LangUtils.hashCode(hash, userInfo);
220 hash = LangUtils.hashCode(hash, hostname);
221 hash = LangUtils.hashCode(hash, port);
222 return hash;
223 }
224
225 }