for toURI and fromURI patches prepared by Jesse Glick, Bugzilla 8031 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@357131 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1390,7 +1390,7 @@ while(<STDIN>) { | |||
<?xml version="1.0"?> | |||
<!DOCTYPE project [ | |||
<!ENTITY common SYSTEM "file:./common.xml"> | |||
<!ENTITY common SYSTEM "common.xml"> | |||
]> | |||
<project name="test" default="test" basedir="."> | |||
@@ -1407,10 +1407,13 @@ while(<STDIN>) { | |||
</pre> | |||
<p>will literally include the contents of <code>common.xml</code> where | |||
you've placed the <code>&common;</code> entity.</p> | |||
<p>(The filename <code>common.xml</code> in this example is resolved | |||
relative to the containing XML file by the XML parser. You may also use | |||
an absolute <code>file:</code> protocol URI.)</p> | |||
<p>In combination with a DTD, this would look like this:</p> | |||
<pre class="code"> | |||
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "file:./ant.dtd" [ | |||
<!ENTITY include SYSTEM "file:./header.xml"> | |||
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "ant.dtd" [ | |||
<!ENTITY include SYSTEM "header.xml"> | |||
]> | |||
</pre> | |||
<p>Starting with Ant 1.6, there is a new | |||
@@ -1217,8 +1217,7 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
if (sealedString != null && sealedString.equalsIgnoreCase("true")) { | |||
try { | |||
// XXX should be using FileUtils! | |||
sealBase = new URL("file:" + container.getPath()); | |||
sealBase = new URL(FileUtils.getFileUtils().toURI(container.getAbsolutePath())); | |||
} catch (MalformedURLException e) { | |||
// ignore | |||
} | |||
@@ -130,8 +130,8 @@ public final class Locator { | |||
* | |||
* <p>Will be an absolute path if the given URI is absolute.</p> | |||
* | |||
* <p>Swallows '%' that are not followed by two characters, | |||
* doesn't deal with non-ASCII characters.</p> | |||
* <p>Prior to Java 1.4, | |||
* swallows '%' that are not followed by two characters.</p> | |||
* | |||
* @see <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a> | |||
* which makes some mention of how | |||
@@ -139,9 +139,45 @@ public final class Locator { | |||
* | |||
* @param uri the URI designating a file in the local filesystem. | |||
* @return the local file system path for the file. | |||
* @throws IllegalArgumentException if the URI is malformed or not a legal file: URL | |||
* @since Ant 1.6 | |||
*/ | |||
public static String fromURI(String uri) { | |||
// #8031: first try Java 1.4. | |||
Class uriClazz = null; | |||
try { | |||
uriClazz = Class.forName("java.net.URI"); | |||
} catch (ClassNotFoundException cnfe) { | |||
// Fine, Java 1.3 or earlier, do it by hand. | |||
} | |||
// Also check for properly formed URIs. Ant formerly recommended using | |||
// nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't | |||
// do that (just "foo.xml" is correct) but for compatibility we special-case | |||
// things when the path is not absolute, and fall back to the old parsing behavior. | |||
if (uriClazz != null && uri.startsWith("file:/")) { | |||
try { | |||
java.lang.reflect.Method createMethod = uriClazz.getMethod("create", new Class[] {String.class}); | |||
Object uriObj = createMethod.invoke(null, new Object[] {uri}); | |||
java.lang.reflect.Constructor fileConst = File.class.getConstructor(new Class[] {uriClazz}); | |||
File f = (File)fileConst.newInstance(new Object[] {uriObj}); | |||
return f.getAbsolutePath(); | |||
} catch (java.lang.reflect.InvocationTargetException e) { | |||
Throwable e2 = e.getTargetException(); | |||
if (e2 instanceof IllegalArgumentException) { | |||
// Bad URI, pass this on. | |||
throw (IllegalArgumentException)e2; | |||
} else { | |||
// Unexpected target exception? Should not happen. | |||
e2.printStackTrace(); | |||
} | |||
} catch (Exception e) { | |||
// Reflection problems? Should not happen, debug. | |||
e.printStackTrace(); | |||
} | |||
} | |||
// Fallback method for Java 1.3 or earlier. | |||
URL url = null; | |||
try { | |||
url = new URL(uri); | |||
@@ -47,6 +47,7 @@ import org.apache.tools.ant.taskdefs.XSLTProcess; | |||
import org.apache.tools.ant.taskdefs.XSLTLogger; | |||
import org.apache.tools.ant.taskdefs.XSLTLoggerAware; | |||
import org.apache.tools.ant.types.XMLCatalog; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.JAXPUtils; | |||
import org.xml.sax.EntityResolver; | |||
import org.xml.sax.InputSource; | |||
@@ -401,8 +402,8 @@ public class TraXLiaison implements XSLTLiaison2, ErrorListener, XSLTLoggerAware | |||
String systemid = locator.getSystemId(); | |||
if (systemid != null) { | |||
String url = systemid; | |||
if (url.startsWith("file:///")) { | |||
url = url.substring(8); | |||
if (url.startsWith("file:")) { | |||
url = FileUtils.newFileUtils().fromURI(url); | |||
} | |||
msg.append(url); | |||
} else { | |||
@@ -35,6 +35,7 @@ import org.apache.tools.ant.taskdefs.rmic.DefaultRmicAdapter; | |||
import org.apache.tools.ant.taskdefs.rmic.WLRmic; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.depend.DependencyAnalyzer; | |||
/** | |||
@@ -393,14 +394,15 @@ public class Depend extends MatchingTask { | |||
if (classURL != null) { | |||
if (classURL.getProtocol().equals("jar")) { | |||
String jarFilePath = classURL.getFile(); | |||
int classMarker = jarFilePath.indexOf('!'); | |||
jarFilePath = jarFilePath.substring(0, classMarker); | |||
if (jarFilePath.startsWith("file:")) { | |||
int classMarker = jarFilePath.indexOf('!'); | |||
jarFilePath = jarFilePath.substring(5, classMarker); | |||
classpathFileObject = new File(FileUtils.getFileUtils().fromURI(jarFilePath)); | |||
} else { | |||
throw new IOException("Bizarre nested path in jar: protocol: " + jarFilePath); | |||
} | |||
classpathFileObject = new File(jarFilePath); | |||
} else if (classURL.getProtocol().equals("file")) { | |||
String classFilePath = classURL.getFile(); | |||
classpathFileObject = new File(classFilePath); | |||
classpathFileObject = new File(FileUtils.getFileUtils().fromURI(classURL.toExternalForm())); | |||
} | |||
log("Class " + className | |||
+ " depends on " + classpathFileObject | |||
@@ -544,9 +546,9 @@ public class Depend extends MatchingTask { | |||
/** | |||
* test for being an RMI stub | |||
* @param affectedClass | |||
* @param className | |||
* @return | |||
* @param affectedClass class being tested | |||
* @param className possible origin of the RMI stub | |||
* @return whether the class affectedClass is a RMI stub | |||
*/ | |||
private boolean isRmiStub(String affectedClass, String className) { | |||
return isStub(affectedClass, className, DefaultRmicAdapter.RMI_STUB_SUFFIX) | |||
@@ -33,6 +33,7 @@ import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.util.DOMElementWriter; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.StringUtils; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.w3c.dom.Document; | |||
@@ -246,7 +247,7 @@ public class XMLResultAggregator extends Task implements XMLConstants { | |||
log("Parsing file: '" + file + "'", Project.MSG_VERBOSE); | |||
if(file.length()>0) { | |||
Document testsuiteDoc | |||
= builder.parse("file:///" + file.getAbsolutePath()); | |||
= builder.parse(FileUtils.getFileUtils().toURI(files[i].getAbsolutePath())); | |||
Element elem = testsuiteDoc.getDocumentElement(); | |||
// make sure that this is REALLY a testsuite. | |||
if (TESTSUITE.equals(elem.getNodeName())) { | |||
@@ -399,7 +399,7 @@ public class CovReport extends CovBase { | |||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |||
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); | |||
Source src = new DOMSource(doc); | |||
Result res = new StreamResult("file:///" + tofile.toString()); | |||
Result res = new StreamResult(tofile); | |||
transformer.transform(src, res); | |||
} catch (Exception e) { | |||
throw new BuildException("Error while performing enhanced XML " | |||
@@ -1006,6 +1006,25 @@ public class FileUtils { | |||
* @since Ant 1.6 | |||
*/ | |||
public String toURI(String path) { | |||
// #8031: first try Java 1.4. | |||
Class uriClazz = null; | |||
try { | |||
uriClazz = Class.forName("java.net.URI"); | |||
} catch (ClassNotFoundException e) { | |||
// OK, Java 1.3. | |||
} | |||
if (uriClazz != null) { | |||
try { | |||
File f = new File(path).getAbsoluteFile(); | |||
java.lang.reflect.Method toURIMethod = File.class.getMethod("toURI", new Class[0]); | |||
Object uriObj = toURIMethod.invoke(f, new Object[] {}); | |||
java.lang.reflect.Method toASCIIStringMethod = uriClazz.getMethod("toASCIIString", new Class[0]); | |||
return (String) toASCIIStringMethod.invoke(uriObj, new Object[] {}); | |||
} catch (Exception e) { | |||
// Reflection problems? Should not happen, debug. | |||
e.printStackTrace(); | |||
} | |||
} | |||
boolean isDir = new File(path).isDirectory(); | |||
StringBuffer sb = new StringBuffer("file:"); | |||
@@ -452,45 +452,66 @@ public class FileUtilsTest extends TestCase { | |||
dosRoot = ""; | |||
} | |||
if (Os.isFamily("dos")) { | |||
assertEquals("file:///C:/foo", FILE_UTILS.toURI("c:\\foo")); | |||
assertEquals("file:/c:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("c:\\foo"))); | |||
} | |||
if (Os.isFamily("netware")) { | |||
assertEquals("file:///SYS:/foo", FILE_UTILS.toURI("sys:\\foo")); | |||
assertEquals("file:/SYS:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("sys:\\foo"))); | |||
} | |||
if (File.pathSeparatorChar == '/') { | |||
assertEquals("file:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("/foo"))); | |||
assertTrue("file: URIs must name absolute paths", FILE_UTILS.toURI("./foo").startsWith("file:/")); | |||
assertTrue(FILE_UTILS.toURI("./foo").endsWith("/foo")); | |||
assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(FILE_UTILS.toURI("/foo bar"))); | |||
assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(FILE_UTILS.toURI("/foo#bar"))); | |||
} else if (File.pathSeparatorChar == '\\') { | |||
assertEquals("file:/" + dosRoot + "foo", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo"))); | |||
assertTrue("file: URIs must name absolute paths", FILE_UTILS.toURI(".\\foo").startsWith("file:/")); | |||
assertTrue(FILE_UTILS.toURI(".\\foo").endsWith("/foo")); | |||
assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo bar"))); | |||
assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo#bar"))); | |||
} | |||
assertEquals("file:///" + dosRoot + "foo", FILE_UTILS.toURI("/foo")); | |||
/* May fail if the directory ${user.dir}/foo/ exists | |||
* (and anyway is the tested behavior actually desirable?): | |||
assertEquals("file:./foo", fu.toURI("./foo")); | |||
*/ | |||
assertEquals("file:///" + dosRoot + "foo", FILE_UTILS.toURI("\\foo")); | |||
/* See above: | |||
assertEquals("file:./foo", fu.toURI(".\\foo")); | |||
*/ | |||
assertEquals("file:///" + dosRoot + "foo%20bar", FILE_UTILS.toURI("/foo bar")); | |||
assertEquals("file:///" + dosRoot + "foo%20bar", FILE_UTILS.toURI("\\foo bar")); | |||
assertEquals("file:///" + dosRoot + "foo%23bar", FILE_UTILS.toURI("/foo#bar")); | |||
assertEquals("file:///" + dosRoot + "foo%23bar", FILE_UTILS.toURI("\\foo#bar")); | |||
// a test with ant for germans | |||
// i would expect here %E4NT ??? | |||
// anyway, this is the fix for the bug 37348wh | |||
assertEquals("file:///" + dosRoot + "%C3%A4nt", FILE_UTILS.toURI("/\u00E4nt")); | |||
// the escaped character used for the test is the "a umlaut" | |||
// this is the fix for the bug 37348 | |||
assertEquals("file:/" + dosRoot + "%C3%A4nt", removeExtraneousAuthority(FILE_UTILS.toURI("/\u00E4nt"))); | |||
} | |||
/** | |||
* Authority field is unnecessary, but harmless, in file: URIs. | |||
* Java 1.4 does not produce it when using File.toURI. | |||
*/ | |||
private static String removeExtraneousAuthority(String uri) { | |||
String prefix = "file:///"; | |||
if (uri.startsWith(prefix)) { | |||
return "file:/" + uri.substring(prefix.length()); | |||
} else { | |||
return uri; | |||
} | |||
} | |||
/** | |||
* test fromUri | |||
*/ | |||
public void testFromURI() { | |||
String dosRoot = null; | |||
if (Os.isFamily("dos") || Os.isFamily("netware")) { | |||
dosRoot = Character.toUpperCase( | |||
System.getProperty("user.dir").charAt(0)) + ":"; | |||
} | |||
else | |||
{ | |||
dosRoot = ""; | |||
} | |||
if (Os.isFamily("netware")) { | |||
assertEqualsIgnoreDriveCase("SYS:\\foo", FILE_UTILS.fromURI("file:///sys:/foo")); | |||
} | |||
if (Os.isFamily("dos")) { | |||
assertEqualsIgnoreDriveCase("C:\\foo", FILE_UTILS.fromURI("file:///c:/foo")); | |||
} | |||
assertEqualsIgnoreDriveCase(File.separator + "foo", FILE_UTILS.fromURI("file:///foo")); | |||
assertEqualsIgnoreDriveCase(dosRoot + File.separator + "foo", FILE_UTILS.fromURI("file:///foo")); | |||
assertEquals("." + File.separator + "foo", | |||
FILE_UTILS.fromURI("file:./foo")); | |||
assertEquals(File.separator + "foo bar", FILE_UTILS.fromURI("file:///foo%20bar")); | |||
assertEquals(File.separator + "foo#bar", FILE_UTILS.fromURI("file:///foo%23bar")); | |||
assertEquals(dosRoot + File.separator + "foo bar", FILE_UTILS.fromURI("file:///foo%20bar")); | |||
assertEquals(dosRoot + File.separator + "foo#bar", FILE_UTILS.fromURI("file:///foo%23bar")); | |||
} | |||
public void testModificationTests() { | |||
@@ -36,7 +36,7 @@ public class JAXPUtilsTest extends TestCase { | |||
file = new File("/user/local/bin"); | |||
} | |||
String systemid = JAXPUtils.getSystemId(file); | |||
assertTrue("SystemIDs should start by file:///", systemid.startsWith("file:///")); | |||
assertTrue("SystemIDs should start by file:/", systemid.startsWith("file:/")); | |||
assertTrue("SystemIDs should not start with file:////", !systemid.startsWith("file:////")); | |||
} | |||
} |
@@ -1067,7 +1067,7 @@ while(<STDIN>) { | |||
<?xml version="1.0"?> | |||
<!DOCTYPE project [ | |||
<!ENTITY common SYSTEM "file:./common.xml"> | |||
<!ENTITY common SYSTEM "common.xml"> | |||
]> | |||
<project name="test" default="test" basedir="."> | |||
@@ -1086,11 +1086,15 @@ while(<STDIN>) { | |||
<p>will literally include the contents of <code>common.xml</code> where | |||
you've placed the <code>&common;</code> entity.</p> | |||
<p>(The filename <code>common.xml</code> in this example is resolved | |||
relative to the containing XML file by the XML parser. You may also use | |||
an absolute <code>file:</code> protocol URI.)</p> | |||
<p>In combination with a DTD, this would look like this:</p> | |||
<source><![CDATA[ | |||
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "file:./ant.dtd" [ | |||
<!ENTITY include SYSTEM "file:./header.xml"> | |||
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "ant.dtd" [ | |||
<!ENTITY include SYSTEM "header.xml"> | |||
]> | |||
]]></source> | |||