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 package org.apache.http.client.utils;
28
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.nio.charset.Charset;
32 import java.util.ArrayList;
33 import java.util.Iterator;
34 import java.util.List;
35
36 import org.apache.http.Consts;
37 import org.apache.http.NameValuePair;
38 import org.apache.http.annotation.NotThreadSafe;
39 import org.apache.http.conn.util.InetAddressUtils;
40 import org.apache.http.message.BasicNameValuePair;
41
42
43
44
45
46
47 @NotThreadSafe
48 public class URIBuilder {
49
50 private String scheme;
51 private String encodedSchemeSpecificPart;
52 private String encodedAuthority;
53 private String userInfo;
54 private String encodedUserInfo;
55 private String host;
56 private int port;
57 private String path;
58 private String encodedPath;
59 private String encodedQuery;
60 private List<NameValuePair> queryParams;
61 private String query;
62 private String fragment;
63 private String encodedFragment;
64
65
66
67
68 public URIBuilder() {
69 super();
70 this.port = -1;
71 }
72
73
74
75
76
77
78
79 public URIBuilder(final String string) throws URISyntaxException {
80 super();
81 digestURI(new URI(string));
82 }
83
84
85
86
87
88 public URIBuilder(final URI uri) {
89 super();
90 digestURI(uri);
91 }
92
93 private List <NameValuePair> parseQuery(final String query, final Charset charset) {
94 if (query != null && query.length() > 0) {
95 return URLEncodedUtils.parse(query, charset);
96 }
97 return null;
98 }
99
100
101
102
103 public URI build() throws URISyntaxException {
104 return new URI(buildString());
105 }
106
107 private String buildString() {
108 final StringBuilder sb = new StringBuilder();
109 if (this.scheme != null) {
110 sb.append(this.scheme).append(':');
111 }
112 if (this.encodedSchemeSpecificPart != null) {
113 sb.append(this.encodedSchemeSpecificPart);
114 } else {
115 if (this.encodedAuthority != null) {
116 sb.append("//").append(this.encodedAuthority);
117 } else if (this.host != null) {
118 sb.append("//");
119 if (this.encodedUserInfo != null) {
120 sb.append(this.encodedUserInfo).append("@");
121 } else if (this.userInfo != null) {
122 sb.append(encodeUserInfo(this.userInfo)).append("@");
123 }
124 if (InetAddressUtils.isIPv6Address(this.host)) {
125 sb.append("[").append(this.host).append("]");
126 } else {
127 sb.append(this.host);
128 }
129 if (this.port >= 0) {
130 sb.append(":").append(this.port);
131 }
132 }
133 if (this.encodedPath != null) {
134 sb.append(normalizePath(this.encodedPath));
135 } else if (this.path != null) {
136 sb.append(encodePath(normalizePath(this.path)));
137 }
138 if (this.encodedQuery != null) {
139 sb.append("?").append(this.encodedQuery);
140 } else if (this.queryParams != null) {
141 sb.append("?").append(encodeUrlForm(this.queryParams));
142 } else if (this.query != null) {
143 sb.append("?").append(encodeUric(this.query));
144 }
145 }
146 if (this.encodedFragment != null) {
147 sb.append("#").append(this.encodedFragment);
148 } else if (this.fragment != null) {
149 sb.append("#").append(encodeUric(this.fragment));
150 }
151 return sb.toString();
152 }
153
154 private void digestURI(final URI uri) {
155 this.scheme = uri.getScheme();
156 this.encodedSchemeSpecificPart = uri.getRawSchemeSpecificPart();
157 this.encodedAuthority = uri.getRawAuthority();
158 this.host = uri.getHost();
159 this.port = uri.getPort();
160 this.encodedUserInfo = uri.getRawUserInfo();
161 this.userInfo = uri.getUserInfo();
162 this.encodedPath = uri.getRawPath();
163 this.path = uri.getPath();
164 this.encodedQuery = uri.getRawQuery();
165 this.queryParams = parseQuery(uri.getRawQuery(), Consts.UTF_8);
166 this.encodedFragment = uri.getRawFragment();
167 this.fragment = uri.getFragment();
168 }
169
170 private String encodeUserInfo(final String userInfo) {
171 return URLEncodedUtils.encUserInfo(userInfo, Consts.UTF_8);
172 }
173
174 private String encodePath(final String path) {
175 return URLEncodedUtils.encPath(path, Consts.UTF_8);
176 }
177
178 private String encodeUrlForm(final List<NameValuePair> params) {
179 return URLEncodedUtils.format(params, Consts.UTF_8);
180 }
181
182 private String encodeUric(final String fragment) {
183 return URLEncodedUtils.encUric(fragment, Consts.UTF_8);
184 }
185
186
187
188
189 public URIBuilder setScheme(final String scheme) {
190 this.scheme = scheme;
191 return this;
192 }
193
194
195
196
197
198 public URIBuilder setUserInfo(final String userInfo) {
199 this.userInfo = userInfo;
200 this.encodedSchemeSpecificPart = null;
201 this.encodedAuthority = null;
202 this.encodedUserInfo = null;
203 return this;
204 }
205
206
207
208
209
210 public URIBuilder setUserInfo(final String username, final String password) {
211 return setUserInfo(username + ':' + password);
212 }
213
214
215
216
217 public URIBuilder setHost(final String host) {
218 this.host = host;
219 this.encodedSchemeSpecificPart = null;
220 this.encodedAuthority = null;
221 return this;
222 }
223
224
225
226
227 public URIBuilder setPort(final int port) {
228 this.port = port < 0 ? -1 : port;
229 this.encodedSchemeSpecificPart = null;
230 this.encodedAuthority = null;
231 return this;
232 }
233
234
235
236
237 public URIBuilder setPath(final String path) {
238 this.path = path;
239 this.encodedSchemeSpecificPart = null;
240 this.encodedPath = null;
241 return this;
242 }
243
244
245
246
247 public URIBuilder removeQuery() {
248 this.queryParams = null;
249 this.query = null;
250 this.encodedQuery = null;
251 this.encodedSchemeSpecificPart = null;
252 return this;
253 }
254
255
256
257
258
259
260
261
262
263
264 @Deprecated
265 public URIBuilder setQuery(final String query) {
266 this.queryParams = parseQuery(query, Consts.UTF_8);
267 this.query = null;
268 this.encodedQuery = null;
269 this.encodedSchemeSpecificPart = null;
270 return this;
271 }
272
273
274
275
276
277
278
279
280
281
282 public URIBuilder setParameters(final List <NameValuePair> nvps) {
283 if (this.queryParams == null) {
284 this.queryParams = new ArrayList<NameValuePair>();
285 } else {
286 this.queryParams.clear();
287 }
288 this.queryParams.addAll(nvps);
289 this.encodedQuery = null;
290 this.encodedSchemeSpecificPart = null;
291 this.query = null;
292 return this;
293 }
294
295
296
297
298
299
300
301
302
303
304 public URIBuilder addParameters(final List <NameValuePair> nvps) {
305 if (this.queryParams == null) {
306 this.queryParams = new ArrayList<NameValuePair>();
307 }
308 this.queryParams.addAll(nvps);
309 this.encodedQuery = null;
310 this.encodedSchemeSpecificPart = null;
311 this.query = null;
312 return this;
313 }
314
315
316
317
318
319
320
321
322
323
324 public URIBuilder setParameters(final NameValuePair... nvps) {
325 if (this.queryParams == null) {
326 this.queryParams = new ArrayList<NameValuePair>();
327 } else {
328 this.queryParams.clear();
329 }
330 for (final NameValuePair nvp: nvps) {
331 this.queryParams.add(nvp);
332 }
333 this.encodedQuery = null;
334 this.encodedSchemeSpecificPart = null;
335 this.query = null;
336 return this;
337 }
338
339
340
341
342
343
344
345
346 public URIBuilder addParameter(final String param, final String value) {
347 if (this.queryParams == null) {
348 this.queryParams = new ArrayList<NameValuePair>();
349 }
350 this.queryParams.add(new BasicNameValuePair(param, value));
351 this.encodedQuery = null;
352 this.encodedSchemeSpecificPart = null;
353 this.query = null;
354 return this;
355 }
356
357
358
359
360
361
362
363
364 public URIBuilder setParameter(final String param, final String value) {
365 if (this.queryParams == null) {
366 this.queryParams = new ArrayList<NameValuePair>();
367 }
368 if (!this.queryParams.isEmpty()) {
369 for (final Iterator<NameValuePair> it = this.queryParams.iterator(); it.hasNext(); ) {
370 final NameValuePair nvp = it.next();
371 if (nvp.getName().equals(param)) {
372 it.remove();
373 }
374 }
375 }
376 this.queryParams.add(new BasicNameValuePair(param, value));
377 this.encodedQuery = null;
378 this.encodedSchemeSpecificPart = null;
379 this.query = null;
380 return this;
381 }
382
383
384
385
386
387
388 public URIBuilder clearParameters() {
389 this.queryParams = null;
390 this.encodedQuery = null;
391 this.encodedSchemeSpecificPart = null;
392 return this;
393 }
394
395
396
397
398
399
400
401
402
403
404 public URIBuilder setCustomQuery(final String query) {
405 this.query = query;
406 this.encodedQuery = null;
407 this.encodedSchemeSpecificPart = null;
408 this.queryParams = null;
409 return this;
410 }
411
412
413
414
415
416 public URIBuilder setFragment(final String fragment) {
417 this.fragment = fragment;
418 this.encodedFragment = null;
419 return this;
420 }
421
422 public String getScheme() {
423 return this.scheme;
424 }
425
426 public String getUserInfo() {
427 return this.userInfo;
428 }
429
430 public String getHost() {
431 return this.host;
432 }
433
434 public int getPort() {
435 return this.port;
436 }
437
438 public String getPath() {
439 return this.path;
440 }
441
442 public List<NameValuePair> getQueryParams() {
443 if (this.queryParams != null) {
444 return new ArrayList<NameValuePair>(this.queryParams);
445 } else {
446 return new ArrayList<NameValuePair>();
447 }
448 }
449
450 public String getFragment() {
451 return this.fragment;
452 }
453
454 @Override
455 public String toString() {
456 return buildString();
457 }
458
459 private static String normalizePath(String path) {
460 if (path == null) {
461 return null;
462 }
463 int n = 0;
464 for (; n < path.length(); n++) {
465 if (path.charAt(n) != '/') {
466 break;
467 }
468 }
469 if (n > 1) {
470 path = path.substring(n - 1);
471 }
472 return path;
473 }
474
475 }