39 |
|
|
40 |
package java.io; |
package java.io; |
41 |
|
|
|
import gnu.java.io.PlatformHelper; |
|
|
|
|
42 |
import java.net.MalformedURLException; |
import java.net.MalformedURLException; |
43 |
import java.net.URI; |
import java.net.URI; |
44 |
import java.net.URISyntaxException; |
import java.net.URISyntaxException; |
68 |
* An example separator string would be "/" on the GNU system. |
* An example separator string would be "/" on the GNU system. |
69 |
*/ |
*/ |
70 |
public static final String separator = System.getProperty("file.separator"); |
public static final String separator = System.getProperty("file.separator"); |
71 |
|
private static final String dupSeparator = separator + separator; |
72 |
|
|
73 |
/** |
/** |
74 |
* This is the first character of the file separator string. On many |
* This is the first character of the file separator string. On many |
256 |
*/ |
*/ |
257 |
public File(String name) |
public File(String name) |
258 |
{ |
{ |
259 |
path = name; |
path = normalizePath (name); |
260 |
|
} |
261 |
|
|
262 |
|
// Remove duplicate and redundant separator characters. |
263 |
|
private String normalizePath(String p) |
264 |
|
{ |
265 |
|
// On Windows, convert any '/' to '\'. This appears to be the same logic |
266 |
|
// that Sun's Win32 Java performs. |
267 |
|
if (separatorChar == '\\') |
268 |
|
{ |
269 |
|
p = p.replace ('/', '\\'); |
270 |
|
// We have to special case the "\c:" prefix. |
271 |
|
if (p.length() > 2 && p.charAt(0) == '\\' && |
272 |
|
((p.charAt(1) >= 'a' && p.charAt(1) <= 'z') || |
273 |
|
(p.charAt(1) >= 'A' && p.charAt(1) <= 'Z')) && |
274 |
|
p.charAt(2) == ':') |
275 |
|
p = p.substring(1); |
276 |
|
} |
277 |
|
|
278 |
|
int dupIndex = p.indexOf(dupSeparator); |
279 |
|
int plen = p.length(); |
280 |
|
|
281 |
|
// Special case: permit Windows UNC path prefix. |
282 |
|
if (dupSeparator.equals("\\\\") && dupIndex == 0) |
283 |
|
dupIndex = p.indexOf(dupSeparator, 1); |
284 |
|
|
285 |
// Per the spec |
if (dupIndex == -1) |
286 |
if (path == null) |
{ |
287 |
throw new NullPointerException("File name is null"); |
// Ignore trailing separator (though on Windows "a:\", for |
288 |
|
// example, is a valid and minimal path). |
289 |
while (!PlatformHelper.isRootDirectory(path) |
if (plen > 1 && p.charAt (plen - 1) == separatorChar) |
290 |
&& PlatformHelper.endWithSeparator(path)) |
{ |
291 |
path = PlatformHelper.removeTailSeparator(path); |
if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')) |
292 |
|
return p.substring (0, plen - 1); |
293 |
|
} |
294 |
|
else |
295 |
|
return p; |
296 |
|
} |
297 |
|
|
298 |
|
StringBuffer newpath = new StringBuffer(plen); |
299 |
|
int last = 0; |
300 |
|
while (dupIndex != -1) |
301 |
|
{ |
302 |
|
newpath.append(p.substring(last, dupIndex)); |
303 |
|
// Ignore the duplicate path characters. |
304 |
|
while (p.charAt(dupIndex) == separatorChar) |
305 |
|
{ |
306 |
|
dupIndex++; |
307 |
|
if (dupIndex == plen) |
308 |
|
return newpath.toString(); |
309 |
|
} |
310 |
|
newpath.append(separatorChar); |
311 |
|
last = dupIndex; |
312 |
|
dupIndex = p.indexOf(dupSeparator, last); |
313 |
|
} |
314 |
|
|
315 |
|
// Again, ignore possible trailing separator (except special cases |
316 |
|
// like "a:\" on Windows). |
317 |
|
int end; |
318 |
|
if (plen > 1 && p.charAt (plen - 1) == separatorChar) |
319 |
|
{ |
320 |
|
if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':') |
321 |
|
end = plen; |
322 |
|
else |
323 |
|
end = plen - 1; |
324 |
|
} |
325 |
|
else |
326 |
|
end = plen; |
327 |
|
newpath.append(p.substring(last, end)); |
328 |
|
|
329 |
|
return newpath.toString(); |
330 |
} |
} |
331 |
|
|
332 |
/** |
/** |
341 |
*/ |
*/ |
342 |
public File(String dirPath, String name) |
public File(String dirPath, String name) |
343 |
{ |
{ |
344 |
this (dirPath == null ? (File) null : new File(dirPath), name); |
if (name == null) |
345 |
|
throw new NullPointerException(); |
346 |
|
if (dirPath != null && dirPath.length() > 0) |
347 |
|
{ |
348 |
|
// Try to be smart about the number of separator characters. |
349 |
|
if (dirPath.charAt(dirPath.length() - 1) == separatorChar |
350 |
|
|| name.length() == 0) |
351 |
|
path = normalizePath(dirPath + name); |
352 |
|
else |
353 |
|
path = normalizePath(dirPath + separatorChar + name); |
354 |
|
} |
355 |
|
else |
356 |
|
path = normalizePath(name); |
357 |
} |
} |
358 |
|
|
359 |
/** |
/** |
368 |
*/ |
*/ |
369 |
public File(File directory, String name) |
public File(File directory, String name) |
370 |
{ |
{ |
371 |
if (name == null) |
this (directory == null ? null : directory.path, name); |
372 |
throw new NullPointerException("filename is null"); |
} |
373 |
|
|
374 |
String dirpath; |
/** |
375 |
|
* This method initializes a new <code>File</code> object to represent |
376 |
if (directory == null) |
* a file corresponding to the specified <code>file:</code> protocol URI. |
377 |
dirpath = ""; |
* |
378 |
else if (directory.getPath() == "") |
* @param uri The uri. |
379 |
dirpath = "/"; |
*/ |
380 |
else |
public File(URI uri) |
381 |
dirpath = directory.getPath(); |
{ |
382 |
|
if (uri == null) |
383 |
|
throw new NullPointerException("uri is null"); |
384 |
|
|
385 |
if (PlatformHelper.isRootDirectory(dirpath) |
if (!uri.getScheme().equals("file")) |
386 |
|| dirpath.equals("")) |
throw new IllegalArgumentException("invalid uri protocol"); |
387 |
path = dirpath + name; |
|
388 |
else |
path = normalizePath(uri.getPath()); |
|
path = dirpath + separator + name; |
|
389 |
} |
} |
390 |
|
|
391 |
/** |
/** |
401 |
{ |
{ |
402 |
if (isAbsolute()) |
if (isAbsolute()) |
403 |
return path; |
return path; |
404 |
|
else if (separatorChar == '\\' |
405 |
String dir = System.getProperty("user.dir"); |
&& path.length() > 0 && path.charAt (0) == '\\') |
406 |
if (dir == null) |
{ |
407 |
return path; |
// On Windows, even if the path starts with a '\\' it is not |
408 |
|
// really absolute until we prefix the drive specifier from |
409 |
if (PlatformHelper.endWithSeparator(dir)) |
// the current working directory to it. |
410 |
return dir + path; |
return System.getProperty ("user.dir").substring (0, 2) + path; |
411 |
|
} |
412 |
return dir + separator + path; |
else if (separatorChar == '\\' |
413 |
|
&& path.length() > 1 && path.charAt (1) == ':' |
414 |
|
&& ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') |
415 |
|
|| (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))) |
416 |
|
{ |
417 |
|
// On Windows, a process has a current working directory for |
418 |
|
// each drive and a path like "G:foo\bar" would mean the |
419 |
|
// absolute path "G:\wombat\foo\bar" if "\wombat" is the |
420 |
|
// working directory on the G drive. |
421 |
|
String drvDir = null; |
422 |
|
try |
423 |
|
{ |
424 |
|
drvDir = new File (path.substring (0, 2)).getCanonicalPath(); |
425 |
|
} |
426 |
|
catch (IOException e) |
427 |
|
{ |
428 |
|
drvDir = path.substring (0, 2) + "\\"; |
429 |
|
} |
430 |
|
|
431 |
|
// Note: this would return "C:\\." for the path "C:.", if "\" |
432 |
|
// is the working folder on the C drive, but this is |
433 |
|
// consistent with what Sun's JRE 1.4.1.01 actually returns! |
434 |
|
if (path.length() > 2) |
435 |
|
return drvDir + '\\' + path.substring (2, path.length()); |
436 |
|
else |
437 |
|
return drvDir; |
438 |
|
} |
439 |
|
else |
440 |
|
return System.getProperty ("user.dir") + separatorChar + path; |
441 |
} |
} |
442 |
|
|
443 |
/** |
/** |
468 |
*/ |
*/ |
469 |
public String getCanonicalPath() throws IOException |
public String getCanonicalPath() throws IOException |
470 |
{ |
{ |
471 |
String abspath = getAbsolutePath(); |
// On Windows, getAbsolutePath might end up calling us, so we |
472 |
return PlatformHelper.toCanonicalForm(abspath); |
// have to special case that call to avoid infinite recursion. |
473 |
|
if (separatorChar == '\\' && path.length() == 2 && |
474 |
|
((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || |
475 |
|
(path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && |
476 |
|
path.charAt(1) == ':') |
477 |
|
{ |
478 |
|
return VMFile.toCanonicalForm(path); |
479 |
|
} |
480 |
|
// Call getAbsolutePath first to make sure that we do the |
481 |
|
// current directory handling, because the native code |
482 |
|
// may have a different idea of the current directory. |
483 |
|
return VMFile.toCanonicalForm(getAbsolutePath()); |
484 |
} |
} |
485 |
|
|
486 |
/** |
/** |
520 |
*/ |
*/ |
521 |
public String getParent() |
public String getParent() |
522 |
{ |
{ |
523 |
if (PlatformHelper.isRootDirectory(path)) |
String prefix = null; |
524 |
return null; |
int nameSeqIndex = 0; |
525 |
|
|
526 |
String par_path = path; |
// The "prefix", if present, is the leading "/" on UNIX and |
527 |
|
// either the drive specifier (e.g. "C:") or the leading "\\" |
528 |
|
// of a UNC network path on Windows. |
529 |
|
if (separatorChar == '/' && path.charAt (0) == '/') |
530 |
|
{ |
531 |
|
prefix = "/"; |
532 |
|
nameSeqIndex = 1; |
533 |
|
} |
534 |
|
else if (separatorChar == '\\' && path.length() > 1) |
535 |
|
{ |
536 |
|
if ((path.charAt (0) == '\\' && path.charAt (1) == '\\') |
537 |
|
|| (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') |
538 |
|
|| (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')) |
539 |
|
&& path.charAt (1) == ':')) |
540 |
|
{ |
541 |
|
prefix = path.substring (0, 2); |
542 |
|
nameSeqIndex = 2; |
543 |
|
} |
544 |
|
} |
545 |
|
|
546 |
int pos = PlatformHelper.lastIndexOfSeparator(par_path); |
// According to the JDK docs, the returned parent path is the |
547 |
if (pos == -1) |
// portion of the name sequence before the last separator |
548 |
return null; |
// character, if found, prefixed by the prefix, otherwise null. |
549 |
|
if (nameSeqIndex < path.length()) |
550 |
|
{ |
551 |
|
String nameSeq = path.substring (nameSeqIndex, path.length()); |
552 |
|
int last = nameSeq.lastIndexOf (separatorChar); |
553 |
|
if (last == -1) |
554 |
|
return prefix; |
555 |
|
else if (last == (nameSeq.length() - 1)) |
556 |
|
// Note: The path would not have a trailing separator |
557 |
|
// except for cases like "C:\" on Windows (see |
558 |
|
// normalizePath( )), where Sun's JRE 1.4 returns null. |
559 |
|
return null; |
560 |
|
else if (last == 0) |
561 |
|
last++; |
562 |
|
|
563 |
return par_path.substring(0, pos); |
if (prefix != null) |
564 |
|
return prefix + nameSeq.substring (0, last); |
565 |
|
else |
566 |
|
return nameSeq.substring (0, last); |
567 |
|
} |
568 |
|
else |
569 |
|
// Sun's JRE 1.4 returns null if the prefix is the only |
570 |
|
// component of the path - so "/" gives null on UNIX and |
571 |
|
// "C:", "\\", etc. return null on Windows. |
572 |
|
return null; |
573 |
} |
} |
574 |
|
|
575 |
/** |
/** |
625 |
*/ |
*/ |
626 |
public boolean isAbsolute() |
public boolean isAbsolute() |
627 |
{ |
{ |
628 |
return PlatformHelper.beginWithRootPathPrefix(path) > 0; |
if (separatorChar == '\\') |
629 |
|
return path.startsWith(dupSeparator) || |
630 |
|
(path.length() > 2 && |
631 |
|
((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || |
632 |
|
(path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && |
633 |
|
path.charAt(1) == ':' && |
634 |
|
path.charAt(2) == '\\'); |
635 |
|
else |
636 |
|
return path.startsWith(separator); |
637 |
} |
} |
638 |
|
|
639 |
/** |
/** |
748 |
{ |
{ |
749 |
checkRead(); |
checkRead(); |
750 |
|
|
751 |
// Get the list of files |
if (!exists() || !isDirectory()) |
|
String list_path = PlatformHelper.removeTailSeparator(path); |
|
|
File dir = new File(list_path); |
|
|
|
|
|
if (! dir.exists() || ! dir.isDirectory()) |
|
752 |
return null; |
return null; |
753 |
|
|
754 |
String files[] = VMFile.list(list_path); |
// Get the list of files |
755 |
|
String files[] = VMFile.list(path); |
756 |
|
|
757 |
// Check if an error occured in listInternal(). |
// Check if an error occured in listInternal(). |
758 |
if (files == null) |
if (files == null) |
935 |
String abspath = getAbsolutePath(); |
String abspath = getAbsolutePath(); |
936 |
|
|
937 |
if (isDirectory()) |
if (isDirectory()) |
938 |
abspath = abspath + separator; |
abspath = abspath + separatorChar; |
939 |
|
|
940 |
|
if (separatorChar == '\\') |
941 |
|
abspath = separatorChar + abspath; |
942 |
|
|
943 |
try |
try |
944 |
{ |
{ |
966 |
*/ |
*/ |
967 |
public URL toURL() throws MalformedURLException |
public URL toURL() throws MalformedURLException |
968 |
{ |
{ |
969 |
String abspath = getAbsolutePath(); |
// On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt", |
970 |
|
// while on UNIX, it returns URLs of the form "file:/foo/bar.txt". |
971 |
if (isDirectory()) |
if (separatorChar == '\\') |
972 |
abspath = abspath + separator; |
return new URL ("file:/" + getAbsolutePath().replace ('\\', '/') |
973 |
|
+ (isDirectory() ? "/" : "")); |
974 |
return new URL("file", "", abspath.replace(separatorChar, '/')); |
else |
975 |
|
return new URL ("file:" + getAbsolutePath() |
976 |
|
+ (isDirectory() ? "/" : "")); |
977 |
} |
} |
978 |
|
|
979 |
|
|
980 |
/** |
/** |
981 |
* This method creates a directory for the path represented by this object. |
* This method creates a directory for the path represented by this object. |
982 |
* |
* |
988 |
public boolean mkdir() |
public boolean mkdir() |
989 |
{ |
{ |
990 |
checkWrite(); |
checkWrite(); |
991 |
return VMFile.mkdir(PlatformHelper.removeTailSeparator(path)); |
return VMFile.mkdir(path); |
992 |
} |
} |
993 |
|
|
994 |
/** |
/** |
1218 |
*/ |
*/ |
1219 |
public int compareTo(File other) |
public int compareTo(File other) |
1220 |
{ |
{ |
|
String p1, p2; |
|
|
|
|
|
try |
|
|
{ |
|
|
p1 = getCanonicalPath(); |
|
|
p2 = other.getCanonicalPath(); |
|
|
} |
|
|
catch(IOException e) |
|
|
{ |
|
|
// FIXME: What do we do here? The spec requires the canonical path. |
|
|
// Even if we don't call the method, we must replicate the functionality |
|
|
// which per the spec can fail. What happens in that situation? |
|
|
// I just assume the files are equal! |
|
|
return 0; |
|
|
} |
|
|
|
|
1221 |
if (VMFile.caseSensitive) |
if (VMFile.caseSensitive) |
1222 |
return p1.compareTo(p2); |
return path.compareTo (other.path); |
1223 |
else |
else |
1224 |
return p1.compareToIgnoreCase(p2); |
return path.compareToIgnoreCase (other.path); |
1225 |
} |
} |
1226 |
|
|
1227 |
/** |
/** |