You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ni...@apache.org on 2008/12/04 02:49:45 UTC
svn commit: r723186 - in /commons/proper/io/trunk/src:
java/org/apache/commons/io/FilenameUtils.java
test/org/apache/commons/io/FilenameUtilsTestCase.java
Author: niallp
Date: Wed Dec 3 17:49:44 2008
New Revision: 723186
URL: http://svn.apache.org/viewvc?rev=723186&view=rev
Log:
IO-156 Add normalize() and normalizeNoEndSeparator() method flavours which allow the separator character to be specified
Modified:
commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsTestCase.java
Modified: commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java?rev=723186&r1=723185&r2=723186&view=diff
==============================================================================
--- commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java (original)
+++ commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java Wed Dec 3 17:49:44 2008
@@ -201,7 +201,54 @@
* @return the normalized filename, or null if invalid
*/
public static String normalize(String filename) {
- return doNormalize(filename, true);
+ return doNormalize(filename, SYSTEM_SEPARATOR, true);
+ }
+ /**
+ * Normalizes a path, removing double and single dot path steps.
+ * <p>
+ * This method normalizes a path to a standard format.
+ * The input may contain separators in either Unix or Windows format.
+ * The output will contain separators in the format specified.
+ * <p>
+ * A trailing slash will be retained.
+ * A double slash will be merged to a single slash (but UNC names are handled).
+ * A single dot path segment will be removed.
+ * A double dot will cause that path segment and the one before to be removed.
+ * If the double dot has no parent path segment to work with, <code>null</code>
+ * is returned.
+ * <p>
+ * The output will be the same on both Unix and Windows except
+ * for the separator character.
+ * <pre>
+ * /foo// --> /foo/
+ * /foo/./ --> /foo/
+ * /foo/../bar --> /bar
+ * /foo/../bar/ --> /bar/
+ * /foo/../bar/../baz --> /baz
+ * //foo//./bar --> /foo/bar
+ * /../ --> null
+ * ../foo --> null
+ * foo/bar/.. --> foo/
+ * foo/../../bar --> null
+ * foo/../bar --> bar
+ * //server/foo/../bar --> //server/bar
+ * //server/../bar --> null
+ * C:\foo\..\bar --> C:\bar
+ * C:\..\bar --> null
+ * ~/foo/../bar/ --> ~/bar/
+ * ~/../bar --> null
+ * </pre>
+ * The output will be the same on both Unix and Windows including
+ * the separator character.
+ *
+ * @param filename the filename to normalize, null returns null
+ * @param unixSeparator <code>true</code> if a unix separator should
+ * be used or <code>false</code> if a windows separtor should be used.
+ * @return the normalized filename, or null if invalid
+ */
+ public static String normalize(String filename, boolean unixSeparator) {
+ char separator = (unixSeparator ? UNIX_SEPARATOR : WINDOWS_SEPARATOR);
+ return doNormalize(filename, separator, true);
}
//-----------------------------------------------------------------------
@@ -247,17 +294,65 @@
* @return the normalized filename, or null if invalid
*/
public static String normalizeNoEndSeparator(String filename) {
- return doNormalize(filename, false);
+ return doNormalize(filename, SYSTEM_SEPARATOR, false);
+ }
+
+ /**
+ * Normalizes a path, removing double and single dot path steps,
+ * and removing any final directory separator.
+ * <p>
+ * This method normalizes a path to a standard format.
+ * The input may contain separators in either Unix or Windows format.
+ * The output will contain separators in the format specified.
+ * <p>
+ * A trailing slash will be removed.
+ * A double slash will be merged to a single slash (but UNC names are handled).
+ * A single dot path segment will be removed.
+ * A double dot will cause that path segment and the one before to be removed.
+ * If the double dot has no parent path segment to work with, <code>null</code>
+ * is returned.
+ * <p>
+ * The output will be the same on both Unix and Windows including
+ * the separator character.
+ * <pre>
+ * /foo// --> /foo
+ * /foo/./ --> /foo
+ * /foo/../bar --> /bar
+ * /foo/../bar/ --> /bar
+ * /foo/../bar/../baz --> /baz
+ * //foo//./bar --> /foo/bar
+ * /../ --> null
+ * ../foo --> null
+ * foo/bar/.. --> foo
+ * foo/../../bar --> null
+ * foo/../bar --> bar
+ * //server/foo/../bar --> //server/bar
+ * //server/../bar --> null
+ * C:\foo\..\bar --> C:\bar
+ * C:\..\bar --> null
+ * ~/foo/../bar/ --> ~/bar
+ * ~/../bar --> null
+ * </pre>
+ *
+ * @param filename the filename to normalize, null returns null
+ * @param unixSeparator <code>true</code> if a unix separator should
+ * be used or <code>false</code> if a windows separtor should be used.
+ * @return the normalized filename, or null if invalid
+ */
+ public static String normalizeNoEndSeparator(String filename, boolean unixSeparator) {
+ char separator = (unixSeparator ? UNIX_SEPARATOR : WINDOWS_SEPARATOR);
+ return doNormalize(filename, separator, false);
}
/**
* Internal method to perform the normalization.
*
* @param filename the filename
+ * @param separator The separator character to use
* @param keepSeparator true to keep the final separator
* @return the normalized filename
*/
- private static String doNormalize(String filename, boolean keepSeparator) {
+ private static String doNormalize(String filename, char separator, boolean keepSeparator) {
if (filename == null) {
return null;
}
@@ -274,22 +369,23 @@
filename.getChars(0, filename.length(), array, 0);
// fix separators throughout
+ char otherSeparator = (separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR);
for (int i = 0; i < array.length; i++) {
- if (array[i] == OTHER_SEPARATOR) {
- array[i] = SYSTEM_SEPARATOR;
+ if (array[i] == otherSeparator) {
+ array[i] = separator;
}
}
// add extra separator on the end to simplify code below
boolean lastIsDirectory = true;
- if (array[size - 1] != SYSTEM_SEPARATOR) {
- array[size++] = SYSTEM_SEPARATOR;
+ if (array[size - 1] != separator) {
+ array[size++] = separator;
lastIsDirectory = false;
}
// adjoining slashes
for (int i = prefix + 1; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == SYSTEM_SEPARATOR) {
+ if (array[i] == separator && array[i - 1] == separator) {
System.arraycopy(array, i, array, i - 1, size - i);
size--;
i--;
@@ -298,8 +394,8 @@
// dot slash
for (int i = prefix + 1; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' &&
- (i == prefix + 1 || array[i - 2] == SYSTEM_SEPARATOR)) {
+ if (array[i] == separator && array[i - 1] == '.' &&
+ (i == prefix + 1 || array[i - 2] == separator)) {
if (i == size - 1) {
lastIsDirectory = true;
}
@@ -312,8 +408,8 @@
// double dot slash
outer:
for (int i = prefix + 2; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' && array[i - 2] == '.' &&
- (i == prefix + 2 || array[i - 3] == SYSTEM_SEPARATOR)) {
+ if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
+ (i == prefix + 2 || array[i - 3] == separator)) {
if (i == prefix + 2) {
return null;
}
@@ -322,7 +418,7 @@
}
int j;
for (j = i - 4 ; j >= prefix; j--) {
- if (array[j] == SYSTEM_SEPARATOR) {
+ if (array[j] == separator) {
// remove b/../ from a/b/../c
System.arraycopy(array, i + 1, array, j + 1, size - i);
size -= (i - j);
Modified: commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsTestCase.java?rev=723186&r1=723185&r2=723186&view=diff
==============================================================================
--- commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsTestCase.java (original)
+++ commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsTestCase.java Wed Dec 3 17:49:44 2008
@@ -232,6 +232,17 @@
assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/"));
}
+ public void testNormalizeUnixWin() throws Exception {
+
+ // Normalize (Unix Separator)
+ assertEquals("/a/c/", FilenameUtils.normalize("/a/b/../c/", true));
+ assertEquals("/a/c/", FilenameUtils.normalize("\\a\\b\\..\\c\\", true));
+
+ // Normalize (Windows Separator)
+ assertEquals("\\a\\c\\", FilenameUtils.normalize("/a/b/../c/", false));
+ assertEquals("\\a\\c\\", FilenameUtils.normalize("\\a\\b\\..\\c\\", false));
+ }
+
//-----------------------------------------------------------------------
public void testNormalizeNoEndSeparator() throws Exception {
assertEquals(null, FilenameUtils.normalizeNoEndSeparator(null));
@@ -382,6 +393,17 @@
assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalizeNoEndSeparator("//server/"));
}
+ public void testNormalizeNoEndSeparatorUnixWin() throws Exception {
+
+ // Normalize (Unix Separator)
+ assertEquals("/a/c", FilenameUtils.normalizeNoEndSeparator("/a/b/../c/", true));
+ assertEquals("/a/c", FilenameUtils.normalizeNoEndSeparator("\\a\\b\\..\\c\\", true));
+
+ // Normalize (Windows Separator)
+ assertEquals("\\a\\c", FilenameUtils.normalizeNoEndSeparator("/a/b/../c/", false));
+ assertEquals("\\a\\c", FilenameUtils.normalizeNoEndSeparator("\\a\\b\\..\\c\\", false));
+ }
+
//-----------------------------------------------------------------------
public void testConcat() {
assertEquals(null, FilenameUtils.concat("", null));