1 /* 2 * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.filechooser; 27 28 29 import javax.swing.*; 30 31 import java.awt.Image; 32 import java.io.File; 33 import java.io.FileNotFoundException; 34 import java.io.IOException; 35 import java.text.MessageFormat; 36 import java.util.List; 37 import java.util.ArrayList; 38 import java.lang.ref.WeakReference; 39 import java.beans.PropertyChangeListener; 40 import java.beans.PropertyChangeEvent; 41 import java.security.AccessController; 42 import java.security.PrivilegedAction; 43 44 import sun.awt.shell.*; 45 46 /** 47 * FileSystemView is JFileChooser's gateway to the 48 * file system. Since the JDK1.1 File API doesn't allow 49 * access to such information as root partitions, file type 50 * information, or hidden file bits, this class is designed 51 * to intuit as much OS-specific file system information as 52 * possible. 53 * 54 * <p> 55 * 56 * Java Licensees may want to provide a different implementation of 57 * FileSystemView to better handle a given operating system. 58 * 59 * @author Jeff Dinkins 60 */ 61 62 // PENDING(jeff) - need to provide a specification for 63 // how Mac/OS2/BeOS/etc file systems can modify FileSystemView 64 // to handle their particular type of file system. 65 66 public abstract class FileSystemView { 67 68 static FileSystemView windowsFileSystemView = null; 69 static FileSystemView unixFileSystemView = null; 70 //static FileSystemView macFileSystemView = null; 71 static FileSystemView genericFileSystemView = null; 72 73 private boolean useSystemExtensionHiding = 74 UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding"); 75 76 /** 77 * Returns the file system view. 78 * @return the file system view 79 */ 80 public static FileSystemView getFileSystemView() { 81 if(File.separatorChar == '\\') { 82 if(windowsFileSystemView == null) { 83 windowsFileSystemView = new WindowsFileSystemView(); 84 } 85 return windowsFileSystemView; 86 } 87 88 if(File.separatorChar == '/') { 89 if(unixFileSystemView == null) { 90 unixFileSystemView = new UnixFileSystemView(); 91 } 92 return unixFileSystemView; 93 } 94 95 // if(File.separatorChar == ':') { 96 // if(macFileSystemView == null) { 97 // macFileSystemView = new MacFileSystemView(); 98 // } 99 // return macFileSystemView; 100 //} 101 102 if(genericFileSystemView == null) { 103 genericFileSystemView = new GenericFileSystemView(); 104 } 105 return genericFileSystemView; 106 } 107 108 /** 109 * Constructs a FileSystemView. 110 */ 111 public FileSystemView() { 112 final WeakReference<FileSystemView> weakReference = new WeakReference<FileSystemView>(this); 113 114 UIManager.addPropertyChangeListener(new PropertyChangeListener() { 115 public void propertyChange(PropertyChangeEvent evt) { 116 FileSystemView fileSystemView = weakReference.get(); 117 118 if (fileSystemView == null) { 119 // FileSystemView was destroyed 120 UIManager.removePropertyChangeListener(this); 121 } else { 122 if (evt.getPropertyName().equals("lookAndFeel")) { 123 fileSystemView.useSystemExtensionHiding = 124 UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding"); 125 } 126 } 127 } 128 }); 129 } 130 131 /** 132 * Determines if the given file is a root in the navigable tree(s). 133 * Examples: Windows 98 has one root, the Desktop folder. DOS has one root 134 * per drive letter, {@code C:\}, {@code D:\}, etc. Unix has one root, 135 * the {@code "/"} directory. 136 * 137 * The default implementation gets information from the {@code ShellFolder} class. 138 * 139 * @param f a {@code File} object representing a directory 140 * @return {@code true} if {@code f} is a root in the navigable tree. 141 * @see #isFileSystemRoot 142 */ 143 public boolean isRoot(File f) { 144 if (f == null || !f.isAbsolute()) { 145 return false; 146 } 147 148 File[] roots = getRoots(); 149 for (File root : roots) { 150 if (root.equals(f)) { 151 return true; 152 } 153 } 154 return false; 155 } 156 157 /** 158 * Returns true if the file (directory) can be visited. 159 * Returns false if the directory cannot be traversed. 160 * 161 * @param f the {@code File} 162 * @return {@code true} if the file/directory can be traversed, otherwise {@code false} 163 * @see JFileChooser#isTraversable 164 * @see FileView#isTraversable 165 * @since 1.4 166 */ 167 public Boolean isTraversable(File f) { 168 return Boolean.valueOf(f.isDirectory()); 169 } 170 171 /** 172 * Name of a file, directory, or folder as it would be displayed in 173 * a system file browser. Example from Windows: the "M:\" directory 174 * displays as "CD-ROM (M:)" 175 * 176 * The default implementation gets information from the ShellFolder class. 177 * 178 * @param f a {@code File} object 179 * @return the file name as it would be displayed by a native file chooser 180 * @see JFileChooser#getName 181 * @since 1.4 182 */ 183 public String getSystemDisplayName(File f) { 184 if (f == null) { 185 return null; 186 } 187 188 String name = f.getName(); 189 190 if (!name.equals("..") && !name.equals(".") && 191 (useSystemExtensionHiding || !isFileSystem(f) || isFileSystemRoot(f)) && 192 (f instanceof ShellFolder || f.exists())) { 193 194 try { 195 name = getShellFolder(f).getDisplayName(); 196 } catch (FileNotFoundException e) { 197 return null; 198 } 199 200 if (name == null || name.length() == 0) { 201 name = f.getPath(); // e.g. "/" 202 } 203 } 204 205 return name; 206 } 207 208 /** 209 * Type description for a file, directory, or folder as it would be displayed in 210 * a system file browser. Example from Windows: the "Desktop" folder 211 * is described as "Desktop". 212 * 213 * Override for platforms with native ShellFolder implementations. 214 * 215 * @param f a {@code File} object 216 * @return the file type description as it would be displayed by a native file chooser 217 * or null if no native information is available. 218 * @see JFileChooser#getTypeDescription 219 * @since 1.4 220 */ 221 public String getSystemTypeDescription(File f) { 222 return null; 223 } 224 225 /** 226 * Icon for a file, directory, or folder as it would be displayed in 227 * a system file browser. Example from Windows: the "M:\" directory 228 * displays a CD-ROM icon. 229 * 230 * The default implementation gets information from the ShellFolder class. 231 * 232 * @param f a {@code File} object 233 * @return an icon as it would be displayed by a native file chooser 234 * @see JFileChooser#getIcon 235 * @since 1.4 236 */ 237 public Icon getSystemIcon(File f) { 238 if (f == null) { 239 return null; 240 } 241 242 ShellFolder sf; 243 244 try { 245 sf = getShellFolder(f); 246 } catch (FileNotFoundException e) { 247 return null; 248 } 249 250 Image img = sf.getIcon(false); 251 252 if (img != null) { 253 return new ImageIcon(img, sf.getFolderType()); 254 } else { 255 return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon"); 256 } 257 } 258 259 /** 260 * On Windows, a file can appear in multiple folders, other than its 261 * parent directory in the filesystem. Folder could for example be the 262 * "Desktop" folder which is not the same as file.getParentFile(). 263 * 264 * @param folder a {@code File} object representing a directory or special folder 265 * @param file a {@code File} object 266 * @return {@code true} if {@code folder} is a directory or special folder and contains {@code file}. 267 * @since 1.4 268 */ 269 public boolean isParent(File folder, File file) { 270 if (folder == null || file == null) { 271 return false; 272 } else if (folder instanceof ShellFolder) { 273 File parent = file.getParentFile(); 274 if (parent != null && parent.equals(folder)) { 275 return true; 276 } 277 File[] children = getFiles(folder, false); 278 for (File child : children) { 279 if (file.equals(child)) { 280 return true; 281 } 282 } 283 return false; 284 } else { 285 return folder.equals(file.getParentFile()); 286 } 287 } 288 289 /** 290 * 291 * @param parent a {@code File} object representing a directory or special folder 292 * @param fileName a name of a file or folder which exists in {@code parent} 293 * @return a File object. This is normally constructed with 294 * {@code new File(parent, fileName)} except when parent and child are both 295 * special folders, in which case the {@code File} is a wrapper containing 296 * a {@code ShellFolder} object. 297 * @since 1.4 298 */ 299 public File getChild(File parent, String fileName) { 300 if (parent instanceof ShellFolder) { 301 File[] children = getFiles(parent, false); 302 for (File child : children) { 303 if (child.getName().equals(fileName)) { 304 return child; 305 } 306 } 307 } 308 return createFileObject(parent, fileName); 309 } 310 311 312 /** 313 * Checks if {@code f} represents a real directory or file as opposed to a 314 * special folder such as {@code "Desktop"}. Used by UI classes to decide if 315 * a folder is selectable when doing directory choosing. 316 * 317 * @param f a {@code File} object 318 * @return {@code true} if {@code f} is a real file or directory. 319 * @since 1.4 320 */ 321 public boolean isFileSystem(File f) { 322 if (f instanceof ShellFolder) { 323 ShellFolder sf = (ShellFolder)f; 324 // Shortcuts to directories are treated as not being file system objects, 325 // so that they are never returned by JFileChooser. 326 return sf.isFileSystem() && !(sf.isLink() && sf.isDirectory()); 327 } else { 328 return true; 329 } 330 } 331 332 /** 333 * Creates a new folder with a default folder name. 334 * 335 * @param containingDir a {@code File} object denoting directory to contain the new folder 336 * @return a {@code File} object denoting the newly created folder 337 * @throws IOException if new folder could not be created 338 */ 339 public abstract File createNewFolder(File containingDir) throws IOException; 340 341 /** 342 * Returns whether a file is hidden or not. 343 * 344 * @param f a {@code File} object 345 * @return true if the given {@code File} denotes a hidden file 346 */ 347 public boolean isHiddenFile(File f) { 348 return f.isHidden(); 349 } 350 351 352 /** 353 * Is dir the root of a tree in the file system, such as a drive 354 * or partition. Example: Returns true for "C:\" on Windows 98. 355 * 356 * @param dir a {@code File} object representing a directory 357 * @return {@code true} if {@code f} is a root of a filesystem 358 * @see #isRoot 359 * @since 1.4 360 */ 361 public boolean isFileSystemRoot(File dir) { 362 return ShellFolder.isFileSystemRoot(dir); 363 } 364 365 /** 366 * Used by UI classes to decide whether to display a special icon 367 * for drives or partitions, e.g. a "hard disk" icon. 368 * 369 * The default implementation has no way of knowing, so always returns false. 370 * 371 * @param dir a directory 372 * @return {@code false} always 373 * @since 1.4 374 */ 375 public boolean isDrive(File dir) { 376 return false; 377 } 378 379 /** 380 * Used by UI classes to decide whether to display a special icon 381 * for a floppy disk. Implies isDrive(dir). 382 * 383 * The default implementation has no way of knowing, so always returns false. 384 * 385 * @param dir a directory 386 * @return {@code false} always 387 * @since 1.4 388 */ 389 public boolean isFloppyDrive(File dir) { 390 return false; 391 } 392 393 /** 394 * Used by UI classes to decide whether to display a special icon 395 * for a computer node, e.g. "My Computer" or a network server. 396 * 397 * The default implementation has no way of knowing, so always returns false. 398 * 399 * @param dir a directory 400 * @return {@code false} always 401 * @since 1.4 402 */ 403 public boolean isComputerNode(File dir) { 404 return ShellFolder.isComputerNode(dir); 405 } 406 407 408 /** 409 * Returns all root partitions on this system. For example, on 410 * Windows, this would be the "Desktop" folder, while on DOS this 411 * would be the A: through Z: drives. 412 * 413 * @return an array of {@code File} objects representing all root partitions 414 * on this system 415 */ 416 public File[] getRoots() { 417 // Don't cache this array, because filesystem might change 418 File[] roots = (File[])ShellFolder.get("roots"); 419 420 for (int i = 0; i < roots.length; i++) { 421 if (isFileSystemRoot(roots[i])) { 422 roots[i] = createFileSystemRoot(roots[i]); 423 } 424 } 425 return roots; 426 } 427 428 429 // Providing default implementations for the remaining methods 430 // because most OS file systems will likely be able to use this 431 // code. If a given OS can't, override these methods in its 432 // implementation. 433 434 /** 435 * Returns the home directory. 436 * @return the home directory 437 */ 438 public File getHomeDirectory() { 439 return createFileObject(System.getProperty("user.home")); 440 } 441 442 /** 443 * Return the user's default starting directory for the file chooser. 444 * 445 * @return a {@code File} object representing the default 446 * starting folder 447 * @since 1.4 448 */ 449 public File getDefaultDirectory() { 450 File f = (File)ShellFolder.get("fileChooserDefaultFolder"); 451 if (isFileSystemRoot(f)) { 452 f = createFileSystemRoot(f); 453 } 454 return f; 455 } 456 457 /** 458 * Returns a File object constructed in dir from the given filename. 459 * 460 * @param dir an abstract pathname denoting a directory 461 * @param filename a {@code String} representation of a pathname 462 * @return a {@code File} object created from {@code dir} and {@code filename} 463 */ 464 public File createFileObject(File dir, String filename) { 465 if(dir == null) { 466 return new File(filename); 467 } else { 468 return new File(dir, filename); 469 } 470 } 471 472 /** 473 * Returns a File object constructed from the given path string. 474 * 475 * @param path {@code String} representation of path 476 * @return a {@code File} object created from the given {@code path} 477 */ 478 public File createFileObject(String path) { 479 File f = new File(path); 480 if (isFileSystemRoot(f)) { 481 f = createFileSystemRoot(f); 482 } 483 return f; 484 } 485 486 487 /** 488 * Gets the list of shown (i.e. not hidden) files. 489 * 490 * @param dir the root directory of files to be returned 491 * @param useFileHiding determine if hidden files are returned 492 * @return an array of {@code File} objects representing files and 493 * directories in the given {@code dir}. It includes hidden 494 * files if {@code useFileHiding} is false. 495 */ 496 public File[] getFiles(File dir, boolean useFileHiding) { 497 List<File> files = new ArrayList<File>(); 498 499 // add all files in dir 500 if (!(dir instanceof ShellFolder)) { 501 try { 502 dir = getShellFolder(dir); 503 } catch (FileNotFoundException e) { 504 return new File[0]; 505 } 506 } 507 508 File[] names = ((ShellFolder) dir).listFiles(!useFileHiding); 509 510 if (names == null) { 511 return new File[0]; 512 } 513 514 for (File f : names) { 515 if (Thread.currentThread().isInterrupted()) { 516 break; 517 } 518 519 if (!(f instanceof ShellFolder)) { 520 if (isFileSystemRoot(f)) { 521 f = createFileSystemRoot(f); 522 } 523 try { 524 f = ShellFolder.getShellFolder(f); 525 } catch (FileNotFoundException e) { 526 // Not a valid file (wouldn't show in native file chooser) 527 // Example: C:\pagefile.sys 528 continue; 529 } catch (InternalError e) { 530 // Not a valid file (wouldn't show in native file chooser) 531 // Example C:\Winnt\Profiles\joe\history\History.IE5 532 continue; 533 } 534 } 535 if (!useFileHiding || !isHiddenFile(f)) { 536 files.add(f); 537 } 538 } 539 540 return files.toArray(new File[files.size()]); 541 } 542 543 544 545 /** 546 * Returns the parent directory of {@code dir}. 547 * @param dir the {@code File} being queried 548 * @return the parent directory of {@code dir}, or 549 * {@code null} if {@code dir} is {@code null} 550 */ 551 public File getParentDirectory(File dir) { 552 if (dir == null || !dir.exists()) { 553 return null; 554 } 555 556 ShellFolder sf; 557 558 try { 559 sf = getShellFolder(dir); 560 } catch (FileNotFoundException e) { 561 return null; 562 } 563 564 File psf = sf.getParentFile(); 565 566 if (psf == null) { 567 return null; 568 } 569 570 if (isFileSystem(psf)) { 571 File f = psf; 572 if (!f.exists()) { 573 // This could be a node under "Network Neighborhood". 574 File ppsf = psf.getParentFile(); 575 if (ppsf == null || !isFileSystem(ppsf)) { 576 // We're mostly after the exists() override for windows below. 577 f = createFileSystemRoot(f); 578 } 579 } 580 return f; 581 } else { 582 return psf; 583 } 584 } 585 586 /** 587 * Throws {@code FileNotFoundException} if file not found or current thread was interrupted 588 */ 589 ShellFolder getShellFolder(File f) throws FileNotFoundException { 590 if (!(f instanceof ShellFolder) && !(f instanceof FileSystemRoot) && isFileSystemRoot(f)) { 591 f = createFileSystemRoot(f); 592 } 593 594 try { 595 return ShellFolder.getShellFolder(f); 596 } catch (InternalError e) { 597 System.err.println("FileSystemView.getShellFolder: f="+f); 598 e.printStackTrace(); 599 return null; 600 } 601 } 602 603 /** 604 * Creates a new {@code File} object for {@code f} with correct 605 * behavior for a file system root directory. 606 * 607 * @param f a {@code File} object representing a file system root 608 * directory, for example "/" on Unix or "C:\" on Windows. 609 * @return a new {@code File} object 610 * @since 1.4 611 */ 612 protected File createFileSystemRoot(File f) { 613 return new FileSystemRoot(f); 614 } 615 616 @SuppressWarnings("serial") // Same-version serialization only 617 static class FileSystemRoot extends File { 618 public FileSystemRoot(File f) { 619 super(f,""); 620 } 621 622 public FileSystemRoot(String s) { 623 super(s); 624 } 625 626 public boolean isDirectory() { 627 return true; 628 } 629 630 public String getName() { 631 return getPath(); 632 } 633 } 634 } 635 636 /** 637 * FileSystemView that handles some specific unix-isms. 638 */ 639 class UnixFileSystemView extends FileSystemView { 640 641 private static final String newFolderString = 642 UIManager.getString("FileChooser.other.newFolder"); 643 private static final String newFolderNextString = 644 UIManager.getString("FileChooser.other.newFolder.subsequent"); 645 646 /** 647 * Creates a new folder with a default folder name. 648 */ 649 public File createNewFolder(File containingDir) throws IOException { 650 if(containingDir == null) { 651 throw new IOException("Containing directory is null:"); 652 } 653 File newFolder; 654 // Unix - using OpenWindows' default folder name. Can't find one for Motif/CDE. 655 newFolder = createFileObject(containingDir, newFolderString); 656 int i = 1; 657 while (newFolder.exists() && i < 100) { 658 newFolder = createFileObject(containingDir, MessageFormat.format( 659 newFolderNextString, i)); 660 i++; 661 } 662 663 if(newFolder.exists()) { 664 throw new IOException("Directory already exists:" + newFolder.getAbsolutePath()); 665 } else { 666 newFolder.mkdirs(); 667 } 668 669 return newFolder; 670 } 671 672 public boolean isFileSystemRoot(File dir) { 673 return dir != null && dir.getAbsolutePath().equals("/"); 674 } 675 676 public boolean isDrive(File dir) { 677 return isFloppyDrive(dir); 678 } 679 680 public boolean isFloppyDrive(File dir) { 681 // Could be looking at the path for Solaris, but wouldn't be reliable. 682 // For example: 683 // return (dir != null && dir.getAbsolutePath().toLowerCase().startsWith("/floppy")); 684 return false; 685 } 686 687 public boolean isComputerNode(File dir) { 688 if (dir != null) { 689 String parent = dir.getParent(); 690 if (parent != null && parent.equals("/net")) { 691 return true; 692 } 693 } 694 return false; 695 } 696 } 697 698 699 /** 700 * FileSystemView that handles some specific windows concepts. 701 */ 702 class WindowsFileSystemView extends FileSystemView { 703 704 private static final String newFolderString = 705 UIManager.getString("FileChooser.win32.newFolder"); 706 private static final String newFolderNextString = 707 UIManager.getString("FileChooser.win32.newFolder.subsequent"); 708 709 public Boolean isTraversable(File f) { 710 return Boolean.valueOf(isFileSystemRoot(f) || isComputerNode(f) || f.isDirectory()); 711 } 712 713 public File getChild(File parent, String fileName) { 714 if (fileName.startsWith("\\") 715 && !fileName.startsWith("\\\\") 716 && isFileSystem(parent)) { 717 718 //Path is relative to the root of parent's drive 719 String path = parent.getAbsolutePath(); 720 if (path.length() >= 2 721 && path.charAt(1) == ':' 722 && Character.isLetter(path.charAt(0))) { 723 724 return createFileObject(path.substring(0, 2) + fileName); 725 } 726 } 727 return super.getChild(parent, fileName); 728 } 729 730 /** 731 * Type description for a file, directory, or folder as it would be displayed in 732 * a system file browser. Example from Windows: the "Desktop" folder 733 * is described as "Desktop". 734 * 735 * The Windows implementation gets information from the ShellFolder class. 736 */ 737 public String getSystemTypeDescription(File f) { 738 if (f == null) { 739 return null; 740 } 741 742 try { 743 return getShellFolder(f).getFolderType(); 744 } catch (FileNotFoundException e) { 745 return null; 746 } 747 } 748 749 /** 750 * @return the Desktop folder. 751 */ 752 public File getHomeDirectory() { 753 File[] roots = getRoots(); 754 return (roots.length == 0) ? null : roots[0]; 755 } 756 757 /** 758 * Creates a new folder with a default folder name. 759 */ 760 public File createNewFolder(File containingDir) throws IOException { 761 if(containingDir == null) { 762 throw new IOException("Containing directory is null:"); 763 } 764 // Using NT's default folder name 765 File newFolder = createFileObject(containingDir, newFolderString); 766 int i = 2; 767 while (newFolder.exists() && i < 100) { 768 newFolder = createFileObject(containingDir, MessageFormat.format( 769 newFolderNextString, i)); 770 i++; 771 } 772 773 if(newFolder.exists()) { 774 throw new IOException("Directory already exists:" + newFolder.getAbsolutePath()); 775 } else { 776 newFolder.mkdirs(); 777 } 778 779 return newFolder; 780 } 781 782 public boolean isDrive(File dir) { 783 return isFileSystemRoot(dir); 784 } 785 786 public boolean isFloppyDrive(final File dir) { 787 String path = AccessController.doPrivileged(new PrivilegedAction<String>() { 788 public String run() { 789 return dir.getAbsolutePath(); 790 } 791 }); 792 793 return path != null && (path.equals("A:\\") || path.equals("B:\\")); 794 } 795 796 /** 797 * Returns a File object constructed from the given path string. 798 */ 799 public File createFileObject(String path) { 800 // Check for missing backslash after drive letter such as "C:" or "C:filename" 801 if (path.length() >= 2 && path.charAt(1) == ':' && Character.isLetter(path.charAt(0))) { 802 if (path.length() == 2) { 803 path += "\\"; 804 } else if (path.charAt(2) != '\\') { 805 path = path.substring(0, 2) + "\\" + path.substring(2); 806 } 807 } 808 return super.createFileObject(path); 809 } 810 811 @SuppressWarnings("serial") // anonymous class 812 protected File createFileSystemRoot(File f) { 813 // Problem: Removable drives on Windows return false on f.exists() 814 // Workaround: Override exists() to always return true. 815 return new FileSystemRoot(f) { 816 public boolean exists() { 817 return true; 818 } 819 }; 820 } 821 822 } 823 824 /** 825 * Fallthrough FileSystemView in case we can't determine the OS. 826 */ 827 class GenericFileSystemView extends FileSystemView { 828 829 private static final String newFolderString = 830 UIManager.getString("FileChooser.other.newFolder"); 831 832 /** 833 * Creates a new folder with a default folder name. 834 */ 835 public File createNewFolder(File containingDir) throws IOException { 836 if(containingDir == null) { 837 throw new IOException("Containing directory is null:"); 838 } 839 // Using NT's default folder name 840 File newFolder = createFileObject(containingDir, newFolderString); 841 842 if(newFolder.exists()) { 843 throw new IOException("Directory already exists:" + newFolder.getAbsolutePath()); 844 } else { 845 newFolder.mkdirs(); 846 } 847 848 return newFolder; 849 } 850 851 } --- EOF ---