src/main/java/org/wymiwyg/commons/util/URI.java
private void initialize(URI p_base, String p_uriSpec)
		throws MalformedURIException {
		if (p_base == null && (p_uriSpec == null || p_uriSpec.length() == 0)) {
			throw new RelativeURIException("Cannot initialize URI with empty parameters.");
		}

		// just make a copy of the base if spec is empty
		if (p_uriSpec == null || p_uriSpec.length() == 0) {
			initialize(p_base);
			return;
		}

		String uriSpec = p_uriSpec;
		int uriSpecLen = uriSpec.length();
		int index = 0;

		// Check for scheme, which must be before '/', '?' or '#'. Also handle
		// names with DOS drive letters ('D:'), so 1-character schemes are not
		// allowed.
		int colonIdx = uriSpec.indexOf(':');
		int slashIdx = uriSpec.indexOf('/');
		int queryIdx = uriSpec.indexOf('?');
		int fragmentIdx = uriSpec.indexOf('#');

		if ((colonIdx < 2)
			|| (colonIdx > slashIdx && slashIdx != -1)
			|| (colonIdx > queryIdx && queryIdx != -1)
			|| (colonIdx > fragmentIdx && fragmentIdx != -1)) {
			// We need to do the relative URI algorithm:

			// jjc: the spec says:
			// 'URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]'
			// My understanding is that if there is only the fragment
			// then this is a relative URI.
			if (p_base == null // del jjc: && fragmentIdx != 0
			) {
				// Nothing to be relative against.
				throw new RelativeURIException("No scheme found in URI." + p_uriSpec );
			} else {
				if ((!p_base.isGenericURI()) && fragmentIdx != 0)
					// Can't be relative against opaque URI (except using the #frag).
					throw new MalformedURIException("Cannot apply relative URI to an opaque URI");
			}
		} else {
			initializeScheme(uriSpec);
			index = m_scheme.length() + 1;
		}

		// two slashes means generic URI syntax, so we get the authority
		if (((index + 1) < uriSpecLen)
			&& (uriSpec.substring(index).startsWith("//"))) {
			index += 2;
			int startPos = index;

			// get authority - everything up to path, query or fragment
			char testChar = '\0';
			while (index < uriSpecLen) {
				testChar = uriSpec.charAt(index);
				if (testChar == '/' || testChar == '?' || testChar == '#') {
					break;
				}
				index++;
			}

			// if we found authority, parse it out, otherwise we set the
			// host to empty string
			if (index > startPos) {
				initializeAuthority(uriSpec.substring(startPos, index));
			} else {
				m_host = "";
			}
		}

		initializePath(uriSpec.substring(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) {

			// 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_scheme = p_base.getScheme();
				m_userinfo = p_base.getUserinfo();
				m_host = p_base.getHost();
				m_port = p_base.m_port;
				n_port = p_base.getPort();
				m_path = p_base.getPath();

				if (m_queryString == null) {
					m_queryString = p_base.getQueryString();
				}
				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_userinfo = p_base.getUserinfo();
				m_host = p_base.getHost();
				m_port = p_base.m_port;
				n_port = p_base.getPort();
			} 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 = // jjc new String();
	"/"; // jjc ins
			String basePath = p_base.getPath();

			// 6a - get all but the last segment of the base URI path
			if (basePath != null) {
				int lastSlash = basePath.lastIndexOf('/');
				if (lastSlash != -1) {
					path = basePath.substring(0, lastSlash + 1);
				}
			}

			// 6b - append the relative URI path
			path = path.concat(m_path);

			// 6c - remove all "./" where "." is a complete path segment
			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 "<segment>" is a complete
			// path segment not equal to ".."
			index = 1;
			int segIndex = -1;

			while ((index = path.indexOf("/../", index)) > 0) {
				segIndex = path.lastIndexOf('/', index - 1);
				if (segIndex != -1
					&& !path.substring(segIndex + 1, index).equals("..")) {
					path =
						path.substring(0, segIndex).concat(
							path.substring(index + 3));
					index = segIndex;
				} else {
					index += 4;
				}
			}

			// 6f - remove ending "<segment>/.." where "<segment>" is a
			// complete path segment
			if (path.endsWith("/..")) {
				index = path.length() - 3;
				segIndex = path.lastIndexOf('/', index - 1);
				if (segIndex != -1
					&& !path.substring(segIndex + 1, index).equals("..")) {
					path = path.substring(0, segIndex + 1);
				}
			}

			m_path = path;
		}
	}
private void initialize(URI p_base, String p_uriSpec)
		throws MalformedURIException {
		if (p_base == null && (p_uriSpec == null || p_uriSpec.length() == 0)) {
			throw new RelativeURIException("Cannot initialize URI with empty parameters.");
		}

		// just make a copy of the base if spec is empty
		if (p_uriSpec == null || p_uriSpec.length() == 0) {
			initialize(p_base);
			return;
		}

		String uriSpec = p_uriSpec;
		int uriSpecLen = uriSpec.length();
		int index = 0;

		// Check for scheme, which must be before '/', '?' or '#'. Also handle
		// names with DOS drive letters ('D:'), so 1-character schemes are not
		// allowed.
		int colonIdx = uriSpec.indexOf(':');
		int slashIdx = uriSpec.indexOf('/');
		int queryIdx = uriSpec.indexOf('?');
		int fragmentIdx = uriSpec.indexOf('#');

		if ((colonIdx < 2)
			|| (colonIdx > slashIdx && slashIdx != -1)
			|| (colonIdx > queryIdx && queryIdx != -1)
			|| (colonIdx > fragmentIdx && fragmentIdx != -1)) {
			// We need to do the relative URI algorithm:

			// jjc: the spec says:
			// 'URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]'
			// My understanding is that if there is only the fragment
			// then this is a relative URI.
			if (p_base == null // del jjc: && fragmentIdx != 0
			) {
				// Nothing to be relative against.
				throw new RelativeURIException("No scheme found in URI." + p_uriSpec );
			} else {
				if ((!p_base.isGenericURI()) && fragmentIdx != 0)
					// Can't be relative against opaque URI (except using the #frag).
					throw new MalformedURIException("Cannot apply relative URI to an opaque URI");
			}
		} else {
			initializeScheme(uriSpec);
			index = m_scheme.length() + 1;
		}

		// two slashes means generic URI syntax, so we get the authority
		if (((index + 1) < uriSpecLen)
			&& (uriSpec.substring(index).startsWith("//"))) {
			index += 2;
			int startPos = index;

			// get authority - everything up to path, query or fragment
			char testChar = '\0';
			while (index < uriSpecLen) {
				testChar = uriSpec.charAt(index);
				if (testChar == '/' || testChar == '?' || testChar == '#') {
					break;
				}
				index++;
			}

			// if we found authority, parse it out, otherwise we set the
			// host to empty string
			if (index > startPos) {
				initializeAuthority(uriSpec.substring(startPos, index));
			} else {
				m_host = "";
			}
		}

		initializePath(uriSpec.substring(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) {

			// 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_scheme = p_base.getScheme();
				m_userinfo = p_base.getUserinfo();
				m_host = p_base.getHost();
				m_port = p_base.m_port;
				n_port = p_base.getPort();
				m_path = p_base.getPath();

				if (m_queryString == null) {
					m_queryString = p_base.getQueryString();
				}
				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_userinfo = p_base.getUserinfo();
				m_host = p_base.getHost();
				m_port = p_base.m_port;
				n_port = p_base.getPort();
			} 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 = // jjc new String();
	"/"; // jjc ins
			String basePath = p_base.getPath();

			// 6a - get all but the last segment of the base URI path
			if (basePath != null) {
				int lastSlash = basePath.lastIndexOf('/');
				if (lastSlash != -1) {
					path = basePath.substring(0, lastSlash + 1);
				}
			}

			// 6b - append the relative URI path
			path = path.concat(m_path);

			// 6c - remove all "./" where "." is a complete path segment
			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 "<segment>" is a complete
			// path segment not equal to ".."
			index = 1;
			int segIndex = -1;

			while ((index = path.indexOf("/../", index)) > 0) {
				segIndex = path.lastIndexOf('/', index - 1);
				if (segIndex != -1
					&& !path.substring(segIndex + 1, index).equals("..")) {
					path =
						path.substring(0, segIndex).concat(
							path.substring(index + 3));
					index = segIndex;
				} else {
					index += 4;
				}
			}

			// 6f - remove ending "<segment>/.." where "<segment>" is a
			// complete path segment
			if (path.endsWith("/..")) {
				index = path.length() - 3;
				segIndex = path.lastIndexOf('/', index - 1);
				if (segIndex != -1
					&& !path.substring(segIndex + 1, index).equals("..")) {
					path = path.substring(0, segIndex + 1);
				}
			}

			m_path = path;
		}
	}
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