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
29
30
31
32 package org.apache.commons.httpclient;
33
34 import org.apache.commons.httpclient.util.URIUtil;
35
36 /***
37 * The HTTP URL.
38 *
39 * @author <a href="mailto:jericho at apache.org">Sung-Gu</a>
40 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
41 */
42 public class HttpURL extends URI {
43
44
45
46 /*** Create an instance as an internal use. */
47 protected HttpURL() {
48 }
49
50
51 /***
52 * Construct a HTTP URL as an escaped form of a character array with the
53 * given charset to do escape encoding.
54 *
55 * @param escaped the HTTP URL character sequence
56 * @param charset the charset string to do escape encoding
57 * @throws URIException If {@link #checkValid()} fails
58 * @throws NullPointerException if <code>escaped</code> is <code>null</code>
59 * @see #getProtocolCharset
60 */
61 public HttpURL(char[] escaped, String charset)
62 throws URIException, NullPointerException {
63 protocolCharset = charset;
64 parseUriReference(new String(escaped), true);
65 checkValid();
66 }
67
68
69 /***
70 * Construct a HTTP URL as an escaped form of a character array.
71 *
72 * @param escaped the HTTP URL character sequence
73 * @throws URIException If {@link #checkValid()} fails
74 * @throws NullPointerException if <code>escaped</code> is <code>null</code>
75 * @see #getDefaultProtocolCharset
76 */
77 public HttpURL(char[] escaped) throws URIException, NullPointerException {
78 parseUriReference(new String(escaped), true);
79 checkValid();
80 }
81
82
83 /***
84 * Construct a HTTP URL from a given string with the given charset to do
85 * escape encoding.
86 *
87 * @param original the HTTP URL string
88 * @param charset the charset string to do escape encoding
89 * @throws URIException If {@link #checkValid()} fails
90 * @see #getProtocolCharset
91 */
92 public HttpURL(String original, String charset) throws URIException {
93 protocolCharset = charset;
94 parseUriReference(original, false);
95 checkValid();
96 }
97
98
99 /***
100 * Construct a HTTP URL from a given string.
101 *
102 * @param original the HTTP URL string
103 * @throws URIException If {@link #checkValid()} fails
104 * @see #getDefaultProtocolCharset
105 */
106 public HttpURL(String original) throws URIException {
107 parseUriReference(original, false);
108 checkValid();
109 }
110
111
112 /***
113 * Construct a HTTP URL from given components.
114 *
115 * @param host the host string
116 * @param port the port number
117 * @param path the path string
118 * @throws URIException If {@link #checkValid()} fails
119 * @see #getDefaultProtocolCharset
120 */
121 public HttpURL(String host, int port, String path) throws URIException {
122 this(null, null, host, port, path, null, null);
123 }
124
125
126 /***
127 * Construct a HTTP URL from given components.
128 *
129 * @param host the host string
130 * @param port the port number
131 * @param path the path string
132 * @param query the query string
133 * @throws URIException If {@link #checkValid()} fails
134 * @see #getDefaultProtocolCharset
135 */
136 public HttpURL(String host, int port, String path, String query)
137 throws URIException {
138
139 this(null, null, host, port, path, query, null);
140 }
141
142
143 /***
144 * Construct a HTTP URL from given components.
145 *
146 * @param user the user name
147 * @param password his or her password
148 * @param host the host string
149 * @throws URIException If {@link #checkValid()} fails
150 * @see #getDefaultProtocolCharset
151 */
152 public HttpURL(String user, String password, String host)
153 throws URIException {
154
155 this(user, password, host, -1, null, null, null);
156 }
157
158
159 /***
160 * Construct a HTTP URL from given components.
161 *
162 * @param user the user name
163 * @param password his or her password
164 * @param host the host string
165 * @param port the port number
166 * @throws URIException If {@link #checkValid()} fails
167 * @see #getDefaultProtocolCharset
168 */
169 public HttpURL(String user, String password, String host, int port)
170 throws URIException {
171
172 this(user, password, host, port, null, null, null);
173 }
174
175
176 /***
177 * Construct a HTTP URL from given components.
178 *
179 * @param user the user name
180 * @param password his or her password
181 * @param host the host string
182 * @param port the port number
183 * @param path the path string
184 * @throws URIException If {@link #checkValid()} fails
185 * @see #getDefaultProtocolCharset
186 */
187 public HttpURL(String user, String password, String host, int port,
188 String path) throws URIException {
189
190 this(user, password, host, port, path, null, null);
191 }
192
193
194 /***
195 * Construct a HTTP URL from given components.
196 *
197 * @param user the user name
198 * @param password his or her password
199 * @param host the host string
200 * @param port the port number
201 * @param path the path string
202 * @param query The query string.
203 * @throws URIException If {@link #checkValid()} fails
204 * @see #getDefaultProtocolCharset
205 */
206 public HttpURL(String user, String password, String host, int port,
207 String path, String query) throws URIException {
208
209 this(user, password, host, port, path, query, null);
210 }
211
212
213 /***
214 * Construct a HTTP URL from given components.
215 *
216 * @param host the host string
217 * @param path the path string
218 * @param query the query string
219 * @param fragment the fragment string
220 * @throws URIException If {@link #checkValid()} fails
221 * @see #getDefaultProtocolCharset
222 */
223 public HttpURL(String host, String path, String query, String fragment)
224 throws URIException {
225
226 this(null, null, host, -1, path, query, fragment);
227 }
228
229
230 /***
231 * Construct a HTTP URL from given components.
232 *
233 * Note: The <code>userinfo</code> format is normally
234 * <code><username>:<password></code> where
235 * username and password must both be URL escaped.
236 *
237 * @param userinfo the userinfo string whose parts are URL escaped
238 * @param host the host string
239 * @param path the path string
240 * @param query the query string
241 * @param fragment the fragment string
242 * @throws URIException If {@link #checkValid()} fails
243 * @see #getDefaultProtocolCharset
244 */
245 public HttpURL(String userinfo, String host, String path, String query,
246 String fragment) throws URIException {
247
248 this(userinfo, host, -1, path, query, fragment);
249 }
250
251
252 /***
253 * Construct a HTTP URL from given components.
254 *
255 * Note: The <code>userinfo</code> format is normally
256 * <code><username>:<password></code> where
257 * username and password must both be URL escaped.
258 *
259 * @param userinfo the userinfo string whose parts are URL escaped
260 * @param host the host string
261 * @param port the port number
262 * @param path the path string
263 * @throws URIException If {@link #checkValid()} fails
264 * @see #getDefaultProtocolCharset
265 */
266 public HttpURL(String userinfo, String host, int port, String path)
267 throws URIException {
268
269 this(userinfo, host, port, path, null, null);
270 }
271
272
273 /***
274 * Construct a HTTP URL from given components.
275 *
276 * Note: The <code>userinfo</code> format is normally
277 * <code><username>:<password></code> where
278 * username and password must both be URL escaped.
279 *
280 * @param userinfo the userinfo string whose parts are URL escaped
281 * @param host the host string
282 * @param port the port number
283 * @param path the path string
284 * @param query the query string
285 * @throws URIException If {@link #checkValid()} fails
286 * @see #getDefaultProtocolCharset
287 */
288 public HttpURL(String userinfo, String host, int port, String path,
289 String query) throws URIException {
290
291 this(userinfo, host, port, path, query, null);
292 }
293
294
295 /***
296 * Construct a HTTP URL from given components.
297 *
298 * Note: The <code>userinfo</code> format is normally
299 * <code><username>:<password></code> where
300 * username and password must both be URL escaped.
301 *
302 * @param userinfo the userinfo string whose parts are URL escaped
303 * @param host the host string
304 * @param port the port number
305 * @param path the path string
306 * @param query the query string
307 * @param fragment the fragment string
308 * @throws URIException If {@link #checkValid()} fails
309 * @see #getDefaultProtocolCharset
310 */
311 public HttpURL(String userinfo, String host, int port, String path,
312 String query, String fragment) throws URIException {
313
314
315 StringBuffer buff = new StringBuffer();
316 if (userinfo != null || host != null || port != -1) {
317 _scheme = DEFAULT_SCHEME;
318 buff.append(_default_scheme);
319 buff.append("://");
320 if (userinfo != null) {
321 buff.append(userinfo);
322 buff.append('@');
323 }
324 if (host != null) {
325 buff.append(URIUtil.encode(host, URI.allowed_host));
326 if (port != -1 || port != DEFAULT_PORT) {
327 buff.append(':');
328 buff.append(port);
329 }
330 }
331 }
332 if (path != null) {
333 if (scheme != null && !path.startsWith("/")) {
334 throw new URIException(URIException.PARSING,
335 "abs_path requested");
336 }
337 buff.append(URIUtil.encode(path, URI.allowed_abs_path));
338 }
339 if (query != null) {
340 buff.append('?');
341 buff.append(URIUtil.encode(query, URI.allowed_query));
342 }
343 if (fragment != null) {
344 buff.append('#');
345 buff.append(URIUtil.encode(fragment, URI.allowed_fragment));
346 }
347 parseUriReference(buff.toString(), true);
348 checkValid();
349 }
350
351
352 /***
353 * Construct a HTTP URL from given components.
354 *
355 * @param user the user name
356 * @param password his or her password
357 * @param host the host string
358 * @param port the port number
359 * @param path the path string
360 * @param query the query string
361 * @param fragment the fragment string
362 * @throws URIException If {@link #checkValid()} fails
363 * @see #getDefaultProtocolCharset
364 */
365 public HttpURL(String user, String password, String host, int port,
366 String path, String query, String fragment) throws URIException {
367 this(toUserinfo(user, password), host, port, path, query, fragment);
368 }
369
370 protected static String toUserinfo(String user, String password) throws URIException {
371 if (user == null) return null;
372 StringBuffer usrinfo = new StringBuffer(20);
373 usrinfo.append(URIUtil.encode(user, URI.allowed_within_userinfo));
374 if (password == null) return usrinfo.toString();
375 usrinfo.append(':');
376 usrinfo.append(URIUtil.encode(password, URI.allowed_within_userinfo));
377 return usrinfo.toString();
378 }
379
380
381 /***
382 * Construct a HTTP URL with a given relative URL string.
383 *
384 * @param base the base HttpURL
385 * @param relative the relative HTTP URL string
386 * @throws URIException If {@link #checkValid()} fails
387 */
388 public HttpURL(HttpURL base, String relative) throws URIException {
389 this(base, new HttpURL(relative));
390 }
391
392
393 /***
394 * Construct a HTTP URL with a given relative URL.
395 *
396 * @param base the base HttpURL
397 * @param relative the relative HttpURL
398 * @throws URIException If {@link #checkValid()} fails
399 */
400 public HttpURL(HttpURL base, HttpURL relative) throws URIException {
401 super(base, relative);
402 checkValid();
403 }
404
405
406
407 /***
408 * Default scheme for HTTP URL.
409 */
410 public static final char[] DEFAULT_SCHEME = { 'h', 't', 't', 'p' };
411
412 /***
413 * Default scheme for HTTP URL.
414 * @deprecated Use {@link #DEFAULT_SCHEME} instead. This one doesn't
415 * conform to the project naming conventions.
416 */
417 public static final char[] _default_scheme = DEFAULT_SCHEME;
418
419 /***
420 * Default port for HTTP URL.
421 */
422 public static final int DEFAULT_PORT = 80;
423
424 /***
425 * Default port for HTTP URL.
426 * @deprecated Use {@link #DEFAULT_PORT} instead. This one doesn't conform
427 * to the project naming conventions.
428 */
429 public static final int _default_port = DEFAULT_PORT;
430
431 /***
432 * The serialVersionUID.
433 */
434 static final long serialVersionUID = -7158031098595039459L;
435
436
437
438 /***
439 * Get the scheme. You can get the scheme explicitly.
440 *
441 * @return the scheme
442 */
443 public char[] getRawScheme() {
444 return (_scheme == null) ? null : HttpURL.DEFAULT_SCHEME;
445 }
446
447
448 /***
449 * Get the scheme. You can get the scheme explicitly.
450 *
451 * @return the scheme null if empty or undefined
452 */
453 public String getScheme() {
454 return (_scheme == null) ? null : new String(HttpURL.DEFAULT_SCHEME);
455 }
456
457
458
459 /***
460 * Get the port number.
461 * @return the port number
462 */
463 public int getPort() {
464 return (_port == -1) ? HttpURL.DEFAULT_PORT : _port;
465 }
466
467
468
469 /***
470 * Set the raw-escaped user and password.
471 *
472 * @param escapedUser the raw-escaped user
473 * @param escapedPassword the raw-escaped password; could be null
474 * @throws URIException escaped user not valid or user required; escaped
475 * password not valid or username missed
476 */
477 public void setRawUserinfo(char[] escapedUser, char[] escapedPassword)
478 throws URIException {
479
480 if (escapedUser == null || escapedUser.length == 0) {
481 throw new URIException(URIException.PARSING, "user required");
482 }
483 if (!validate(escapedUser, within_userinfo)
484 || ((escapedPassword != null)
485 && !validate(escapedPassword, within_userinfo))) {
486 throw new URIException(URIException.ESCAPING,
487 "escaped userinfo not valid");
488 }
489 String username = new String(escapedUser);
490 String password = (escapedPassword == null)
491 ? null : new String(escapedPassword);
492 String userinfo = username + ((password == null) ? "" : ":" + password);
493 String hostname = new String(getRawHost());
494 String hostport = (_port == -1) ? hostname : hostname + ":" + _port;
495 String authority = userinfo + "@" + hostport;
496 _userinfo = userinfo.toCharArray();
497 _authority = authority.toCharArray();
498 setURI();
499 }
500
501
502 /***
503 * Set the raw-escaped user and password.
504 *
505 * @param escapedUser the escaped user
506 * @param escapedPassword the escaped password; could be null
507 * @throws URIException escaped user not valid or user required; escaped
508 * password not valid or username missed
509 * @throws NullPointerException null user
510 */
511 public void setEscapedUserinfo(String escapedUser, String escapedPassword)
512 throws URIException, NullPointerException {
513
514 setRawUserinfo(escapedUser.toCharArray(), (escapedPassword == null)
515 ? null : escapedPassword.toCharArray());
516 }
517
518
519 /***
520 * Set the user and password.
521 *
522 * @param user the user
523 * @param password the password; could be null
524 * @throws URIException encoding error or username missed
525 * @throws NullPointerException null user
526 */
527 public void setUserinfo(String user, String password)
528 throws URIException, NullPointerException {
529
530 String charset = getProtocolCharset();
531 setRawUserinfo(encode(user, within_userinfo, charset),
532 (password == null)
533 ? null
534 : encode(password, within_userinfo, charset));
535 }
536
537
538 /***
539 * Set the raw-escaped user.
540 *
541 * @param escapedUser the raw-escaped user
542 * @throws URIException escaped user not valid or user required
543 */
544 public void setRawUser(char[] escapedUser) throws URIException {
545 if (escapedUser == null || escapedUser.length == 0) {
546 throw new URIException(URIException.PARSING, "user required");
547 }
548 if (!validate(escapedUser, within_userinfo)) {
549 throw new URIException(URIException.ESCAPING,
550 "escaped user not valid");
551 }
552 String username = new String(escapedUser);
553 String password = new String(getRawPassword());
554 String userinfo = username + ((password == null) ? "" : ":" + password);
555 String hostname = new String(getRawHost());
556 String hostport = (_port == -1) ? hostname : hostname + ":" + _port;
557 String authority = userinfo + "@" + hostport;
558 _userinfo = userinfo.toCharArray();
559 _authority = authority.toCharArray();
560 setURI();
561 }
562
563
564 /***
565 * Set the escaped user string.
566 *
567 * @param escapedUser the escaped user string
568 * @throws URIException escaped user not valid
569 * @throws NullPointerException null user
570 */
571 public void setEscapedUser(String escapedUser)
572 throws URIException, NullPointerException {
573 setRawUser(escapedUser.toCharArray());
574 }
575
576
577 /***
578 * Set the user string.
579 *
580 * @param user the user string
581 * @throws URIException user encoding error
582 * @throws NullPointerException null user
583 */
584 public void setUser(String user) throws URIException, NullPointerException {
585 setRawUser(encode(user, allowed_within_userinfo, getProtocolCharset()));
586 }
587
588
589 /***
590 * Get the raw-escaped user.
591 *
592 * @return the raw-escaped user
593 */
594 public char[] getRawUser() {
595 if (_userinfo == null || _userinfo.length == 0) {
596 return null;
597 }
598 int to = indexFirstOf(_userinfo, ':');
599
600 if (to == -1) {
601 return _userinfo;
602 }
603 char[] result = new char[to];
604 System.arraycopy(_userinfo, 0, result, 0, to);
605 return result;
606 }
607
608
609 /***
610 * Get the escaped user
611 *
612 * @return the escaped user
613 */
614 public String getEscapedUser() {
615 char[] user = getRawUser();
616 return (user == null) ? null : new String(user);
617 }
618
619
620 /***
621 * Get the user.
622 *
623 * @return the user name
624 * @throws URIException If {@link #decode} fails
625 */
626 public String getUser() throws URIException {
627 char[] user = getRawUser();
628 return (user == null) ? null : decode(user, getProtocolCharset());
629 }
630
631
632 /***
633 * Set the raw-escaped password.
634 *
635 * @param escapedPassword the raw-escaped password; could be null
636 * @throws URIException escaped password not valid or username missed
637 */
638 public void setRawPassword(char[] escapedPassword) throws URIException {
639 if (escapedPassword != null
640 && !validate(escapedPassword, within_userinfo)) {
641 throw new URIException(URIException.ESCAPING,
642 "escaped password not valid");
643 }
644 if (getRawUser() == null || getRawUser().length == 0) {
645 throw new URIException(URIException.PARSING, "username required");
646 }
647 String username = new String(getRawUser());
648 String password = new String(escapedPassword);
649
650 String userinfo = username + ((password == null) ? "" : ":" + password);
651 String hostname = new String(getRawHost());
652 String hostport = (_port == -1) ? hostname : hostname + ":" + _port;
653 String authority = userinfo + "@" + hostport;
654 _userinfo = userinfo.toCharArray();
655 _authority = authority.toCharArray();
656 setURI();
657 }
658
659
660 /***
661 * Set the escaped password string.
662 *
663 * @param escapedPassword the escaped password string; could be null
664 * @throws URIException escaped password not valid or username missed
665 */
666 public void setEscapedPassword(String escapedPassword) throws URIException {
667 setRawPassword((escapedPassword == null) ? null
668 : escapedPassword.toCharArray());
669 }
670
671
672 /***
673 * Set the password string.
674 *
675 * @param password the password string; could be null
676 * @throws URIException encoding error or username missed
677 */
678 public void setPassword(String password) throws URIException {
679 setRawPassword((password == null) ? null : encode(password,
680 allowed_within_userinfo, getProtocolCharset()));
681 }
682
683
684 /***
685 * Get the raw-escaped password.
686 *
687 * @return the raw-escaped password
688 */
689 public char[] getRawPassword() {
690 int from = indexFirstOf(_userinfo, ':');
691 if (from == -1) {
692 return null;
693 }
694 int len = _userinfo.length - from - 1;
695 char[] result = new char[len];
696 System.arraycopy(_userinfo, from + 1, result, 0, len);
697 return result;
698 }
699
700
701 /***
702 * Get the escaped password.
703 *
704 * @return the escaped password
705 */
706 public String getEscapedPassword() {
707 char[] password = getRawPassword();
708 return (password == null) ? null : new String(password);
709 }
710
711
712 /***
713 * Get the password.
714 *
715 * @return the password
716 * @throws URIException If {@link #decode(char[],String)} fails.
717 */
718 public String getPassword() throws URIException {
719 char[] password = getRawPassword();
720 return (password == null) ? null : decode(password,
721 getProtocolCharset());
722 }
723
724
725
726 /***
727 * Get the raw-escaped current hierarchy level.
728 *
729 * @return the raw-escaped current hierarchy level
730 * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
731 */
732 public char[] getRawCurrentHierPath() throws URIException {
733 return (_path == null || _path.length == 0) ? rootPath
734 : super.getRawCurrentHierPath(_path);
735 }
736
737
738 /***
739 * Get the level above the this hierarchy level.
740 *
741 * @return the raw above hierarchy level
742 * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
743 */
744 public char[] getRawAboveHierPath() throws URIException {
745 char[] path = getRawCurrentHierPath();
746 return (path == null || path.length == 0) ? rootPath : getRawCurrentHierPath(path);
747 }
748
749
750 /***
751 * Get the raw escaped path.
752 *
753 * @return the path '/' if empty or undefined
754 */
755 public char[] getRawPath() {
756 char[] path = super.getRawPath();
757 return (path == null || path.length == 0) ? rootPath : path;
758 }
759
760
761
762 /***
763 * Set the query as the name and value pair.
764 *
765 * @param queryName the query string.
766 * @param queryValue the query string.
767 * @throws URIException incomplete trailing escape pattern
768 * Or unsupported character encoding
769 * @throws NullPointerException null query
770 * @see #encode
771 */
772 public void setQuery(String queryName, String queryValue)
773 throws URIException, NullPointerException {
774
775 StringBuffer buff = new StringBuffer();
776
777 String charset = getProtocolCharset();
778 buff.append(encode(queryName, allowed_within_query, charset));
779 buff.append('=');
780 buff.append(encode(queryValue, allowed_within_query, charset));
781 _query = buff.toString().toCharArray();
782 setURI();
783 }
784
785
786 /***
787 * Set the query as the name and value pairs.
788 *
789 * @param queryName the array of the query string.
790 * @param queryValue the array of the query string.
791 * @throws URIException incomplete trailing escape pattern,
792 * unsupported character encoding or wrong array size
793 * @throws NullPointerException null query
794 * @see #encode
795 */
796 public void setQuery(String[] queryName, String[] queryValue)
797 throws URIException, NullPointerException {
798
799 int length = queryName.length;
800 if (length != queryValue.length) {
801 throw new URIException("wrong array size of query");
802 }
803
804 StringBuffer buff = new StringBuffer();
805
806 String charset = getProtocolCharset();
807 for (int i = 0; i < length; i++) {
808 buff.append(encode(queryName[i], allowed_within_query, charset));
809 buff.append('=');
810 buff.append(encode(queryValue[i], allowed_within_query, charset));
811 if (i + 1 < length) {
812 buff.append('&');
813 }
814 }
815 _query = buff.toString().toCharArray();
816 setURI();
817 }
818
819
820
821 /***
822 * Verify the valid class use for construction.
823 *
824 * @throws URIException the wrong scheme use
825 */
826 protected void checkValid() throws URIException {
827
828 if (!(equals(_scheme, DEFAULT_SCHEME) || _scheme == null)) {
829 throw new URIException(URIException.PARSING, "wrong class use");
830 }
831 }
832
833 }
834