View Javadoc

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