2
* $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpURL.java,v 1.12.2.5 2004/09/30 17:26:27 oglueck Exp $
3
* $Revision: 1.12.2.5 $
4
* $Date: 2004/09/30 17:26:27 $
6
* ====================================================================
8
* Copyright 2002-2004 The Apache Software Foundation
10
* Licensed under the Apache License, Version 2.0 (the "License");
11
* you may not use this file except in compliance with the License.
12
* You may obtain a copy of the License at
14
* http://www.apache.org/licenses/LICENSE-2.0
16
* Unless required by applicable law or agreed to in writing, software
17
* distributed under the License is distributed on an "AS IS" BASIS,
18
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
* See the License for the specific language governing permissions and
20
* limitations under the License.
21
* ====================================================================
23
* This software consists of voluntary contributions made by many
24
* individuals on behalf of the Apache Software Foundation. For more
25
* information on the Apache Software Foundation, please see
26
* <http://www.apache.org/>.
28
* [Additional notices, if required by prior licensing conditions]
32
package org.apache.commons.httpclient;
34
import org.apache.commons.httpclient.util.URIUtil;
39
* @author <a href="mailto:jericho at apache.org">Sung-Gu</a>
40
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
42
public class HttpURL extends URI {
44
// ----------------------------------------------------------- Constructors
46
/** Create an instance as an internal use. */
52
* Construct a HTTP URL as an escaped form of a character array with the
53
* given charset to do escape encoding.
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
61
public HttpURL(char[] escaped, String charset)
62
throws URIException, NullPointerException {
63
protocolCharset = charset;
64
parseUriReference(new String(escaped), true);
70
* Construct a HTTP URL as an escaped form of a character array.
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
77
public HttpURL(char[] escaped) throws URIException, NullPointerException {
78
parseUriReference(new String(escaped), true);
84
* Construct a HTTP URL from a given string with the given charset to do
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
92
public HttpURL(String original, String charset) throws URIException {
93
protocolCharset = charset;
94
parseUriReference(original, false);
100
* Construct a HTTP URL from a given string.
102
* @param original the HTTP URL string
103
* @throws URIException If {@link #checkValid()} fails
104
* @see #getDefaultProtocolCharset
106
public HttpURL(String original) throws URIException {
107
parseUriReference(original, false);
113
* Construct a HTTP URL from given components.
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
121
public HttpURL(String host, int port, String path) throws URIException {
122
this(null, null, host, port, path, null, null);
127
* Construct a HTTP URL from given components.
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
136
public HttpURL(String host, int port, String path, String query)
137
throws URIException {
139
this(null, null, host, port, path, query, null);
144
* Construct a HTTP URL from given components.
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
152
public HttpURL(String user, String password, String host)
153
throws URIException {
155
this(user, password, host, -1, null, null, null);
160
* Construct a HTTP URL from given components.
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
169
public HttpURL(String user, String password, String host, int port)
170
throws URIException {
172
this(user, password, host, port, null, null, null);
177
* Construct a HTTP URL from given components.
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
187
public HttpURL(String user, String password, String host, int port,
188
String path) throws URIException {
190
this(user, password, host, port, path, null, null);
195
* Construct a HTTP URL from given components.
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
206
public HttpURL(String user, String password, String host, int port,
207
String path, String query) throws URIException {
209
this(user, password, host, port, path, query, null);
214
* Construct a HTTP URL from given components.
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
223
public HttpURL(String host, String path, String query, String fragment)
224
throws URIException {
226
this(null, null, host, -1, path, query, fragment);
231
* Construct a HTTP URL from given components.
233
* Note: The <code>userinfo</code> format is normally
234
* <code><username>:<password></code> where
235
* username and password must both be URL escaped.
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
245
public HttpURL(String userinfo, String host, String path, String query,
246
String fragment) throws URIException {
248
this(userinfo, host, -1, path, query, fragment);
253
* Construct a HTTP URL from given components.
255
* Note: The <code>userinfo</code> format is normally
256
* <code><username>:<password></code> where
257
* username and password must both be URL escaped.
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
266
public HttpURL(String userinfo, String host, int port, String path)
267
throws URIException {
269
this(userinfo, host, port, path, null, null);
274
* Construct a HTTP URL from given components.
276
* Note: The <code>userinfo</code> format is normally
277
* <code><username>:<password></code> where
278
* username and password must both be URL escaped.
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
288
public HttpURL(String userinfo, String host, int port, String path,
289
String query) throws URIException {
291
this(userinfo, host, port, path, query, null);
296
* Construct a HTTP URL from given components.
298
* Note: The <code>userinfo</code> format is normally
299
* <code><username>:<password></code> where
300
* username and password must both be URL escaped.
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
311
public HttpURL(String userinfo, String host, int port, String path,
312
String query, String fragment) throws URIException {
314
// validate and contruct the URI character sequence
315
StringBuffer buff = new StringBuffer();
316
if (userinfo != null || host != null || port != -1) {
317
_scheme = DEFAULT_SCHEME; // in order to verify the own protocol
318
buff.append(_default_scheme);
320
if (userinfo != null) {
321
buff.append(userinfo);
325
buff.append(URIUtil.encode(host, URI.allowed_host));
326
if (port != -1 || port != DEFAULT_PORT) {
332
if (path != null) { // accept empty path
333
if (scheme != null && !path.startsWith("/")) {
334
throw new URIException(URIException.PARSING,
335
"abs_path requested");
337
buff.append(URIUtil.encode(path, URI.allowed_abs_path));
341
buff.append(URIUtil.encode(query, URI.allowed_query));
343
if (fragment != null) {
345
buff.append(URIUtil.encode(fragment, URI.allowed_fragment));
347
parseUriReference(buff.toString(), true);
353
* Construct a HTTP URL from given components.
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
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);
370
protected static String toUserinfo(String user, String password) throws URIException {
371
if (user == null) return null;
372
StringBuffer usrinfo = new StringBuffer(20); //sufficient for real world
373
usrinfo.append(URIUtil.encode(user, URI.allowed_within_userinfo));
374
if (password == null) return usrinfo.toString();
376
usrinfo.append(URIUtil.encode(password, URI.allowed_within_userinfo));
377
return usrinfo.toString();
382
* Construct a HTTP URL with a given relative URL string.
384
* @param base the base HttpURL
385
* @param relative the relative HTTP URL string
386
* @throws URIException If {@link #checkValid()} fails
388
public HttpURL(HttpURL base, String relative) throws URIException {
389
this(base, new HttpURL(relative));
394
* Construct a HTTP URL with a given relative URL.
396
* @param base the base HttpURL
397
* @param relative the relative HttpURL
398
* @throws URIException If {@link #checkValid()} fails
400
public HttpURL(HttpURL base, HttpURL relative) throws URIException {
401
super(base, relative);
405
// -------------------------------------------------------------- Constants
408
* Default scheme for HTTP URL.
410
public static final char[] DEFAULT_SCHEME = { 'h', 't', 't', 'p' };
413
* Default scheme for HTTP URL.
414
* @deprecated Use {@link #DEFAULT_SCHEME} instead. This one doesn't
415
* conform to the project naming conventions.
417
public static final char[] _default_scheme = DEFAULT_SCHEME;
420
* Default port for HTTP URL.
422
public static final int DEFAULT_PORT = 80;
425
* Default port for HTTP URL.
426
* @deprecated Use {@link #DEFAULT_PORT} instead. This one doesn't conform
427
* to the project naming conventions.
429
public static final int _default_port = DEFAULT_PORT;
432
* The serialVersionUID.
434
static final long serialVersionUID = -7158031098595039459L;
436
// ------------------------------------------------------------- The scheme
439
* Get the scheme. You can get the scheme explicitly.
443
public char[] getRawScheme() {
444
return (_scheme == null) ? null : HttpURL.DEFAULT_SCHEME;
449
* Get the scheme. You can get the scheme explicitly.
451
* @return the scheme null if empty or undefined
453
public String getScheme() {
454
return (_scheme == null) ? null : new String(HttpURL.DEFAULT_SCHEME);
457
// --------------------------------------------------------------- The port
460
* Get the port number.
461
* @return the port number
463
public int getPort() {
464
return (_port == -1) ? HttpURL.DEFAULT_PORT : _port;
467
// ----------------------------------------------------------- The userinfo
470
* Set the raw-escaped user and password.
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
477
public void setRawUserinfo(char[] escapedUser, char[] escapedPassword)
478
throws URIException {
480
if (escapedUser == null || escapedUser.length == 0) {
481
throw new URIException(URIException.PARSING, "user required");
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");
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();
503
* Set the raw-escaped user and password.
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
511
public void setEscapedUserinfo(String escapedUser, String escapedPassword)
512
throws URIException, NullPointerException {
514
setRawUserinfo(escapedUser.toCharArray(), (escapedPassword == null)
515
? null : escapedPassword.toCharArray());
520
* Set the user and password.
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
527
public void setUserinfo(String user, String password)
528
throws URIException, NullPointerException {
529
// set the charset to do escape encoding
530
String charset = getProtocolCharset();
531
setRawUserinfo(encode(user, within_userinfo, charset),
534
: encode(password, within_userinfo, charset));
539
* Set the raw-escaped user.
541
* @param escapedUser the raw-escaped user
542
* @throws URIException escaped user not valid or user required
544
public void setRawUser(char[] escapedUser) throws URIException {
545
if (escapedUser == null || escapedUser.length == 0) {
546
throw new URIException(URIException.PARSING, "user required");
548
if (!validate(escapedUser, within_userinfo)) {
549
throw new URIException(URIException.ESCAPING,
550
"escaped user not valid");
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();
565
* Set the escaped user string.
567
* @param escapedUser the escaped user string
568
* @throws URIException escaped user not valid
569
* @throws NullPointerException null user
571
public void setEscapedUser(String escapedUser)
572
throws URIException, NullPointerException {
573
setRawUser(escapedUser.toCharArray());
578
* Set the user string.
580
* @param user the user string
581
* @throws URIException user encoding error
582
* @throws NullPointerException null user
584
public void setUser(String user) throws URIException, NullPointerException {
585
setRawUser(encode(user, allowed_within_userinfo, getProtocolCharset()));
590
* Get the raw-escaped user.
592
* @return the raw-escaped user
594
public char[] getRawUser() {
595
if (_userinfo == null || _userinfo.length == 0) {
598
int to = indexFirstOf(_userinfo, ':');
599
// String.indexOf(':', 0, _userinfo.length, _userinfo, 0, 1, 0);
601
return _userinfo; // only user.
603
char[] result = new char[to];
604
System.arraycopy(_userinfo, 0, result, 0, to);
610
* Get the escaped user
612
* @return the escaped user
614
public String getEscapedUser() {
615
char[] user = getRawUser();
616
return (user == null) ? null : new String(user);
623
* @return the user name
624
* @throws URIException If {@link #decode} fails
626
public String getUser() throws URIException {
627
char[] user = getRawUser();
628
return (user == null) ? null : decode(user, getProtocolCharset());
633
* Set the raw-escaped password.
635
* @param escapedPassword the raw-escaped password; could be null
636
* @throws URIException escaped password not valid or username missed
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");
644
if (getRawUser() == null || getRawUser().length == 0) {
645
throw new URIException(URIException.PARSING, "username required");
647
String username = new String(getRawUser());
648
String password = new String(escapedPassword);
649
// an emtpy string is allowed as a password
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();
661
* Set the escaped password string.
663
* @param escapedPassword the escaped password string; could be null
664
* @throws URIException escaped password not valid or username missed
666
public void setEscapedPassword(String escapedPassword) throws URIException {
667
setRawPassword((escapedPassword == null) ? null
668
: escapedPassword.toCharArray());
673
* Set the password string.
675
* @param password the password string; could be null
676
* @throws URIException encoding error or username missed
678
public void setPassword(String password) throws URIException {
679
setRawPassword((password == null) ? null : encode(password,
680
allowed_within_userinfo, getProtocolCharset()));
685
* Get the raw-escaped password.
687
* @return the raw-escaped password
689
public char[] getRawPassword() {
690
int from = indexFirstOf(_userinfo, ':');
692
return null; // null or only user.
694
int len = _userinfo.length - from - 1;
695
char[] result = new char[len];
696
System.arraycopy(_userinfo, from + 1, result, 0, len);
702
* Get the escaped password.
704
* @return the escaped password
706
public String getEscapedPassword() {
707
char[] password = getRawPassword();
708
return (password == null) ? null : new String(password);
715
* @return the password
716
* @throws URIException If {@link #decode(char[],String)} fails.
718
public String getPassword() throws URIException {
719
char[] password = getRawPassword();
720
return (password == null) ? null : decode(password,
721
getProtocolCharset());
724
// --------------------------------------------------------------- The path
727
* Get the raw-escaped current hierarchy level.
729
* @return the raw-escaped current hierarchy level
730
* @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
732
public char[] getRawCurrentHierPath() throws URIException {
733
return (_path == null || _path.length == 0) ? rootPath
734
: super.getRawCurrentHierPath(_path);
739
* Get the level above the this hierarchy level.
741
* @return the raw above hierarchy level
742
* @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
744
public char[] getRawAboveHierPath() throws URIException {
745
char[] path = getRawCurrentHierPath();
746
return (path == null || path.length == 0) ? rootPath : getRawCurrentHierPath(path);
751
* Get the raw escaped path.
753
* @return the path '/' if empty or undefined
755
public char[] getRawPath() {
756
char[] path = super.getRawPath();
757
return (path == null || path.length == 0) ? rootPath : path;
760
// -------------------------------------------------------------- The query
763
* Set the query as the name and value pair.
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
772
public void setQuery(String queryName, String queryValue)
773
throws URIException, NullPointerException {
775
StringBuffer buff = new StringBuffer();
776
// set the charset to do escape encoding
777
String charset = getProtocolCharset();
778
buff.append(encode(queryName, allowed_within_query, charset));
780
buff.append(encode(queryValue, allowed_within_query, charset));
781
_query = buff.toString().toCharArray();
787
* Set the query as the name and value pairs.
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
796
public void setQuery(String[] queryName, String[] queryValue)
797
throws URIException, NullPointerException {
799
int length = queryName.length;
800
if (length != queryValue.length) {
801
throw new URIException("wrong array size of query");
804
StringBuffer buff = new StringBuffer();
805
// set the charset to do escape encoding
806
String charset = getProtocolCharset();
807
for (int i = 0; i < length; i++) {
808
buff.append(encode(queryName[i], allowed_within_query, charset));
810
buff.append(encode(queryValue[i], allowed_within_query, charset));
811
if (i + 1 < length) {
815
_query = buff.toString().toCharArray();
819
// ---------------------------------------------------------------- Utility
822
* Verify the valid class use for construction.
824
* @throws URIException the wrong scheme use
826
protected void checkValid() throws URIException {
827
// could be explicit protocol or undefined.
828
if (!(equals(_scheme, DEFAULT_SCHEME) || _scheme == null)) {
829
throw new URIException(URIException.PARSING, "wrong class use");