scolebourne 2004/11/27 09:00:51 Modified: io/src/test/org/apache/commons/io FilenameUtilsTestCase.java io/src/java/org/apache/commons/io FilenameUtils.java Log: Rewrite catPath, renaming to concat Revision Changes Path 1.22 +32 -13 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.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- FilenameUtilsTestCase.java 27 Nov 2004 01:22:05 -0000 1.21 +++ FilenameUtilsTestCase.java 27 Nov 2004 17:00:51 -0000 1.22 @@ -82,18 +82,6 @@ } //----------------------------------------------------------------------- - public void testCatPath() { - // TODO StringIndexOutOfBoundsException thrown if file doesn't contain slash. - // Is this acceptable? - //assertEquals("", FilenameUtils.catPath("a", "b")); - - assertEquals("/a" + File.separator + "c", FilenameUtils.catPath("/a/b", "c")); - assertEquals("/a" + File.separator + "d", FilenameUtils.catPath("/a/b/c", "../d")); - assertEquals("C:\\a" + File.separator + "c", FilenameUtils.catPath("C:\\a\\b", "c")); - assertEquals("C:\\a" + File.separator + "d", FilenameUtils.catPath("C:\\a\\b\\c", "../d")); - } - - //----------------------------------------------------------------------- public void testNormalize() throws Exception { assertEquals(null, FilenameUtils.normalize(null)); assertEquals(null, FilenameUtils.normalize(":")); @@ -213,6 +201,37 @@ assertEquals(null, FilenameUtils.normalize("//server/../a")); assertEquals(null, FilenameUtils.normalize("//server/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/")); + } + + //----------------------------------------------------------------------- + public void testConcat() { + assertEquals(null, FilenameUtils.concat("", null)); + assertEquals(null, FilenameUtils.concat(null, null)); + assertEquals(null, FilenameUtils.concat(null, "")); + assertEquals(null, FilenameUtils.concat(null, "a")); + assertEquals(SEP + "a", FilenameUtils.concat(null, "/a")); + + assertEquals(null, FilenameUtils.concat("", ":")); // invalid prefix + assertEquals(null, FilenameUtils.concat(":", "")); // invalid prefix + + assertEquals("f", FilenameUtils.concat("", "f/")); + assertEquals("f", FilenameUtils.concat("", "f")); + assertEquals("a" + SEP + "f", FilenameUtils.concat("a/", "f/")); + assertEquals("a" + SEP + "f", FilenameUtils.concat("a", "f")); + assertEquals("a" + SEP + "b" + SEP + "f", FilenameUtils.concat("a/b/", "f/")); + assertEquals("a" + SEP + "b" + SEP + "f", FilenameUtils.concat("a/b", "f")); + + assertEquals("a" + SEP + "f", FilenameUtils.concat("a/b/", "../f/")); + assertEquals("a" + SEP + "f", FilenameUtils.concat("a/b", "../f")); + assertEquals("a" + SEP + "c" + SEP + "g", FilenameUtils.concat("a/b/../c/", "f/../g/")); + assertEquals("a" + SEP + "c" + SEP + "g", FilenameUtils.concat("a/b/../c", "f/../g")); + + assertEquals("a" + SEP + "c.txt" + SEP + "f", FilenameUtils.concat("a/c.txt", "f")); + + assertEquals(SEP + "f", FilenameUtils.concat("", "/f/")); + assertEquals(SEP + "f", FilenameUtils.concat("", "/f")); + assertEquals(SEP + "f", FilenameUtils.concat("a/", "/f/")); + assertEquals(SEP + "f", FilenameUtils.concat("a", "/f")); } //----------------------------------------------------------------------- 1.30 +71 -47 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.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- FilenameUtils.java 27 Nov 2004 01:22:05 -0000 1.29 +++ FilenameUtils.java 27 Nov 2004 17:00:51 -0000 1.30 @@ -31,13 +31,28 @@ * <li>the base name - file</li> * <li>the extension - txt</li> * </ul> - * The class only supports Unix and Windows style names. + * The class only supports Unix and Windows style names. Prefixes are matched as follows: + * <pre> + * Windows style: + * a\b\c.txt --> "" --> relative + * \a\b\c.txt --> "\" --> drive relative + * C:\a\b\c.txt --> "C:\" --> absolute + * \\server\a\b\c.txt --> "\\server\" --> UNC + * + * Unix style: + * a/b/c.txt --> "" --> relative + * /a/b/c.txt --> "/" --> absolute + * ~/a/b/c.txt --> "~/" --> current user relative + * ~user/a/b/c.txt --> "~user/" --> named user relative + * </pre> + * * </p> * <h3>Origin of code</h3> * <ul> * <li>Commons Utils</li> * <li>Alexandria's FileUtils</li> * <li>Avalon Excalibur's IO</li> + * <li>Tomcat</li> * </ul> * * @author <a href="mailto:[EMAIL PROTECTED]">Kevin A. Burton</A> @@ -90,14 +105,15 @@ /** * Instances should NOT be constructed in standard programming. */ - public FilenameUtils() { } + public FilenameUtils() { + } //----------------------------------------------------------------------- /** * Checks if the character is a separator. * * @param ch the character to check - * @return true if it is a separators + * @return true if it is a separator character */ private static boolean isSeparator(char ch) { return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR); @@ -135,9 +151,10 @@ * ~/foo/../bar --> ~/bar * ~/../bar --> null * </pre> + * (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 too many ..'s. + * @return the normalized String, or null if invalid */ public static String normalize(String filename) { if (filename == null) { @@ -215,49 +232,53 @@ } /** - * Will concatenate 2 paths. Paths with <code>..</code> will be - * properly handled. The path separator between the 2 paths is the - * system default path separator. - * - * <p>Eg. on UNIX,<br /> - * <code>/a/b/c</code> + <code>d</code> = <code>/a/b/d</code><br /> - * <code>/a/b/c</code> + <code>../d</code> = <code>/a/d</code><br /> - * </p> - * - * <p>Eg. on Microsoft Windows,<br /> - * <code>C:\a\b\c</code> + <code>d</code> = <code>C:\a\b\d</code><br /> - * <code>C:\a\b\c</code> + <code>..\d</code> = <code>C:\a\d</code><br /> - * <code>/a/b/c</code> + <code>d</code> = <code>/a/b\d</code><br /> - * </p> - * - * Thieved from Tomcat sources... + * Concatenates two paths using normal command line style rules. + * <p> + * The first argument is the base path, the second is the path to concatenate. + * The returned path is always normalized via [EMAIL PROTECTED] #normalize(String)}, + * thus <code>..</code> is handled. + * <p> + * If <code>pathToAdd</code> is absolute (has a prefix), then it will + * be normalized and returned. + * Otherwise, the paths will be joined, normalized and returned. + * <pre> + * /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 + * </pre> + * 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 [EMAIL PROTECTED] #getFullPath(String)} on the base path argument. * - * @param lookupPath the base path to attach to - * @param path path the second path to attach to the first - * @return The concatenated paths, or null if error occurs - */ - // TODO UNIX/Windows only. Is this a problem? - public static String catPath(String lookupPath, String path) { - // Cut off the last slash and everything beyond - int index = indexOfLastSeparator(lookupPath); - String lookup = lookupPath.substring(0, index); - String pth = path; - - // Deal with .. by chopping dirs off the lookup path - while (pth.startsWith("../") || pth.startsWith("..\\")) { - if (lookup.length() > 0) { - index = indexOfLastSeparator(lookup); - lookup = lookup.substring(0, index); - } else { - // More ..'s than dirs, return null - return null; - } - - pth = pth.substring(3); + * @param basePath the base path to attach to, always treated as a path + * @param pathToAdd path the second path to attach to the first + * @return the concatenated path, or null if invalid + */ + public static String concat(String basePath, String pathToAdd) { + int prefix = getPrefixLength(pathToAdd); + if (prefix < 0) { + return null; + } + if (prefix > 0) { + return normalize(pathToAdd); + } + if (basePath == null) { + return null; + } + int len = basePath.length(); + if (len == 0) { + return normalize(pathToAdd); + } + char ch = basePath.charAt(len - 1); + if (isSeparator(basePath.charAt(len - 1))) { + return normalize(basePath + pathToAdd); + } else { + return normalize(basePath + '/' + pathToAdd); } - - return new StringBuffer(lookup). - append(File.separator).append(pth).toString(); } //----------------------------------------------------------------------- @@ -338,8 +359,11 @@ return 0; } char ch0 = filename.charAt(0); + if (ch0 == ':') { + return -1; + } if (len == 1) { - if (ch0 == '~' || ch0 == ':') { + if (ch0 == '~') { return -1; } return (isSeparator(ch0) ? 1 : 0);
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]