Source code: org/apache/axis/types/URI.java
1 /*
2 * Copyright 1999-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.types;
18
19 import java.io.IOException;
20 import java.io.Serializable;
21
22 /**********************************************************************
23 * <i>Axis Note: This class was 'borrowed' from Xerces 2:
24 * org.apache.xerces.util.URI.java, version 1.22 </i>
25 * <p>
26 * A class to represent a Uniform Resource Identifier (URI). This class
27 * is designed to handle the parsing of URIs and provide access to
28 * the various components (scheme, host, port, userinfo, path, query
29 * string and fragment) that may constitute a URI.
30 * <p>
31 * Parsing of a URI specification is done according to the URI
32 * syntax described in
33 * <a href="http://www.ietf.org/rfc/rfc2396.txt?number=2396">RFC 2396</a>,
34 * and amended by
35 * <a href="http://www.ietf.org/rfc/rfc2732.txt?number=2732">RFC 2732</a>.
36 * <p>
37 * Every absolute URI consists of a scheme, followed by a colon (':'),
38 * followed by a scheme-specific part. For URIs that follow the
39 * "generic URI" syntax, the scheme-specific part begins with two
40 * slashes ("//") and may be followed by an authority segment (comprised
41 * of user information, host, and port), path segment, query segment
42 * and fragment. Note that RFC 2396 no longer specifies the use of the
43 * parameters segment and excludes the "user:password" syntax as part of
44 * the authority segment. If "user:password" appears in a URI, the entire
45 * user/password string is stored as userinfo.
46 * <p>
47 * For URIs that do not follow the "generic URI" syntax (e.g. mailto),
48 * the entire scheme-specific part is treated as the "path" portion
49 * of the URI.
50 * <p>
51 * Note that, unlike the java.net.URL class, this class does not provide
52 * any built-in network access functionality nor does it provide any
53 * scheme-specific functionality (for example, it does not know a
54 * default port for a specific scheme). Rather, it only knows the
55 * grammar and basic set of operations that can be applied to a URI.
56 *
57 **********************************************************************/
58 public class URI implements Serializable {
59
60 /*******************************************************************
61 * MalformedURIExceptions are thrown in the process of building a URI
62 * or setting fields on a URI when an operation would result in an
63 * invalid URI specification.
64 *
65 ********************************************************************/
66 public static class MalformedURIException extends IOException {
67
68 /** Serialization version. */
69 static final long serialVersionUID = -6695054834342951930L;
70
71 /******************************************************************
72 * Constructs a <code>MalformedURIException</code> with no specified
73 * detail message.
74 ******************************************************************/
75 public MalformedURIException() {
76 super();
77 }
78
79 /*****************************************************************
80 * Constructs a <code>MalformedURIException</code> with the
81 * specified detail message.
82 *
83 * @param p_msg the detail message.
84 ******************************************************************/
85 public MalformedURIException(String p_msg) {
86 super(p_msg);
87 }
88 }
89
90 /** Serialization version. */
91 static final long serialVersionUID = 1601921774685357214L;
92
93 private static final byte [] fgLookupTable = new byte[128];
94
95 /**
96 * Character Classes
97 */
98
99 /** reserved characters ;/?:@&=+$,[] */
100 //RFC 2732 added '[' and ']' as reserved characters
101 private static final int RESERVED_CHARACTERS = 0x01;
102
103 /** URI punctuation mark characters: -_.!~*'() - these, combined with
104 alphanumerics, constitute the "unreserved" characters */
105 private static final int MARK_CHARACTERS = 0x02;
106
107 /** scheme can be composed of alphanumerics and these characters: +-. */
108 private static final int SCHEME_CHARACTERS = 0x04;
109
110 /** userinfo can be composed of unreserved, escaped and these
111 characters: ;:&=+$, */
112 private static final int USERINFO_CHARACTERS = 0x08;
113
114 /** ASCII letter characters */
115 private static final int ASCII_ALPHA_CHARACTERS = 0x10;
116
117 /** ASCII digit characters */
118 private static final int ASCII_DIGIT_CHARACTERS = 0x20;
119
120 /** ASCII hex characters */
121 private static final int ASCII_HEX_CHARACTERS = 0x40;
122
123 /** Path characters */
124 private static final int PATH_CHARACTERS = 0x80;
125
126 /** Mask for alpha-numeric characters */
127 private static final int MASK_ALPHA_NUMERIC = ASCII_ALPHA_CHARACTERS | ASCII_DIGIT_CHARACTERS;
128
129 /** Mask for unreserved characters */
130 private static final int MASK_UNRESERVED_MASK = MASK_ALPHA_NUMERIC | MARK_CHARACTERS;
131
132 /** Mask for URI allowable characters except for % */
133 private static final int MASK_URI_CHARACTER = MASK_UNRESERVED_MASK | RESERVED_CHARACTERS;
134
135 /** Mask for scheme characters */
136 private static final int MASK_SCHEME_CHARACTER = MASK_ALPHA_NUMERIC | SCHEME_CHARACTERS;
137
138 /** Mask for userinfo characters */
139 private static final int MASK_USERINFO_CHARACTER = MASK_UNRESERVED_MASK | USERINFO_CHARACTERS;
140
141 /** Mask for path characters */
142 private static final int MASK_PATH_CHARACTER = MASK_UNRESERVED_MASK | PATH_CHARACTERS;
143
144 static {
145 // Add ASCII Digits and ASCII Hex Numbers
146 for (int i = '0'; i <= '9'; ++i) {
147 fgLookupTable[i] |= ASCII_DIGIT_CHARACTERS | ASCII_HEX_CHARACTERS;
148 }
149
150 // Add ASCII Letters and ASCII Hex Numbers
151 for (int i = 'A'; i <= 'F'; ++i) {
152 fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS;
153 fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS;
154 }
155
156 // Add ASCII Letters
157 for (int i = 'G'; i <= 'Z'; ++i) {
158 fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS;
159 fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS;
160 }
161
162 // Add Reserved Characters
163 fgLookupTable[';'] |= RESERVED_CHARACTERS;
164 fgLookupTable['/'] |= RESERVED_CHARACTERS;
165 fgLookupTable['?'] |= RESERVED_CHARACTERS;
166 fgLookupTable[':'] |= RESERVED_CHARACTERS;
167 fgLookupTable['@'] |= RESERVED_CHARACTERS;
168 fgLookupTable['&'] |= RESERVED_CHARACTERS;
169 fgLookupTable['='] |= RESERVED_CHARACTERS;
170 fgLookupTable['+'] |= RESERVED_CHARACTERS;
171 fgLookupTable['$'] |= RESERVED_CHARACTERS;
172 fgLookupTable[','] |= RESERVED_CHARACTERS;
173 fgLookupTable['['] |= RESERVED_CHARACTERS;
174 fgLookupTable[']'] |= RESERVED_CHARACTERS;
175
176 // Add Mark Characters
177 fgLookupTable['-'] |= MARK_CHARACTERS;
178 fgLookupTable['_'] |= MARK_CHARACTERS;
179 fgLookupTable['.'] |= MARK_CHARACTERS;
180 fgLookupTable['!'] |= MARK_CHARACTERS;
181 fgLookupTable['~'] |= MARK_CHARACTERS;
182 fgLookupTable['*'] |= MARK_CHARACTERS;
183 fgLookupTable['\''] |= MARK_CHARACTERS;
184 fgLookupTable['('] |= MARK_CHARACTERS;
185 fgLookupTable[')'] |= MARK_CHARACTERS;
186
187 // Add Scheme Characters
188 fgLookupTable['+'] |= SCHEME_CHARACTERS;
189 fgLookupTable['-'] |= SCHEME_CHARACTERS;
190 fgLookupTable['.'] |= SCHEME_CHARACTERS;
191
192 // Add Userinfo Characters
193 fgLookupTable[';'] |= USERINFO_CHARACTERS;
194 fgLookupTable[':'] |= USERINFO_CHARACTERS;
195 fgLookupTable['&'] |= USERINFO_CHARACTERS;
196 fgLookupTable['='] |= USERINFO_CHARACTERS;
197 fgLookupTable['+'] |= USERINFO_CHARACTERS;
198 fgLookupTable['$'] |= USERINFO_CHARACTERS;
199 fgLookupTable[','] |= USERINFO_CHARACTERS;
200
201 // Add Path Characters
202 fgLookupTable[';'] |= PATH_CHARACTERS;
203 fgLookupTable['/'] |= PATH_CHARACTERS;
204 fgLookupTable[':'] |= PATH_CHARACTERS;
205 fgLookupTable['@'] |= PATH_CHARACTERS;
206 fgLookupTable['&'] |= PATH_CHARACTERS;
207 fgLookupTable['='] |= PATH_CHARACTERS;
208 fgLookupTable['+'] |= PATH_CHARACTERS;
209 fgLookupTable['$'] |= PATH_CHARACTERS;
210 fgLookupTable[','] |= PATH_CHARACTERS;
211 }
212
213 /** Stores the scheme (usually the protocol) for this URI. */
214 private String m_scheme = null;
215
216 /** If specified, stores the userinfo for this URI; otherwise null */
217 private String m_userinfo = null;
218
219 /** If specified, stores the host for this URI; otherwise null */
220 private String m_host = null;
221
222 /** If specified, stores the port for this URI; otherwise -1 */
223 private int m_port = -1;
224
225 /** If specified, stores the registry based authority for this URI; otherwise -1 */
226 private String m_regAuthority = null;
227
228 /** If specified, stores the path for this URI; otherwise null */
229 private String m_path = null;
230
231 /** If specified, stores the query string for this URI; otherwise
232 null. */
233 private String m_queryString = null;
234
235 /** If specified, stores the fragment for this URI; otherwise null */
236 private String m_fragment = null;
237
238 private static boolean DEBUG = false;
239
240 /**
241 * Construct a new and uninitialized URI.
242 */
243 public URI() {
244 }
245
246 /**
247 * Construct a new URI from another URI. All fields for this URI are
248 * set equal to the fields of the URI passed in.
249 *
250 * @param p_other the URI to copy (cannot be null)
251 */
252 public URI(URI p_other) {
253 initialize(p_other);
254 }
255
256 /**
257 * Construct a new URI from a URI specification string. If the
258 * specification follows the "generic URI" syntax, (two slashes
259 * following the first colon), the specification will be parsed
260 * accordingly - setting the scheme, userinfo, host,port, path, query
261 * string and fragment fields as necessary. If the specification does
262 * not follow the "generic URI" syntax, the specification is parsed
263 * into a scheme and scheme-specific part (stored as the path) only.
264 *
265 * @param p_uriSpec the URI specification string (cannot be null or
266 * empty)
267 *
268 * @exception MalformedURIException if p_uriSpec violates any syntax
269 * rules
270 */
271 public URI(String p_uriSpec) throws MalformedURIException {
272 this((URI)null, p_uriSpec);
273 }
274
275 /**
276 * Construct a new URI from a URI specification string. If the
277 * specification follows the "generic URI" syntax, (two slashes
278 * following the first colon), the specification will be parsed
279 * accordingly - setting the scheme, userinfo, host,port, path, query
280 * string and fragment fields as necessary. If the specification does
281 * not follow the "generic URI" syntax, the specification is parsed
282 * into a scheme and scheme-specific part (stored as the path) only.
283 * Construct a relative URI if boolean is assigned to "true"
284 * and p_uriSpec is not valid absolute URI, instead of throwing an exception.
285 *
286 * @param p_uriSpec the URI specification string (cannot be null or
287 * empty)
288 * @param allowNonAbsoluteURI true to permit non-absolute URIs,
289 * false otherwise.
290 *
291 * @exception MalformedURIException if p_uriSpec violates any syntax
292 * rules
293 */
294 public URI(String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException {
295 this((URI)null, p_uriSpec, allowNonAbsoluteURI);
296 }
297
298 /**
299 * Construct a new URI from a base URI and a URI specification string.
300 * The URI specification string may be a relative URI.
301 *
302 * @param p_base the base URI (cannot be null if p_uriSpec is null or
303 * empty)
304 * @param p_uriSpec the URI specification string (cannot be null or
305 * empty if p_base is null)
306 *
307 * @exception MalformedURIException if p_uriSpec violates any syntax
308 * rules
309 */
310 public URI(URI p_base, String p_uriSpec) throws MalformedURIException {
311 initialize(p_base, p_uriSpec);
312 }
313
314 /**
315 * Construct a new URI from a base URI and a URI specification string.
316 * The URI specification string may be a relative URI.
317 * Construct a relative URI if boolean is assigned to "true"
318 * and p_uriSpec is not valid absolute URI and p_base is null
319 * instead of throwing an exception.
320 *
321 * @param p_base the base URI (cannot be null if p_uriSpec is null or
322 * empty)
323 * @param p_uriSpec the URI specification string (cannot be null or
324 * empty if p_base is null)
325 * @param allowNonAbsoluteURI true to permit non-absolute URIs,
326 * false otherwise.
327 *
328 * @exception MalformedURIException if p_uriSpec violates any syntax
329 * rules
330 */
331 public URI(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException {
332 initialize(p_base, p_uriSpec, allowNonAbsoluteURI);
333 }
334
335 /**
336 * Construct a new URI that does not follow the generic URI syntax.
337 * Only the scheme and scheme-specific part (stored as the path) are
338 * initialized.
339 *
340 * @param p_scheme the URI scheme (cannot be null or empty)
341 * @param p_schemeSpecificPart the scheme-specific part (cannot be
342 * null or empty)
343 *
344 * @exception MalformedURIException if p_scheme violates any
345 * syntax rules
346 */
347 public URI(String p_scheme, String p_schemeSpecificPart)
348 throws MalformedURIException {
349 if (p_scheme == null || p_scheme.trim().length() == 0) {
350 throw new MalformedURIException(
351 "Cannot construct URI with null/empty scheme!");
352 }
353 if (p_schemeSpecificPart == null ||
354 p_schemeSpecificPart.trim().length() == 0) {
355 throw new MalformedURIException(
356 "Cannot construct URI with null/empty scheme-specific part!");
357 }
358 setScheme(p_scheme);
359 setPath(p_schemeSpecificPart);
360 }
361
362 /**
363 * Construct a new URI that follows the generic URI syntax from its
364 * component parts. Each component is validated for syntax and some
365 * basic semantic checks are performed as well. See the individual
366 * setter methods for specifics.
367 *
368 * @param p_scheme the URI scheme (cannot be null or empty)
369 * @param p_host the hostname, IPv4 address or IPv6 reference for the URI
370 * @param p_path the URI path - if the path contains '?' or '#',
371 * then the query string and/or fragment will be
372 * set from the path; however, if the query and
373 * fragment are specified both in the path and as
374 * separate parameters, an exception is thrown
375 * @param p_queryString the URI query string (cannot be specified
376 * if path is null)
377 * @param p_fragment the URI fragment (cannot be specified if path
378 * is null)
379 *
380 * @exception MalformedURIException if any of the parameters violates
381 * syntax rules or semantic rules
382 */
383 public URI(String p_scheme, String p_host, String p_path,
384 String p_queryString, String p_fragment)
385 throws MalformedURIException {
386 this(p_scheme, null, p_host, -1, p_path, p_queryString, p_fragment);
387 }
388
389 /**
390 * Construct a new URI that follows the generic URI syntax from its
391 * component parts. Each component is validated for syntax and some
392 * basic semantic checks are performed as well. See the individual
393 * setter methods for specifics.
394 *
395 * @param p_scheme the URI scheme (cannot be null or empty)
396 * @param p_userinfo the URI userinfo (cannot be specified if host
397 * is null)
398 * @param p_host the hostname, IPv4 address or IPv6 reference for the URI
399 * @param p_port the URI port (may be -1 for "unspecified"; cannot
400 * be specified if host is null)
401 * @param p_path the URI path - if the path contains '?' or '#',
402 * then the query string and/or fragment will be
403 * set from the path; however, if the query and
404 * fragment are specified both in the path and as
405 * separate parameters, an exception is thrown
406 * @param p_queryString the URI query string (cannot be specified
407 * if path is null)
408 * @param p_fragment the URI fragment (cannot be specified if path
409 * is null)
410 *
411 * @exception MalformedURIException if any of the parameters violates
412 * syntax rules or semantic rules
413 */
414 public URI(String p_scheme, String p_userinfo,
415 String p_host, int p_port, String p_path,
416 String p_queryString, String p_fragment)
417 throws MalformedURIException {
418 if (p_scheme == null || p_scheme.trim().length() == 0) {
419 throw new MalformedURIException("Scheme is required!");
420 }
421
422 if (p_host == null) {
423 if (p_userinfo != null) {
424 throw new MalformedURIException(
425 "Userinfo may not be specified if host is not specified!");
426 }
427 if (p_port != -1) {
428 throw new MalformedURIException(
429 "Port may not be specified if host is not specified!");
430 }
431 }
432
433 if (p_path != null) {
434 if (p_path.indexOf('?') != -1 && p_queryString != null) {
435 throw new MalformedURIException(
436 "Query string cannot be specified in path and query string!");
437 }
438
439 if (p_path.indexOf('#') != -1 && p_fragment != null) {
440 throw new MalformedURIException(
441 "Fragment cannot be specified in both the path and fragment!");
442 }
443 }
444
445 setScheme(p_scheme);
446 setHost(p_host);
447 setPort(p_port);
448 setUserinfo(p_userinfo);
449 setPath(p_path);
450 setQueryString(p_queryString);
451 setFragment(p_fragment);
452 }
453
454 /**
455 * Initialize all fields of this URI from another URI.
456 *
457 * @param p_other the URI to copy (cannot be null)
458 */
459 private void initialize(URI p_other) {
460 m_scheme = p_other.getScheme();
461 m_userinfo = p_other.getUserinfo();
462 m_host = p_other.getHost();
463 m_port = p_other.getPort();
464 m_regAuthority = p_other.getRegBasedAuthority();
465 m_path = p_other.getPath();
466 m_queryString = p_other.getQueryString();
467 m_fragment = p_other.getFragment();
468 }
469
470 /**
471 * Initializes this URI from a base URI and a URI specification string.
472 * See RFC 2396 Section 4 and Appendix B for specifications on parsing
473 * the URI and Section 5 for specifications on resolving relative URIs
474 * and relative paths.
475 *
476 * @param p_base the base URI (may be null if p_uriSpec is an absolute
477 * URI)
478 * @param p_uriSpec the URI spec string which may be an absolute or
479 * relative URI (can only be null/empty if p_base
480 * is not null)
481 * @param allowNonAbsoluteURI true to permit non-absolute URIs,
482 * in case of relative URI, false otherwise.
483 *
484 * @exception MalformedURIException if p_base is null and p_uriSpec
485 * is not an absolute URI or if
486 * p_uriSpec violates syntax rules
487 */
488 private void initialize(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI)
489 throws MalformedURIException {
490
491 String uriSpec = p_uriSpec;
492 int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0;
493
494 if (p_base == null && uriSpecLen == 0) {
495 if (allowNonAbsoluteURI) {
496 m_path = "";
497 return;
498 }
499 throw new MalformedURIException("Cannot initialize URI with empty parameters.");
500 }
501
502 // just make a copy of the base if spec is empty
503 if (uriSpecLen == 0) {
504 initialize(p_base);
505 return;
506 }
507
508 int index = 0;
509
510 // Check for scheme, which must be before '/', '?' or '#'.
511 int colonIdx = uriSpec.indexOf(':');
512 if (colonIdx != -1) {
513 final int searchFrom = colonIdx - 1;
514 // search backwards starting from character before ':'.
515 int slashIdx = uriSpec.lastIndexOf('/', searchFrom);
516 int queryIdx = uriSpec.lastIndexOf('?', searchFrom);
517 int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom);
518
519 if (colonIdx == 0 || slashIdx != -1 ||
520 queryIdx != -1 || fragmentIdx != -1) {
521 // A standalone base is a valid URI according to spec
522 if (colonIdx == 0 || (p_base == null && fragmentIdx != 0 && !allowNonAbsoluteURI)) {
523 throw new MalformedURIException("No scheme found in URI.");
524 }
525 }
526 else {
527 initializeScheme(uriSpec);
528 index = m_scheme.length()+1;
529
530 // Neither 'scheme:' or 'scheme:#fragment' are valid URIs.
531 if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') {
532 throw new MalformedURIException("Scheme specific part cannot be empty.");
533 }
534 }
535 }
536 else if (p_base == null && uriSpec.indexOf('#') != 0 && !allowNonAbsoluteURI) {
537 throw new MalformedURIException("No scheme found in URI.");
538 }
539
540 // Two slashes means we may have authority, but definitely means we're either
541 // matching net_path or abs_path. These two productions are ambiguous in that
542 // every net_path (except those containing an IPv6Reference) is an abs_path.
543 // RFC 2396 resolves this ambiguity by applying a greedy left most matching rule.
544 // Try matching net_path first, and if that fails we don't have authority so
545 // then attempt to match abs_path.
546 //
547 // net_path = "//" authority [ abs_path ]
548 // abs_path = "/" path_segments
549 if (((index+1) < uriSpecLen) &&
550 (uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) {
551 index += 2;
552 int startPos = index;
553
554 // Authority will be everything up to path, query or fragment
555 char testChar = '\0';
556 while (index < uriSpecLen) {
557 testChar = uriSpec.charAt(index);
558 if (testChar == '/' || testChar == '?' || testChar == '#') {
559 break;
560 }
561 index++;
562 }
563
564 // Attempt to parse authority. If the section is an empty string
565 // this is a valid server based authority, so set the host to this
566 // value.
567 if (index > startPos) {
568 // If we didn't find authority we need to back up. Attempt to
569 // match against abs_path next.
570 if (!initializeAuthority(uriSpec.substring(startPos, index))) {
571 index = startPos - 2;
572 }
573 }
574 else {
575 m_host = "";
576 }
577 }
578
579 initializePath(uriSpec, index);
580
581 // Resolve relative URI to base URI - see RFC 2396 Section 5.2
582 // In some cases, it might make more sense to throw an exception
583 // (when scheme is specified is the string spec and the base URI
584 // is also specified, for example), but we're just following the
585 // RFC specifications
586 if (p_base != null) {
587 absolutize(p_base);
588 }
589 }
590
591 /**
592 * Initializes this URI from a base URI and a URI specification string.
593 * See RFC 2396 Section 4 and Appendix B for specifications on parsing
594 * the URI and Section 5 for specifications on resolving relative URIs
595 * and relative paths.
596 *
597 * @param p_base the base URI (may be null if p_uriSpec is an absolute
598 * URI)
599 * @param p_uriSpec the URI spec string which may be an absolute or
600 * relative URI (can only be null/empty if p_base
601 * is not null)
602 *
603 * @exception MalformedURIException if p_base is null and p_uriSpec
604 * is not an absolute URI or if
605 * p_uriSpec violates syntax rules
606 */
607 private void initialize(URI p_base, String p_uriSpec)
608 throws MalformedURIException {
609
610 String uriSpec = p_uriSpec;
611 int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0;
612
613 if (p_base == null && uriSpecLen == 0) {
614 throw new MalformedURIException(
615 "Cannot initialize URI with empty parameters.");
616 }
617
618 // just make a copy of the base if spec is empty
619 if (uriSpecLen == 0) {
620 initialize(p_base);
621 return;
622 }
623
624 int index = 0;
625
626 // Check for scheme, which must be before '/', '?' or '#'.
627 int colonIdx = uriSpec.indexOf(':');
628 if (colonIdx != -1) {
629 final int searchFrom = colonIdx - 1;
630 // search backwards starting from character before ':'.
631 int slashIdx = uriSpec.lastIndexOf('/', searchFrom);
632 int queryIdx = uriSpec.lastIndexOf('?', searchFrom);
633 int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom);
634
635 if (colonIdx == 0 || slashIdx != -1 ||
636 queryIdx != -1 || fragmentIdx != -1) {
637 // A standalone base is a valid URI according to spec
638 if (colonIdx == 0 || (p_base == null && fragmentIdx != 0)) {
639 throw new MalformedURIException("No scheme found in URI.");
640 }
641 }
642 else {
643 initializeScheme(uriSpec);
644 index = m_scheme.length()+1;
645
646 // Neither 'scheme:' or 'scheme:#fragment' are valid URIs.
647 if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') {
648 throw new MalformedURIException("Scheme specific part cannot be empty.");
649 }
650 }
651 }
652 else if (p_base == null && uriSpec.indexOf('#') != 0) {
653 throw new MalformedURIException("No scheme found in URI.");
654 }
655
656 // Two slashes means we may have authority, but definitely means we're either
657 // matching net_path or abs_path. These two productions are ambiguous in that
658 // every net_path (except those containing an IPv6Reference) is an abs_path.
659 // RFC 2396 resolves this ambiguity by applying a greedy left most matching rule.
660 // Try matching net_path first, and if that fails we don't have authority so
661 // then attempt to match abs_path.
662 //
663 // net_path = "//" authority [ abs_path ]
664 // abs_path = "/" path_segments
665 if (((index+1) < uriSpecLen) &&
666 (uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) {
667 index += 2;
668 int startPos = index;
669
670 // Authority will be everything up to path, query or fragment
671 char testChar = '\0';
672 while (index < uriSpecLen) {
673 testChar = uriSpec.charAt(index);
674 if (testChar == '/' || testChar == '?' || testChar == '#') {
675 break;
676 }
677 index++;
678 }
679
680 // Attempt to parse authority. If the section is an empty string
681 // this is a valid server based authority, so set the host to this
682 // value.
683 if (index > startPos) {
684 // If we didn't find authority we need to back up. Attempt to
685 // match against abs_path next.
686 if (!initializeAuthority(uriSpec.substring(startPos, index))) {
687 index = startPos - 2;
688 }
689 }
690 else {
691 m_host = "";
692 }
693 }
694
695 initializePath(uriSpec, index);
696
697 // Resolve relative URI to base URI - see RFC 2396 Section 5.2
698 // In some cases, it might make more sense to throw an exception
699 // (when scheme is specified is the string spec and the base URI
700 // is also specified, for example), but we're just following the
701 // RFC specifications
702 if (p_base != null) {
703 absolutize(p_base);
704 }
705 }
706
707 /**
708 * Absolutize URI with given base URI.
709 *
710 * @param p_base base URI for absolutization
711 */
712 public void absolutize(URI p_base) {
713
714 // check to see if this is the current doc - RFC 2396 5.2 #2
715 // note that this is slightly different from the RFC spec in that
716 // we don't include the check for query string being null
717 // - this handles cases where the urispec is just a query
718 // string or a fragment (e.g. "?y" or "#s") -
719 // see <http://www.ics.uci.edu/~fielding/url/test1.html> which
720 // identified this as a bug in the RFC
721 if (m_path.length() == 0 && m_scheme == null &&
722 m_host == null && m_regAuthority == null) {
723 m_scheme = p_base.getScheme();
724 m_userinfo = p_base.getUserinfo();
725 m_host = p_base.getHost();
726 m_port = p_base.getPort();
727 m_regAuthority = p_base.getRegBasedAuthority();
728 m_path = p_base.getPath();
729
730 if (m_queryString == null) {
731 m_queryString = p_base.getQueryString();
732
733 if (m_fragment == null) {
734 m_fragment = p_base.getFragment();
735 }
736 }
737 return;
738 }
739
740 // check for scheme - RFC 2396 5.2 #3
741 // if we found a scheme, it means absolute URI, so we're done
742 if (m_scheme == null) {
743 m_scheme = p_base.getScheme();
744 }
745 else {
746 return;
747 }
748
749 // check for authority - RFC 2396 5.2 #4
750 // if we found a host, then we've got a network path, so we're done
751 if (m_host == null && m_regAuthority == null) {
752 m_userinfo = p_base.getUserinfo();
753 m_host = p_base.getHost();
754 m_port = p_base.getPort();
755 m_regAuthority = p_base.getRegBasedAuthority();
756 }
757 else {
758 return;
759 }
760
761 // check for absolute path - RFC 2396 5.2 #5
762 if (m_path.length() > 0 &&
763 m_path.startsWith("/")) {
764 return;
765 }
766
767 // if we get to this point, we need to resolve relative path
768 // RFC 2396 5.2 #6
769 String path = "";
770 String basePath = p_base.getPath();
771
772 // 6a - get all but the last segment of the base URI path
773 if (basePath != null && basePath.length() > 0) {
774 int lastSlash = basePath.lastIndexOf('/');
775 if (lastSlash != -1) {
776 path = basePath.substring(0, lastSlash+1);
777 }
778 }
779 else if (m_path.length() > 0) {
780 path = "/";
781 }
782
783 // 6b - append the relative URI path
784 path = path.concat(m_path);
785
786 // 6c - remove all "./" where "." is a complete path segment
787 int index = -1;
788 while ((index = path.indexOf("/./")) != -1) {
789 path = path.substring(0, index+1).concat(path.substring(index+3));
790 }
791
792 // 6d - remove "." if path ends with "." as a complete path segment
793 if (path.endsWith("/.")) {
794 path = path.substring(0, path.length()-1);
795 }
796
797 // 6e - remove all "<segment>/../" where "<segment>" is a complete
798 // path segment not equal to ".."
799 index = 1;
800 int segIndex = -1;
801 String tempString = null;
802
803 while ((index = path.indexOf("/../", index)) > 0) {
804 tempString = path.substring(0, path.indexOf("/../"));
805 segIndex = tempString.lastIndexOf('/');
806 if (segIndex != -1) {
807 if (!tempString.substring(segIndex).equals("..")) {
808 path = path.substring(0, segIndex+1).concat(path.substring(index+4));
809 index = segIndex;
810 }
811 else {
812 index += 4;
813 }
814 }
815 else {
816 index += 4;
817 }
818 }
819
820 // 6f - remove ending "<segment>/.." where "<segment>" is a
821 // complete path segment
822 if (path.endsWith("/..")) {
823 tempString = path.substring(0, path.length()-3);
824 segIndex = tempString.lastIndexOf('/');
825 if (segIndex != -1) {
826 path = path.substring(0, segIndex+1);
827 }
828 }
829 m_path = path;
830 }
831
832 /**
833 * Initialize the scheme for this URI from a URI string spec.
834 *
835 * @param p_uriSpec the URI specification (cannot be null)
836 *
837 * @exception MalformedURIException if URI does not have a conformant
838 * scheme
839 */
840 private void initializeScheme(String p_uriSpec)
841 throws MalformedURIException {
842 int uriSpecLen = p_uriSpec.length();
843 int index = 0;
844 String scheme = null;
845 char testChar = '\0';
846
847 while (index < uriSpecLen) {
848 testChar = p_uriSpec.charAt(index);
849 if (testChar == ':' || testChar == '/' ||
850 testChar == '?' || testChar == '#') {
851 break;
852 }
853 index++;
854 }
855 scheme = p_uriSpec.substring(0, index);
856
857 if (scheme.length() == 0) {
858 throw new MalformedURIException("No scheme found in URI.");
859 }
860 else {
861 setScheme(scheme);
862 }
863 }
864
865 /**
866 * Initialize the authority (either server or registry based)
867 * for this URI from a URI string spec.
868 *
869 * @param p_uriSpec the URI specification (cannot be null)
870 *
871 * @return true if the given string matched server or registry
872 * based authority
873 */
874 private boolean initializeAuthority(String p_uriSpec) {
875
876 int index = 0;
877 int start = 0;
878 int end = p_uriSpec.length();
879
880 char testChar = '\0';
881 String userinfo = null;
882
883 // userinfo is everything up to @
884 if (p_uriSpec.indexOf('@', start) != -1) {
885 while (index < end) {
886 testChar = p_uriSpec.charAt(index);
887 if (testChar == '@') {
888 break;
889 }
890 index++;
891 }
892 userinfo = p_uriSpec.substring(start, index);
893 index++;
894 }
895
896 // host is everything up to last ':', or up to
897 // and including ']' if followed by ':'.
898 String host = null;
899 start = index;
900 boolean hasPort = false;
901 if (index < end) {
902 if (p_uriSpec.charAt(start) == '[') {
903 int bracketIndex = p_uriSpec.indexOf(']', start);
904 index = (bracketIndex != -1) ? bracketIndex : end;
905 if (index+1 < end && p_uriSpec.charAt(index+1) == ':') {
906 ++index;
907 hasPort = true;
908 }
909 else {
910 index = end;
911 }
912 }
913 else {
914 int colonIndex = p_uriSpec.lastIndexOf(':', end);
915 index = (colonIndex > start) ? colonIndex : end;
916 hasPort = (index != end);
917 }
918 }
919 host = p_uriSpec.substring(start, index);
920 int port = -1;
921 if (host.length() > 0) {
922 // port
923 if (hasPort) {
924 index++;
925 start = index;
926 while (index < end) {
927 index++;
928 }
929 String portStr = p_uriSpec.substring(start, index);
930 if (portStr.length() > 0) {
931 // REVISIT: Remove this code.
932 /** for (int i = 0; i < portStr.length(); i++) {
933 if (!isDigit(portStr.charAt(i))) {
934 throw new MalformedURIException(
935 portStr +
936 " is invalid. Port should only contain digits!");
937 }
938 }**/
939 // REVISIT: Remove this code.
940 // Store port value as string instead of integer.
941 try {
942 port = Integer.parseInt(portStr);
943 if (port == -1) --port;
944 }
945 catch (NumberFormatException nfe) {
946 port = -2;
947 }
948 }
949 }
950 }
951
952 if (isValidServerBasedAuthority(host, port, userinfo)) {
953 m_host = host;
954 m_port = port;
955 m_userinfo = userinfo;
956 return true;
957 }
958 // Note: Registry based authority is being removed from a
959 // new spec for URI which would obsolete RFC 2396. If the
960 // spec is added to XML errata, processing of reg_name
961 // needs to be removed. - mrglavas.
962 else if (isValidRegistryBasedAuthority(p_uriSpec)) {
963 m_regAuthority = p_uriSpec;
964 return true;
965 }
966 return false;
967 }
968
969 /**
970 * Determines whether the components host, port, and user info
971 * are valid as a server authority.
972 *
973 * @param host the host component of authority
974 * @param port the port number component of authority
975 * @param userinfo the user info component of authority
976 *
977 * @return true if the given host, port, and userinfo compose
978 * a valid server authority
979 */
980 private boolean isValidServerBasedAuthority(String host, int port, String userinfo) {
981
982 // Check if the host is well formed.
983 if (!isWellFormedAddress(host)) {
984 return false;
985 }
986
987 // Check that port is well formed if it exists.
988 // REVISIT: There's no restriction on port value ranges, but
989 // perform the same check as in setPort to be consistent. Pass
990 // in a string to this method instead of an integer.
991 if (port < -1 || port > 65535) {
992 return false;
993 }
994
995 // Check that userinfo is well formed if it exists.
996 if (userinfo != null) {
997 // Userinfo can contain alphanumerics, mark characters, escaped
998 // and ';',':','&','=','+','$',','
999 int index = 0;
1000 int end = userinfo.length();
1001 char testChar = '\0';
1002 while (index < end) {
1003 testChar = userinfo.charAt(index);
1004 if (testChar == '%') {
1005 if (index+2 >= end ||
1006 !isHex(userinfo.charAt(index+1)) ||
1007 !isHex(userinfo.charAt(index+2))) {
1008 return false;
1009 }
1010 index += 2;
1011 }
1012 else if (!isUserinfoCharacter(testChar)) {
1013 return false;
1014 }
1015 ++index;
1016 }
1017 }
1018 return true;
1019 }
1020
1021 /**
1022 * Determines whether the given string is a registry based authority.
1023 *
1024 * @param authority the authority component of a URI
1025 *
1026 * @return true if the given string is a registry based authority
1027 */
1028 private boolean isValidRegistryBasedAuthority(String authority) {
1029 int index = 0;
1030 int end = authority.length();
1031 char testChar;
1032
1033 while (index < end) {
1034 testChar = authority.charAt(index);
1035
1036 // check for valid escape sequence
1037 if (testChar == '%') {
1038 if (index+2 >= end ||
1039 !isHex(authority.charAt(index+1)) ||
1040 !isHex(authority.charAt(index+2))) {
1041 return false;
1042 }
1043 index += 2;
1044 }
1045 // can check against path characters because the set
1046 // is the same except for '/' which we've already excluded.
1047 else if (!isPathCharacter(testChar)) {
1048 return false;
1049 }
1050 ++index;
1051 }
1052 return true;
1053 }
1054
1055 /**
1056 * Initialize the path for this URI from a URI string spec.
1057 *
1058 * @param p_uriSpec the URI specification (cannot be null)
1059 * @param p_nStartIndex the index to begin scanning from
1060 *
1061 * @exception MalformedURIException if p_uriSpec violates syntax rules
1062 */
1063 private void initializePath(String p_uriSpec, int p_nStartIndex)
1064 throws MalformedURIException {
1065 if (p_uriSpec == null) {
1066 throw new MalformedURIException(
1067 "Cannot initialize path from null string!");
1068 }
1069
1070 int index = p_nStartIndex;
1071 int start = p_nStartIndex;
1072 int end = p_uriSpec.length();
1073 char testChar = '\0';
1074
1075 // path - everything up to query string or fragment
1076 if (start < end) {
1077 // RFC 2732 only allows '[' and ']' to appear in the opaque part.
1078 if (getScheme() == null || p_uriSpec.charAt(start) == '/') {
1079
1080 // Scan path.
1081 // abs_path = "/" path_segments
1082 // rel_path = rel_segment [ abs_path ]
1083 while (index < end) {
1084 testChar = p_uriSpec.charAt(index);
1085
1086 // check for valid escape sequence
1087 if (testChar == '%') {
1088 if (index+2 >= end ||
1089 !isHex(p_uriSpec.charAt(index+1)) ||
1090 !isHex(p_uriSpec.charAt(index+2))) {
1091 throw new MalformedURIException(
1092 "Path contains invalid escape sequence!");
1093 }
1094 index += 2;
1095 }
1096 // Path segments cannot contain '[' or ']' since pchar
1097 // production was not changed by RFC 2732.
1098 else if (!isPathCharacter(testChar)) {
1099 if (testChar == '?' || testChar == '#') {
1100 break;
1101 }
1102 throw new MalformedURIException(
1103 "Path contains invalid character: " + testChar);
1104 }
1105 ++index;
1106 }
1107 }
1108 else {
1109
1110 // Scan opaque part.
1111 // opaque_part = uric_no_slash *uric
1112 while (index < end) {
1113 testChar = p_uriSpec.charAt(index);
1114
1115 if (testChar == '?' || testChar == '#') {
1116 break;
1117 }
1118
1119 // check for valid escape sequence
1120 if (testChar == '%') {
1121 if (index+2 >= end ||
1122 !isHex(p_uriSpec.charAt(index+1)) ||
1123 !isHex(p_uriSpec.charAt(index+2))) {
1124 throw new MalformedURIException(
1125 "Opaque part contains invalid escape sequence!");
1126 }
1127 index += 2;
1128 }
1129 // If the scheme specific part is opaque, it can contain '['
1130 // and ']'. uric_no_slash wasn't modified by RFC 2732, which
1131 // I've interpreted as an error in the spec, since the
1132 // production should be equivalent to (uric - '/'), and uric
1133 // contains '[' and ']'. - mrglavas
1134 else if (!isURICharacter(testChar)) {
1135 throw new MalformedURIException(
1136 "Opaque part contains invalid character: " + testChar);
1137 }
1138 ++index;
1139 }
1140 }
1141 }
1142 m_path = p_uriSpec.substring(start, index);
1143
1144 // query - starts with ? and up to fragment or end
1145 if (testChar == '?') {
1146 index++;
1147 start = index;
1148 while (index < end) {
1149 testChar = p_uriSpec.charAt(index);
1150 if (testChar == '#') {
1151 break;
1152 }
1153 if (testChar == '%') {
1154 if (index+2 >= end ||
1155 !isHex(p_uriSpec.charAt(index+1)) ||
1156 !isHex(p_uriSpec.charAt(index+2))) {
1157 throw new MalformedURIException(
1158 "Query string contains invalid escape sequence!");
1159 }
1160 index += 2;
1161 }
1162 else if (!isURICharacter(testChar)) {
1163 throw new MalformedURIException(
1164 "Query string contains invalid character: " + testChar);
1165 }
1166 index++;
1167 }
1168 m_queryString = p_uriSpec.substring(start, index);
1169 }
1170
1171 // fragment - starts with #
1172 if (testChar == '#') {
1173 index++;
1174 start = index;
1175 while (index < end) {
1176 testChar = p_uriSpec.charAt(index);
1177
1178 if (testChar == '%') {
1179 if (index+2 >= end ||
1180 !isHex(p_uriSpec.charAt(index+1)) ||
1181 !isHex(p_uriSpec.charAt(index+2))) {
1182 throw new MalformedURIException(
1183 "Fragment contains invalid escape sequence!");
1184 }
1185 index += 2;
1186 }
1187 else if (!isURICharacter(testChar)) {
1188 throw new MalformedURIException(
1189 "Fragment contains invalid character: "+testChar);
1190 }
1191 index++;
1192 }
1193 m_fragment = p_uriSpec.substring(start, index);
1194 }
1195 }
1196
1197 /**
1198 * Get the scheme for this URI.
1199 *
1200 * @return the scheme for this URI
1201 */
1202 public String getScheme() {
1203 return m_scheme;
1204 }
1205
1206 /**
1207 * Get the scheme-specific part for this URI (everything following the
1208 * scheme and the first colon). See RFC 2396 Section 5.2 for spec.
1209 *
1210 * @return the scheme-specific part for this URI
1211 */
1212 public String getSchemeSpecificPart() {
1213 StringBuffer schemespec = new StringBuffer();
1214
1215 if (m_host != null || m_regAuthority != null) {
1216 schemespec.append("//");
1217
1218 // Server based authority.
1219 if (m_host != null) {
1220
1221 if (m_userinfo != null) {
1222 schemespec.append(m_userinfo);
1223 schemespec.append('@');
1224 }
1225
1226 schemespec.append(m_host);
1227
1228 if (m_port != -1) {
1229 schemespec.append(':');
1230 schemespec.append(m_port);
1231 }
1232 }
1233 // Registry based authority.
1234 else {
1235 schemespec.append(m_regAuthority);
1236 }
1237 }
1238
1239 if (m_path != null) {
1240 schemespec.append((m_path));
1241 }
1242
1243 if (m_queryString != null) {
1244 schemespec.append('?');
1245 schemespec.append(m_queryString);
1246 }
1247
1248 if (m_fragment != null) {
1249 schemespec.append('#');
1250 schemespec.append(m_fragment);
1251 }
1252
1253 return schemespec.toString();
1254 }
1255
1256 /**
1257 * Get the userinfo for this URI.
1258 *
1259 * @return the userinfo for this URI (null if not specified).
1260 */
1261 public String getUserinfo() {
1262 return m_userinfo;
1263 }
1264
1265 /**
1266 * Get the host for this URI.
1267 *
1268 * @return the host for this URI (null if not specified).
1269 */
1270 public String getHost() {
1271 return m_host;
1272 }
1273
1274 /**
1275 * Get the port for this URI.
1276 *
1277 * @return the port for this URI (-1 if not specified).
1278 */
1279 public int getPort() {
1280 return m_port;
1281 }
1282
1283 /**
1284 * Get the registry based authority for this URI.
1285 *
1286 * @return the registry based authority (null if not specified).
1287 */
1288 public String getRegBasedAuthority() {
1289 return m_regAuthority;
1290 }
1291
1292 /**
1293 * Get the path for this URI (optionally with the query string and
1294 * fragment).
1295 *
1296 * @param p_includeQueryString if true (and query string is not null),
1297 * then a "?" followed by the query string
1298 * will be appended
1299 * @param p_includeFragment if true (and fragment is not null),
1300 * then a "#" followed by the fragment
1301 * will be appended
1302 *
1303 * @return the path for this URI possibly including the query string
1304 * and fragment
1305 */
1306 public String getPath(boolean p_includeQueryString,
1307 boolean p_includeFragment) {
1308 StringBuffer pathString = new StringBuffer(m_path);
1309
1310 if (p_includeQueryString && m_queryString != null) {
1311 pathString.append('?');
1312 pathString.append(m_queryString);
1313 }
1314
1315 if (p_includeFragment && m_fragment != null) {
1316 pathString.append('#');
1317 pathString.append(m_fragment);
1318 }
1319 return pathString.toString();
1320 }
1321
1322 /**
1323 * Get the path for this URI. Note that the value returned is the path
1324 * only and does not include the query string or fragment.
1325 *
1326 * @return the path for this URI.
1327 */
1328 public String getPath() {
1329 return m_path;
1330 }
1331
1332 /**
1333 * Get the query string for this URI.
1334 *
1335 * @return the query string for this URI. Null is returned if there
1336 * was no "?" in the URI spec, empty string if there was a
1337 * "?" but no query string following it.
1338 */
1339 public String getQueryString() {
1340 return m_queryString;
1341 }
1342
1343 /**
1344 * Get the fragment for this URI.
1345 *
1346 * @return the fragment for this URI. Null is returned if there
1347 * was no "#" in the URI spec, empty string if there was a
1348 * "#" but no fragment following it.
1349 */
1350 public String getFragment() {
1351 return m_fragment;
1352 }
1353
1354 /**
1355 * Set the scheme for this URI. The scheme is converted to lowercase
1356 * before it is set.
1357 *
1358 * @param p_scheme the scheme for this URI (cannot be null)
1359 *
1360 * @exception MalformedURIException if p_scheme is not a conformant
1361 * scheme name
1362 */
1363 public void setScheme(String p_scheme) throws MalformedURIException {
1364 if (p_scheme == null) {
1365 throw new MalformedURIException(
1366 "Cannot set scheme from null string!");
1367 }
1368 if (!isConformantSchemeName(p_scheme)) {
1369 throw new MalformedURIException("The scheme is not conformant.");
1370 }
1371
1372 m_scheme = p_scheme.toLowerCase();
1373 }
1374
1375 /**
1376 * Set the userinfo for this URI. If a non-null value is passed in and
1377 * the host value is null, then an exception is thrown.
1378 *
1379 * @param p_userinfo the userinfo for this URI
1380 *
1381 * @exception MalformedURIException if p_userinfo contains invalid
1382 * characters
1383 */
1384 public void setUserinfo(String p_userinfo) throws MalformedURIException {
1385 if (p_userinfo == null) {
1386 m_userinfo = null;
1387 return;
1388 }
1389 else {
1390 if (m_host == null) {
1391 throw new MalformedURIException(
1392 "Userinfo cannot be set when host is null!");
1393 }
1394
1395 // userinfo can contain alphanumerics, mark characters, escaped
1396 // and ';',':','&','=','+','$',','
1397 int index = 0;
1398 int end = p_userinfo.length();
1399 char testChar = '\0';
1400 while (index < end) {
1401 testChar = p_userinfo.charAt(index);
1402 if (testChar == '%') {
1403 if (index+2 >= end ||
1404 !isHex(p_userinfo.charAt(index+1)) ||
1405 !isHex(p_userinfo.charAt(index+2))) {
1406 throw new MalformedURIException(
1407 "Userinfo contains invalid escape sequence!");
1408 }
1409 }
1410 else if (!isUserinfoCharacter(testChar)) {
1411 throw new MalformedURIException(
1412 "Userinfo contains invalid character:"+testChar);
1413 }
1414 index++;
1415 }
1416 }
1417 m_userinfo = p_userinfo;
1418 }
1419
1420 /**
1421 * <p>Set the host for this URI. If null is passed in, the userinfo
1422 * field is also set to null and the port is set to -1.</p>
1423 *
1424 * <p>Note: This method overwrites registry based authority if it
1425 * previously existed in this URI.</p>
1426 *
1427 * @param p_host the host for this URI
1428 *
1429 * @exception MalformedURIException if p_host is not a valid IP
1430 * address or DNS hostname.
1431 */
1432 public void setHost(String p_host) throws MalformedURIException {
1433 if (p_host == null || p_host.length() == 0) {
1434 if (p_host != null) {
1435 m_regAuthority = null;
1436 }
1437 m_host = p_host;
1438 m_userinfo = null;
1439 m_port = -1;
1440 return;
1441 }
1442 else if (!isWellFormedAddress(p_host)) {
1443 throw new MalformedURIException("Host is not a well formed address!");
1444 }
1445 m_host = p_host;
1446 m_regAuthority = null;
1447 }
1448
1449 /**
1450 * Set the port for this URI. -1 is used to indicate that the port is
1451 * not specified, otherwise valid port numbers are between 0 and 65535.
1452 * If a valid port number is passed in and the host field is null,
1453 * an exception is thrown.
1454 *
1455 * @param p_port the port number for this URI
1