VFS-398
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/vfs/branches/VFS-398@1848367 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.gitignore b/.gitignore
index 838eb26..6f2b095 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@
.classpath
.settings/
.svn/
+.idea/
+*.iml
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
index 781d98a..131a6c6 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
@@ -764,7 +764,7 @@
// Adjust separators
UriParser.fixSeparators(buffer);
- String scheme = UriParser.extractScheme(buffer.toString());
+ String scheme = UriParser.extractScheme(providers.keySet(), buffer.toString());
// Determine whether to prepend the base path
if (name.length() == 0 || (scheme == null && buffer.charAt(0) != FileName.SEPARATOR_CHAR)) {
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
index 6e90ea4..23b68cb 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
@@ -16,6 +16,7 @@
*/
package org.apache.commons.vfs2.provider;
+import java.util.Set;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
@@ -46,7 +47,203 @@
private static final char LOW_MASK = 0x0F;
- private UriParser() {
+ /**
+ * Encodes and appends a string to a StringBuilder.
+ *
+ * @param buffer The StringBuilder to append to.
+ * @param unencodedValue The String to encode and append.
+ * @param reserved characters to encode.
+ */
+ public static void appendEncoded(final StringBuilder buffer, final String unencodedValue, final char[] reserved) {
+ final int offset = buffer.length();
+ buffer.append(unencodedValue);
+ encode(buffer, offset, unencodedValue.length(), reserved);
+ }
+
+ public static void canonicalizePath(final StringBuilder buffer, final int offset, final int length,
+ final 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
+ final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
+ final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
+ if (dig1 == -1 || dig2 == -1) {
+ throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
+ buffer.substring(index, index + 3));
+ }
+ final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
+
+ final boolean match = value == '%' || 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
+ final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
+ Character.forDigit(ch & LOW_MASK, HEX_BASE) };
+ buffer.setCharAt(index, '%');
+ buffer.insert(index + 1, digits);
+ index += 2;
+ }
+ }
+ }
+
+ /**
+ * Decodes the String.
+ *
+ * @param uri The String to decode.
+ * @throws FileSystemException if an error occurs.
+ */
+ public static void checkUriEncoding(final String uri) throws FileSystemException {
+ decode(uri);
+ }
+
+ /**
+ * Removes %nn encodings from a string.
+ *
+ * @param encodedStr The encoded String.
+ * @return The decoded String.
+ * @throws FileSystemException if an error occurs.
+ */
+ public static String decode(final String encodedStr) throws FileSystemException {
+ if (encodedStr == null) {
+ return null;
+ }
+ if (encodedStr.indexOf('%') < 0) {
+ return encodedStr;
+ }
+ final StringBuilder buffer = new StringBuilder(encodedStr);
+ decode(buffer, 0, buffer.length());
+ return buffer.toString();
+ }
+
+ /**
+ * Removes %nn encodings from a string.
+ *
+ * @param buffer StringBuilder containing the string to decode.
+ * @param offset The position in the string to start decoding.
+ * @param length The number of characters to decode.
+ * @throws FileSystemException if an error occurs.
+ */
+ public static void decode(final StringBuilder 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
+ final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
+ final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
+ if (dig1 == -1 || dig2 == -1) {
+ throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
+ buffer.substring(index, index + 3));
+ }
+ final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
+
+ // Replace
+ buffer.setCharAt(index, value);
+ buffer.delete(index + 1, index + 3);
+ count -= 2;
+ }
+ }
+
+ /**
+ * Removes %nn encodings from a string.
+ *
+ * @param decodedStr The decoded String.
+ * @return The encoded String.
+ */
+ public static String encode(final String decodedStr) {
+ return encode(decodedStr, null);
+ }
+
+ /**
+ * Converts "special" characters to their %nn value.
+ *
+ * @param decodedStr The decoded String.
+ * @param reserved Characters to encode.
+ * @return The encoded String
+ */
+ public static String encode(final String decodedStr, final char[] reserved) {
+ if (decodedStr == null) {
+ return null;
+ }
+ final StringBuilder buffer = new StringBuilder(decodedStr);
+ encode(buffer, 0, buffer.length(), reserved);
+ return buffer.toString();
+ }
+
+ /**
+ * Encode an array of Strings.
+ *
+ * @param strings The array of Strings to encode.
+ * @return An array of encoded Strings.
+ */
+ public static String[] encode(final String[] strings) {
+ if (strings == null) {
+ return null;
+ }
+ for (int i = 0; i < strings.length; i++) {
+ strings[i] = encode(strings[i]);
+ }
+ return strings;
+ }
+
+ /**
+ * Encodes a set of reserved characters in a StringBuilder, using the URI %nn encoding. Always encodes % characters.
+ *
+ * @param buffer The StringBuilder to append to.
+ * @param offset The position in the buffer to start encoding at.
+ * @param length The number of characters to encode.
+ * @param reserved characters to encode.
+ */
+ public static void encode(final StringBuilder 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
+ final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
+ Character.forDigit(ch & LOW_MASK, HEX_BASE) };
+ buffer.setCharAt(index, '%');
+ buffer.insert(index + 1, digits);
+ index += 2;
+ }
+ }
}
/**
@@ -80,6 +277,156 @@
}
/**
+ * Extract the query String from the URI.
+ *
+ * @param name StringBuilder containing the URI.
+ * @return The query string, if any. null otherwise.
+ */
+ public static String extractQueryString(final StringBuilder name) {
+ for (int pos = 0; pos < name.length(); pos++) {
+ if (name.charAt(pos) == '?') {
+ final String queryString = name.substring(pos + 1);
+ name.delete(pos, name.length());
+ return queryString;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from the front of the URI.
+ * <p>
+ * The scheme is extracted based on the currently supported schemes in the system. That is to say the schemes
+ * supported by the registered providers.
+ * </p>
+ * <p>
+ * This allows us to handle varying scheme's without making assumptions based on the ':' character. Specifically
+ * handle scheme extraction calls for URI parameters that are not actually uri's, but may be names with ':' in them.
+ * </p>
+ * @param schemes The schemes to check.
+ * @param uri The potential URI. May also be a name.
+ * @return The scheme name. Returns null if there is no scheme.
+ */
+ public static String extractScheme(final Set<String> schemes, final String uri) {
+ return extractScheme(schemes, uri, null);
+ }
+
+ /**
+ * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from the front of the URI.
+ * <p>
+ * The scheme is extracted based on the given set of schemes. Normally, that is to say the schemes
+ * supported by the registered providers.
+ * </p>
+ * <p>
+ * This allows us to handle varying scheme's without making assumptions based on the ':' character. Specifically
+ * handle scheme extraction calls for URI parameters that are not actually uri's, but may be names with ':' in them.
+ * </p>
+ * @param schemes The schemes to check.
+ * @param uri The potential URI. May also just be a name.
+ * @param buffer Returns the remainder of the URI.
+ * @return The scheme name. Returns null if there is no scheme.
+ */
+ public static String extractScheme(final Set<String> schemes, final String uri, StringBuilder buffer) {
+ if (buffer != null) {
+ buffer.setLength(0);
+ buffer.append(uri);
+ }
+
+ for(String scheme : schemes) {
+ if(uri.startsWith(scheme + ":")) {
+ if (buffer != null) {
+ buffer.delete(0, uri.indexOf(':') + 1);
+ }
+ return scheme;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Extracts the scheme from a URI.
+ *
+ * @param uri The URI.
+ * @return The scheme name. Returns null if there is no scheme.
+ * @deprecated Use instead {@link #extractdScheme}. Will be removed in 3.0.
+ */
+ @Deprecated
+ 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.
+ * @deprecated Use instead {@link #extractScheme}. Will be removed in 3.0.
+ */
+ @Deprecated
+ public static String extractScheme(final String uri, final StringBuilder 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 (scheme.length() <= 1 && Os.isFamily(Os.OS_FAMILY_WINDOWS)) {
+ // This is not a scheme, but a Windows drive letter
+ return null;
+ }
+ if (buffer != null) {
+ buffer.delete(0, pos + 1);
+ }
+ return scheme.intern();
+ }
+
+ 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;
+ }
+
+ /**
+ * Normalises the separators in a name.
+ *
+ * @param name The StringBuilder containing the name
+ * @return true if the StringBuilder was modified.
+ */
+ public static boolean fixSeparators(final StringBuilder 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;
+ }
+
+ /**
* Normalises a path. Does the following:
* <ul>
* <li>Removes empty path elements.
@@ -169,298 +516,6 @@
return fileType;
}
- /**
- * Normalises the separators in a name.
- *
- * @param name The StringBuilder containing the name
- * @return true if the StringBuilder was modified.
- */
- public static boolean fixSeparators(final StringBuilder 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 StringBuilder 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 (scheme.length() <= 1 && Os.isFamily(Os.OS_FAMILY_WINDOWS)) {
- // This is not a scheme, but a Windows drive letter
- return null;
- }
- if (buffer != null) {
- buffer.delete(0, pos + 1);
- }
- return scheme.intern();
- }
-
- 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.
- *
- * @param encodedStr The encoded String.
- * @return The decoded String.
- * @throws FileSystemException if an error occurs.
- */
- public static String decode(final String encodedStr) throws FileSystemException {
- if (encodedStr == null) {
- return null;
- }
- if (encodedStr.indexOf('%') < 0) {
- return encodedStr;
- }
- final StringBuilder buffer = new StringBuilder(encodedStr);
- decode(buffer, 0, buffer.length());
- return buffer.toString();
- }
-
- /**
- * Removes %nn encodings from a string.
- *
- * @param buffer StringBuilder containing the string to decode.
- * @param offset The position in the string to start decoding.
- * @param length The number of characters to decode.
- * @throws FileSystemException if an error occurs.
- */
- public static void decode(final StringBuilder 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
- final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
- final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
- if (dig1 == -1 || dig2 == -1) {
- throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
- buffer.substring(index, index + 3));
- }
- final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
-
- // Replace
- buffer.setCharAt(index, value);
- buffer.delete(index + 1, index + 3);
- count -= 2;
- }
- }
-
- /**
- * Encodes and appends a string to a StringBuilder.
- *
- * @param buffer The StringBuilder to append to.
- * @param unencodedValue The String to encode and append.
- * @param reserved characters to encode.
- */
- public static void appendEncoded(final StringBuilder 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 StringBuilder, using the URI %nn encoding. Always encodes % characters.
- *
- * @param buffer The StringBuilder to append to.
- * @param offset The position in the buffer to start encoding at.
- * @param length The number of characters to encode.
- * @param reserved characters to encode.
- */
- public static void encode(final StringBuilder 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
- final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
- Character.forDigit(ch & LOW_MASK, HEX_BASE) };
- buffer.setCharAt(index, '%');
- buffer.insert(index + 1, digits);
- index += 2;
- }
- }
- }
-
- /**
- * Removes %nn encodings from a string.
- *
- * @param decodedStr The decoded String.
- * @return The encoded String.
- */
- public static String encode(final String decodedStr) {
- return encode(decodedStr, null);
- }
-
- /**
- * Converts "special" characters to their %nn value.
- *
- * @param decodedStr The decoded String.
- * @param reserved Characters to encode.
- * @return The encoded String
- */
- public static String encode(final String decodedStr, final char[] reserved) {
- if (decodedStr == null) {
- return null;
- }
- final StringBuilder buffer = new StringBuilder(decodedStr);
- encode(buffer, 0, buffer.length(), reserved);
- return buffer.toString();
- }
-
- /**
- * Encode an array of Strings.
- *
- * @param strings The array of Strings to encode.
- * @return An array of encoded Strings.
- */
- public static String[] encode(final String[] strings) {
- if (strings == null) {
- return null;
- }
- for (int i = 0; i < strings.length; i++) {
- strings[i] = encode(strings[i]);
- }
- return strings;
- }
-
- /**
- * Decodes the String.
- *
- * @param uri The String to decode.
- * @throws FileSystemException if an error occurs.
- */
- public static void checkUriEncoding(final String uri) throws FileSystemException {
- decode(uri);
- }
-
- public static void canonicalizePath(final StringBuilder buffer, final int offset, final int length,
- final 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
- final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
- final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
- if (dig1 == -1 || dig2 == -1) {
- throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
- buffer.substring(index, index + 3));
- }
- final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
-
- final boolean match = value == '%' || 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
- final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
- Character.forDigit(ch & LOW_MASK, HEX_BASE) };
- buffer.setCharAt(index, '%');
- buffer.insert(index + 1, digits);
- index += 2;
- }
- }
- }
-
- /**
- * Extract the query String from the URI.
- *
- * @param name StringBuilder containing the URI.
- * @return The query string, if any. null otherwise.
- */
- public static String extractQueryString(final StringBuilder name) {
- for (int pos = 0; pos < name.length(); pos++) {
- if (name.charAt(pos) == '?') {
- final String queryString = name.substring(pos + 1);
- name.delete(pos, name.length());
- return queryString;
- }
- }
-
- return null;
+ private UriParser() {
}
}
diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/UriParserTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/UriParserTestCase.java
index a82b301..a4ac63c 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/UriParserTestCase.java
+++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/UriParserTestCase.java
@@ -16,7 +16,11 @@
*/
package org.apache.commons.vfs2.provider;
+import java.util.HashSet;
+import java.util.Set;
import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
/**
@@ -24,15 +28,49 @@
* @version $Id$
*/
public class UriParserTestCase {
+ private static final Set<String> schemes = new HashSet<String>();
+
+ @BeforeClass
+ public static void setupSchemes() {
+ schemes.add("ftp");
+ schemes.add("file");
+ }
@Test
- public void testColonInFileName() {
- Assert.assertEquals(null, UriParser.extractScheme("some/path/some:file"));
+ public void testColonInFileNameAndNotSupportedScheme() {
+ Assert.assertEquals(null, UriParser.extractScheme(schemes,"some:file"));
+ }
+ @Test
+ public void testColonInFileNameWithPath() {
+ Assert.assertEquals(null, UriParser.extractScheme(schemes,"some/path/some:file"));
}
@Test
public void testNormalScheme() {
- Assert.assertEquals("ftp", UriParser.extractScheme("ftp://user:pass@host/some/path/some:file"));
+ Assert.assertEquals("ftp", UriParser.extractScheme(schemes,"ftp://user:pass@host/some/path/some:file"));
}
+ @Test
+ public void testOneSlashScheme() {
+ Assert.assertEquals("file", UriParser.extractScheme(schemes,"file:/user:pass@host/some/path/some:file"));
+ }
+
+ @Test
+ public void testColonNotFollowedBySlash() {
+ Assert.assertEquals("file",UriParser.extractScheme(schemes,"file:user/subdir/some/path/some:file"));
+ }
+
+ @Test
+ public void testNormalSchemeWithBuffer() {
+ StringBuilder buffer = new StringBuilder();
+ UriParser.extractScheme(schemes,"ftp://user:pass@host/some/path/some:file",buffer);
+ Assert.assertEquals("//user:pass@host/some/path/some:file",buffer.toString());
+ }
+
+ @Test
+ public void testOneSlashSchemeWithBuffer() {
+ StringBuilder buffer = new StringBuilder();
+ UriParser.extractScheme(schemes,"file:/user:pass@host/some/path/some:file",buffer);
+ Assert.assertEquals("/user:pass@host/some/path/some:file",buffer.toString());
+ }
}
diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/test/FileNameTests.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/test/FileNameTests.java
index 8104d8a..bd674c9 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/test/FileNameTests.java
+++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/test/FileNameTests.java
@@ -17,7 +17,7 @@
package org.apache.commons.vfs2.provider.local.test;
import java.io.File;
-
+import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.test.AbstractProviderTestCase;
diff --git a/pom.xml b/pom.xml
index 2070289..01585c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -135,6 +135,10 @@
<name>Jose Juan Montiel</name>
<email>josejuan.montiel -at- gmail.com</email>
</contributor>
+ <contributor>
+ <name>Otto Fowler</name>
+ <email>otto -at- apache.org</email>
+ </contributor>
</contributors>
<properties>