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