~ubuntu-branches/ubuntu/lucid/commons-httpclient/lucid

« back to all changes in this revision

Viewing changes to src/java/org/apache/commons/httpclient/HttpURL.java

  • Committer: Bazaar Package Importer
  • Author(s): Barry Hawkins
  • Date: 2005-11-25 13:12:23 UTC
  • Revision ID: james.westby@ubuntu.com-20051125131223-2g7eyo21pqgrohpo
Tags: upstream-2.0.2
ImportĀ upstreamĀ versionĀ 2.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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 $
 
5
 *
 
6
 * ====================================================================
 
7
 *
 
8
 *  Copyright 2002-2004 The Apache Software Foundation
 
9
 *
 
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
 
13
 *
 
14
 *      http://www.apache.org/licenses/LICENSE-2.0
 
15
 *
 
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
 * ====================================================================
 
22
 *
 
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/>.
 
27
 *
 
28
 * [Additional notices, if required by prior licensing conditions]
 
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
    // ----------------------------------------------------------- Constructors
 
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>&lt;username&gt;:&lt;password&gt;</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>&lt;username&gt;:&lt;password&gt;</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>&lt;username&gt;:&lt;password&gt;</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>&lt;username&gt;:&lt;password&gt;</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
        // 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);
 
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) {  // accept empty path
 
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); //sufficient for real world
 
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
    // -------------------------------------------------------------- Constants
 
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
    // ------------------------------------------------------------- The scheme
 
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
    // --------------------------------------------------------------- The port
 
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
    // ----------------------------------------------------------- The userinfo
 
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
        // set the charset to do escape encoding
 
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
        // String.indexOf(':', 0, _userinfo.length, _userinfo, 0, 1, 0);
 
600
        if (to == -1) {
 
601
            return _userinfo; // only user.
 
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
        // 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();
 
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; // null or only user.
 
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
    // --------------------------------------------------------------- The path
 
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
    // -------------------------------------------------------------- The query
 
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
        // set the charset to do escape encoding
 
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
        // 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));
 
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
    // ---------------------------------------------------------------- Utility
 
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
        // could be explicit protocol or undefined.
 
828
        if (!(equals(_scheme, DEFAULT_SCHEME) || _scheme == null)) {
 
829
            throw new URIException(URIException.PARSING, "wrong class use");
 
830
        }
 
831
    }
 
832
 
 
833
}
 
834