You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by im...@apache.org on 2005/11/04 21:11:40 UTC

svn commit: r330878 - in /jakarta/commons/proper/vfs/trunk: ./ src/java/org/apache/commons/vfs/provider/ src/java/org/apache/commons/vfs/provider/local/ src/java/org/apache/commons/vfs/provider/temp/ src/test/org/apache/commons/vfs/perf/

Author: imario
Date: Fri Nov  4 12:11:27 2005
New Revision: 330878

URL: http://svn.apache.org/viewcvs?rev=330878&view=rev
Log:
enh: Some speedup in filename parsing (Thanks to Filip, filipdef@cirquedigital.com)

Added:
    jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/
    jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java   (with props)
Modified:
    jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/HostFileNameParser.java
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/URLFileNameParser.java
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/UriParser.java
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java

Modified: jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt (original)
+++ jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt Fri Nov  4 12:11:27 2005
@@ -1,5 +1,12 @@
 2005-11 comons-vfs 1.0 RC6
 
+uri praser:
+We have had lots of duplicate calls to fixSeparator, so normalizePath now no longer calls it.
+Now normalizePath assumes this has been called.
+This only bothers you if you use normalizePath which should never be the case and is not
+needed to work with VFS.
+(Thanks to Filip - filipdef -at - cirquedigital.com)
+
 sftp:
 new configuration parameter SftpFileSystemConfigBuilder.timeout
 upgrade to jsch-0.1.23

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/HostFileNameParser.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/HostFileNameParser.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/HostFileNameParser.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/HostFileNameParser.java Fri Nov  4 12:11:27 2005
@@ -57,6 +57,7 @@
 
         // Decode and normalise the file name
         UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
         FileType fileType = UriParser.normalisePath(name);
         final String path = name.toString();
 

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java Fri Nov  4 12:11:27 2005
@@ -55,6 +55,7 @@
 
         // Decode and normalise the path
         UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
         FileType fileType = UriParser.normalisePath(name);
         final String path = name.toString();
 

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/URLFileNameParser.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/URLFileNameParser.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/URLFileNameParser.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/URLFileNameParser.java Fri Nov  4 12:11:27 2005
@@ -51,6 +51,7 @@
 
         // Decode and normalise the file name
         UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
         FileType fileType = UriParser.normalisePath(name);
         final String path = name.toString();
 

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/UriParser.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/UriParser.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/UriParser.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/UriParser.java Fri Nov  4 12:11:27 2005
@@ -21,465 +21,466 @@
 import org.apache.commons.vfs.VFS;
 
 /**
- * Utilities for dealing with URIs.  See RFC 2396 for details.
- *
+ * Utilities for dealing with URIs. See RFC 2396 for details.
+ * 
  * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
- * @version $Revision$ $Date$
+ * @version $Revision$ $Date: 2005-10-13 21:11:33 +0200 (Do, 13 Okt
+ *          2005) $
  */
 public final class UriParser
 {
-    /**
-     * The normalised separator to use.
-     */
-    private static final char SEPARATOR_CHAR = FileName.SEPARATOR_CHAR;
-
-    /**
-     * The set of valid separators.  These are all converted to the normalised one.
-     * Does <i>not</i> contain the normalised separator
-     */
-    public static final char[] separators = {'\\'};
-
-    private UriParser()
-    {
-    }
-
-    /**
-     * Extracts the first element of a path.
-     */
-    public static String extractFirstElement(final StringBuffer name)
-    {
-        final int len = name.length();
-        if (len < 1)
-        {
-            return null;
-        }
-        int startPos = 0;
-        if (name.charAt(0) == SEPARATOR_CHAR)
-        {
-            startPos = 1;
-        }
-        for (int pos = startPos; pos < len; pos++)
-        {
-            if (name.charAt(pos) == SEPARATOR_CHAR)
-            {
-                // Found a separator
-                final String elem = name.substring(startPos, pos);
-                name.delete(startPos, pos + 1);
-                return elem;
-            }
-        }
-
-        // No separator
-        final String elem = name.substring(startPos);
-        name.setLength(0);
-        return elem;
-    }
-
-    /**
-     * Normalises a path.  Does the following:
-     * <ul>
-     * <li>Normalises separators, where more than one can be used.
-     * <li>Removes empty path elements.
-     * <li>Handles '.' and '..' elements.
-     * <li>Removes trailing separator.
-     * </ul>
-     */
-    public static FileType normalisePath(final StringBuffer path)
-        throws FileSystemException
-    {
-        FileType fileType = FileType.FOLDER;
-        if (path.length() == 0)
-        {
-            return fileType;
-        }
-
-        if (path.charAt(path.length() - 1) != '/')
-        {
-            fileType = FileType.FILE;
-        }
-
-        // Adjust separators
-        fixSeparators(path);
-
-        // Determine the start of the first element
-        int startFirstElem = 0;
-        if (path.charAt(0) == SEPARATOR_CHAR)
-        {
-            if (path.length() == 1)
-            {
-                return fileType;
-            }
-            startFirstElem = 1;
-        }
-
-        // Iterate over each element
-        int startElem = startFirstElem;
-        int maxlen = path.length();
-        while (startElem < maxlen)
-        {
-            // Find the end of the element
-            int endElem = startElem;
-            for (; endElem < maxlen && path.charAt(endElem) != SEPARATOR_CHAR; endElem++)
-            {
-            }
-
-            final int elemLen = endElem - startElem;
-            if (elemLen == 0)
-            {
-                // An empty element - axe it
-                path.delete(endElem, endElem + 1);
-                maxlen = path.length();
-                continue;
-            }
-            if (elemLen == 1 && path.charAt(startElem) == '.')
-            {
-                // A '.' element - axe it
-                path.delete(startElem, endElem + 1);
-                maxlen = path.length();
-                continue;
-            }
-            if (elemLen == 2
-                && path.charAt(startElem) == '.'
-                && path.charAt(startElem + 1) == '.')
-            {
-                // A '..' element - remove the previous element
-                if (startElem == startFirstElem)
-                {
-                    // Previous element is missing
-                    throw new FileSystemException("vfs.provider/invalid-relative-path.error");
-                }
-
-                // Find start of previous element
-                int pos = startElem - 2;
-                for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--)
-                {
-                }
-                startElem = pos + 1;
-
-                path.delete(startElem, endElem + 1);
-                maxlen = path.length();
-                continue;
-            }
-
-            // A regular element
-            startElem = endElem + 1;
-        }
-
-        // Remove trailing separator
-        if (!VFS.isUriStyle())
-        {
-            if (maxlen > 0 && path.charAt(maxlen - 1) == SEPARATOR_CHAR && maxlen > 1)
-            {
-                path.delete(maxlen - 1, maxlen);
-            }
-        }
-
-        return fileType;
-    }
-
-    /**
-     * Normalises the separators in a name.
-     */
-    public static boolean fixSeparators(final StringBuffer name)
-    {
-        if (separators.length == 0)
-        {
-            // Only one valid separator, so don't need to do anything
-            return false;
-        }
-
-        boolean changed = false;
-        final int maxlen = name.length();
-        for (int i = 0; i < maxlen; i++)
-        {
-            final char ch = name.charAt(i);
-            for (int j = 0; j < separators.length; j++)
-            {
-                char separator = separators[j];
-                if (ch == separator)
-                {
-                    name.setCharAt(i, SEPARATOR_CHAR);
-                    changed = true;
-                    break;
-                }
-            }
-        }
-        return changed;
-    }
-
-    /**
-     * Extracts the scheme from a URI.
-     *
-     * @param uri The URI.
-     * @return The scheme name.  Returns null if there is no scheme.
-     */
-    public static String extractScheme(final String uri)
-    {
-        return extractScheme(uri, null);
-    }
-
-    /**
-     * Extracts the scheme from a URI.  Removes the scheme and ':' delimiter
-     * from the front of the URI.
-     *
-     * @param uri    The URI.
-     * @param buffer Returns the remainder of the URI.
-     * @return The scheme name.  Returns null if there is no scheme.
-     */
-    public static String extractScheme(final String uri,
-                                       final StringBuffer buffer)
-    {
-        if (buffer != null)
-        {
-            buffer.setLength(0);
-            buffer.append(uri);
-        }
-
-        final int maxPos = uri.length();
-        for (int pos = 0; pos < maxPos; pos++)
-        {
-            final char ch = uri.charAt(pos);
-
-            if (ch == ':')
-            {
-                // Found the end of the scheme
-                final String scheme = uri.substring(0, pos);
-                if (buffer != null)
-                {
-                    buffer.delete(0, pos + 1);
-                }
-                return scheme;
-            }
-
-            if ((ch >= 'a' && ch <= 'z')
-                || (ch >= 'A' && ch <= 'Z'))
-            {
-                // A scheme character
-                continue;
-            }
-            if (pos > 0
-                && ((ch >= '0' && ch <= '9')
-                || ch == '+' || ch == '-' || ch == '.'))
-            {
-                // A scheme character (these are not allowed as the first
-                // character of the scheme, but can be used as subsequent
-                // characters.
-                continue;
-            }
-
-            // Not a scheme character
-            break;
-        }
-
-        // No scheme in URI
-        return null;
-    }
-
-    /**
-     * Removes %nn encodings from a string.
-     */
-    public static String decode(final String encodedStr)
-        throws FileSystemException
-    {
-        if (encodedStr == null)
-        {
-            return null;
-        }
-        final StringBuffer buffer = new StringBuffer(encodedStr);
-        decode(buffer, 0, buffer.length());
-        return buffer.toString();
-    }
-
-    /**
-     * Removes %nn encodings from a string.
-     */
-    public static void decode(final StringBuffer buffer,
-                              final int offset,
-                              final int length)
-        throws FileSystemException
-    {
-        int index = offset;
-        int count = length;
-        for (; count > 0; count--, index++)
-        {
-            final char ch = buffer.charAt(index);
-            if (ch != '%')
-            {
-                continue;
-            }
-            if (count < 3)
-            {
-                throw new FileSystemException("vfs.provider/invalid-escape-sequence.error", buffer.substring(index, index + count));
-            }
-
-            // Decode
-            int dig1 = Character.digit(buffer.charAt(index + 1), 16);
-            int dig2 = Character.digit(buffer.charAt(index + 2), 16);
-            if (dig1 == -1 || dig2 == -1)
-            {
-                throw new FileSystemException("vfs.provider/invalid-escape-sequence.error", buffer.substring(index, index + 3));
-            }
-            char value = (char) (dig1 << 4 | dig2);
-
-            // Replace
-            buffer.setCharAt(index, value);
-            buffer.delete(index + 1, index + 3);
-            count -= 2;
-        }
-    }
-
-    /**
-     * Encodes and appends a string to a StringBuffer.
-     */
-    public static void appendEncoded(final StringBuffer buffer,
-                                     final String unencodedValue,
-                                     final char[] reserved)
-    {
-        final int offset = buffer.length();
-        buffer.append(unencodedValue);
-        encode(buffer, offset, unencodedValue.length(), reserved);
-    }
-
-    /**
-     * Encodes a set of reserved characters in a StringBuffer, using the URI
-     * %nn encoding.  Always encodes % characters.
-     */
-    public static void encode(final StringBuffer buffer,
-                              final int offset,
-                              final int length,
-                              final char[] reserved)
-    {
-        int index = offset;
-        int count = length;
-        for (; count > 0; index++, count--)
-        {
-            final char ch = buffer.charAt(index);
-            boolean match = (ch == '%');
-            if (reserved != null)
-            {
-                for (int i = 0; !match && i < reserved.length; i++)
-                {
-                    if (ch == reserved[i])
-                    {
-                        match = true;
-                    }
-                }
-            }
-            if (match)
-            {
-                // Encode
-                char[] digits = {
-                    Character.forDigit(((ch >> 4) & 0xF), 16),
-                    Character.forDigit((ch & 0xF), 16)
-                };
-                buffer.setCharAt(index, '%');
-                buffer.insert(index + 1, digits);
-                index += 2;
-            }
-        }
-    }
-
-    /**
-     * Removes %nn encodings from a string.
-     */
-    public static String encode(final String decodedStr)
-    {
-        return encode(decodedStr, null);
-    }
-
-    public static String encode(final String decodedStr, final char[] reserved)
-    {
-        if (decodedStr == null)
-        {
-            return null;
-        }
-        final StringBuffer buffer = new StringBuffer(decodedStr);
-        encode(buffer, 0, buffer.length(), reserved);
-        return buffer.toString();
-    }
-
-    public static String[] encode(String[] strings)
-    {
-        if (strings == null)
-        {
-            return null;
-        }
-        for (int i = 0; i < strings.length; i++)
-        {
-            strings[i] = encode(strings[i]);
-        }
-        return strings;
-    }
-
-    public static void checkUriEncoding(String uri) throws FileSystemException
-    {
-        decode(uri);
-    }
-
-    public static void canonicalizePath(StringBuffer buffer, int offset, int length, FileNameParser fileNameParser) throws FileSystemException
-    {
-        int index = offset;
-        int count = length;
-        for (; count > 0; count--, index++)
-        {
-            final char ch = buffer.charAt(index);
-            if (ch == '%')
-            {
-                if (count < 3)
-                {
-                    throw new FileSystemException("vfs.provider/invalid-escape-sequence.error", buffer.substring(index, index + count));
-                }
-
-                // Decode
-                int dig1 = Character.digit(buffer.charAt(index + 1), 16);
-                int dig2 = Character.digit(buffer.charAt(index + 2), 16);
-                if (dig1 == -1 || dig2 == -1)
-                {
-                    throw new FileSystemException("vfs.provider/invalid-escape-sequence.error", buffer.substring(index, index + 3));
-                }
-                char value = (char) (dig1 << 4 | dig2);
-
-                boolean match = (value == '%') || (fileNameParser != null && fileNameParser.encodeCharacter(value));
-
-                if (match)
-                {
-                    // this is a reserved character, not allowed to decode
-                    index += 2;
-                    count -= 2;
-                    continue;
-                }
-
-                // Replace
-                buffer.setCharAt(index, value);
-                buffer.delete(index + 1, index + 3);
-                count -= 2;
-            }
-            else if (fileNameParser.encodeCharacter(ch))
-            {
-                // Encode
-                char[] digits = {
-                    Character.forDigit(((ch >> 4) & 0xF), 16),
-                    Character.forDigit((ch & 0xF), 16)
-                };
-                buffer.setCharAt(index, '%');
-                buffer.insert(index + 1, digits);
-                index += 2;
-            }
-        }
-    }
-
-    public static String extractQueryString(StringBuffer name)
-    {
-        for (int pos = 0; pos < name.length(); pos++)
-        {
-            if (name.charAt(pos) == '?')
-            {
-                String queryString = name.substring(pos + 1);
-                name.delete(pos, name.length());
-                return queryString;
-            }
-        }
+	/**
+	 * The normalised separator to use.
+	 */
+	private static final char SEPARATOR_CHAR = FileName.SEPARATOR_CHAR;
+
+	/**
+	 * The set of valid separators. These are all converted to the normalised
+	 * one. Does <i>not</i> contain the normalised separator
+	 */
+	// public static final char[] separators = {'\\'};
+	public static final char TRANS_SEPARATOR = '\\';
+
+	private UriParser()
+	{
+	}
+
+	/**
+	 * Extracts the first element of a path.
+	 */
+	public static String extractFirstElement(final StringBuffer name)
+	{
+		final int len = name.length();
+		if (len < 1)
+		{
+			return null;
+		}
+		int startPos = 0;
+		if (name.charAt(0) == SEPARATOR_CHAR)
+		{
+			startPos = 1;
+		}
+		for (int pos = startPos; pos < len; pos++)
+		{
+			if (name.charAt(pos) == SEPARATOR_CHAR)
+			{
+				// Found a separator
+				final String elem = name.substring(startPos, pos);
+				name.delete(startPos, pos + 1);
+				return elem;
+			}
+		}
+
+		// No separator
+		final String elem = name.substring(startPos);
+		name.setLength(0);
+		return elem;
+	}
+
+	/**
+	 * Normalises a path. Does the following:
+	 * <ul>
+	 * <li>Removes empty path elements.
+	 * <li>Handles '.' and '..' elements.
+	 * <li>Removes trailing separator.
+	 * </ul>
+	 * 
+	 * Its assumed that the separators are already fixed.
+	 * 
+	 *  @see #fixSeparators
+	 */
+	public static FileType normalisePath(final StringBuffer path)
+			throws FileSystemException
+	{
+		FileType fileType = FileType.FOLDER;
+		if (path.length() == 0)
+		{
+			return fileType;
+		}
+
+		if (path.charAt(path.length() - 1) != '/')
+		{
+			fileType = FileType.FILE;
+		}
+
+		// Adjust separators
+		// fixSeparators(path);
+
+		// Determine the start of the first element
+		int startFirstElem = 0;
+		if (path.charAt(0) == SEPARATOR_CHAR)
+		{
+			if (path.length() == 1)
+			{
+				return fileType;
+			}
+			startFirstElem = 1;
+		}
+
+		// Iterate over each element
+		int startElem = startFirstElem;
+		int maxlen = path.length();
+		while (startElem < maxlen)
+		{
+			// Find the end of the element
+			int endElem = startElem;
+			for (; endElem < maxlen && path.charAt(endElem) != SEPARATOR_CHAR; endElem++)
+			{
+			}
+
+			final int elemLen = endElem - startElem;
+			if (elemLen == 0)
+			{
+				// An empty element - axe it
+				path.delete(endElem, endElem + 1);
+				maxlen = path.length();
+				continue;
+			}
+			if (elemLen == 1 && path.charAt(startElem) == '.')
+			{
+				// A '.' element - axe it
+				path.delete(startElem, endElem + 1);
+				maxlen = path.length();
+				continue;
+			}
+			if (elemLen == 2 && path.charAt(startElem) == '.'
+					&& path.charAt(startElem + 1) == '.')
+			{
+				// A '..' element - remove the previous element
+				if (startElem == startFirstElem)
+				{
+					// Previous element is missing
+					throw new FileSystemException(
+							"vfs.provider/invalid-relative-path.error");
+				}
+
+				// Find start of previous element
+				int pos = startElem - 2;
+				for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--)
+				{
+				}
+				startElem = pos + 1;
+
+				path.delete(startElem, endElem + 1);
+				maxlen = path.length();
+				continue;
+			}
+
+			// A regular element
+			startElem = endElem + 1;
+		}
+
+		// Remove trailing separator
+		if (!VFS.isUriStyle())
+		{
+			if (maxlen > 0 && path.charAt(maxlen - 1) == SEPARATOR_CHAR
+					&& maxlen > 1)
+			{
+				path.delete(maxlen - 1, maxlen);
+			}
+		}
+
+		return fileType;
+	}
+
+	/**
+	 * Normalises the separators in a name.
+	 */
+	public static boolean fixSeparators(final StringBuffer name)
+	{
+		boolean changed = false;
+		final int maxlen = name.length();
+		for (int i = 0; i < maxlen; i++)
+		{
+			final char ch = name.charAt(i);
+			if (ch == TRANS_SEPARATOR)
+			{
+				name.setCharAt(i, SEPARATOR_CHAR);
+				changed = true;
+			}
+		}
+		return changed;
+	}
+
+	/**
+	 * Extracts the scheme from a URI.
+	 * 
+	 * @param uri
+	 *            The URI.
+	 * @return The scheme name. Returns null if there is no scheme.
+	 */
+	public static String extractScheme(final String uri)
+	{
+		return extractScheme(uri, null);
+	}
+
+	/**
+	 * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from
+	 * the front of the URI.
+	 * 
+	 * @param uri
+	 *            The URI.
+	 * @param buffer
+	 *            Returns the remainder of the URI.
+	 * @return The scheme name. Returns null if there is no scheme.
+	 */
+	public static String extractScheme(final String uri,
+			final StringBuffer buffer)
+	{
+		if (buffer != null)
+		{
+			buffer.setLength(0);
+			buffer.append(uri);
+		}
+
+		final int maxPos = uri.length();
+		for (int pos = 0; pos < maxPos; pos++)
+		{
+			final char ch = uri.charAt(pos);
+
+			if (ch == ':')
+			{
+				// Found the end of the scheme
+				final String scheme = uri.substring(0, pos);
+				if (buffer != null)
+				{
+					buffer.delete(0, pos + 1);
+				}
+				return scheme;
+			}
+
+			if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
+			{
+				// A scheme character
+				continue;
+			}
+			if (pos > 0
+					&& ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.'))
+			{
+				// A scheme character (these are not allowed as the first
+				// character of the scheme, but can be used as subsequent
+				// characters.
+				continue;
+			}
+
+			// Not a scheme character
+			break;
+		}
+
+		// No scheme in URI
+		return null;
+	}
+
+	/**
+	 * Removes %nn encodings from a string.
+	 */
+	public static String decode(final String encodedStr)
+			throws FileSystemException
+	{
+		if (encodedStr == null)
+		{
+			return null;
+		}
+		final StringBuffer buffer = new StringBuffer(encodedStr);
+		decode(buffer, 0, buffer.length());
+		return buffer.toString();
+	}
+
+	/**
+	 * Removes %nn encodings from a string.
+	 */
+	public static void decode(final StringBuffer buffer, final int offset,
+			final int length) throws FileSystemException
+	{
+		int index = offset;
+		int count = length;
+		for (; count > 0; count--, index++)
+		{
+			final char ch = buffer.charAt(index);
+			if (ch != '%')
+			{
+				continue;
+			}
+			if (count < 3)
+			{
+				throw new FileSystemException(
+						"vfs.provider/invalid-escape-sequence.error", buffer
+								.substring(index, index + count));
+			}
+
+			// Decode
+			int dig1 = Character.digit(buffer.charAt(index + 1), 16);
+			int dig2 = Character.digit(buffer.charAt(index + 2), 16);
+			if (dig1 == -1 || dig2 == -1)
+			{
+				throw new FileSystemException(
+						"vfs.provider/invalid-escape-sequence.error", buffer
+								.substring(index, index + 3));
+			}
+			char value = (char) (dig1 << 4 | dig2);
+
+			// Replace
+			buffer.setCharAt(index, value);
+			buffer.delete(index + 1, index + 3);
+			count -= 2;
+		}
+	}
+
+	/**
+	 * Encodes and appends a string to a StringBuffer.
+	 */
+	public static void appendEncoded(final StringBuffer buffer,
+			final String unencodedValue, final char[] reserved)
+	{
+		final int offset = buffer.length();
+		buffer.append(unencodedValue);
+		encode(buffer, offset, unencodedValue.length(), reserved);
+	}
+
+	/**
+	 * Encodes a set of reserved characters in a StringBuffer, using the URI %nn
+	 * encoding. Always encodes % characters.
+	 */
+	public static void encode(final StringBuffer buffer, final int offset,
+			final int length, final char[] reserved)
+	{
+		int index = offset;
+		int count = length;
+		for (; count > 0; index++, count--)
+		{
+			final char ch = buffer.charAt(index);
+			boolean match = (ch == '%');
+			if (reserved != null)
+			{
+				for (int i = 0; !match && i < reserved.length; i++)
+				{
+					if (ch == reserved[i])
+					{
+						match = true;
+					}
+				}
+			}
+			if (match)
+			{
+				// Encode
+				char[] digits =
+				{ Character.forDigit(((ch >> 4) & 0xF), 16),
+						Character.forDigit((ch & 0xF), 16) };
+				buffer.setCharAt(index, '%');
+				buffer.insert(index + 1, digits);
+				index += 2;
+			}
+		}
+	}
+
+	/**
+	 * Removes %nn encodings from a string.
+	 */
+	public static String encode(final String decodedStr)
+	{
+		return encode(decodedStr, null);
+	}
+
+	public static String encode(final String decodedStr, final char[] reserved)
+	{
+		if (decodedStr == null)
+		{
+			return null;
+		}
+		final StringBuffer buffer = new StringBuffer(decodedStr);
+		encode(buffer, 0, buffer.length(), reserved);
+		return buffer.toString();
+	}
+
+	public static String[] encode(String[] strings)
+	{
+		if (strings == null)
+		{
+			return null;
+		}
+		for (int i = 0; i < strings.length; i++)
+		{
+			strings[i] = encode(strings[i]);
+		}
+		return strings;
+	}
+
+	public static void checkUriEncoding(String uri) throws FileSystemException
+	{
+		decode(uri);
+	}
+
+	public static void canonicalizePath(StringBuffer buffer, int offset,
+			int length, FileNameParser fileNameParser)
+			throws FileSystemException
+	{
+		int index = offset;
+		int count = length;
+		for (; count > 0; count--, index++)
+		{
+			final char ch = buffer.charAt(index);
+			if (ch == '%')
+			{
+				if (count < 3)
+				{
+					throw new FileSystemException(
+							"vfs.provider/invalid-escape-sequence.error",
+							buffer.substring(index, index + count));
+				}
+
+				// Decode
+				int dig1 = Character.digit(buffer.charAt(index + 1), 16);
+				int dig2 = Character.digit(buffer.charAt(index + 2), 16);
+				if (dig1 == -1 || dig2 == -1)
+				{
+					throw new FileSystemException(
+							"vfs.provider/invalid-escape-sequence.error",
+							buffer.substring(index, index + 3));
+				}
+				char value = (char) (dig1 << 4 | dig2);
+
+				boolean match = (value == '%')
+						|| (fileNameParser != null && fileNameParser
+								.encodeCharacter(value));
+
+				if (match)
+				{
+					// this is a reserved character, not allowed to decode
+					index += 2;
+					count -= 2;
+					continue;
+				}
+
+				// Replace
+				buffer.setCharAt(index, value);
+				buffer.delete(index + 1, index + 3);
+				count -= 2;
+			}
+			else if (fileNameParser.encodeCharacter(ch))
+			{
+				// Encode
+				char[] digits =
+				{ Character.forDigit(((ch >> 4) & 0xF), 16),
+						Character.forDigit((ch & 0xF), 16) };
+				buffer.setCharAt(index, '%');
+				buffer.insert(index + 1, digits);
+				index += 2;
+			}
+		}
+	}
+
+	public static String extractQueryString(StringBuffer name)
+	{
+		for (int pos = 0; pos < name.length(); pos++)
+		{
+			if (name.charAt(pos) == '?')
+			{
+				String queryString = name.substring(pos + 1);
+				name.delete(pos, name.length());
+				return queryString;
+			}
+		}
 
-        return null;
-    }
+		return null;
+	}
 }

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java Fri Nov  4 12:11:27 2005
@@ -70,13 +70,15 @@
 
         // Remove encoding, and adjust the separators
         UriParser.canonicalizePath(name, 0, name.length(), this);
-        UriParser.fixSeparators(name);
 
+        UriParser.fixSeparators(name);
+        
         // Extract the root prefix
         final String rootFile = extractRootPrefix(filename, name);
 
         // Normalise the path
         FileType fileType = UriParser.normalisePath(name);
+
         final String path = name.toString();
 
         return createFileName(

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java?rev=330878&r1=330877&r2=330878&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java Fri Nov  4 12:11:27 2005
@@ -93,6 +93,9 @@
         // Parse the name
         final StringBuffer buffer = new StringBuffer(uri);
         final String scheme = UriParser.extractScheme(uri, buffer);
+
+        UriParser.fixSeparators(buffer);
+        
         FileType fileType = UriParser.normalisePath(buffer);
         final String path = buffer.toString();
 

Added: jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java?rev=330878&view=auto
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java (added)
+++ jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java Fri Nov  4 12:11:27 2005
@@ -0,0 +1,86 @@
+package org.apache.commons.vfs.perf;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.VFS;
+
+public class FileNamePerformance
+{
+	private final static int NUOF_RESOLVES = 100000;
+
+	public static void main(String[] args) throws FileSystemException
+	{
+		FileSystemManager mgr = VFS.getManager();
+
+		FileObject root = mgr
+				.resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr");
+		FileName rootName = root.getName();
+	
+		testNames(mgr, rootName);
+
+		testChildren(root);
+
+		testFiles(mgr);
+	}
+
+	private static void testFiles(FileSystemManager mgr) throws FileSystemException
+	{
+		for (int i = 0; i < 10; i++)
+		{
+			// warmup jvm
+			mgr.resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+
+		long start = System.currentTimeMillis();
+		for (int i = 0; i < NUOF_RESOLVES; i++)
+		{
+			mgr.resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+		long end = System.currentTimeMillis();
+
+		System.err.println("time to resolve " + NUOF_RESOLVES + " files: "
+				+ (end - start) + "ms");
+	}
+
+	private static void testChildren(FileObject root) throws FileSystemException
+	{
+		for (int i = 0; i < 10; i++)
+		{
+			// warmup jvm
+			root.resolveFile("/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+
+		long start = System.currentTimeMillis();
+		for (int i = 0; i < NUOF_RESOLVES; i++)
+		{
+			root.resolveFile("/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+		long end = System.currentTimeMillis();
+
+		System.err.println("time to resolve " + NUOF_RESOLVES + " childs: "
+				+ (end - start) + "ms");
+	}
+
+	private static void testNames(FileSystemManager mgr, FileName rootName) throws FileSystemException
+	{
+		for (int i = 0; i < 10; i++)
+		{
+			// warmup jvm
+			mgr.resolveName(rootName,
+					"/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+
+		long start = System.currentTimeMillis();
+		for (int i = 0; i < NUOF_RESOLVES; i++)
+		{
+			mgr.resolveName(rootName,
+					"/many/path/elements/with%25esc/any%25where/to/file.txt");
+		}
+		long end = System.currentTimeMillis();
+
+		System.err.println("time to resolve " + NUOF_RESOLVES + " names: "
+				+ (end - start) + "ms");
+	}
+}

Propchange: jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/vfs/trunk/src/test/org/apache/commons/vfs/perf/FileNamePerformance.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org