Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 48564 invoked from network); 4 Dec 2004 19:28:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 4 Dec 2004 19:28:46 -0000 Received: (qmail 10067 invoked by uid 500); 4 Dec 2004 19:28:43 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 10001 invoked by uid 500); 4 Dec 2004 19:28:43 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 9988 invoked by uid 500); 4 Dec 2004 19:28:42 -0000 Received: (qmail 9985 invoked by uid 99); 4 Dec 2004 19:28:42 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Sat, 04 Dec 2004 11:28:42 -0800 Received: (qmail 48518 invoked by uid 1529); 4 Dec 2004 19:28:40 -0000 Date: 4 Dec 2004 19:28:40 -0000 Message-ID: <20041204192840.48517.qmail@minotaur.apache.org> From: scolebourne@apache.org To: jakarta-commons-cvs@apache.org Subject: cvs commit: jakarta-commons/io/src/java/org/apache/commons/io FilenameUtils.java X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N scolebourne 2004/12/04 11:28:40 Modified: io/src/test/org/apache/commons/io FilenameUtilsTestCase.java io/src/java/org/apache/commons/io FilenameUtils.java Log: Add equals methods, document Unix/Windows behaviour Revision Changes Path 1.23 +23 -1 jakarta-commons/io/src/test/org/apache/commons/io/FilenameUtilsTestCase.java Index: FilenameUtilsTestCase.java =================================================================== RCS file: /home/cvs/jakarta-commons/io/src/test/org/apache/commons/io/FilenameUtilsTestCase.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- FilenameUtilsTestCase.java 27 Nov 2004 17:00:51 -0000 1.22 +++ FilenameUtilsTestCase.java 4 Dec 2004 19:28:40 -0000 1.23 @@ -451,6 +451,28 @@ } //----------------------------------------------------------------------- + public void testEquals() { + assertEquals(true, FilenameUtils.equals(null, null)); + assertEquals(false, FilenameUtils.equals(null, "")); + assertEquals(false, FilenameUtils.equals("", null)); + assertEquals(true, FilenameUtils.equals("", "")); + assertEquals(true, FilenameUtils.equals("file.txt", "file.txt")); + assertEquals(WINDOWS, FilenameUtils.equals("file.txt", "FILE.TXT")); + assertEquals(false, FilenameUtils.equals("a\\b\\file.txt", "a/b/file.txt")); + } + + public void testEqualsNormalized() { + assertEquals(true, FilenameUtils.equalsNormalized(null, null)); + assertEquals(false, FilenameUtils.equalsNormalized(null, "")); + assertEquals(false, FilenameUtils.equalsNormalized("", null)); + assertEquals(true, FilenameUtils.equalsNormalized("", "")); + assertEquals(true, FilenameUtils.equalsNormalized("file.txt", "file.txt")); + assertEquals(WINDOWS, FilenameUtils.equalsNormalized("file.txt", "FILE.TXT")); + assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\file.txt", "a/b/file.txt")); + assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\", "a/b")); + } + + //----------------------------------------------------------------------- public void testIsExtension() { assertEquals(false, FilenameUtils.isExtension(null, (String) null)); assertEquals(false, FilenameUtils.isExtension("file.txt", (String) null)); 1.31 +134 -26 jakarta-commons/io/src/java/org/apache/commons/io/FilenameUtils.java Index: FilenameUtils.java =================================================================== RCS file: /home/cvs/jakarta-commons/io/src/java/org/apache/commons/io/FilenameUtils.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- FilenameUtils.java 27 Nov 2004 17:00:51 -0000 1.30 +++ FilenameUtils.java 4 Dec 2004 19:28:40 -0000 1.31 @@ -22,6 +22,16 @@ /** * Utility class that provides methods to manipulate filenames and filepaths. *

+ * When dealing with filenames you can hit problems when moving from a Windows + * based development machine to a Unix based production machine. + * This class aims to help avoid those problems. + *

+ * Most methods on this class are designed to work the same on both Unix and Windows. + * Both separators (forward and back) are recognised, and both sets of prefixes. + * The comparison methods do differ by machine however, comparing case insensitive + * on Windows and case sensitive on Unix. + * See the javadoc of each method for details. + *

* This class defines six components within a filename (example C:\dev\project\file.txt): *

    *
  • the prefix - C:\
  • @@ -31,7 +41,9 @@ *
  • the base name - file
  • *
  • the extension - txt
  • *
- * The class only supports Unix and Windows style names. Prefixes are matched as follows: + * Note that the path of a directory is the parent directory. + *

+ * This class only supports Unix and Windows style names. Prefixes are matched as follows: *

    * Windows style:
    * a\b\c.txt           --> ""          --> relative
  @@ -45,6 +57,8 @@
    * ~/a/b/c.txt         --> "~/"        --> current user relative
    * ~user/a/b/c.txt     --> "~user/"    --> named user relative
    * 
+ * Both prefix styles are matched always, irrespective of the machine that you are + * currently running on. * *

*

Origin of code

@@ -133,6 +147,9 @@ * 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, null * is returned. + *

+ * The output will be the same on both Unix and Windows except + * for the separator character. *

        * /foo//               -->   /foo
        * /foo/./              -->   /foo
  @@ -151,7 +168,7 @@
        * ~/foo/../bar         -->   ~/bar
        * ~/../bar             -->   null
        * 
- * (Note the file separator returned will be correct for windows/unix) + * (Note the file separator returned will be correct for Windows/Unix) * * @param filename the filename to normalize, null returns null * @return the normalized String, or null if invalid @@ -232,7 +249,7 @@ } /** - * Concatenates two paths using normal command line style rules. + * Concatenates a filename to a base path using normal command line style rules. *

* The first argument is the base path, the second is the path to concatenate. * The returned path is always normalized via {@link #normalize(String)}, @@ -241,43 +258,47 @@ * If pathToAdd is absolute (has a prefix), then it will * be normalized and returned. * Otherwise, the paths will be joined, normalized and returned. + *

+ * The output will be the same on both Unix and Windows except + * for the separator character. *

        * /foo/ + bar          -->   /foo/bar
        * /foo/a + bar         -->   /foo/a/bar
  -     * /foo/c.txt + bar     -->   /foo/c.txt/bar
        * /foo/ + ../bar       -->   /bar
        * /foo/ + ../../bar    -->   null
        * /foo/ + /bar         -->   /bar
        * /foo/.. + /bar       -->   /bar
  +     * /foo + bar/c.txt     -->   /foo/bar/c.txt
  +     * /foo/c.txt + bar     -->   /foo/c.txt/bar (!)
        * 
- * Note that the first parameter must be a path. If it ends with a name, then + * (!) Note that the first parameter must be a path. If it ends with a name, then * the name will be built into the concatenated path. If this might be a problem, * use {@link #getFullPath(String)} on the base path argument. * * @param basePath the base path to attach to, always treated as a path - * @param pathToAdd path the second path to attach to the first + * @param fullFilenameToAdd the filename (or path) to attach to the base * @return the concatenated path, or null if invalid */ - public static String concat(String basePath, String pathToAdd) { - int prefix = getPrefixLength(pathToAdd); + public static String concat(String basePath, String fullFilenameToAdd) { + int prefix = getPrefixLength(fullFilenameToAdd); if (prefix < 0) { return null; } if (prefix > 0) { - return normalize(pathToAdd); + return normalize(fullFilenameToAdd); } if (basePath == null) { return null; } int len = basePath.length(); if (len == 0) { - return normalize(pathToAdd); + return normalize(fullFilenameToAdd); } char ch = basePath.charAt(len - 1); if (isSeparator(basePath.charAt(len - 1))) { - return normalize(basePath + pathToAdd); + return normalize(basePath + fullFilenameToAdd); } else { - return normalize(basePath + '/' + pathToAdd); + return normalize(basePath + '/' + fullFilenameToAdd); } } @@ -344,8 +365,9 @@ * ~/a/b/c.txt --> "~/" --> current user relative * ~user/a/b/c.txt --> "~user/" --> named user relative * - * Both sets of prefixes will be matched regardless of the system - * on which the code runs. + *

+ * The output will be the same irrespective of the machine that the code is running on. + * ie. both Unix and Windows prefixes are matched regardless. * * @param filename the filename to find the prefix in, null returns -1 * @return the length of the prefix, -1 if invalid or null @@ -406,6 +428,8 @@ *

* This method will handle a file in either Unix or Windows format. * The position of the last forward or backslash is returned. + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there @@ -426,6 +450,8 @@ * This method also checks that there is no directory separator after the last dot. * To do this it uses {@link #indexOfLastSeparator(String)} which will * handle a file in either Unix or Windows format. + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there @@ -459,6 +485,9 @@ * ~/a/b/c.txt --> "~/" --> current user relative * ~user/a/b/c.txt --> "~user/" --> named user relative * + *

+ * The output will be the same irrespective of the machine that the code is running on. + * ie. both Unix and Windows prefixes are matched regardless. * * @param filename the filename to query, null returns null * @return the prefix of the file, null if invalid @@ -476,6 +505,7 @@ /** * Gets the path from a full filename, which excludes the prefix. + * The path of a directory is the parent directory. *

* This method will handle a file in either Unix or Windows format. * The text before the last forward or backslash is returned. @@ -486,6 +516,8 @@ * a/b/c --> a/b * a/b/c/ --> a/b/c * + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid @@ -508,6 +540,7 @@ /** * Gets the full path from a full filename, which is the prefix + path. + * The path of a directory is the parent directory. *

* This method will handle a file in either Unix or Windows format. * The text before the last forward or backslash is returned. @@ -518,6 +551,8 @@ * a/b/c --> a/b * a/b/c/ --> a/b/c * + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid @@ -549,6 +584,8 @@ * a/b/c --> c * a/b/c/ --> "" * + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to query, null returns null * @return the name of the file without the path, or an empty string if none exists @@ -572,6 +609,8 @@ * a/b/c --> c * a/b/c/ --> "" * + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to query, null returns null * @return the name of the file without the path, or an empty string if none exists @@ -591,6 +630,8 @@ * a/b.txt/c --> "" * a/b/c --> "" * + *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to retrieve the extension of. * @return the extension of the file or an empty string if none exists. @@ -615,10 +656,12 @@ * There must be no directory separator after the dot. *

        * foo.txt    --> foo
  -     * a\b\c.jpg --> a\b\c
  -     * a\b\c     --> a\b\c
  -     * a.b\c        --> a.b\c
  +     * a\b\c.jpg  --> a\b\c
  +     * a\b\c      --> a\b\c
  +     * a.b\c      --> a.b\c
        * 
+ *

+ * The output will be the same irrespective of the machine that the code is running on. * * @param filename the filename to query, null returns null * @return the filename minus the extension @@ -637,7 +680,60 @@ //----------------------------------------------------------------------- /** - * Checks whether the extension of the filename is that specified. + * Checks whether two filenames are equal using the case rules of the system. + *

+ * No processing is performed on the filenames other than comparison. + * The check is case sensitive on Unix and case insensitive on Windows. + * + * @param filename1 the first filename to query, may be null + * @param filename2 the second filename to query, may be null + * @return true if the filenames are equal, null equals null + */ + public static boolean equals(String filename1, String filename2) { + if (filename1 == filename2) { + return true; + } + if (filename1 == null || filename2 == null) { + return false; + } + if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) { + return filename1.equalsIgnoreCase(filename2); + } else { + return filename1.equals(filename2); + } + } + + /** + * Checks whether two filenames are equal after both have been normalized + * and using the case rules of the system. + *

+ * Both filenames are first passed to {@link #normalize(String)}. + * The check is then performed case sensitive on Unix and case insensitive on Windows. + * + * @param filename1 the first filename to query, may be null + * @param filename2 the second filename to query, may be null + * @return true if the filenames are equal, null equals null + */ + public static boolean equalsNormalized(String filename1, String filename2) { + if (filename1 == filename2) { + return true; + } + if (filename1 == null || filename2 == null) { + return false; + } + filename1 = normalize(filename1); + filename2 = normalize(filename2); + if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) { + return filename1.equalsIgnoreCase(filename2); + } else { + return filename1.equals(filename2); + } + } + + //----------------------------------------------------------------------- + /** + * Checks whether the extension of the filename is that specified + * using the case rules of the system. *

* This method obtains the extension as the textual part of the filename * after the last dot. There must be no directory separator after the dot. @@ -663,7 +759,8 @@ } /** - * Checks whether the extension of the filename is one of those specified. + * Checks whether the extension of the filename is one of those specified + * using the case rules of the system. *

* This method obtains the extension as the textual part of the filename * after the last dot. There must be no directory separator after the dot. @@ -698,7 +795,8 @@ } /** - * Checks whether the extension of the filename is one of those specified. + * Checks whether the extension of the filename is one of those specified + * using the case rules of the system. *

* This method obtains the extension as the textual part of the filename * after the last dot. There must be no directory separator after the dot. @@ -721,15 +819,25 @@ //----------------------------------------------------------------------- /** - * See if a particular piece of text, often a filename, - * matches to a specified wildcard, as seen on DOS/UNIX command lines. + * Checks a filename to see if it matches the specified wildcard matcher. + *

+ * The wildcard matcher uses the characters '?' and '*' to represent a + * single or multiple wildcard characters. + * This is the same as often found on Dos/Unix command lines. + *

  +     * wildcardMatch("c.txt", "*.txt")      --> true
  +     * wildcardMatch("c.txt", "*.jpg")      --> false
  +     * wildcardMatch("a/b/c.txt", "a/b/*")  --> true
  +     * wildcardMatch("c.txt", "*.???")      --> true
  +     * wildcardMatch("c.txt", "*.????")     --> false
  +     * 
* * @param filename the filename to match on - * @param wildcard the wildcard string to match against + * @param wildcardMatcher the wildcard string to match against * @return true if the filename matches the wilcard string */ - public static boolean wildcardMatch(String filename, String wildcard) { - String[] wcs = splitOnTokens(wildcard); + public static boolean wildcardMatch(String filename, String wildcardMatcher) { + String[] wcs = splitOnTokens(wildcardMatcher); int textIdx = 0; int wcsIdx = 0; --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org