1 18 19 package org.apache.tools.ant.util; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.InputStreamReader ; 25 import java.io.Reader ; 26 import java.io.UnsupportedEncodingException ; 27 import java.io.Writer ; 28 import java.io.OutputStream ; 29 import java.net.MalformedURLException ; 30 import java.net.URL ; 31 import java.text.DecimalFormat ; 32 import java.util.ArrayList ; 33 import java.util.Arrays ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Random ; 37 import java.util.Stack ; 38 import java.util.StringTokenizer ; 39 import java.util.Vector ; 40 import org.apache.tools.ant.BuildException; 41 import org.apache.tools.ant.PathTokenizer; 42 import org.apache.tools.ant.Project; 43 import org.apache.tools.ant.taskdefs.condition.Os; 44 import org.apache.tools.ant.types.FilterSetCollection; 45 import org.apache.tools.ant.types.resources.FileResource; 46 import org.apache.tools.ant.launch.Locator; 47 48 55 public class FileUtils { 56 57 private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); 58 59 private static Random rand = new Random (System.currentTimeMillis() 61 + Runtime.getRuntime().freeMemory()); 62 63 private static boolean onNetWare = Os.isFamily("netware"); 64 private static boolean onDos = Os.isFamily("dos"); 65 private static boolean onWin9x = Os.isFamily("win9x"); 66 private static boolean onWindows = Os.isFamily("windows"); 67 68 static final int BUF_SIZE = 8192; 69 70 71 74 public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000; 75 76 79 public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; 80 81 86 public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1; 87 88 89 95 private Object cacheFromUriLock = new Object (); 96 private String cacheFromUriRequest = null; 97 private String cacheFromUriResponse = null; 98 99 107 public static FileUtils newFileUtils() { 108 return new FileUtils(); 109 } 110 111 117 public static FileUtils getFileUtils() { 118 return PRIMARY_INSTANCE; 119 } 120 121 124 protected FileUtils() { 125 } 126 127 135 public URL getFileURL(File file) throws MalformedURLException { 136 return new URL (toURI(file.getAbsolutePath())); 137 } 138 139 150 public void copyFile(String sourceFile, String destFile) 151 throws IOException { 152 copyFile(new File (sourceFile), new File (destFile), null, false, false); 153 } 154 155 167 public void copyFile(String sourceFile, String destFile, 168 FilterSetCollection filters) 169 throws IOException { 170 copyFile(new File (sourceFile), new File (destFile), filters, 171 false, false); 172 } 173 174 189 public void copyFile(String sourceFile, String destFile, FilterSetCollection filters, 190 boolean overwrite) throws IOException { 191 copyFile(new File (sourceFile), new File (destFile), filters, 192 overwrite, false); 193 } 194 195 215 public void copyFile(String sourceFile, String destFile, FilterSetCollection filters, 216 boolean overwrite, boolean preserveLastModified) 217 throws IOException { 218 copyFile(new File (sourceFile), new File (destFile), filters, 219 overwrite, preserveLastModified); 220 } 221 222 245 public void copyFile(String sourceFile, String destFile, 246 FilterSetCollection filters, boolean overwrite, 247 boolean preserveLastModified, String encoding) 248 throws IOException { 249 copyFile(new File (sourceFile), new File (destFile), filters, 250 overwrite, preserveLastModified, encoding); 251 } 252 253 280 public void copyFile(String sourceFile, String destFile, 281 FilterSetCollection filters, Vector filterChains, 282 boolean overwrite, boolean preserveLastModified, 283 String encoding, Project project) 284 throws IOException { 285 copyFile(new File (sourceFile), new File (destFile), filters, 286 filterChains, overwrite, preserveLastModified, 287 encoding, project); 288 } 289 290 317 public void copyFile(String sourceFile, String destFile, 318 FilterSetCollection filters, Vector filterChains, 319 boolean overwrite, boolean preserveLastModified, 320 String inputEncoding, String outputEncoding, 321 Project project) 322 throws IOException { 323 copyFile(new File (sourceFile), new File (destFile), filters, 324 filterChains, overwrite, preserveLastModified, 325 inputEncoding, outputEncoding, project); 326 } 327 328 339 public void copyFile(File sourceFile, File destFile) throws IOException { 340 copyFile(sourceFile, destFile, null, false, false); 341 } 342 343 355 public void copyFile(File sourceFile, File destFile, FilterSetCollection filters) 356 throws IOException { 357 copyFile(sourceFile, destFile, filters, false, false); 358 } 359 360 375 public void copyFile(File sourceFile, File destFile, FilterSetCollection filters, 376 boolean overwrite) throws IOException { 377 copyFile(sourceFile, destFile, filters, overwrite, false); 378 } 379 380 400 public void copyFile(File sourceFile, File destFile, FilterSetCollection filters, 401 boolean overwrite, boolean preserveLastModified) 402 throws IOException { 403 copyFile(sourceFile, destFile, filters, overwrite, 404 preserveLastModified, null); 405 } 406 407 431 public void copyFile(File sourceFile, File destFile, 432 FilterSetCollection filters, boolean overwrite, 433 boolean preserveLastModified, String encoding) 434 throws IOException { 435 copyFile(sourceFile, destFile, filters, null, overwrite, 436 preserveLastModified, encoding, null); 437 } 438 439 465 public void copyFile(File sourceFile, File destFile, 466 FilterSetCollection filters, Vector filterChains, 467 boolean overwrite, boolean preserveLastModified, 468 String encoding, Project project) 469 throws IOException { 470 copyFile(sourceFile, destFile, filters, filterChains, 471 overwrite, preserveLastModified, encoding, encoding, project); 472 } 473 474 502 public void copyFile(File sourceFile, File destFile, 503 FilterSetCollection filters, Vector filterChains, 504 boolean overwrite, boolean preserveLastModified, 505 String inputEncoding, String outputEncoding, 506 Project project) 507 throws IOException { 508 ResourceUtils.copyResource( 509 new FileResource(sourceFile), new FileResource(destFile), 510 filters, filterChains, overwrite, preserveLastModified, 511 inputEncoding, outputEncoding, project); 512 } 513 514 516 524 public void setFileLastModified(File file, long time) { 525 ResourceUtils.setLastModified(new FileResource(file), time); 526 } 527 528 549 public File resolveFile(File file, String filename) { 550 if (!isAbsolutePath(filename)) { 551 char sep = File.separatorChar; 552 filename = filename.replace('/', sep).replace('\\', sep); 553 if (isContextRelativePath(filename)) { 554 file = null; 555 String udir = System.getProperty("user.dir"); 558 if (filename.charAt(0) == sep && udir.charAt(0) == sep) { 559 filename = dissect(udir)[0] + filename.substring(1); 560 } 561 } 562 filename = new File (file, filename).getAbsolutePath(); 563 } 564 return normalize(filename); 565 } 566 567 578 public static boolean isContextRelativePath(String filename) { 579 if (!(onDos || onNetWare) || filename.length() == 0) { 580 return false; 581 } 582 char sep = File.separatorChar; 583 filename = filename.replace('/', sep).replace('\\', sep); 584 char c = filename.charAt(0); 585 int len = filename.length(); 586 return (c == sep && (len == 1 || filename.charAt(1) != sep)) 587 || (Character.isLetter(c) && len > 1 588 && filename.indexOf(':') == 1 589 && (len == 2 || filename.charAt(2) != sep)); 590 } 591 592 602 public static boolean isAbsolutePath(String filename) { 603 int len = filename.length(); 604 if (len == 0) { 605 return false; 606 } 607 char sep = File.separatorChar; 608 filename = filename.replace('/', sep).replace('\\', sep); 609 char c = filename.charAt(0); 610 if (!(onDos || onNetWare)) { 611 return (c == sep); 612 } 613 if (c == sep) { 614 if (!(onDos && len > 4 && filename.charAt(1) == sep)) { 615 return false; 616 } 617 int nextsep = filename.indexOf(sep, 2); 618 return nextsep > 2 && nextsep + 1 < len; 619 } 620 int colon = filename.indexOf(':'); 621 return (Character.isLetter(c) && colon == 1 622 && filename.length() > 2 && filename.charAt(2) == sep) 623 || (onNetWare && colon > 0); 624 } 625 626 643 public static String translatePath(String toProcess) { 644 if (toProcess == null || toProcess.length() == 0) { 645 return ""; 646 } 647 StringBuffer path = new StringBuffer (toProcess.length() + 50); 648 PathTokenizer tokenizer = new PathTokenizer(toProcess); 649 while (tokenizer.hasMoreTokens()) { 650 String pathComponent = tokenizer.nextToken(); 651 pathComponent = pathComponent.replace('/', File.separatorChar); 652 pathComponent = pathComponent.replace('\\', File.separatorChar); 653 if (path.length() != 0) { 654 path.append(File.pathSeparatorChar); 655 } 656 path.append(pathComponent); 657 } 658 return path.toString(); 659 } 660 661 680 public File normalize(final String path) { 681 Stack s = new Stack (); 682 String [] dissect = dissect(path); 683 s.push(dissect[0]); 684 685 StringTokenizer tok = new StringTokenizer(dissect[1], File.separator); 686 while (tok.hasMoreTokens()) { 687 String thisToken = tok.nextToken(); 688 if (".".equals(thisToken)) { 689 continue; 690 } else if ("..".equals(thisToken)) { 691 if (s.size() < 2) { 692 return new File (path); 694 } 695 s.pop(); 696 } else { s.push(thisToken); 698 } 699 } 700 StringBuffer sb = new StringBuffer (); 701 for (int i = 0; i < s.size(); i++) { 702 if (i > 1) { 703 sb.append(File.separatorChar); 706 } 707 sb.append(s.elementAt(i)); 708 } 709 return new File (sb.toString()); 710 } 711 712 719 public String [] dissect(String path) { 720 char sep = File.separatorChar; 721 path = path.replace('/', sep).replace('\\', sep); 722 723 if (!isAbsolutePath(path)) { 725 throw new BuildException(path + " is not an absolute path"); 726 } 727 String root = null; 728 int colon = path.indexOf(':'); 729 if (colon > 0 && (onDos || onNetWare)) { 730 731 int next = colon + 1; 732 root = path.substring(0, next); 733 char[] ca = path.toCharArray(); 734 root += sep; 735 next = (ca[next] == sep) ? next + 1 : next; 737 738 StringBuffer sbPath = new StringBuffer (); 739 for (int i = next; i < ca.length; i++) { 741 if (ca[i] != sep || ca[i - 1] != sep) { 742 sbPath.append(ca[i]); 743 } 744 } 745 path = sbPath.toString(); 746 } else if (path.length() > 1 && path.charAt(1) == sep) { 747 int nextsep = path.indexOf(sep, 2); 749 nextsep = path.indexOf(sep, nextsep + 1); 750 root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path; 751 path = path.substring(root.length()); 752 } else { 753 root = File.separator; 754 path = path.substring(1); 755 } 756 return new String [] {root, path}; 757 } 758 759 768 public String toVMSPath(File f) { 769 String osPath; 771 String path = normalize(f.getAbsolutePath()).getPath(); 772 String name = f.getName(); 773 boolean isAbsolute = path.charAt(0) == File.separatorChar; 774 boolean isDirectory = f.isDirectory() 776 && !name.regionMatches(true, name.length() - 4, ".DIR", 0, 4); 777 778 String device = null; 779 StringBuffer directory = null; 780 String file = null; 781 782 int index = 0; 783 784 if (isAbsolute) { 785 index = path.indexOf(File.separatorChar, 1); 786 if (index == -1) { 787 return path.substring(1) + ":[000000]"; 788 } else { 789 device = path.substring(1, index++); 790 } 791 } 792 if (isDirectory) { 793 directory = new StringBuffer (path.substring(index). 794 replace(File.separatorChar, '.')); 795 } else { 796 int dirEnd = 797 path.lastIndexOf(File.separatorChar, path.length()); 798 if (dirEnd == -1 || dirEnd < index) { 799 file = path.substring(index); 800 } else { 801 directory = new StringBuffer (path.substring(index, dirEnd). 802 replace(File.separatorChar, '.')); 803 index = dirEnd + 1; 804 if (path.length() > index) { 805 file = path.substring(index); 806 } 807 } 808 } 809 if (!isAbsolute && directory != null) { 810 directory.insert(0, '.'); 811 } 812 osPath = ((device != null) ? device + ":" : "") 813 + ((directory != null) ? "[" + directory + "]" : "") 814 + ((file != null) ? file : ""); 815 return osPath; 816 } 817 818 839 public File createTempFile(String prefix, String suffix, File parentDir) { 840 return createTempFile(prefix, suffix, parentDir, false); 841 } 842 843 866 public File createTempFile(String prefix, String suffix, File parentDir, 867 boolean deleteOnExit) { 868 File result = null; 869 String parent = (parentDir == null) 870 ? System.getProperty("java.io.tmpdir") 871 : parentDir.getPath(); 872 873 DecimalFormat fmt = new DecimalFormat ("#####"); 874 synchronized (rand) { 875 do { 876 result = new File (parent, 877 prefix + fmt.format(Math.abs(rand.nextInt())) 878 + suffix); 879 } while (result.exists()); 880 } 881 if (deleteOnExit) { 882 result.deleteOnExit(); 883 } 884 return result; 885 } 886 887 897 public boolean contentEquals(File f1, File f2) throws IOException { 898 return contentEquals(f1, f2, false); 899 } 900 901 914 public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { 915 return ResourceUtils.contentEquals( 916 new FileResource(f1), new FileResource(f2), textfile); 917 } 918 919 929 public File getParentFile(File f) { 930 return (f == null) ? null : f.getParentFile(); 931 } 932 933 941 public static final String readFully(Reader rdr) throws IOException { 942 return readFully(rdr, BUF_SIZE); 943 } 944 945 956 public static final String readFully(Reader rdr, int bufferSize) 957 throws IOException { 958 if (bufferSize <= 0) { 959 throw new IllegalArgumentException ("Buffer size must be greater " 960 + "than 0"); 961 } 962 final char[] buffer = new char[bufferSize]; 963 int bufferLength = 0; 964 StringBuffer textBuffer = null; 965 while (bufferLength != -1) { 966 bufferLength = rdr.read(buffer); 967 if (bufferLength > 0) { 968 textBuffer = (textBuffer == null) ? new StringBuffer () : textBuffer; 969 textBuffer.append(new String (buffer, 0, bufferLength)); 970 } 971 } 972 return (textBuffer == null) ? null : textBuffer.toString(); 973 } 974 975 987 public boolean createNewFile(File f) throws IOException { 988 return f.createNewFile(); 989 } 990 991 1000 public boolean createNewFile(File f, boolean mkdirs) throws IOException { 1001 File parent = f.getParentFile(); 1002 if (mkdirs && !(parent.exists())) { 1003 parent.mkdirs(); 1004 } 1005 return f.createNewFile(); 1006 } 1007 1008 1022 public boolean isSymbolicLink(File parent, String name) 1023 throws IOException { 1024 if (parent == null) { 1025 File f = new File (name); 1026 parent = f.getParentFile(); 1027 name = f.getName(); 1028 } 1029 File toTest = new File (parent.getCanonicalPath(), name); 1030 return !toTest.getAbsolutePath().equals(toTest.getCanonicalPath()); 1031 } 1032 1033 1044 public String removeLeadingPath(File leading, File path) { 1045 String l = normalize(leading.getAbsolutePath()).getAbsolutePath(); 1046 String p = normalize(path.getAbsolutePath()).getAbsolutePath(); 1047 if (l.equals(p)) { 1048 return ""; 1049 } 1050 1051 if (!l.endsWith(File.separator)) { 1054 l += File.separator; 1055 } 1056 return (p.startsWith(l)) ? p.substring(l.length()) : p; 1057 } 1058 1059 1066 public boolean isLeadingPath(File leading, File path) { 1067 String l = normalize(leading.getAbsolutePath()).getAbsolutePath(); 1068 String p = normalize(path.getAbsolutePath()).getAbsolutePath(); 1069 if (l.equals(p)) { 1070 return true; 1071 } 1072 if (!l.endsWith(File.separator)) { 1075 l += File.separator; 1076 } 1077 return p.startsWith(l); 1078 } 1079 1080 1098 public String toURI(String path) { 1099 Class uriClazz = null; 1101 try { 1102 uriClazz = Class.forName("java.net.URI"); 1103 } catch (ClassNotFoundException e) { 1104 } 1106 if (uriClazz != null) { 1107 try { 1108 File f = new File (path).getAbsoluteFile(); 1109 java.lang.reflect.Method toURIMethod = File .class.getMethod("toURI", new Class [0]); 1110 Object uriObj = toURIMethod.invoke(f, new Object [] {}); 1111 java.lang.reflect.Method toASCIIStringMethod 1112 = uriClazz.getMethod("toASCIIString", new Class [0]); 1113 return (String ) toASCIIStringMethod.invoke(uriObj, new Object [] {}); 1114 } catch (Exception e) { 1115 e.printStackTrace(); 1117 } 1118 } 1119 boolean isDir = new File (path).isDirectory(); 1120 1121 StringBuffer sb = new StringBuffer ("file:"); 1122 1123 path = resolveFile(null, path).getPath(); 1124 sb.append("//"); 1125 if (!path.startsWith(File.separator)) { 1127 sb.append("/"); 1128 } 1129 path = path.replace('\\', '/'); 1130 try { 1131 sb.append(Locator.encodeURI(path)); 1132 } catch (UnsupportedEncodingException exc) { 1133 throw new BuildException(exc); 1134 } 1135 if (isDir && !path.endsWith("/")) { 1136 sb.append('/'); 1137 } 1138 return sb.toString(); 1139 } 1140 1141 1153 public String fromURI(String uri) { 1154 synchronized (cacheFromUriLock) { 1155 if (uri.equals(cacheFromUriRequest)) { 1156 return cacheFromUriResponse; 1157 } 1158 String path = Locator.fromURI(uri); 1159 String ret = isAbsolutePath(path) 1160 ? normalize(path).getAbsolutePath() : path; 1161 cacheFromUriRequest = uri; 1162 cacheFromUriResponse = ret; 1163 return ret; 1164 } 1165 } 1166 1167 1181 public boolean fileNameEquals(File f1, File f2) { 1182 return normalize(f1.getAbsolutePath()) 1183 .equals(normalize(f2.getAbsolutePath())); 1184 } 1185 1186 1203 public void rename(File from, File to) throws IOException { 1204 if (to.exists() && !to.delete()) { 1205 throw new IOException ("Failed to delete " + to 1206 + " while trying to rename " + from); 1207 } 1208 File parent = to.getParentFile(); 1209 if (parent != null && !parent.exists() && !parent.mkdirs()) { 1210 throw new IOException ("Failed to create directory " + parent 1211 + " while trying to rename " + from); 1212 } 1213 if (!from.renameTo(to)) { 1214 copyFile(from, to); 1215 if (!from.delete()) { 1216 throw new IOException ("Failed to delete " + from 1217 + " while trying to rename it."); 1218 } 1219 } 1220 } 1221 1222 1230 public long getFileTimestampGranularity() { 1231 if (onWin9x) { 1232 return FAT_FILE_TIMESTAMP_GRANULARITY; 1233 } else if (onWindows) { 1234 return NTFS_FILE_TIMESTAMP_GRANULARITY; 1235 } else if (onDos) { 1236 return FAT_FILE_TIMESTAMP_GRANULARITY; 1237 } 1238 return UNIX_FILE_TIMESTAMP_GRANULARITY; 1239 } 1240 1241 1252 public boolean isUpToDate(File source, File dest, long granularity) { 1253 if (!dest.exists()) { 1255 return false; 1257 } 1258 long sourceTime = source.lastModified(); 1259 long destTime = dest.lastModified(); 1260 return isUpToDate(sourceTime, destTime, granularity); 1261 } 1262 1263 1270 public boolean isUpToDate(File source, File dest) { 1271 return isUpToDate(source, dest, getFileTimestampGranularity()); 1272 } 1273 1274 1283 public boolean isUpToDate(long sourceTime, long destTime, long granularity) { 1284 if (destTime == -1) { 1285 return false; 1286 } 1287 return destTime >= sourceTime + granularity; 1288 } 1289 1290 1298 public boolean isUpToDate(long sourceTime, long destTime) { 1299 return isUpToDate(sourceTime, destTime, getFileTimestampGranularity()); 1300 } 1301 1302 1307 public static void close(Writer device) { 1308 if (device != null) { 1309 try { 1310 device.close(); 1311 } catch (IOException ioex) { 1312 } 1314 } 1315 } 1316 1317 1323 public static void close(Reader device) { 1324 if (device != null) { 1325 try { 1326 device.close(); 1327 } catch (IOException ioex) { 1328 } 1330 } 1331 } 1332 1333 1339 public static void close(OutputStream device) { 1340 if (device != null) { 1341 try { 1342 device.close(); 1343 } catch (IOException ioex) { 1344 } 1346 } 1347 } 1348 1349 1355 public static void close(InputStream device) { 1356 if (device != null) { 1357 try { 1358 device.close(); 1359 } catch (IOException ioex) { 1360 } 1362 } 1363 } 1364 1365 1370 public static void delete(File file) { 1371 if (file != null) { 1372 file.delete(); 1373 } 1374 } 1375 1376 1394 public static String getRelativePath( 1395 File fromFile, 1396 File toFile 1397 ) throws Exception { 1398 String fromPath = fromFile.getCanonicalPath(); 1399 String toPath = toFile.getCanonicalPath(); 1400 1401 String [] fromPathStack = getPathStack(fromPath); 1403 String [] toPathStack = getPathStack(toPath); 1404 1405 if (0 < toPathStack.length && 0 < fromPathStack.length) { 1406 if (!fromPathStack[0].equals(toPathStack[0])) { 1407 1409 return getPath(Arrays.asList(toPathStack)); 1410 } 1411 } else { 1412 return getPath(Arrays.asList(toPathStack)); 1414 } 1415 1416 int minLength = Math 1417 .min(fromPathStack.length, toPathStack.length); 1418 1419 int same = 1; 1420 1421 for (; same < minLength; same++) { 1423 if (!fromPathStack[same].equals(toPathStack[same])) { 1424 break; 1425 } 1426 } 1427 1428 List relativePathStack = new ArrayList (); 1429 1430 for (int i = same; i < fromPathStack.length; i++) { 1433 relativePathStack.add(".."); 1434 } 1435 1436 for (int i = same; i < toPathStack.length; i++) { 1438 relativePathStack.add(toPathStack[i]); 1439 } 1440 1441 return getPath(relativePathStack); 1442 } 1443 1444 1453 public static String [] getPathStack(String path) { 1454 String normalizedPath = path.replace(File.separatorChar, '/'); 1455 1456 Object [] tokens = StringUtils.split(normalizedPath, '/').toArray(); 1460 String [] rv = new String [tokens.length]; 1461 System.arraycopy(tokens, 0, rv, 0, tokens.length); 1462 1463 return rv; 1464 } 1465 1466 1476 public static String getPath(List pathStack) { 1477 return getPath(pathStack, '/'); 1479 } 1480 1481 1494 public static String getPath(final List pathStack, final char separatorChar) { 1495 final StringBuffer buffer = new StringBuffer (); 1496 1497 final Iterator iter = pathStack.iterator(); 1498 if (iter.hasNext()) { 1499 buffer.append(iter.next()); 1500 } 1501 1502 while (iter.hasNext()) { 1503 buffer.append(separatorChar); 1504 buffer.append(iter.next()); 1505 } 1506 1507 return buffer.toString(); 1508 } 1509 1510 1518 public String getDefaultEncoding() { 1519 InputStreamReader is = new InputStreamReader ( 1520 new InputStream () { 1521 public int read() { 1522 return -1; 1523 } 1524 }); 1525 try { 1526 return is.getEncoding(); 1527 } finally { 1528 close(is); 1529 } 1530 } 1531} 1532 | Popular Tags |