mkwan 2002/11/01 08:24:00
Modified: java/src/org/apache/xml/utils SystemIDResolver.java
Log:
Rework the SystemIDResolver class for Bugzilla 13651 and 13977.
The getAbsoluteURI interfaces have been rewritten so that they always
return a good absolute URI for a systemId string, no matter it is a
URI or a local filesystem path. The path is resolved to be absolute
whenever possible. We also do conversions from space to "%20" and
backslash to forward slash to ensure that the returned URI is a
well-formed URI. The URI might not be in a normalized form because
normalization takes extra cycles.
Revision Changes Path
1.17 +155 -157
xml-xalan/java/src/org/apache/xml/utils/SystemIDResolver.java
Index: SystemIDResolver.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xml/utils/SystemIDResolver.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- SystemIDResolver.java 30 Jul 2002 18:00:00 -0000 1.16
+++ SystemIDResolver.java 1 Nov 2002 16:24:00 -0000 1.17
@@ -57,7 +57,6 @@
package org.apache.xml.utils;
import javax.xml.transform.TransformerException;
-
import org.apache.xml.utils.URI;
import org.apache.xml.utils.URI.MalformedURIException;
@@ -78,196 +77,195 @@
{
/**
- * Get absolute URI from a given relative URI.
+ * Get an absolute URI from a given relative URI (local path).
*
- * <p>The URI is resolved relative to the system property "user.dir"
- * if it is available; if not (i.e. in an Applet perhaps which
- * throws SecurityException) then it is currently resolved
- * relative to "" or a blank string. Also replaces all
- * backslashes with forward slashes.</p>
+ * <p>The relative URI is a local filesystem path. The path can be
+ * absolute or relative. If it is a relative path, it is resolved relative
+ * to the system property "user.dir" if it is available; if not (i.e. in
an
+ * Applet perhaps which throws SecurityException) then we just return the
+ * relative path. The space and backslash characters are also replaced to
+ * generate a good absolute URI.</p>
*
- * @param uri Relative URI to resolve
+ * @param localPath The relative URI to resolve
*
- * @return Resolved absolute URI or the input relative URI if
- * it could not be resolved.
+ * @return Resolved absolute URI
*/
- public static String getAbsoluteURIFromRelative(String uri)
+ public static String getAbsoluteURIFromRelative(String localPath)
{
-
- String curdir = "";
- try {
- curdir = System.getProperty("user.dir");
- }
- catch (SecurityException se) {}// user.dir not accessible from applet
-
- if (null != curdir)
+ // If the local path is absolute, just prepend the scheme part to
+ // generate the absolute URI.
+ String urlString = localPath;
+ if (isAbsolutePath(localPath))
{
- String base;
- if (curdir.startsWith(File.separator))
- base = "file://" + curdir;
- else
- base = "file:///" + curdir;
-
- if (uri != null)
- // Note: this should arguably stick in a '/' forward
- // slash character instead of the file separator,
- // since we're effectively assuming it's a hierarchical
- // URI and adding in the abs_path separator -sc
- uri = base + System.getProperty("file.separator") + uri;
+ if (localPath.startsWith(File.separator))
+ urlString = "file://" + localPath;
else
- uri = base + System.getProperty("file.separator");
+ urlString = "file:///" + localPath;
}
+ // If it is a relative path, the path is resolved against the current
+ // "user.dir" system property.
+ else
+ {
+ String absolutePath = localPath;
+ try {
+ absolutePath = new File(localPath).getAbsolutePath();
+ }
+ // user.dir not accessible from applet
+ catch (SecurityException se) {}
- if (null != uri && (uri.indexOf('\\') > -1))
- uri = uri.replace('\\', '/');
-
- return uri;
+ if (null != absolutePath)
+ {
+ if (absolutePath.startsWith(File.separator))
+ urlString = "file://" + absolutePath;
+ else
+ urlString = "file:///" + absolutePath;
+ }
+ else
+ urlString = "file:///" + localPath;
+ }
+
+ String result = replaceChars(urlString);
+ return result;
+ }
+
+ /**
+ * Return true if the systemId denotes an absolute URI (contains the
scheme part).
+ *
+ * @param systemId The systemId string
+ * @return true if the systemId contains a scheme part
+ */
+ public static boolean isAbsoluteURI(String systemId)
+ {
+ // If there is more than one character before the ':' character,
+ // then it is considered to be an absolute URI; otherwise it is a local
path.
+ int colonIndex = systemId.indexOf(':');
+ if (colonIndex > 1)
+ return true;
+ else
+ return false;
}
/**
- * Take a SystemID string and try and turn it into a good absolute URL.
+ * Return true if the local path is an absolute path.
*
- * @param urlString url A URL string, which may be relative or absolute.
+ * @param systemId The path string
+ * @return true if the path is absolute
+ */
+ public static boolean isAbsolutePath(String systemId)
+ {
+ // On Unix, an absolute path starts with '/'.
+ if (systemId.startsWith(File.separator))
+ return true;
+
+ // On Windows, an absolute path starts with "[drive_letter]:\".
+ if (systemId.length() > 2
+ && systemId.charAt(1) == ':'
+ && Character.isLetter(systemId.charAt(0))
+ && (systemId.charAt(2) == '\\' || systemId.charAt(2) == '/'))
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Replace spaces with "%20" and backslashes with forward slashes in
+ * the input string to generate a well-formed URI string.
*
- * @return The resolved absolute URI
- * @throws TransformerException thrown if the string can't be turned into
a URL.
+ * @param str The input string
+ * @return The string after conversion
*/
- public static String getAbsoluteURI(String url)
- throws TransformerException
+ private static String replaceChars(String str)
{
- if (url.startsWith(".."))
- url = new File(url).getAbsolutePath();
-
- if (url.startsWith(File.separator))
- {
- // If the url starts with a path separator, we assume it's
- // a reference to a file: scheme (why do we do this? -sc)
- url = "file://" + url;
- }
- else if (url.indexOf(':') < 0)
- {
- // If the url does not have a colon: character (which
- // separates the scheme part from the rest) then it
- // must be a relative one, so go get an absolute one -sc
- url = getAbsoluteURIFromRelative(url);
- }
-
- // Bugzilla#5701: the below else if is incorrect, if you read
- // section 5.2 of RFC 2396. If the url did start with file:,
- // it implies we should assume it's absolute and be done
- // with resolving. Note that I'm not even sure why we put
- // in the second check for '/' anyways -sc
- //else if (url.startsWith("file:") && url.charAt(5) != '/')
- //{
- // url = getAbsoluteURIFromRelative(url.substring(5));
- //}
- // Bugzilla#5701 comment out code end
-
- return url;
+ StringBuffer buf = new StringBuffer(str);
+ int length = buf.length();
+ for (int i = 0; i < length; i++)
+ {
+ char currentChar = buf.charAt(i);
+ // Replace space with "%20"
+ if (currentChar == ' ')
+ {
+ buf.setCharAt(i, '%');
+ buf.insert(i+1, "20");
+ length = length + 2;
+ i = i + 2;
+ }
+ // Replace backslash with forward slash
+ else if (currentChar == '\\')
+ {
+ buf.setCharAt(i, '/');
+ }
+ }
+
+ return buf.toString();
}
-
-
+
/**
- * Take a SystemID string and try and turn it into a good absolute URL.
+ * Take a SystemID string and try to turn it into a good absolute URI.
*
- * @param urlString SystemID string
- * @param base Base URI to use to resolve the given systemID
+ * @param systemId A URI string, which may be absolute or relative.
*
* @return The resolved absolute URI
- * @throws TransformerException thrown if the string can't be turned into
a URL.
*/
- public static String getAbsoluteURI(String urlString, String base)
- throws TransformerException
+ public static String getAbsoluteURI(String systemId)
{
- boolean isAbsouteUrl = false;
- boolean needToResolve = false;
-
- // Bugzilla#5701: the below if is incorrect, if you read
- // section 5.2 of RFC 2396. If the url did start with file:,
- // it implies we should assume it's absolute and be done
- // with resolving. Note that I'm not even sure why we put
- // in the second check for '/' anyways -sc
- //if(urlString.startsWith("file:") && urlString.charAt(5) != '/')
- //{
- // needToResolve = true;
- //}
- //else if (urlString.indexOf(':') > 0)
- // Bugzilla#5701 comment out code end
- if (urlString.indexOf(':') > 0)
- {
- // If there is a colon to separate the scheme from the rest,
- // it should be an absolute URL
- isAbsouteUrl = true;
- }
- else if (urlString.startsWith(File.separator))
- {
- // If the url starts with a path separator, we assume it's
- // a reference to a file: scheme (why do we do this? -sc)
- urlString = "file://" + urlString;
- isAbsouteUrl = true;
- }
-
- if ((!isAbsouteUrl) && ((null == base)
- || (base.indexOf(':') < 0)))
- {
- if (base != null && base.startsWith(File.separator))
- base = "file://" + base;
- else
- base = getAbsoluteURIFromRelative(base);
- }
-
- // bit of a hack here. Need to talk to URI person to see if this can be
fixed.
- if ((null != base) && needToResolve)
-
+ if (isAbsoluteURI(systemId))
{
- if(base.equals(urlString))
+ // Only process the systemId if it starts with "file:".
+ if (systemId.startsWith("file:"))
{
- base = "";
+ int secondColonIndex = systemId.indexOf(':', 5);
+ // If the path contains a drive letter.
+ if (secondColonIndex > 5
+ && Character.isLetter(systemId.charAt(secondColonIndex-1)))
+ {
+ String localPath = systemId.substring(secondColonIndex-1);
+ if (!isAbsolutePath(localPath))
+ return getAbsoluteURIFromRelative(localPath);
+ }
+ else if (systemId.charAt(5) != '/')
+ {
+ return getAbsoluteURIFromRelative(systemId.substring(5));
+ }
+
+ String absoluteURI = replaceChars(systemId);
+ return absoluteURI;
}
else
- {
- urlString = urlString.substring(5);
- isAbsouteUrl = false;
- }
- }
-
- // This is probably a bad idea, we should at least check for quotes...
- if (null != base && (base.indexOf('\\') > -1))
- base = base.replace('\\', '/');
-
- if (null != urlString && (urlString.indexOf('\\') > -1))
- urlString = urlString.replace('\\', '/');
+ return systemId;
+ }
+ else
+ return getAbsoluteURIFromRelative(systemId);
+
+ }
- URI uri;
- try
+ /**
+ * Take a SystemID string and try to turn it into a good absolute URI.
+ *
+ * @param urlString SystemID string
+ * @param base The URI string used as the base for resolving the systemID
+ *
+ * @return The resolved absolute URI
+ * @throws TransformerException thrown if the string can't be turned into
a URI.
+ */
+ public static String getAbsoluteURI(String urlString, String base)
+ throws TransformerException
+ {
+ if (base == null)
+ return getAbsoluteURI(urlString);
+
+ String absoluteBase = getAbsoluteURI(base);
+ URI uri = null;
+ try
{
- if ((null == base) || (base.length() == 0) || (isAbsouteUrl))
- {
- uri = new URI(urlString);
- }
- else
- {
- URI baseURI = new URI(base);
-
- uri = new URI(baseURI, urlString);
- }
+ URI baseURI = new URI(absoluteBase);
+ uri = new URI(baseURI, urlString);
}
catch (MalformedURIException mue)
{
throw new TransformerException(mue);
}
-
- String uriStr = uri.toString();
- // Not so sure if this is good. But, for now, I'll try it. We really
must
- // make sure the return from this function is a URL!
- if((Character.isLetter(uriStr.charAt(0)) && (uriStr.charAt(1) == ':')
- && (uriStr.charAt(2) == '/') && (uriStr.length() == 3 ||
uriStr.charAt(3) != '/'))
- || ((uriStr.charAt(0) == '/') && (uriStr.length() == 1 ||
uriStr.charAt(1) != '/')))
- {
- uriStr = "file:///"+uriStr;
- }
- return uriStr;
- }
+ return replaceChars(uri.toString());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]