diff --git a/docs/manual/platform.html b/docs/manual/platform.html index 27dc88ee0..4091a0fd4 100644 --- a/docs/manual/platform.html +++ b/docs/manual/platform.html @@ -52,4 +52,7 @@ Support for other platforms is not guaranteed to be complete, as certain techniques to hide platform details from build files need to be written and tested on every particular platform. Contributions in this area are welcome. +
+

Copyright © 2002 Apache Software Foundation. All rights +Reserved.

diff --git a/src/main/org/apache/tools/ant/PathTokenizer.java b/src/main/org/apache/tools/ant/PathTokenizer.java index c8addd958..da82d26b6 100644 --- a/src/main/org/apache/tools/ant/PathTokenizer.java +++ b/src/main/org/apache/tools/ant/PathTokenizer.java @@ -53,6 +53,8 @@ */ package org.apache.tools.ant; +import org.apache.tools.ant.taskdefs.condition.Os; + import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.io.File; @@ -79,6 +81,18 @@ public class PathTokenizer { */ private String lookahead = null; + /** + * A boolean that determines if we are running on Novell NetWare, which + * exhibits slightly different path name characteristics (multi-character + * volume / drive names) + */ + private boolean onNetWare = Os.isFamily("netware"); + + /** + * This will be used for String comparisons of the path Separator later + */ + private String pathSeparatorStr = String.valueOf(File.pathSeparatorChar); + /** * Flag to indicate whether or not we are running on a platform with a * DOS style filesystem @@ -91,8 +105,17 @@ public class PathTokenizer { * @param path The path to tokenize. Must not be null. */ public PathTokenizer(String path) { - tokenizer = new StringTokenizer(path, ":;", false); - dosStyleFilesystem = File.pathSeparatorChar == ';'; + if (onNetWare) { + // For NetWare, use the boolean=true mode, so we can use delimiter + // information to make a better decision later. + tokenizer = new StringTokenizer(path, ":;", true); + } + else { + // on Windows and Unix, we can ignore delimiters and still have + // enough information to tokenize correctly. + tokenizer = new StringTokenizer(path, ":;", false); + } + dosStyleFilesystem = File.pathSeparatorChar == ';'; } /** @@ -129,23 +152,60 @@ public class PathTokenizer { token = tokenizer.nextToken().trim(); } - if (token.length() == 1 && Character.isLetter(token.charAt(0)) - && dosStyleFilesystem - && tokenizer.hasMoreTokens()) { - // we are on a dos style system so this path could be a drive - // spec. We look at the next token - String nextToken = tokenizer.nextToken().trim(); - if (nextToken.startsWith("\\") || nextToken.startsWith("/")) { - // we know we are on a DOS style platform and the next path starts with a - // slash or backslash, so we know this is a drive spec - token += ":" + nextToken; + if (!onNetWare) { + if (token.length() == 1 && Character.isLetter(token.charAt(0)) + && dosStyleFilesystem + && tokenizer.hasMoreTokens()) { + // we are on a dos style system so this path could be a drive + // spec. We look at the next token + String nextToken = tokenizer.nextToken().trim(); + if (nextToken.startsWith("\\") || nextToken.startsWith("/")) { + // we know we are on a DOS style platform and the next path + // starts with a slash or backslash, so we know this is a + // drive spec + token += ":" + nextToken; + } + else { + // store the token just read for next time + lookahead = nextToken; + } } - else { - // store the token just read for next time - lookahead = nextToken; + } + else { + // we are on NetWare, tokenizing is handled a little differently, + // due to the fact that NetWare has multiple-character volume names. + if (token.equals(pathSeparatorStr)) { + // ignore ";" and get the next token + token = tokenizer.nextToken().trim(); + } + + if (tokenizer.hasMoreTokens()) { + // this path could be a drive spec, so look at the next token + String nextToken = tokenizer.nextToken().trim(); + + // make sure we aren't going to get the path separator next + if (!nextToken.equals(pathSeparatorStr)) { + if (nextToken.equals(":")) { + if (!token.startsWith("/") && !token.startsWith("\\")){ + // it indeed is a drive spec, get the next bit + String oneMore = tokenizer.nextToken().trim(); + if (!oneMore.equals(pathSeparatorStr)) { + token += ":" + oneMore; + } + else { + token += ":"; + } + } + // implicit else: ignore the ':' since we have either a + // UNIX or a relative path + } + else { + // store the token just read for next time + lookahead = nextToken; + } + } } } - return token; } } diff --git a/src/testcases/org/apache/tools/ant/types/PathTest.java b/src/testcases/org/apache/tools/ant/types/PathTest.java index f6b9d800e..3f37925b3 100644 --- a/src/testcases/org/apache/tools/ant/types/PathTest.java +++ b/src/testcases/org/apache/tools/ant/types/PathTest.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,7 +86,7 @@ public class PathTest extends TestCase { } // actually tests constructor as well as setPath - public void testConstructor() { + public void testConstructorUnixStyle() { Path p = new Path(project, "/a:/b"); String[] l = p.list(); assertEquals("two items, Unix style", 2, l.length); @@ -100,9 +100,11 @@ public class PathTest extends TestCase { assertEquals(":\\a", l[0].substring(1)); assertEquals(":\\b", l[1].substring(1)); } + } - p = new Path(project, "\\a;\\b"); - l = p.list(); + public void testConstructorWindowsStyle() { + Path p = new Path(project, "\\a;\\b"); + String[] l = p.list(); assertEquals("two items, DOS style", 2, l.length); if (isUnixStyle) { assertEquals("/a", l[0]); @@ -115,36 +117,39 @@ public class PathTest extends TestCase { assertEquals(":\\b", l[1].substring(1)); } - p = new Path(project, "\\a;\\b:/c"); + p = new Path(project, "c:\\test"); l = p.list(); - assertEquals("three items, mixed style", 3, l.length); if (isUnixStyle) { - assertEquals("/a", l[0]); - assertEquals("/b", l[1]); - assertEquals("/c", l[2]); + assertEquals("no drives on Unix", 2, l.length); + assertTrue("c resolved relative to project\'s basedir", + l[0].endsWith("/c")); + assertEquals("/test", l[1]); } else if (isNetWare) { - assertEquals("\\a", l[0]); - assertEquals("\\b", l[1]); - assertEquals("\\c", l[2]); + assertEquals("volumes on NetWare", 1, l.length); + assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); } else { - assertEquals(":\\a", l[0].substring(1)); - assertEquals(":\\b", l[1].substring(1)); - assertEquals(":\\c", l[2].substring(1)); - } + assertEquals("drives on DOS", 1, l.length); + assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); + } - p = new Path(project, "c:\\test"); + p = new Path(project, "c:\\test;d:\\programs"); l = p.list(); if (isUnixStyle) { - assertEquals("no drives on Unix", 2, l.length); + assertEquals("no drives on Unix", 4, l.length); assertTrue("c resolved relative to project\'s basedir", l[0].endsWith("/c")); assertEquals("/test", l[1]); + assertTrue("d resolved relative to project\'s basedir", + l[2].endsWith("/d")); + assertEquals("/programs", l[3]); } else if (isNetWare) { - assertEquals("volumes on NetWare", 1, l.length); + assertEquals("volumes on NetWare", 2, l.length); assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("d:\\programs", l[1].toLowerCase(Locale.US)); } else { - assertEquals("drives on DOS", 1, l.length); + assertEquals("drives on DOS", 2, l.length); assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("d:\\programs", l[1].toLowerCase(Locale.US)); } p = new Path(project, "c:/test"); @@ -161,6 +166,139 @@ public class PathTest extends TestCase { assertEquals("drives on DOS", 1, l.length); assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); } + + p = new Path(project, "c:/test;d:/programs"); + l = p.list(); + if (isUnixStyle) { + assertEquals("no drives on Unix", 4, l.length); + assertTrue("c resolved relative to project\'s basedir", + l[0].endsWith("/c")); + assertEquals("/test", l[1]); + assertTrue("d resolved relative to project\'s basedir", + l[2].endsWith("/d")); + assertEquals("/programs", l[3]); + } else if (isNetWare) { + assertEquals("volumes on NetWare", 2, l.length); + assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("d:\\programs", l[1].toLowerCase(Locale.US)); + } else { + assertEquals("drives on DOS", 2, l.length); + assertEquals("c:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("d:\\programs", l[1].toLowerCase(Locale.US)); + } + } + + public void testConstructorNetWareStyle() { + // try a netware-volume length path, see how it is handled + Path p = new Path(project, "sys:\\test"); + String[] l = p.list(); + if (isUnixStyle) { + assertEquals("no drives on Unix", 2, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("/sys")); + assertEquals("/test", l[1]); + } else if (isNetWare) { + assertEquals("sys:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("volumes on NetWare", 1, l.length); + } else { + assertEquals("no multiple character-length volumes on Windows", 2, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("\\sys")); + assertTrue("test resolved relative to project\'s basedir", + l[1].endsWith("\\test")); + } + + // try a multi-part netware-volume length path, see how it is handled + p = new Path(project, "sys:\\test;dev:\\temp"); + l = p.list(); + if (isUnixStyle) { + assertEquals("no drives on Unix", 4, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("/sys")); + assertEquals("/test", l[1]); + assertTrue("dev resolved relative to project\'s basedir", + l[2].endsWith("/dev")); + assertEquals("/temp", l[3]); + } else if (isNetWare) { + assertEquals("volumes on NetWare", 2, l.length); + assertEquals("sys:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("dev:\\temp", l[1].toLowerCase(Locale.US)); + } else { + assertEquals("no multiple character-length volumes on Windows", 4, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("\\sys")); + assertTrue("test resolved relative to project\'s basedir", + l[1].endsWith("\\test")); + assertTrue("dev resolved relative to project\'s basedir", + l[2].endsWith("\\dev")); + assertTrue("temp resolved relative to project\'s basedir", + l[3].endsWith("\\temp")); + } + + // try a netware-volume length path w/forward slash, see how it is handled + p = new Path(project, "sys:/test"); + l = p.list(); + if (isUnixStyle) { + assertEquals("no drives on Unix", 2, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("/sys")); + assertEquals("/test", l[1]); + } else if (isNetWare) { + assertEquals("volumes on NetWare", 1, l.length); + assertEquals("sys:\\test", l[0].toLowerCase(Locale.US)); + } else { + assertEquals("no multiple character-length volumes on Windows", 2, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("\\sys")); + assertTrue("test resolved relative to project\'s basedir", + l[1].endsWith("\\test")); + } + + // try a multi-part netware-volume length path w/forward slash, see how it is handled + p = new Path(project, "sys:/test;dev:/temp"); + l = p.list(); + if (isUnixStyle) { + assertEquals("no drives on Unix", 4, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("/sys")); + assertEquals("/test", l[1]); + assertTrue("dev resolved relative to project\'s basedir", + l[2].endsWith("/dev")); + assertEquals("/temp", l[3]); + } else if (isNetWare) { + assertEquals("volumes on NetWare", 2, l.length); + assertEquals("sys:\\test", l[0].toLowerCase(Locale.US)); + assertEquals("dev:\\temp", l[1].toLowerCase(Locale.US)); + } else { + assertEquals("no multiple character-length volumes on Windows", 4, l.length); + assertTrue("sys resolved relative to project\'s basedir", + l[0].endsWith("\\sys")); + assertTrue("test resolved relative to project\'s basedir", + l[1].endsWith("\\test")); + assertTrue("dev resolved relative to project\'s basedir", + l[2].endsWith("\\dev")); + assertTrue("temp resolved relative to project\'s basedir", + l[3].endsWith("\\temp")); + } + } + + public void testConstructorMixedStyle() { + Path p = new Path(project, "\\a;\\b:/c"); + String[] l = p.list(); + assertEquals("three items, mixed style", 3, l.length); + if (isUnixStyle) { + assertEquals("/a", l[0]); + assertEquals("/b", l[1]); + assertEquals("/c", l[2]); + } else if (isNetWare) { + assertEquals("\\a", l[0]); + assertEquals("\\b", l[1]); + assertEquals("\\c", l[2]); + } else { + assertEquals(":\\a", l[0].substring(1)); + assertEquals(":\\b", l[1].substring(1)); + assertEquals(":\\c", l[2].substring(1)); + } } public void testSetLocation() {