1 19 20 package org.openide.filesystems; 21 22 import java.io.File ; 23 import java.io.FileFilter ; 24 import java.io.FilenameFilter ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.OutputStream ; 28 import java.io.SyncFailedException ; 29 import java.lang.reflect.InvocationTargetException ; 30 import java.net.MalformedURLException ; 31 import java.net.URI ; 32 import java.net.URL ; 33 import java.net.URLStreamHandler ; 34 import java.util.Arrays ; 35 import java.util.Dictionary ; 36 import java.util.Enumeration ; 37 import java.util.HashMap ; 38 import java.util.HashSet ; 39 import java.util.Hashtable ; 40 import java.util.Iterator ; 41 import java.util.Map ; 42 import java.util.Set ; 43 import java.util.Stack ; 44 import java.util.StringTokenizer ; 45 import java.util.WeakHashMap ; 46 import java.util.jar.JarEntry ; 47 import java.util.jar.JarInputStream ; 48 import java.util.logging.Level ; 49 import java.util.logging.Logger ; 50 import javax.swing.Icon ; 51 import javax.swing.JFileChooser ; 52 import javax.swing.SwingUtilities ; 53 import javax.swing.filechooser.FileSystemView ; 54 import org.openide.util.Exceptions; 55 import org.openide.util.NbBundle; 56 import org.openide.util.Utilities; 57 import org.openide.util.WeakListeners; 58 59 62 public final class FileUtil extends Object { 63 64 65 private static byte[] ZIP_HEADER_1 = {0x50, 0x4b, 0x03, 0x04}; 66 67 private static byte[] ZIP_HEADER_2 = {0x50, 0x4b, 0x05, 0x06}; 68 69 72 static final Set <String > transientAttributes = new HashSet <String >(); 73 74 static { 75 transientAttributes.add("templateWizardURL"); transientAttributes.add("templateWizardIterator"); transientAttributes.add("templateWizardDescResource"); transientAttributes.add("templateCategory"); transientAttributes.add("instantiatingIterator"); transientAttributes.add("instantiatingWizardURL"); transientAttributes.add("SystemFileSystem.localizingBundle"); transientAttributes.add("SystemFileSystem.icon"); transientAttributes.add("SystemFileSystem.icon32"); } 85 86 87 private static Dictionary <String , String > map = new Hashtable <String , String >(); 88 89 static { 90 setMIMEType("xml", "text/xml"); } 95 96 97 private static final Map <FileObject, Boolean > archiveFileCache = new WeakHashMap <FileObject,Boolean >(); 98 99 private FileUtil() { 100 } 101 102 112 public static FileObject createFolder (final File folder) throws IOException { 113 FileObject retval = null; 114 File root = getRoot(folder); 115 if (!root.exists()) { 116 throw new IOException (folder.getAbsolutePath()); 117 } 118 FileObject rootFo = FileUtil.toFileObject(root); 119 assert rootFo != null : root.getAbsolutePath(); 120 final String relativePath = getRelativePath(root, folder); 121 try { 122 retval = FileUtil.createFolder(rootFo,relativePath); 123 } catch (IOException ex) { 124 } 126 if (retval == null || !retval.isValid()) { 128 rootFo.getFileSystem().refresh(false); 129 retval = FileUtil.createFolder(rootFo,relativePath); 130 } 131 assert retval != null; 132 return retval; 133 } 134 135 144 public static FileObject createData (final File data) throws IOException { 145 FileObject retval = null; 146 File root = getRoot(data); 147 if (!root.exists()) { 148 throw new IOException (data.getAbsolutePath()); 149 } 150 FileObject rootFo = FileUtil.toFileObject(root); 151 assert rootFo != null : root.getAbsolutePath(); 152 final String relativePath = getRelativePath(root, data); 153 try { 154 retval = FileUtil.createData(rootFo,relativePath); 155 } catch (IOException ex) { 156 } 158 if (retval == null || !retval.isValid()) { 160 rootFo.getFileSystem().refresh(false); 161 retval = FileUtil.createData(rootFo,relativePath); 162 } 163 assert retval != null; 164 return retval; 165 } 166 167 private static File getRoot(final File dir) { 168 File retval = dir; 169 for (; retval.getParentFile() != null; retval = retval.getParentFile()); 170 assert retval != null; 171 return retval; 172 } 173 174 private static String getRelativePath(final File dir, final File file) { 175 Stack <String > stack = new Stack <String >(); 176 File tempFile = file; 177 while(tempFile != null && !tempFile.equals(dir)) { 178 stack.push (tempFile.getName()); 179 tempFile = tempFile.getParentFile(); 180 } 181 assert tempFile != null : file.getAbsolutePath() + "not found in " + dir.getAbsolutePath(); StringBuilder retval = new StringBuilder (); 183 while (!stack.isEmpty()) { 184 retval.append(stack.pop()); 185 if (!stack.isEmpty()) { 186 retval.append('/'); } 188 } 189 return retval.toString(); 190 } 191 192 198 public static void copy(InputStream is, OutputStream os) 199 throws IOException { 200 final byte[] BUFFER = new byte[4096]; 201 int len; 202 203 for (;;) { 204 len = is.read(BUFFER); 205 206 if (len == -1) { 207 return; 208 } 209 210 os.write(BUFFER, 0, len); 211 } 212 } 213 214 224 static FileObject copyFileImpl(FileObject source, FileObject destFolder, String newName, String newExt) 225 throws IOException { 226 FileObject dest = destFolder.createData(newName, newExt); 227 228 FileLock lock = null; 229 InputStream bufIn = null; 230 OutputStream bufOut = null; 231 232 try { 233 lock = dest.lock(); 234 bufIn = source.getInputStream(); 235 236 if (dest instanceof AbstractFileObject) { 237 238 bufOut = ((AbstractFileObject) dest).getOutputStream(lock, false); 239 } else { 240 bufOut = dest.getOutputStream(lock); 241 } 242 243 copy(bufIn, bufOut); 244 copyAttributes(source, dest); 245 } finally { 246 if (bufIn != null) { 247 bufIn.close(); 248 } 249 250 if (bufOut != null) { 251 bufOut.close(); 252 } 253 254 if (lock != null) { 255 lock.releaseLock(); 256 } 257 } 258 259 return dest; 260 } 261 262 266 271 public static FileSystem createMemoryFileSystem() { 272 return new MemoryFileSystem(); 273 } 274 275 285 public static FileObject copyFile(FileObject source, FileObject destFolder, String newName, String newExt) 286 throws IOException { 287 return source.copy(destFolder, newName, newExt); 288 } 289 290 300 public static FileObject copyFile(FileObject source, FileObject destFolder, String newName) 301 throws IOException { 302 return copyFile(source, destFolder, newName, source.getExt()); 303 } 304 305 313 public static FileObject moveFile(FileObject source, FileObject destFolder, String newName) 314 throws IOException { 315 FileLock lock = null; 316 317 try { 318 lock = source.lock(); 319 320 return source.move(lock, destFolder, newName, source.getExt()); 321 } finally { 322 if (lock != null) { 323 lock.releaseLock(); 324 } 325 } 326 } 327 328 341 public static FileObject createFolder(FileObject folder, String name) 342 throws IOException { 343 String separators; 344 345 if (File.separatorChar != '/') { 346 separators = "/" + File.separatorChar; } else { 348 separators = "/"; } 350 351 StringTokenizer st = new StringTokenizer (name, separators); 352 353 while (st.hasMoreElements()) { 354 name = st.nextToken(); 355 356 if (name.length() > 0) { 357 FileObject f = folder.getFileObject(name); 358 359 if (f == null) { 360 try { 361 f = folder.createFolder(name); 362 } catch (SyncFailedException ex) { 363 folder.refresh(); 366 367 f = folder.getFileObject(name); 369 370 if (f == null) { 371 throw ex; 374 } 375 } 376 } 377 378 folder = f; 379 } 380 } 381 382 return folder; 383 } 384 385 396 public static FileObject createData(FileObject folder, String name) 397 throws IOException { 398 if (folder == null) { 399 throw new IllegalArgumentException ("Null folder"); } 401 402 if (name == null) { 403 throw new IllegalArgumentException ("Null name"); } 405 406 String foldername; 407 String dataname; 408 String fname; 409 String ext; 410 int index = name.lastIndexOf('/'); 411 FileObject data; 412 413 if (index >= name.length()) { 415 throw new IOException ("Wrong file name."); } 417 418 if (index != -1) { 420 foldername = name.substring(0, index); 421 dataname = name.substring(index + 1); 422 folder = createFolder(folder, foldername); 423 assert folder != null; 424 } else { 425 dataname = name; 426 } 427 428 index = dataname.lastIndexOf('.'); 430 431 if (index != -1) { 432 fname = dataname.substring(0, index); 433 ext = dataname.substring(index + 1); 434 } else { 435 fname = dataname; 436 ext = ""; } 438 439 data = folder.getFileObject(fname, ext); 440 441 if (data == null) { 442 try { 443 data = folder.createData(fname, ext); 444 assert data != null : "FileObject.createData cannot return null; called on " + folder + " + " + fname + 445 " + " + ext; } catch (SyncFailedException ex) { 447 folder.refresh(); 450 451 data = folder.getFileObject(fname, ext); 453 454 if (data == null) { 455 throw ex; 458 } 459 } 460 } 461 462 return data; 463 } 464 465 472 public static File toFile(FileObject fo) { 473 File retVal = (File ) fo.getAttribute("java.io.File"); 475 if (retVal == null) { 476 URL fileURL = null; 477 int[] types = new int[] { URLMapper.INTERNAL, URLMapper.EXTERNAL }; 478 479 for (int i = 0; ((fileURL == null) || "file".equals(fileURL.getProtocol())) && (i < types.length); i++) { fileURL = URLMapper.findURL(fo, types[i]); 481 } 482 483 if ((fileURL != null) && "file".equals(fileURL.getProtocol())) { 484 retVal = new File (URI.create(fileURL.toExternalForm())); 485 } 486 } 487 488 return (retVal != null) ? normalizeFile(retVal) : null; 489 } 490 491 504 public static FileObject toFileObject(File file) { 505 boolean asserts = false; 506 assert asserts = true; 507 if (asserts && !file.equals(normalizeFile(file))) { 508 throw new IllegalArgumentException ( 509 "Parameter file was not " + "normalized. Was " + file + " instead of " + normalizeFile(file) 511 ); } 513 514 FileObject retVal = null; 515 516 try { 517 URL url = fileToURL(file); 518 519 if ( 520 (url.getAuthority() != null) && 521 (Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2)) 522 ) { 523 return null; 524 } 525 526 retVal = URLMapper.findFileObject(url); 527 528 529 } catch (MalformedURLException e) { 530 retVal = null; 531 } 532 533 return retVal; 534 } 535 536 static URL fileToURL(File file) throws MalformedURLException { 537 URL retVal = null; 538 539 if (canBeCanonicalizedOnWindows(file)) { 540 retVal = file.toURI().toURL(); 541 } else { 542 retVal = new URL ("file:/" + file.getAbsolutePath()); } 544 545 return retVal; 546 } 547 548 559 @Deprecated 560 public static FileObject[] fromFile(File file) { 561 FileObject[] retVal; 562 563 if (!file.equals(normalizeFile(file))) { 564 throw new IllegalArgumentException ( 565 "Parameter file was not " + "normalized. Was " + file + " instead of " + normalizeFile(file) 567 ); } 569 570 try { 571 URL url = (file.toURI().toURL()); 572 573 if ( 574 (url.getAuthority() != null) && 575 (Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2)) 576 ) { 577 return null; 578 } 579 580 retVal = URLMapper.findFileObjects(url); 581 } catch (MalformedURLException e) { 582 retVal = null; 583 } 584 585 return retVal; 586 } 587 588 596 public static void copyAttributes(FileObject source, FileObject dest) 597 throws IOException { 598 Enumeration <String > attrKeys = source.getAttributes(); 599 600 while (attrKeys.hasMoreElements()) { 601 String key = attrKeys.nextElement(); 602 603 if (transientAttributes.contains(key)) { 604 continue; 605 } 606 607 if (isTransient(source, key)) { 608 continue; 609 } 610 611 Object value = source.getAttribute(key); 612 613 if (value != null) { 614 dest.setAttribute(key, value); 615 } 616 } 617 } 618 619 static boolean isTransient(FileObject fo, String attrName) { 620 return XMLMapAttr.ModifiedAttribute.isTransient(fo, attrName); 621 } 622 623 634 @Deprecated 635 public static void extractJar(final FileObject fo, final InputStream is) 636 throws IOException { 637 FileSystem fs = fo.getFileSystem(); 638 639 fs.runAtomicAction( 640 new FileSystem.AtomicAction() { 641 public void run() throws IOException { 642 extractJarImpl(fo, is); 643 } 644 } 645 ); 646 } 647 648 650 private static void extractJarImpl(FileObject fo, InputStream is) 651 throws IOException { 652 JarInputStream jis; 653 JarEntry je; 654 655 HashMap <String , DefaultAttributes.Table> attributes = 657 new HashMap <String , DefaultAttributes.Table>(7); 658 659 jis = new JarInputStream (is); 660 661 while ((je = jis.getNextJarEntry()) != null) { 662 String name = je.getName(); 663 664 if (name.toLowerCase().startsWith("meta-inf/")) { 665 continue; } 667 668 if (je.isDirectory()) { 669 createFolder(fo, name); 670 671 continue; 672 } 673 674 if (DefaultAttributes.acceptName(name)) { 675 DefaultAttributes.Table table = DefaultAttributes.loadTable(jis, name); 677 attributes.put(name, table); 678 } else { 679 FileObject fd = createData(fo, name); 681 FileLock lock = fd.lock(); 682 683 try { 684 OutputStream os = fd.getOutputStream(lock); 685 686 try { 687 copy(jis, os); 688 } finally { 689 os.close(); 690 } 691 } finally { 692 lock.releaseLock(); 693 } 694 } 695 } 696 697 Iterator it = attributes.entrySet().iterator(); 701 702 while (it.hasNext()) { 703 Map.Entry entry = (Map.Entry ) it.next(); 704 705 String fileName = (String ) entry.getKey(); 706 int last = fileName.lastIndexOf('/'); 707 String dirName; 708 709 if (last != -1) { 710 dirName = fileName.substring(0, last + 1); 711 } else { 712 dirName = ""; } 714 715 String prefix = fo.isRoot() ? dirName : (fo.getPath() + '/' + dirName); 716 717 DefaultAttributes.Table t = (DefaultAttributes.Table) entry.getValue(); 718 Iterator files = t.keySet().iterator(); 719 720 while (files.hasNext()) { 721 String orig = (String ) files.next(); 722 String fn = prefix + orig; 723 FileObject obj = fo.getFileSystem().findResource(fn); 724 725 if (obj == null) { 726 continue; 727 } 728 729 Enumeration <String > attrEnum = t.attrs(orig); 730 731 while (attrEnum.hasMoreElements()) { 732 String attrName = attrEnum.nextElement(); 734 735 Object value = t.getAttr(orig, attrName); 737 738 if (value != null) { 739 obj.setAttribute(attrName, value); 740 } 741 } 742 } 743 } 744 } 745 747 753 public static String getExtension(String fileName) { 754 int index = fileName.lastIndexOf("."); 756 if (index == -1) { 757 return ""; } else { 759 return fileName.substring(index + 1); 760 } 761 } 762 763 784 public static String findFreeFileName(FileObject folder, String name, String ext) { 785 if (checkFreeName(folder, name, ext)) { 786 return name; 787 } 788 789 for (int i = 1;; i++) { 790 String destName = name + "_" + i; 792 if (checkFreeName(folder, destName, ext)) { 793 return destName; 794 } 795 } 796 } 797 798 805 public static String findFreeFolderName(FileObject folder, String name) { 806 if (checkFreeName(folder, name, null)) { 807 return name; 808 } 809 810 for (int i = 1;; i++) { 811 String destName = name + "_" + i; 813 if (checkFreeName(folder, destName, null)) { 814 return destName; 815 } 816 } 817 } 818 819 830 public static String getRelativePath(FileObject folder, FileObject fo) { 831 if (!isParentOf(folder, fo) && (folder != fo)) { 832 return null; 833 } 834 835 String result = fo.getPath().substring(folder.getPath().length()); 836 837 if (result.startsWith("/")) { 838 result = result.substring(1); 839 } 840 841 return result; 842 } 843 844 850 private static boolean checkFreeName(FileObject fo, String name, String ext) { 851 if ((Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2)) || Utilities.isMac()) { 852 Enumeration <? extends FileObject> en = fo.getChildren(false); 854 855 while (en.hasMoreElements()) { 856 fo = en.nextElement(); 857 858 String n = fo.getName(); 859 String e = fo.getExt(); 860 861 if (!n.equalsIgnoreCase(name)) { 863 continue; 864 } 865 866 if (((ext == null) || (ext.trim().length() == 0)) && ((e == null) || (e.trim().length() == 0))) { 868 return fo.isVirtual(); 869 } 870 871 if ((ext == null) || (e == null)) { 873 continue; 874 } 875 876 if (ext.equalsIgnoreCase(e)) { 877 return fo.isVirtual(); 879 } 880 } 881 882 return true; 884 } else { 885 if (ext == null) { 886 fo = fo.getFileObject(name); 887 888 if (fo == null) { 889 return true; 890 } 891 892 return fo.isVirtual(); 893 } else { 894 fo = fo.getFileObject(name, ext); 895 896 if (fo == null) { 897 return true; 898 } 899 900 return fo.isVirtual(); 901 } 902 } 903 } 904 905 907 913 public static FileObject findBrother(FileObject fo, String ext) { 914 if (fo == null) { 915 return null; 916 } 917 918 FileObject parent = fo.getParent(); 919 920 if (parent == null) { 921 return null; 922 } 923 924 return parent.getFileObject(fo.getName(), ext); 925 } 926 927 935 @Deprecated 936 public static String getMIMEType(String ext) { 937 String s = map.get(ext); 938 939 if (s != null) { 940 return s; 941 } else { 942 return map.get(ext.toLowerCase()); 943 } 944 } 945 946 952 public static String getMIMEType(FileObject fo) { 953 String retVal = MIMESupport.findMIMEType(fo, null); 954 955 if (retVal == null) { 956 retVal = getMIMEType(fo.getExt()); 957 } 958 959 return retVal; 960 } 961 962 966 static String getMIMETypeOrDefault(FileObject fo) { 967 String def = getMIMEType(fo.getExt()); 968 String t = MIMESupport.findMIMEType(fo, def); 969 970 if (t == null) { 971 t = "content/unknown"; } 974 975 return t; 976 } 977 978 991 @Deprecated 992 public static void setMIMEType(String ext, String mimeType) { 993 synchronized (map) { 994 String old = map.get(ext); 995 996 if (old == null) { 997 map.put(ext, mimeType); 998 } else { 999 if (!old.equals(mimeType)) { 1000 throw new IllegalArgumentException ( 1001 "Cannot overwrite existing MIME type mapping for extension `" + ext + "' with " + mimeType + " (was " + old + ")" 1003 ); } 1005 1006 } 1008 } 1009 } 1010 1011 1020 public static URLStreamHandler nbfsURLStreamHandler() { 1021 return FileURL.HANDLER; 1022 } 1023 1024 1036 public static boolean isParentOf(FileObject folder, FileObject fo) { 1037 if (folder == null) { 1038 throw new IllegalArgumentException ("Tried to pass null folder arg"); } 1040 1041 if (fo == null) { 1042 throw new IllegalArgumentException ("Tried to pass null fo arg"); } 1044 1045 if (folder.isData()) { 1046 return false; 1047 } 1048 1049 try { 1050 if (folder.getFileSystem() != fo.getFileSystem()) { 1051 return false; 1052 } 1053 } catch (FileStateInvalidException e) { 1054 return false; 1055 } 1056 1057 FileObject parent = fo.getParent(); 1058 1059 while (parent != null) { 1060 if (parent == folder) { 1061 return true; 1062 } 1063 1064 parent = parent.getParent(); 1065 } 1066 1067 return false; 1068 } 1069 1070 1078 public static FileChangeListener weakFileChangeListener(FileChangeListener l, Object source) { 1079 return WeakListeners.create(FileChangeListener.class, l, source); 1080 } 1081 1082 1090 public static FileStatusListener weakFileStatusListener(FileStatusListener l, Object source) { 1091 return WeakListeners.create(FileStatusListener.class, l, source); 1092 } 1093 1094 1105 public static String getFileDisplayName(FileObject fo) { 1106 String displayName = null; 1107 File f = FileUtil.toFile(fo); 1108 1109 if (f != null) { 1110 displayName = f.getAbsolutePath(); 1111 } else { 1112 FileObject archiveFile = FileUtil.getArchiveFile(fo); 1113 1114 if (archiveFile != null) { 1115 displayName = getArchiveDisplayName(fo, archiveFile); 1116 } 1117 } 1118 1119 if (displayName == null) { 1120 try { 1121 if (fo.isRoot()) { 1122 displayName = fo.getFileSystem().getDisplayName(); 1123 } else { 1124 displayName = NbBundle.getMessage( 1125 FileUtil.class, "LBL_file_in_filesystem", fo.getPath(), fo.getFileSystem().getDisplayName() 1126 ); 1127 } 1128 } catch (FileStateInvalidException e) { 1129 displayName = fo.getPath(); 1131 } 1132 } 1133 1134 return displayName; 1135 } 1136 1137 private static String getArchiveDisplayName(FileObject fo, FileObject archiveFile) { 1138 String displayName = null; 1139 1140 File f = FileUtil.toFile(archiveFile); 1141 1142 if (f != null) { 1143 String archivDisplayName = f.getAbsolutePath(); 1144 1145 if (fo.isRoot()) { 1146 displayName = archivDisplayName; 1147 } else { 1148 String entryPath = fo.getPath(); 1149 displayName = NbBundle.getMessage( 1150 FileUtil.class, "LBL_file_in_filesystem", entryPath, archivDisplayName 1151 ); 1152 } 1153 } 1154 1155 return displayName; 1156 } 1157 1158 1174 public static File normalizeFile(final File file) { 1175 File retFile; 1176 1177 if ((Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2))) { 1178 retFile = normalizeFileOnWindows(file); 1179 } else if (Utilities.isMac()) { 1180 retFile = normalizeFileOnMac(file); 1181 } else { 1182 retFile = normalizeFileOnUnixAlike(file); 1183 } 1184 1185 return (file.getPath().equals(retFile.getPath())) ? file : retFile; 1186 } 1187 1188 private static File normalizeFileOnUnixAlike(File file) { 1189 if (file.getAbsolutePath().equals("/..")) { 1192 file = new File ("/"); } else { 1195 file = new File (file.toURI().normalize()).getAbsoluteFile(); 1197 } 1198 1199 return file; 1200 } 1201 1202 private static File normalizeFileOnMac(final File file) { 1203 File retVal = file; 1204 1205 try { 1206 File absoluteFile = new File (file.toURI().normalize()); 1208 File canonicalFile = file.getCanonicalFile(); 1209 boolean isSymLink = !canonicalFile.getAbsolutePath().equalsIgnoreCase(absoluteFile.getAbsolutePath()); 1210 1211 if (isSymLink) { 1212 retVal = normalizeSymLinkOnMac(absoluteFile); 1213 } else { 1214 retVal = canonicalFile; 1215 } 1216 } catch (IOException ioe) { 1217 Logger.getAnonymousLogger().severe("Normalization failed on file " + file + ": " + ioe); 1218 1219 retVal = file.getAbsoluteFile(); 1221 } 1222 1223 return retVal; 1224 } 1225 1226 1229 private static File normalizeSymLinkOnMac(final File file) 1230 throws IOException { 1231 File retVal = File.listRoots()[0]; 1232 File pureCanonicalFile = retVal; 1233 1234 final String pattern = File.separator + ".." + File.separator; final String fileName; 1236 1237 { 1239 String tmpFileName = file.getAbsolutePath(); 1240 int index = tmpFileName.lastIndexOf(pattern); 1241 1242 if (index > -1) { 1243 tmpFileName = tmpFileName.substring(index + pattern.length()); } 1245 1246 fileName = tmpFileName; 1247 } 1248 1249 1250 StringTokenizer fileSegments = new StringTokenizer (fileName, File.separator); 1251 1252 while (fileSegments.hasMoreTokens()) { 1253 File absolutelyEndingFile = new File (pureCanonicalFile, fileSegments.nextToken()); 1254 pureCanonicalFile = absolutelyEndingFile.getCanonicalFile(); 1255 1256 boolean isSymLink = !pureCanonicalFile.getAbsolutePath().equalsIgnoreCase( 1257 absolutelyEndingFile.getAbsolutePath() 1258 ); 1259 1260 if (isSymLink) { 1261 retVal = new File (retVal, absolutelyEndingFile.getName()); 1262 } else { 1263 retVal = new File (retVal, pureCanonicalFile.getName()); 1264 } 1265 } 1266 1267 return retVal; 1268 } 1269 1270 private static File normalizeFileOnWindows(final File file) { 1271 File retVal = null; 1272 1273 if (canBeCanonicalizedOnWindows(file)) { 1274 try { 1275 retVal = file.getCanonicalFile(); 1276 } catch (IOException e) { 1277 Logger.getAnonymousLogger().severe( 1278 "getCanonicalFile() on file " + file + " failed. " + e.toString() 1279 ); } 1281 } 1282 1283 return (retVal != null) ? retVal : file.getAbsoluteFile(); 1284 } 1285 1286 private static FileSystemView fileSystemView; 1287 private static float javaSpecVersion; 1288 private static boolean canBeCanonicalizedOnWindows(final File file) { 1289 1290 boolean canBeCanonizalized = true; 1291 if (file.getParent() == null && is4089199()) { FileSystemView fsv = getFileSystemView(); 1293 canBeCanonizalized = (fsv != null) ? !fsv.isFloppyDrive(file) && file.exists() : false; 1294 } 1295 1296 return canBeCanonizalized; 1297 } 1298 1299 private static boolean is4089199() { 1300 return getJavaSpecVersion() < 1.6; 1301 } 1302 1303 private static float getJavaSpecVersion() { 1304 synchronized(FileUtil.class) { 1305 if (javaSpecVersion == 0) { 1306 javaSpecVersion = Float.valueOf(System.getProperty("java.specification.version")); } 1308 } 1309 return javaSpecVersion; 1310 } 1311 1312 private static FileSystemView getFileSystemView() { 1313 boolean init = false; 1314 final FileSystemView [] fsv = {fileSystemView}; 1315 1316 synchronized(FileUtil.class) { 1317 init = is4089199() && fsv[0] == null; 1318 } 1319 1320 if (init) { 1321 try { 1322 if (SwingUtilities.isEventDispatchThread()) { 1323 fsv[0] = javax.swing.filechooser.FileSystemView.getFileSystemView(); 1324 } else { 1325 SwingUtilities.invokeAndWait(new java.lang.Runnable () { 1326 public void run() { 1327 fsv[0] = javax.swing.filechooser.FileSystemView.getFileSystemView(); 1328 } 1329 }); 1330 } 1331 } catch (InterruptedException ex) { 1332 Thread.currentThread().interrupt(); 1333 } catch (InvocationTargetException ex) {} 1334 1335 synchronized(FileUtil.class) { 1336 fileSystemView = fsv[0]; 1337 } 1338 } 1339 return fileSystemView; 1340 } 1341 1342 1350 public static FileObject getArchiveRoot(FileObject fo) { 1351 URL archiveURL = URLMapper.findURL(fo, URLMapper.EXTERNAL); 1352 1353 if (archiveURL == null) { 1354 return null; 1355 } 1356 1357 return URLMapper.findFileObject(getArchiveRoot(archiveURL)); 1358 } 1359 1360 1368 public static URL getArchiveRoot(URL url) { 1369 try { 1370 return new URL ("jar:" + url + "!/"); } catch (MalformedURLException e) { 1373 throw new AssertionError (e); 1374 } 1375 } 1376 1377 1387 public static FileObject getArchiveFile(FileObject fo) { 1388 try { 1389 FileSystem fs = fo.getFileSystem(); 1390 1391 if (fs instanceof JarFileSystem) { 1392 File jarFile = ((JarFileSystem) fs).getJarFile(); 1393 1394 return toFileObject(jarFile); 1395 } 1396 } catch (FileStateInvalidException e) { 1397 Exceptions.printStackTrace(e); 1398 } 1399 1400 return null; 1401 } 1402 1403 1413 public static URL getArchiveFile(URL url) { 1414 String protocol = url.getProtocol(); 1415 1416 if ("jar".equals(protocol)) { 1418 String path = url.getPath(); 1419 int index = path.indexOf("!/"); 1421 if (index >= 0) { 1422 try { 1423 return new URL (path.substring(0, index)); 1424 } catch (MalformedURLException mue) { 1425 Exceptions.printStackTrace(mue); 1426 } 1427 } 1428 } 1429 1430 return null; 1431 } 1432 1433 1439 public static boolean isArchiveFile(FileObject fo) { 1440 if (fo == null) { 1441 throw new IllegalArgumentException ("Cannot pass null to FileUtil.isArchiveFile"); } 1443 1444 if (!fo.isValid()) { 1445 return false; 1446 } 1447 if (fo.isVirtual()) { 1450 String path = fo.getPath(); 1451 int index = path.lastIndexOf('.'); 1452 1453 return (index != -1) && (index > path.lastIndexOf('/') + 1); 1454 } 1455 1456 if (fo.isFolder()) { 1457 return false; 1458 } 1459 1460 Boolean b = archiveFileCache.get(fo); 1462 1463 if (b == null) { 1464 try { 1466 InputStream in = fo.getInputStream(); 1467 1468 try { 1469 byte[] buffer = new byte[4]; 1470 int len = in.read(buffer, 0, 4); 1471 1472 if (len == 4) { 1473 b = Boolean.valueOf(Arrays.equals(ZIP_HEADER_1, buffer) || Arrays.equals(ZIP_HEADER_2, buffer)); 1475 } else { 1476 return false; 1481 } 1482 } finally { 1483 in.close(); 1484 } 1485 } catch (IOException ioe) { 1486 Logger.getLogger(FileUtil.class.getName()).log(Level.INFO, null, ioe); 1487 } 1488 1489 if (b == null) { 1490 String path = fo.getPath(); 1491 int index = path.lastIndexOf('.'); 1492 b = ((index != -1) && (index > path.lastIndexOf('/') + 1)) ? Boolean.TRUE : Boolean.FALSE; 1493 } 1494 1495 archiveFileCache.put(fo, b); 1496 } 1497 1498 return b.booleanValue(); 1499 } 1500 1501 1509 public static boolean isArchiveFile(URL url) { 1510 if (url == null) { 1511 throw new NullPointerException ("Cannot pass null URL to FileUtil.isArchiveFile"); } 1513 1514 if ("jar".equals(url.getProtocol())) { 1516 return false; 1518 } 1519 1520 FileObject fo = URLMapper.findFileObject(url); 1521 1522 if ((fo != null) && !fo.isVirtual()) { 1523 return isArchiveFile(fo); 1524 } else { 1525 String urlPath = url.getPath(); 1526 int index = urlPath.lastIndexOf('.'); 1527 1528 return (index != -1) && (index > urlPath.lastIndexOf('/') + 1); 1529 } 1530 } 1531 1532 1541 public static void preventFileChooserSymlinkTraversal(JFileChooser chooser, File currentDirectory) { 1542 if (!(Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2))) { 1543 chooser.setCurrentDirectory(wrapFileNoCanonicalize(currentDirectory)); 1544 chooser.setFileSystemView(new NonCanonicalizingFileSystemView()); 1545 } else { 1546 chooser.setCurrentDirectory(currentDirectory); 1547 } 1548 } 1549 1550 static boolean assertDeprecatedMethod() { 1551 Thread.dumpStack(); 1552 1553 return true; 1554 } 1555 1556 private static File wrapFileNoCanonicalize(File f) { 1557 if (f instanceof NonCanonicalizingFile) { 1558 return f; 1559 } else if (f != null) { 1560 return new NonCanonicalizingFile(f); 1561 } else { 1562 return null; 1563 } 1564 } 1565 1566 private static File [] wrapFilesNoCanonicalize(File [] fs) { 1567 if (fs != null) { 1568 for (int i = 0; i < fs.length; i++) { 1569 fs[i] = wrapFileNoCanonicalize(fs[i]); 1570 } 1571 } 1572 1573 return fs; 1574 } 1575 1576 private static final class NonCanonicalizingFile extends File { 1577 public NonCanonicalizingFile(File orig) { 1578 this(orig.getPath()); 1579 } 1580 1581 private NonCanonicalizingFile(String path) { 1582 super(path); 1583 } 1584 1585 private NonCanonicalizingFile(URI uri) { 1586 super(uri); 1587 } 1588 1589 public File getCanonicalFile() throws IOException { 1590 return wrapFileNoCanonicalize(normalizeFile(super.getAbsoluteFile())); 1591 } 1592 1593 public String getCanonicalPath() throws IOException { 1594 return normalizeFile(super.getAbsoluteFile()).getAbsolutePath(); 1595 } 1596 1597 public File getParentFile() { 1598 return wrapFileNoCanonicalize(super.getParentFile()); 1599 } 1600 1601 public File getAbsoluteFile() { 1602 return wrapFileNoCanonicalize(super.getAbsoluteFile()); 1603 } 1604 1605 public File [] listFiles() { 1606 return wrapFilesNoCanonicalize(super.listFiles()); 1607 } 1608 1609 public File [] listFiles(FileFilter filter) { 1610 return wrapFilesNoCanonicalize(super.listFiles(filter)); 1611 } 1612 1613 public File [] listFiles(FilenameFilter filter) { 1614 return wrapFilesNoCanonicalize(super.listFiles(filter)); 1615 } 1616 } 1617 1618 private static final class NonCanonicalizingFileSystemView extends FileSystemView { 1619 private final FileSystemView delegate = FileSystemView.getFileSystemView(); 1620 1621 public NonCanonicalizingFileSystemView() { 1622 } 1623 1624 public boolean isFloppyDrive(File dir) { 1625 return delegate.isFloppyDrive(dir); 1626 } 1627 1628 public boolean isComputerNode(File dir) { 1629 return delegate.isComputerNode(dir); 1630 } 1631 1632 public File createNewFolder(File containingDir) 1633 throws IOException { 1634 return wrapFileNoCanonicalize(delegate.createNewFolder(containingDir)); 1635 } 1636 1637 public boolean isDrive(File dir) { 1638 return delegate.isDrive(dir); 1639 } 1640 1641 public boolean isFileSystemRoot(File dir) { 1642 return delegate.isFileSystemRoot(dir); 1643 } 1644 1645 public File getHomeDirectory() { 1646 return wrapFileNoCanonicalize(delegate.getHomeDirectory()); 1647 } 1648 1649 public File createFileObject(File dir, String filename) { 1650 return wrapFileNoCanonicalize(delegate.createFileObject(dir, filename)); 1651 } 1652 1653 public Boolean isTraversable(File f) { 1654 return delegate.isTraversable(f); 1655 } 1656 1657 public boolean isFileSystem(File f) { 1658 return delegate.isFileSystem(f); 1659 } 1660 1661 1666 public File getChild(File parent, String fileName) { 1667 return wrapFileNoCanonicalize(delegate.getChild(parent, fileName)); 1668 } 1669 1670 public File getParentDirectory(File dir) { 1671 return wrapFileNoCanonicalize(delegate.getParentDirectory(dir)); 1672 } 1673 1674 public Icon getSystemIcon(File f) { 1675 return delegate.getSystemIcon(f); 1676 } 1677 1678 public boolean isParent(File folder, File file) { 1679 return delegate.isParent(folder, file); 1680 } 1681 1682 public String getSystemTypeDescription(File f) { 1683 return delegate.getSystemTypeDescription(f); 1684 } 1685 1686 public File getDefaultDirectory() { 1687 return wrapFileNoCanonicalize(delegate.getDefaultDirectory()); 1688 } 1689 1690 public String getSystemDisplayName(File f) { 1691 return delegate.getSystemDisplayName(f); 1692 } 1693 1694 public File [] getRoots() { 1695 return wrapFilesNoCanonicalize(delegate.getRoots()); 1696 } 1697 1698 public boolean isHiddenFile(File f) { 1699 return delegate.isHiddenFile(f); 1700 } 1701 1702 public File [] getFiles(File dir, boolean useFileHiding) { 1703 return wrapFilesNoCanonicalize(delegate.getFiles(dir, useFileHiding)); 1704 } 1705 1706 public boolean isRoot(File f) { 1707 return delegate.isRoot(f); 1708 } 1709 1710 public File createFileObject(String path) { 1711 return wrapFileNoCanonicalize(delegate.createFileObject(path)); 1712 } 1713 } 1714} 1715 | Popular Tags |