From 6e72d89be84e4a3b021e1d59f14a97d2f4959adc Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Tue, 26 Feb 2008 15:52:51 +0000 Subject: [PATCH] Bug 42275 running ant off a network share can cause Ant to fail git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@631263 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/launch/Launcher.java | 75 ++++++++++++++++--- .../org/apache/tools/ant/launch/Locator.java | 36 +++++++-- .../apache/tools/ant/launch/LocatorTest.java | 42 ++++++++++- 3 files changed, 132 insertions(+), 21 deletions(-) diff --git a/src/main/org/apache/tools/ant/launch/Launcher.java b/src/main/org/apache/tools/ant/launch/Launcher.java index 889e0cf26..c0d033c23 100644 --- a/src/main/org/apache/tools/ant/launch/Launcher.java +++ b/src/main/org/apache/tools/ant/launch/Launcher.java @@ -59,6 +59,11 @@ public class Launcher { */ public static final String ANT_PRIVATELIB = "lib"; + /** + * launch diagnostics flag; for debugging trouble at launch time. + */ + public static boolean launchDiag = false; + /** * The location of a per-user library directory. *

@@ -110,6 +115,9 @@ public class Launcher { t.printStackTrace(System.err); } if (exitCode != 0) { + if (launchDiag) { + System.out.println("Exit code: "+exitCode); + } System.exit(exitCode); } } @@ -122,6 +130,7 @@ public class Launcher { * @param getJars if true and a path is a directory, add the jars in * the directory to the path urls * @param libPathURLs the list of paths to add to + * @throws MalformedURLException if we can't create a URL */ private void addPath(String path, boolean getJars, List libPathURLs) throws MalformedURLException { @@ -129,18 +138,21 @@ public class Launcher { while (tokenizer.hasMoreElements()) { String elementName = tokenizer.nextToken(); File element = new File(elementName); - if (elementName.indexOf("%") != -1 && !element.exists()) { + if (elementName.indexOf('%') != -1 && !element.exists()) { continue; } if (getJars && element.isDirectory()) { // add any jars in the directory URL[] dirURLs = Locator.getLocationURLs(element); for (int j = 0; j < dirURLs.length; ++j) { + if (launchDiag) { System.out.println("adding library JAR: " + dirURLs[j]);} libPathURLs.add(dirURLs[j]); } } - libPathURLs.add(Locator.fileToURL(element)); + URL url = Locator.fileToURL(element); + if (launchDiag) { System.out.println("adding library URL: " + url) ;} + libPathURLs.add(url); } } @@ -150,8 +162,9 @@ public class Launcher { * @param args the command line arguments * @return an exit code. As the normal ant main calls exit when it ends, * this is for handling failures at bind-time - * @exception MalformedURLException if the URLs required for the classloader + * @throws MalformedURLException if the URLs required for the classloader * cannot be created. + * @throws LaunchException for launching problems */ private int run(String[] args) throws LaunchException, MalformedURLException { @@ -168,12 +181,12 @@ public class Launcher { if (antHome == null || !antHome.exists()) { antHome = jarDir.getParentFile(); - System.setProperty(ANTHOME_PROPERTY, antHome.getAbsolutePath()); + setProperty(ANTHOME_PROPERTY, antHome.getAbsolutePath()); } if (!antHome.exists()) { throw new LaunchException("Ant home is set incorrectly or " - + "ant could not be located"); + + "ant could not be located (estimated value="+antHome.getAbsolutePath()+")"); } List libPaths = new ArrayList(); @@ -202,6 +215,8 @@ public class Launcher { cpString = args[++i]; } else if (args[i].equals("--nouserlib") || args[i].equals("-nouserlib")) { noUserLib = true; + } else if (args[i].equals("--launchdiag")) { + launchDiag = true; } else if (args[i].equals("--noclasspath") || args[i].equals("-noclasspath")) { noClassPath = true; } else if (args[i].equals("-main")) { @@ -215,6 +230,10 @@ public class Launcher { } } + logPath("Launcher JAR",sourceJar); + logPath("Launcher JAR directory", sourceJar.getParentFile()); + logPath("java.home", new File(System.getProperty("java.home"))); + //decide whether to copy the existing arg set, or //build a new one from the list of all args excluding the special //operations that only we handle @@ -229,8 +248,10 @@ public class Launcher { URL[] systemURLs = getSystemURLs(jarDir); URL[] userURLs = noUserLib ? new URL[0] : getUserURLs(); + File toolsJAR = Locator.getToolsJar(); + logPath("tools.jar",toolsJAR); URL[] jars = getJarArray( - libURLs, userURLs, systemURLs, Locator.getToolsJar()); + libURLs, userURLs, systemURLs, toolsJAR); // now update the class.path property StringBuffer baseClassPath @@ -245,12 +266,13 @@ public class Launcher { baseClassPath.append(Locator.fromURI(jars[i].toString())); } - System.setProperty(JAVA_CLASS_PATH, baseClassPath.toString()); + setProperty(JAVA_CLASS_PATH, baseClassPath.toString()); URLClassLoader loader = new URLClassLoader(jars); Thread.currentThread().setContextClassLoader(loader); Class mainClass = null; int exitCode = 0; + Throwable thrown=null; try { mainClass = loader.loadClass(mainClassname); AntMain main = (AntMain) mainClass.newInstance(); @@ -261,9 +283,20 @@ public class Launcher { File mainJar = Locator.getClassSource(mainClass); System.err.println( "Location of this class " + mainJar); - exitCode = EXIT_CODE_ERROR; + thrown = ex; + } catch (ClassNotFoundException cnfe) { + System.err.println( + "Failed to locate" + mainClassname); + thrown = cnfe; } catch (Throwable t) { t.printStackTrace(System.err); + thrown=t; + } + if(thrown!=null) { + System.err.println(ANTHOME_PROPERTY+": "+antHome.getAbsolutePath()); + System.err.println("Classpath: " + baseClassPath.toString()); + System.err.println("Launcher JAR: " + sourceJar.getAbsolutePath()); + System.err.println("Launcher Directory: " + jarDir.getAbsolutePath()); exitCode = EXIT_CODE_ERROR; } return exitCode; @@ -275,6 +308,7 @@ public class Launcher { * @param cpString the classpath string * @param libPaths the list of -lib entries. * @return an array of URLs. + * @throws MalformedURLException if the URLs cannot be created. */ private URL[] getLibPathURLs(String cpString, List libPaths) throws MalformedURLException { @@ -296,6 +330,9 @@ public class Launcher { * Get the jar files in ANT_HOME/lib. * determine ant library directory for system jars: use property * or default using location of ant-launcher.jar + * @param antLauncherDir the dir that ant-launcher ran from + * @return the URLs + * @throws MalformedURLException if the URLs cannot be created. */ private URL[] getSystemURLs(File antLauncherDir) throws MalformedURLException { File antLibDir = null; @@ -305,13 +342,15 @@ public class Launcher { } if ((antLibDir == null) || !antLibDir.exists()) { antLibDir = antLauncherDir; - System.setProperty(ANTLIBDIR_PROPERTY, antLibDir.getAbsolutePath()); + setProperty(ANTLIBDIR_PROPERTY, antLibDir.getAbsolutePath()); } return Locator.getLocationURLs(antLibDir); } /** * Get the jar files in user.home/.ant/lib + * @return the URLS from the user's lib dir + * @throws MalformedURLException if the URLs cannot be created. */ private URL[] getUserURLs() throws MalformedURLException { File userLibDir @@ -347,4 +386,22 @@ public class Launcher { } return jars; } + + /** + * set a system property, optionally log what is going on + * @param name property name + * @param value value + */ + private void setProperty(String name, String value) { + if (launchDiag) { + System.out.println("Setting \"" + name + "\" to \"" + value + "\""); + } + System.setProperty(name, value); + } + + private void logPath(String name,File path) { + if(launchDiag) { + System.out.println(name+"= \""+path+"\""); + } + } } diff --git a/src/main/org/apache/tools/ant/launch/Locator.java b/src/main/org/apache/tools/ant/launch/Locator.java index ed60087f1..160f25bb8 100644 --- a/src/main/org/apache/tools/ant/launch/Locator.java +++ b/src/main/org/apache/tools/ant/launch/Locator.java @@ -144,9 +144,7 @@ public final class Locator { String u = url.toString(); try { if (u.startsWith("jar:file:")) { - int pling = u.indexOf("!"); - String jarName = u.substring("jar:".length(), pling); - return new File(fromURI(jarName)); + return new File(fromJarURI(u)); } else if (u.startsWith("file:")) { int tail = u.indexOf(resource); String dirName = u.substring(0, tail); @@ -160,6 +158,8 @@ public final class Locator { return null; } + + /** * Constructs a file path from a file: URI. * @@ -238,13 +238,16 @@ public final class Locator { return null; } + + + /** - * package-private for testing in same classloader + * This method is public for testing; we may delete it without any warning -it is not part of Ant's stable API. * @param uri uri to expand * @return the decoded URI * @since Ant1.7.1 */ - static String fromURIJava13(String uri) { + public static String fromURIJava13(String uri) { // Fallback method for Java 1.3 or earlier. URL url = null; @@ -273,10 +276,14 @@ public final class Locator { String path = null; try { path = decodeUri(uri); + //consider adding the current directory. This is not done when + //the path is a UNC name String cwd = System.getProperty("user.dir"); - int posi = cwd.indexOf(":"); - if ((posi > 0) && path.startsWith(File.separator)) { - path = cwd.substring(0, posi + 1) + path; + int posi = cwd.indexOf(':'); + boolean pathStartsWithFileSeparator = path.startsWith(File.separator); + boolean pathStartsWithUNC = path.startsWith("" + File.separator + File.separator); + if ((posi > 0) && pathStartsWithFileSeparator && !pathStartsWithUNC) { + path = cwd.substring(0, posi + 1) + path; } } catch (UnsupportedEncodingException exc) { // not sure whether this is clean, but this method is @@ -288,6 +295,19 @@ public final class Locator { return path; } + /** + * Crack a JAR URI. + * This method is public for testing; we may delete it without any warning -it is not part of Ant's stable API. + * @param uri uri to expand; contains jar: somewhere in it + * @return the decoded URI + * @since Ant1.7.1 + */ + public static String fromJarURI(String uri) { + int pling = uri.indexOf('!'); + String jarName = uri.substring("jar:".length(), pling); + return fromURI(jarName); + } + /** * Decodes an Uri with % characters. * The URI is escaped diff --git a/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java b/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java index f29f7c8cf..dc093a7f3 100644 --- a/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java +++ b/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java @@ -27,6 +27,8 @@ import org.apache.tools.ant.taskdefs.condition.Os; public class LocatorTest extends TestCase { private boolean windows; private boolean unix; + private static final String LAUNCHER_JAR = "//morzine/slo/Java/Apache/ant/lib/ant-launcher.jar"; + private static final String SHARED_JAR_URI = "jar:file:"+ LAUNCHER_JAR +"!/org/apache/tools/ant/launch/Launcher.class"; /** * No-arg constructor to enable serialization. This method is not intended to be used by mere mortals without calling @@ -35,7 +37,9 @@ public class LocatorTest extends TestCase { public LocatorTest() { } - /** Constructs a test case with the given name. */ + /** Constructs a test case with the given name. + * @param name + */ public LocatorTest(String name) { super(name); } @@ -63,6 +67,7 @@ public class LocatorTest extends TestCase { * @param uri uri to parse * @param expectedUnix unix string (or null to skip that test) * @param expectedDos DOS string (or null to skip that test) + * @return the resolved string */ private String resolveTo(String uri, String expectedUnix, String expectedDos) { String result = resolve(uri); @@ -71,8 +76,15 @@ public class LocatorTest extends TestCase { return result; } - private void assertResolved(String uri, String expectedResult, String result, boolean condition) { - if (condition && expectedResult != null && expectedResult.length() > 0) { + /** + * Assert something resolved + * @param uri original URI + * @param expectedResult what we expected + * @param result what we got + * @param enabled is the test enabled? + */ + private void assertResolved(String uri, String expectedResult, String result, boolean enabled) { + if (enabled && expectedResult != null && expectedResult.length() > 0) { assertEquals("Expected " + uri + " to resolve to \n" + expectedResult + "\n but got\n" + result + "\n", expectedResult, result); } @@ -83,7 +95,7 @@ public class LocatorTest extends TestCase { * @param path filename with no directory separators * @return the trailing filename */ - private String assertResolves(String path) throws Exception { + private String assertResolves(String path) { String asuri = new File(path).toURI().toASCIIString(); String fullpath = System.getProperty("user.dir") + File.separator + path; String result = resolveTo(asuri, fullpath, fullpath); @@ -127,6 +139,28 @@ public class LocatorTest extends TestCase { "C:\\Program Files\\Ant\\lib"); } + /** + * Bug 42275; Ant failing to run off a remote share + * @throws Throwable if desired + */ + public void testAntOnRemoteShare() throws Throwable { + String resolved=Locator.fromJarURI(SHARED_JAR_URI); + assertResolved(SHARED_JAR_URI, LAUNCHER_JAR,resolved,true); + } + + /** + * Bug 42275; Ant failing to run off a remote share + * + * @throws Throwable if desired + */ + public void testFileFromRemoteShare() throws Throwable { + String resolved = Locator.fromJarURI(SHARED_JAR_URI); + assertResolved(SHARED_JAR_URI, LAUNCHER_JAR, resolved, true); + File f=new File(resolved); + String path = f.getAbsolutePath(); + assertTrue(path.indexOf("\\\\")==0); + } + public void testHttpURI() throws Exception { String url = "http://ant.apache.org"; try {