git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@350061 13f79535-47bb-0310-9956-ffa450edef68master
@@ -38,6 +38,37 @@ public final class Locator { | |||
* encoding used to represent URIs | |||
*/ | |||
public static String URI_ENCODING = "UTF-8"; | |||
// stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir() | |||
// of the Xerces-J team | |||
// which ASCII characters need to be escaped | |||
private static boolean gNeedEscaping[] = new boolean[128]; | |||
// the first hex character if a character needs to be escaped | |||
private static char gAfterEscaping1[] = new char[128]; | |||
// the second hex character if a character needs to be escaped | |||
private static char gAfterEscaping2[] = new char[128]; | |||
private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', | |||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |||
// initialize the above 3 arrays | |||
static { | |||
for (int i = 0; i <= 0x1f; i++) { | |||
gNeedEscaping[i] = true; | |||
gAfterEscaping1[i] = gHexChs[i >> 4]; | |||
gAfterEscaping2[i] = gHexChs[i & 0xf]; | |||
} | |||
gNeedEscaping[0x7f] = true; | |||
gAfterEscaping1[0x7f] = '7'; | |||
gAfterEscaping2[0x7f] = 'F'; | |||
char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', | |||
'|', '\\', '^', '~', '[', ']', '`'}; | |||
int len = escChs.length; | |||
char ch; | |||
for (int i = 0; i < len; i++) { | |||
ch = escChs[i]; | |||
gNeedEscaping[ch] = true; | |||
gAfterEscaping1[ch] = gHexChs[ch >> 4]; | |||
gAfterEscaping2[ch] = gHexChs[ch & 0xf]; | |||
} | |||
} | |||
/** | |||
* Not instantiable | |||
*/ | |||
@@ -176,7 +207,66 @@ public final class Locator { | |||
sb.write(c); | |||
} | |||
} | |||
return sb.toString("UTF-8"); | |||
return sb.toString(URI_ENCODING); | |||
} | |||
/** | |||
* Encodes an Uri with % characters. | |||
* The URI is escaped | |||
* @param path String to encode. | |||
* @return The encoded string, according to URI norms | |||
* @throws UnsupportedEncodingException if UTF-8 is not available | |||
* @since Ant 1.7 | |||
*/ | |||
public static String encodeUri(String path) throws UnsupportedEncodingException { | |||
int i = 0; | |||
int len = path.length(); | |||
int ch = 0; | |||
StringBuffer sb = new StringBuffer(len); | |||
for (; i < len; i++) { | |||
ch = path.charAt(i); | |||
// if it's not an ASCII character, break here, and use UTF-8 encoding | |||
if (ch >= 128) | |||
break; | |||
if (gNeedEscaping[ch]) { | |||
sb.append('%'); | |||
sb.append(gAfterEscaping1[ch]); | |||
sb.append(gAfterEscaping2[ch]); | |||
// record the fact that it's escaped | |||
} | |||
else { | |||
sb.append((char)ch); | |||
} | |||
} | |||
// we saw some non-ascii character | |||
if (i < len) { | |||
// get UTF-8 bytes for the remaining sub-string | |||
byte[] bytes = null; | |||
byte b; | |||
bytes = path.substring(i).getBytes(URI_ENCODING); | |||
len = bytes.length; | |||
// for each byte | |||
for (i = 0; i < len; i++) { | |||
b = bytes[i]; | |||
// for non-ascii character: make it positive, then escape | |||
if (b < 0) { | |||
ch = b + 256; | |||
sb.append('%'); | |||
sb.append(gHexChs[ch >> 4]); | |||
sb.append(gHexChs[ch & 0xf]); | |||
} | |||
else if (gNeedEscaping[b]) { | |||
sb.append('%'); | |||
sb.append(gAfterEscaping1[b]); | |||
sb.append(gAfterEscaping2[b]); | |||
} | |||
else { | |||
sb.append((char)b); | |||
} | |||
} | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
@@ -17,10 +17,12 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.io.UnsupportedEncodingException; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.launch.Locator; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
@@ -123,10 +125,15 @@ public class ManifestClassPath | |||
if (File.separatorChar != '/') { | |||
relPath = relPath.replace(File.separatorChar, '/'); | |||
} | |||
buffer.append(relPath); | |||
if (pathEntry.isDirectory()) { | |||
buffer.append('/'); | |||
relPath = relPath + '/'; | |||
} | |||
try { | |||
relPath = Locator.encodeUri(relPath); | |||
} catch (UnsupportedEncodingException exc) { | |||
throw new BuildException(exc); | |||
} | |||
buffer.append(relPath); | |||
buffer.append(' '); | |||
} | |||
@@ -59,37 +59,6 @@ public class FileUtils { | |||
static final int BUF_SIZE = 8192; | |||
// stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir() | |||
// of the Xerces-J team | |||
// which ASCII characters need to be escaped | |||
private static boolean gNeedEscaping[] = new boolean[128]; | |||
// the first hex character if a character needs to be escaped | |||
private static char gAfterEscaping1[] = new char[128]; | |||
// the second hex character if a character needs to be escaped | |||
private static char gAfterEscaping2[] = new char[128]; | |||
private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', | |||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |||
// initialize the above 3 arrays | |||
static { | |||
for (int i = 0; i <= 0x1f; i++) { | |||
gNeedEscaping[i] = true; | |||
gAfterEscaping1[i] = gHexChs[i >> 4]; | |||
gAfterEscaping2[i] = gHexChs[i & 0xf]; | |||
} | |||
gNeedEscaping[0x7f] = true; | |||
gAfterEscaping1[0x7f] = '7'; | |||
gAfterEscaping2[0x7f] = 'F'; | |||
char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', | |||
'|', '\\', '^', '~', '[', ']', '`'}; | |||
int len = escChs.length; | |||
char ch; | |||
for (int i = 0; i < len; i++) { | |||
ch = escChs[i]; | |||
gNeedEscaping[ch] = true; | |||
gAfterEscaping1[ch] = gHexChs[ch >> 4]; | |||
gAfterEscaping2[ch] = gHexChs[ch & 0xf]; | |||
} | |||
} | |||
/** | |||
* The granularity of timestamps under FAT. | |||
@@ -1048,58 +1017,11 @@ public class FileUtils { | |||
sb.append("/"); | |||
} | |||
path = path.replace('\\', '/'); | |||
int i = 0; | |||
for (; i < len; i++) { | |||
ch = path.charAt(i); | |||
// if it's not an ASCII character, break here, and use UTF-8 encoding | |||
if (ch >= 128) | |||
break; | |||
if (gNeedEscaping[ch]) { | |||
sb.append('%'); | |||
sb.append(gAfterEscaping1[ch]); | |||
sb.append(gAfterEscaping2[ch]); | |||
// record the fact that it's escaped | |||
} | |||
else { | |||
sb.append((char)ch); | |||
} | |||
} | |||
// we saw some non-ascii character | |||
if (i < len) { | |||
// get UTF-8 bytes for the remaining sub-string | |||
byte[] bytes = null; | |||
byte b; | |||
try { | |||
bytes = path.substring(i).getBytes(Locator.URI_ENCODING); | |||
} catch (java.io.UnsupportedEncodingException e) { | |||
// should never happen | |||
throw new BuildException(e); | |||
} | |||
len = bytes.length; | |||
// for each byte | |||
for (i = 0; i < len; i++) { | |||
b = bytes[i]; | |||
// for non-ascii character: make it positive, then escape | |||
if (b < 0) { | |||
ch = b + 256; | |||
sb.append('%'); | |||
sb.append(gHexChs[ch >> 4]); | |||
sb.append(gHexChs[ch & 0xf]); | |||
} | |||
else if (gNeedEscaping[b]) { | |||
sb.append('%'); | |||
sb.append(gAfterEscaping1[b]); | |||
sb.append(gAfterEscaping2[b]); | |||
} | |||
else { | |||
sb.append((char)b); | |||
} | |||
} | |||
try { | |||
sb.append(Locator.encodeUri(path)); | |||
} catch (UnsupportedEncodingException exc) { | |||
throw new BuildException(exc); | |||
} | |||
if (isDir && !path.endsWith("/")) { | |||
sb.append('/'); | |||
} | |||