|
Java example source code file (URI.java)
The URI.java Java example source code
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xerces.internal.util;
import java.io.IOException;
import java.io.Serializable;
import java.util.Objects;
/**********************************************************************
* A class to represent a Uniform Resource Identifier (URI). This class
* is designed to handle the parsing of URIs and provide access to
* the various components (scheme, host, port, userinfo, path, query
* string and fragment) that may constitute a URI.
* <p>
* Parsing of a URI specification is done according to the URI
* syntax described in
* <a href="http://www.ietf.org/rfc/rfc2396.txt?number=2396">RFC 2396,
* and amended by
* <a href="http://www.ietf.org/rfc/rfc2732.txt?number=2732">RFC 2732.
* <p>
* Every absolute URI consists of a scheme, followed by a colon (':'),
* followed by a scheme-specific part. For URIs that follow the
* "generic URI" syntax, the scheme-specific part begins with two
* slashes ("//") and may be followed by an authority segment (comprised
* of user information, host, and port), path segment, query segment
* and fragment. Note that RFC 2396 no longer specifies the use of the
* parameters segment and excludes the "user:password" syntax as part of
* the authority segment. If "user:password" appears in a URI, the entire
* user/password string is stored as userinfo.
* <p>
* For URIs that do not follow the "generic URI" syntax (e.g. mailto),
* the entire scheme-specific part is treated as the "path" portion
* of the URI.
* <p>
* Note that, unlike the java.net.URL class, this class does not provide
* any built-in network access functionality nor does it provide any
* scheme-specific functionality (for example, it does not know a
* default port for a specific scheme). Rather, it only knows the
* grammar and basic set of operations that can be applied to a URI.
*
*
**********************************************************************/
public class URI implements Serializable {
/*******************************************************************
* MalformedURIExceptions are thrown in the process of building a URI
* or setting fields on a URI when an operation would result in an
* invalid URI specification.
*
********************************************************************/
public static class MalformedURIException extends IOException {
/** Serialization version. */
static final long serialVersionUID = -6695054834342951930L;
/******************************************************************
* Constructs a <code>MalformedURIException with no specified
* detail message.
******************************************************************/
public MalformedURIException() {
super();
}
/*****************************************************************
* Constructs a <code>MalformedURIException with the
* specified detail message.
*
* @param p_msg the detail message.
******************************************************************/
public MalformedURIException(String p_msg) {
super(p_msg);
}
}
/** Serialization version. */
static final long serialVersionUID = 1601921774685357214L;
private static final byte [] fgLookupTable = new byte[128];
/**
* Character Classes
*/
/** reserved characters ;/?:@&=+$,[] */
//RFC 2732 added '[' and ']' as reserved characters
private static final int RESERVED_CHARACTERS = 0x01;
/** URI punctuation mark characters: -_.!~*'() - these, combined with
alphanumerics, constitute the "unreserved" characters */
private static final int MARK_CHARACTERS = 0x02;
/** scheme can be composed of alphanumerics and these characters: +-. */
private static final int SCHEME_CHARACTERS = 0x04;
/** userinfo can be composed of unreserved, escaped and these
characters: ;:&=+$, */
private static final int USERINFO_CHARACTERS = 0x08;
/** ASCII letter characters */
private static final int ASCII_ALPHA_CHARACTERS = 0x10;
/** ASCII digit characters */
private static final int ASCII_DIGIT_CHARACTERS = 0x20;
/** ASCII hex characters */
private static final int ASCII_HEX_CHARACTERS = 0x40;
/** Path characters */
private static final int PATH_CHARACTERS = 0x80;
/** Mask for alpha-numeric characters */
private static final int MASK_ALPHA_NUMERIC = ASCII_ALPHA_CHARACTERS | ASCII_DIGIT_CHARACTERS;
/** Mask for unreserved characters */
private static final int MASK_UNRESERVED_MASK = MASK_ALPHA_NUMERIC | MARK_CHARACTERS;
/** Mask for URI allowable characters except for % */
private static final int MASK_URI_CHARACTER = MASK_UNRESERVED_MASK | RESERVED_CHARACTERS;
/** Mask for scheme characters */
private static final int MASK_SCHEME_CHARACTER = MASK_ALPHA_NUMERIC | SCHEME_CHARACTERS;
/** Mask for userinfo characters */
private static final int MASK_USERINFO_CHARACTER = MASK_UNRESERVED_MASK | USERINFO_CHARACTERS;
/** Mask for path characters */
private static final int MASK_PATH_CHARACTER = MASK_UNRESERVED_MASK | PATH_CHARACTERS;
static {
// Add ASCII Digits and ASCII Hex Numbers
for (int i = '0'; i <= '9'; ++i) {
fgLookupTable[i] |= ASCII_DIGIT_CHARACTERS | ASCII_HEX_CHARACTERS;
}
// Add ASCII Letters and ASCII Hex Numbers
for (int i = 'A'; i <= 'F'; ++i) {
fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS;
fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS;
}
// Add ASCII Letters
for (int i = 'G'; i <= 'Z'; ++i) {
fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS;
fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS;
}
// Add Reserved Characters
fgLookupTable[';'] |= RESERVED_CHARACTERS;
fgLookupTable['/'] |= RESERVED_CHARACTERS;
fgLookupTable['?'] |= RESERVED_CHARACTERS;
fgLookupTable[':'] |= RESERVED_CHARACTERS;
fgLookupTable['@'] |= RESERVED_CHARACTERS;
fgLookupTable['&'] |= RESERVED_CHARACTERS;
fgLookupTable['='] |= RESERVED_CHARACTERS;
fgLookupTable['+'] |= RESERVED_CHARACTERS;
fgLookupTable['$'] |= RESERVED_CHARACTERS;
fgLookupTable[','] |= RESERVED_CHARACTERS;
fgLookupTable['['] |= RESERVED_CHARACTERS;
fgLookupTable[']'] |= RESERVED_CHARACTERS;
// Add Mark Characters
fgLookupTable['-'] |= MARK_CHARACTERS;
fgLookupTable['_'] |= MARK_CHARACTERS;
fgLookupTable['.'] |= MARK_CHARACTERS;
fgLookupTable['!'] |= MARK_CHARACTERS;
fgLookupTable['~'] |= MARK_CHARACTERS;
fgLookupTable['*'] |= MARK_CHARACTERS;
fgLookupTable['\''] |= MARK_CHARACTERS;
fgLookupTable['('] |= MARK_CHARACTERS;
fgLookupTable[')'] |= MARK_CHARACTERS;
// Add Scheme Characters
fgLookupTable['+'] |= SCHEME_CHARACTERS;
fgLookupTable['-'] |= SCHEME_CHARACTERS;
fgLookupTable['.'] |= SCHEME_CHARACTERS;
// Add Userinfo Characters
fgLookupTable[';'] |= USERINFO_CHARACTERS;
fgLookupTable[':'] |= USERINFO_CHARACTERS;
fgLookupTable['&'] |= USERINFO_CHARACTERS;
fgLookupTable['='] |= USERINFO_CHARACTERS;
fgLookupTable['+'] |= USERINFO_CHARACTERS;
fgLookupTable['$'] |= USERINFO_CHARACTERS;
fgLookupTable[','] |= USERINFO_CHARACTERS;
// Add Path Characters
fgLookupTable[';'] |= PATH_CHARACTERS;
fgLookupTable['/'] |= PATH_CHARACTERS;
fgLookupTable[':'] |= PATH_CHARACTERS;
fgLookupTable['@'] |= PATH_CHARACTERS;
fgLookupTable['&'] |= PATH_CHARACTERS;
fgLookupTable['='] |= PATH_CHARACTERS;
fgLookupTable['+'] |= PATH_CHARACTERS;
fgLookupTable['$'] |= PATH_CHARACTERS;
fgLookupTable[','] |= PATH_CHARACTERS;
}
/** Stores the scheme (usually the protocol) for this URI. */
private String m_scheme = null;
/** If specified, stores the userinfo for this URI; otherwise null */
private String m_userinfo = null;
/** If specified, stores the host for this URI; otherwise null */
private String m_host = null;
/** If specified, stores the port for this URI; otherwise -1 */
private int m_port = -1;
/** If specified, stores the registry based authority for this URI; otherwise -1 */
private String m_regAuthority = null;
/** If specified, stores the path for this URI; otherwise null */
private String m_path = null;
/** If specified, stores the query string for this URI; otherwise
null. */
private String m_queryString = null;
/** If specified, stores the fragment for this URI; otherwise null */
private String m_fragment = null;
private static boolean DEBUG = false;
/**
* Construct a new and uninitialized URI.
*/
public URI() {
}
/**
* Construct a new URI from another URI. All fields for this URI are
* set equal to the fields of the URI passed in.
*
* @param p_other the URI to copy (cannot be null)
*/
public URI(URI p_other) {
initialize(p_other);
}
/**
* Construct a new URI from a URI specification string. If the
* specification follows the "generic URI" syntax, (two slashes
* following the first colon), the specification will be parsed
* accordingly - setting the scheme, userinfo, host,port, path, query
* string and fragment fields as necessary. If the specification does
* not follow the "generic URI" syntax, the specification is parsed
* into a scheme and scheme-specific part (stored as the path) only.
*
* @param p_uriSpec the URI specification string (cannot be null or
* empty)
*
* @exception MalformedURIException if p_uriSpec violates any syntax
* rules
*/
public URI(String p_uriSpec) throws MalformedURIException {
this((URI)null, p_uriSpec);
}
/**
* Construct a new URI from a URI specification string. If the
* specification follows the "generic URI" syntax, (two slashes
* following the first colon), the specification will be parsed
* accordingly - setting the scheme, userinfo, host,port, path, query
* string and fragment fields as necessary. If the specification does
* not follow the "generic URI" syntax, the specification is parsed
* into a scheme and scheme-specific part (stored as the path) only.
* Construct a relative URI if boolean is assigned to "true"
* and p_uriSpec is not valid absolute URI, instead of throwing an exception.
*
* @param p_uriSpec the URI specification string (cannot be null or
* empty)
* @param allowNonAbsoluteURI true to permit non-absolute URIs,
* false otherwise.
*
* @exception MalformedURIException if p_uriSpec violates any syntax
* rules
*/
public URI(String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException {
this((URI)null, p_uriSpec, allowNonAbsoluteURI);
}
/**
* Construct a new URI from a base URI and a URI specification string.
* The URI specification string may be a relative URI.
*
* @param p_base the base URI (cannot be null if p_uriSpec is null or
* empty)
* @param p_uriSpec the URI specification string (cannot be null or
* empty if p_base is null)
*
* @exception MalformedURIException if p_uriSpec violates any syntax
* rules
*/
public URI(URI p_base, String p_uriSpec) throws MalformedURIException {
initialize(p_base, p_uriSpec);
}
/**
* Construct a new URI from a base URI and a URI specification string.
* The URI specification string may be a relative URI.
* Construct a relative URI if boolean is assigned to "true"
* and p_uriSpec is not valid absolute URI and p_base is null
* instead of throwing an exception.
*
* @param p_base the base URI (cannot be null if p_uriSpec is null or
* empty)
* @param p_uriSpec the URI specification string (cannot be null or
* empty if p_base is null)
* @param allowNonAbsoluteURI true to permit non-absolute URIs,
* false otherwise.
*
* @exception MalformedURIException if p_uriSpec violates any syntax
* rules
*/
public URI(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException {
initialize(p_base, p_uriSpec, allowNonAbsoluteURI);
}
/**
* Construct a new URI that does not follow the generic URI syntax.
* Only the scheme and scheme-specific part (stored as the path) are
* initialized.
*
* @param p_scheme the URI scheme (cannot be null or empty)
* @param p_schemeSpecificPart the scheme-specific part (cannot be
* null or empty)
*
* @exception MalformedURIException if p_scheme violates any
* syntax rules
*/
public URI(String p_scheme, String p_schemeSpecificPart)
throws MalformedURIException {
if (p_scheme == null || p_scheme.trim().length() == 0) {
throw new MalformedURIException(
"Cannot construct URI with null/empty scheme!");
}
if (p_schemeSpecificPart == null ||
p_schemeSpecificPart.trim().length() == 0) {
throw new MalformedURIException(
"Cannot construct URI with null/empty scheme-specific part!");
}
setScheme(p_scheme);
setPath(p_schemeSpecificPart);
}
/**
* Construct a new URI that follows the generic URI syntax from its
* component parts. Each component is validated for syntax and some
* basic semantic checks are performed as well. See the individual
* setter methods for specifics.
*
* @param p_scheme the URI scheme (cannot be null or empty)
* @param p_host the hostname, IPv4 address or IPv6 reference for the URI
* @param p_path the URI path - if the path contains '?' or '#',
* then the query string and/or fragment will be
* set from the path; however, if the query and
* fragment are specified both in the path and as
* separate parameters, an exception is thrown
* @param p_queryString the URI query string (cannot be specified
* if path is null)
* @param p_fragment the URI fragment (cannot be specified if path
* is null)
*
* @exception MalformedURIException if any of the parameters violates
* syntax rules or semantic rules
*/
public URI(String p_scheme, String p_host, String p_path,
String p_queryString, String p_fragment)
throws MalformedURIException {
this(p_scheme, null, p_host, -1, p_path, p_queryString, p_fragment);
}
/**
* Construct a new URI that follows the generic URI syntax from its
* component parts. Each component is validated for syntax and some
* basic semantic checks are performed as well. See the individual
* setter methods for specifics.
*
* @param p_scheme the URI scheme (cannot be null or empty)
* @param p_userinfo the URI userinfo (cannot be specified if host
* is null)
* @param p_host the hostname, IPv4 address or IPv6 reference for the URI
* @param p_port the URI port (may be -1 for "unspecified"; cannot
* be specified if host is null)
* @param p_path the URI path - if the path contains '?' or '#',
* then the query string and/or fragment will be
* set from the path; however, if the query and
* fragment are specified both in the path and as
* separate parameters, an exception is thrown
* @param p_queryString the URI query string (cannot be specified
* if path is null)
* @param p_fragment the URI fragment (cannot be specified if path
* is null)
*
* @exception MalformedURIException if any of the parameters violates
* syntax rules or semantic rules
*/
public URI(String p_scheme, String p_userinfo,
String p_host, int p_port, String p_path,
String p_queryString, String p_fragment)
throws MalformedURIException {
if (p_scheme == null || p_scheme.trim().length() == 0) {
throw new MalformedURIException("Scheme is required!");
}
if (p_host == null) {
if (p_userinfo != null) {
throw new MalformedURIException(
"Userinfo may not be specified if host is not specified!");
}
if (p_port != -1) {
throw new MalformedURIException(
"Port may not be specified if host is not specified!");
}
}
if (p_path != null) {
if (p_path.indexOf('?') != -1 && p_queryString != null) {
throw new MalformedURIException(
"Query string cannot be specified in path and query string!");
}
if (p_path.indexOf('#') != -1 && p_fragment != null) {
throw new MalformedURIException(
"Fragment cannot be specified in both the path and fragment!");
}
}
setScheme(p_scheme);
setHost(p_host);
setPort(p_port);
setUserinfo(p_userinfo);
setPath(p_path);
setQueryString(p_queryString);
setFragment(p_fragment);
}
/**
* Initialize all fields of this URI from another URI.
*
* @param p_other the URI to copy (cannot be null)
*/
private void initialize(URI p_other) {
m_scheme = p_other.getScheme();
m_userinfo = p_other.getUserinfo();
m_host = p_other.getHost();
m_port = p_other.getPort();
m_regAuthority = p_other.getRegBasedAuthority();
m_path = p_other.getPath();
m_queryString = p_other.getQueryString();
m_fragment = p_other.getFragment();
}
/**
* Initializes this URI from a base URI and a URI specification string.
* See RFC 2396 Section 4 and Appendix B for specifications on parsing
* the URI and Section 5 for specifications on resolving relative URIs
* and relative paths.
*
* @param p_base the base URI (may be null if p_uriSpec is an absolute
* URI)
* @param p_uriSpec the URI spec string which may be an absolute or
* relative URI (can only be null/empty if p_base
* is not null)
* @param allowNonAbsoluteURI true to permit non-absolute URIs,
* in case of relative URI, false otherwise.
*
* @exception MalformedURIException if p_base is null and p_uriSpec
* is not an absolute URI or if
* p_uriSpec violates syntax rules
*/
private void initialize(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI)
throws MalformedURIException {
String uriSpec = p_uriSpec;
int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0;
if (p_base == null && uriSpecLen == 0) {
if (allowNonAbsoluteURI) {
m_path = "";
return;
}
throw new MalformedURIException("Cannot initialize URI with empty parameters.");
}
// just make a copy of the base if spec is empty
if (uriSpecLen == 0) {
initialize(p_base);
return;
}
int index = 0;
// Check for scheme, which must be before '/', '?' or '#'.
int colonIdx = uriSpec.indexOf(':');
if (colonIdx != -1) {
final int searchFrom = colonIdx - 1;
// search backwards starting from character before ':'.
int slashIdx = uriSpec.lastIndexOf('/', searchFrom);
int queryIdx = uriSpec.lastIndexOf('?', searchFrom);
int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom);
if (colonIdx == 0 || slashIdx != -1 ||
queryIdx != -1 || fragmentIdx != -1) {
// A standalone base is a valid URI according to spec
if (colonIdx == 0 || (p_base == null && fragmentIdx != 0 && !allowNonAbsoluteURI)) {
throw new MalformedURIException("No scheme found in URI.");
}
}
else {
initializeScheme(uriSpec);
index = m_scheme.length()+1;
// Neither 'scheme:' or 'scheme:#fragment' are valid URIs.
if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') {
throw new MalformedURIException("Scheme specific part cannot be empty.");
}
}
}
else if (p_base == null && uriSpec.indexOf('#') != 0 && !allowNonAbsoluteURI) {
throw new MalformedURIException("No scheme found in URI.");
}
// Two slashes means we may have authority, but definitely means we're either
// matching net_path or abs_path. These two productions are ambiguous in that
// every net_path (except those containing an IPv6Reference) is an abs_path.
// RFC 2396 resolves this ambiguity by applying a greedy left most matching rule.
// Try matching net_path first, and if that fails we don't have authority so
// then attempt to match abs_path.
//
// net_path = "//" authority [ abs_path ]
// abs_path = "/" path_segments
if (((index+1) < uriSpecLen) &&
(uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) {
index += 2;
int startPos = index;
// Authority will be everything up to path, query or fragment
char testChar = '\0';
while (index < uriSpecLen) {
testChar = uriSpec.charAt(index);
if (testChar == '/' || testChar == '?' || testChar == '#') {
break;
}
index++;
}
// Attempt to parse authority. If the section is an empty string
// this is a valid server based authority, so set the host to this
// value.
if (index > startPos) {
// If we didn't find authority we need to back up. Attempt to
// match against abs_path next.
if (!initializeAuthority(uriSpec.substring(startPos, index))) {
index = startPos - 2;
}
}
else {
m_host = "";
}
}
initializePath(uriSpec, index);
// Resolve relative URI to base URI - see RFC 2396 Section 5.2
// In some cases, it might make more sense to throw an exception
// (when scheme is specified is the string spec and the base URI
// is also specified, for example), but we're just following the
// RFC specifications
if (p_base != null) {
absolutize(p_base);
}
}
/**
* Initializes this URI from a base URI and a URI specification string.
* See RFC 2396 Section 4 and Appendix B for specifications on parsing
* the URI and Section 5 for specifications on resolving relative URIs
* and relative paths.
*
* @param p_base the base URI (may be null if p_uriSpec is an absolute
* URI)
* @param p_uriSpec the URI spec string which may be an absolute or
* relative URI (can only be null/empty if p_base
* is not null)
*
* @exception MalformedURIException if p_base is null and p_uriSpec
* is not an absolute URI or if
* p_uriSpec violates syntax rules
*/
private void initialize(URI p_base, String p_uriSpec)
throws MalformedURIException {
String uriSpec = p_uriSpec;
int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0;
if (p_base == null && uriSpecLen == 0) {
throw new MalformedURIException(
"Cannot initialize URI with empty parameters.");
}
// just make a copy of the base if spec is empty
if (uriSpecLen == 0) {
initialize(p_base);
return;
}
int index = 0;
// Check for scheme, which must be before '/', '?' or '#'.
int colonIdx = uriSpec.indexOf(':');
if (colonIdx != -1) {
final int searchFrom = colonIdx - 1;
// search backwards starting from character before ':'.
int slashIdx = uriSpec.lastIndexOf('/', searchFrom);
int queryIdx = uriSpec.lastIndexOf('?', searchFrom);
int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom);
if (colonIdx == 0 || slashIdx != -1 ||
queryIdx != -1 || fragmentIdx != -1) {
// A standalone base is a valid URI according to spec
if (colonIdx == 0 || (p_base == null && fragmentIdx != 0)) {
throw new MalformedURIException("No scheme found in URI.");
}
}
else {
initializeScheme(uriSpec);
index = m_scheme.length()+1;
// Neither 'scheme:' or 'scheme:#fragment' are valid URIs.
if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') {
throw new MalformedURIException("Scheme specific part cannot be empty.");
}
}
}
else if (p_base == null && uriSpec.indexOf('#') != 0) {
throw new MalformedURIException("No scheme found in URI.");
}
// Two slashes means we may have authority, but definitely means we're either
// matching net_path or abs_path. These two productions are ambiguous in that
// every net_path (except those containing an IPv6Reference) is an abs_path.
// RFC 2396 resolves this ambiguity by applying a greedy left most matching rule.
// Try matching net_path first, and if that fails we don't have authority so
// then attempt to match abs_path.
//
// net_path = "//" authority [ abs_path ]
// abs_path = "/" path_segments
if (((index+1) < uriSpecLen) &&
(uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) {
index += 2;
int startPos = index;
// Authority will be everything up to path, query or fragment
char testChar = '\0';
while (index < uriSpecLen) {
testChar = uriSpec.charAt(index);
if (testChar == '/' || testChar == '?' || testChar == '#') {
break;
}
index++;
}
// Attempt to parse authority. If the section is an empty string
// this is a valid server based authority, so set the host to this
// value.
if (index > startPos) {
// If we didn't find authority we need to back up. Attempt to
// match against abs_path next.
if (!initializeAuthority(uriSpec.substring(startPos, index))) {
index = startPos - 2;
}
} else if (index < uriSpecLen) {
//Same as java.net.URI:
// DEVIATION: Allow empty authority prior to non-empty
// path, query component or fragment identifier
m_host = "";
} else {
throw new MalformedURIException("Expected authority.");
}
}
initializePath(uriSpec, index);
// Resolve relative URI to base URI - see RFC 2396 Section 5.2
// In some cases, it might make more sense to throw an exception
// (when scheme is specified is the string spec and the base URI
// is also specified, for example), but we're just following the
// RFC specifications
if (p_base != null) {
absolutize(p_base);
}
}
/**
* Absolutize URI with given base URI.
*
* @param p_base base URI for absolutization
*/
public void absolutize(URI p_base) {
// check to see if this is the current doc - RFC 2396 5.2 #2
// note that this is slightly different from the RFC spec in that
// we don't include the check for query string being null
// - this handles cases where the urispec is just a query
// string or a fragment (e.g. "?y" or "#s") -
// see <http://www.ics.uci.edu/~fielding/url/test1.html> which
// identified this as a bug in the RFC
if (m_path.length() == 0 && m_scheme == null &&
m_host == null && m_regAuthority == null) {
m_scheme = p_base.getScheme();
m_userinfo = p_base.getUserinfo();
m_host = p_base.getHost();
m_port = p_base.getPort();
m_regAuthority = p_base.getRegBasedAuthority();
m_path = p_base.getPath();
if (m_queryString == null) {
m_queryString = p_base.getQueryString();
if (m_fragment == null) {
m_fragment = p_base.getFragment();
}
}
return;
}
// check for scheme - RFC 2396 5.2 #3
// if we found a scheme, it means absolute URI, so we're done
if (m_scheme == null) {
m_scheme = p_base.getScheme();
}
else {
return;
}
// check for authority - RFC 2396 5.2 #4
// if we found a host, then we've got a network path, so we're done
if (m_host == null && m_regAuthority == null) {
m_userinfo = p_base.getUserinfo();
m_host = p_base.getHost();
m_port = p_base.getPort();
m_regAuthority = p_base.getRegBasedAuthority();
}
else {
return;
}
// check for absolute path - RFC 2396 5.2 #5
if (m_path.length() > 0 &&
m_path.startsWith("/")) {
return;
}
// if we get to this point, we need to resolve relative path
// RFC 2396 5.2 #6
String path = "";
String basePath = p_base.getPath();
// 6a - get all but the last segment of the base URI path
if (basePath != null && basePath.length() > 0) {
int lastSlash = basePath.lastIndexOf('/');
if (lastSlash != -1) {
path = basePath.substring(0, lastSlash+1);
}
}
else if (m_path.length() > 0) {
path = "/";
}
// 6b - append the relative URI path
path = path.concat(m_path);
// 6c - remove all "./" where "." is a complete path segment
int index = -1;
while ((index = path.indexOf("/./")) != -1) {
path = path.substring(0, index+1).concat(path.substring(index+3));
}
// 6d - remove "." if path ends with "." as a complete path segment
if (path.endsWith("/.")) {
path = path.substring(0, path.length()-1);
}
// 6e - remove all "<segment>/../" where "
Other Java examples (source code examples)Here is a short list of links related to this Java URI.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.