< prev index next >

src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java

Print this page




  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


 630      * @throws FileNotFoundException if the linked file does not exist
 631      * @throws NullPointerException if {@code file} equals {@code null}
 632      * @throws SecurityException if the caller does not have necessary
 633      *                           permissions
 634      * @since 9
 635      */
 636     public File getLinkLocation(File file) throws FileNotFoundException {
 637         if (file == null) {
 638             throw new NullPointerException("file is null");
 639         }
 640         ShellFolder shellFolder;
 641         try {
 642             shellFolder = ShellFolder.getShellFolder(file);
 643         } catch (FileNotFoundException e) {
 644             return null;
 645         }
 646         return shellFolder.isLink() ? shellFolder.getLinkLocation() : null;
 647     }
 648 
 649     /**






















































































 650      * Throws {@code FileNotFoundException} if file not found or current thread was interrupted
 651      */
 652     ShellFolder getShellFolder(File f) throws FileNotFoundException {
 653         if (!(f instanceof ShellFolder) && !(f instanceof FileSystemRoot) && isFileSystemRoot(f)) {
 654             f = createFileSystemRoot(f);
 655         }
 656 
 657         try {
 658             return ShellFolder.getShellFolder(f);
 659         } catch (InternalError e) {
 660             System.err.println("FileSystemView.getShellFolder: f="+f);
 661             e.printStackTrace();
 662             return null;
 663         }
 664     }
 665 
 666     /**
 667      * Creates a new <code>File</code> object for <code>f</code> with correct
 668      * behavior for a file system root directory.
 669      *


 741     public boolean isDrive(File dir) {
 742         return isFloppyDrive(dir);
 743     }
 744 
 745     public boolean isFloppyDrive(File dir) {
 746         // Could be looking at the path for Solaris, but wouldn't be reliable.
 747         // For example:
 748         // return (dir != null && dir.getAbsolutePath().toLowerCase().startsWith("/floppy"));
 749         return false;
 750     }
 751 
 752     public boolean isComputerNode(File dir) {
 753         if (dir != null) {
 754             String parent = dir.getParent();
 755             if (parent != null && parent.equals("/net")) {
 756                 return true;
 757             }
 758         }
 759         return false;
 760     }







 761 }
 762 
 763 
 764 /**
 765  * FileSystemView that handles some specific windows concepts.
 766  */
 767 class WindowsFileSystemView extends FileSystemView {
 768 
 769     private static final String newFolderString =
 770             UIManager.getString("FileChooser.win32.newFolder");
 771     private static final String newFolderNextString  =
 772             UIManager.getString("FileChooser.win32.newFolder.subsequent");
 773 
 774     public Boolean isTraversable(File f) {
 775         return Boolean.valueOf(isFileSystemRoot(f) || isComputerNode(f) || f.isDirectory());
 776     }
 777 
 778     public File getChild(File parent, String fileName) {
 779         if (fileName.startsWith("\\")
 780             && !fileName.startsWith("\\\\")


 855             public String run() {
 856                 return dir.getAbsolutePath();
 857             }
 858         });
 859 
 860         return path != null && (path.equals("A:\\") || path.equals("B:\\"));
 861     }
 862 
 863     /**
 864      * Returns a File object constructed from the given path string.
 865      */
 866     public File createFileObject(String path) {
 867         // Check for missing backslash after drive letter such as "C:" or "C:filename"
 868         if (path.length() >= 2 && path.charAt(1) == ':' && Character.isLetter(path.charAt(0))) {
 869             if (path.length() == 2) {
 870                 path += "\\";
 871             } else if (path.charAt(2) != '\\') {
 872                 path = path.substring(0, 2) + "\\" + path.substring(2);
 873             }
 874         }
 875         return super.createFileObject(path);







































 876     }
 877 
 878     @SuppressWarnings("serial") // anonymous class
 879     protected File createFileSystemRoot(File f) {
 880         // Problem: Removable drives on Windows return false on f.exists()
 881         // Workaround: Override exists() to always return true.
 882         return new FileSystemRoot(f) {
 883             public boolean exists() {
 884                 return true;
 885             }
 886         };
 887     }
 888 
 889 }
 890 
 891 /**
 892  * Fallthrough FileSystemView in case we can't determine the OS.
 893  */
 894 class GenericFileSystemView extends FileSystemView {
 895 


 897             UIManager.getString("FileChooser.other.newFolder");
 898 
 899     /**
 900      * Creates a new folder with a default folder name.
 901      */
 902     public File createNewFolder(File containingDir) throws IOException {
 903         if(containingDir == null) {
 904             throw new IOException("Containing directory is null:");
 905         }
 906         // Using NT's default folder name
 907         File newFolder = createFileObject(containingDir, newFolderString);
 908 
 909         if(newFolder.exists()) {
 910             throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
 911         } else {
 912             if(!newFolder.mkdirs()) {
 913                 throw new IOException(newFolder.getAbsolutePath());
 914             }
 915         }
 916         return newFolder;







 917     }
 918 
 919 }


  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.beans.BeanProperty;
  33 import java.beans.JavaBean;
  34 import java.io.File;
  35 import java.io.FileNotFoundException;
  36 import java.io.IOException;
  37 import java.text.MessageFormat;
  38 import java.util.List;
  39 import java.util.ArrayList;
  40 import java.lang.ref.WeakReference;
  41 import java.beans.PropertyChangeListener;
  42 import java.beans.PropertyChangeEvent;
  43 import java.beans.PropertyChangeSupport;
  44 import java.security.AccessController;
  45 import java.security.PrivilegedAction;
  46 import java.util.Arrays;
  47 import java.util.Collections;
  48 import java.util.Objects;
  49 import sun.awt.OSInfo;
  50 
  51 import sun.awt.shell.*;
  52 
  53 /**
  54  * FileSystemView is JFileChooser's gateway to the
  55  * file system. Since the JDK1.1 File API doesn't allow
  56  * access to such information as root partitions, file type
  57  * information, or hidden file bits, this class is designed
  58  * to intuit as much OS-specific file system information as
  59  * possible.
  60  *
  61  * <p>
  62  *
  63  * Java Licensees may want to provide a different implementation of
  64  * FileSystemView to better handle a given operating system.
  65  *
  66  * @author Jeff Dinkins
  67  */
  68 
  69 // PENDING(jeff) - need to provide a specification for


 637      * @throws FileNotFoundException if the linked file does not exist
 638      * @throws NullPointerException if {@code file} equals {@code null}
 639      * @throws SecurityException if the caller does not have necessary
 640      *                           permissions
 641      * @since 9
 642      */
 643     public File getLinkLocation(File file) throws FileNotFoundException {
 644         if (file == null) {
 645             throw new NullPointerException("file is null");
 646         }
 647         ShellFolder shellFolder;
 648         try {
 649             shellFolder = ShellFolder.getShellFolder(file);
 650         } catch (FileNotFoundException e) {
 651             return null;
 652         }
 653         return shellFolder.isLink() ? shellFolder.getLinkLocation() : null;
 654     }
 655 
 656     /**
 657      * A group of essential folder that are intented to appear in a left pane of 
 658      * a file chooser. 
 659      */
 660     @JavaBean(description = "A group of essential folder that are intented to "
 661             + "appear in a left pane of a file chooser. ")
 662     public static class EssentialFolderSection {
 663         
 664         public static final String FOLDERS_PROPERTY = "folders";
 665         
 666         private final PropertyChangeSupport propertyChangeSupport = 
 667                 new PropertyChangeSupport(this);
 668         
 669         private List<File> folders = Collections.emptyList();
 670 
 671         /**
 672          * Creates a new {@code EssentialFolderSection} with no folders. 
 673          */
 674         public EssentialFolderSection() {
 675         }
 676         
 677         /**
 678          * Creates a new {@code EssentialFolderSection} with the specified 
 679          * folders. 
 680          * 
 681          * @param folders 
 682          */
 683         public EssentialFolderSection(File... folders) {
 684             setFolders(Arrays.asList(folders));
 685         }
 686 
 687         
 688         /**
 689          * Gets a list of the essential folders in this section. 
 690          *
 691          * @return the value of folders
 692          */
 693         @SuppressWarnings("ReturnOfCollectionOrArrayField") // already an unmodifiableList or emptyList
 694         public List<File> getFolders() {
 695             return folders;
 696         }
 697 
 698         /**
 699          * Updates the list of the essential folders in this section to the specified list. 
 700          * 
 701          * @param folders 
 702          * @throws NullPointerException if the argument is null
 703          */
 704         @BeanProperty(description = "The folders that are in ", bound = true, visualUpdate =true)
 705         public void setFolders(List<File> folders) {
 706             Objects.requireNonNull(folders);
 707             folders = Collections.unmodifiableList(new ArrayList<>(folders));
 708             
 709             List<File> oldFolders = this.folders;
 710             this.folders = folders;
 711             propertyChangeSupport.firePropertyChange(FOLDERS_PROPERTY, oldFolders, folders);
 712         }
 713 
 714         /**
 715          * Adds a PropertyChangeListener to the listener list. Currently the 
 716          * listener will be fired only when the 
 717          * {@link #setFolders(java.util.List) folders} property is changed, 
 718          * but in the future more properties will be added. 
 719          * @param listener the PropertyChangeListener to be added
 720          */
 721         public void addPropertyChangeListener(PropertyChangeListener listener) {
 722             propertyChangeSupport.addPropertyChangeListener(listener);
 723         }
 724 
 725         /** 
 726          * Removes a PropertyChangeListener from the listener list. If listener is null, 
 727          * or was never added, no exception is thrown and no action is taken.
 728          * 
 729          * @param listener the PropertyChangeListener to be removed (registered using
 730          *                 {@link #addPropertyChangeListener(java.beans.PropertyChangeListener)})
 731          */
 732         public void removePropertyChangeListener(PropertyChangeListener listener) {
 733             propertyChangeSupport.removePropertyChangeListener(listener);
 734         }
 735 
 736     }
 737     
 738     public EssentialFolderSection[] getEssentialFolders() {
 739         return FileSystemView.getFileSystemView().getEssentialFolders();
 740     }
 741     
 742     /**
 743      * Throws {@code FileNotFoundException} if file not found or current thread was interrupted
 744      */
 745     ShellFolder getShellFolder(File f) throws FileNotFoundException {
 746         if (!(f instanceof ShellFolder) && !(f instanceof FileSystemRoot) && isFileSystemRoot(f)) {
 747             f = createFileSystemRoot(f);
 748         }
 749 
 750         try {
 751             return ShellFolder.getShellFolder(f);
 752         } catch (InternalError e) {
 753             System.err.println("FileSystemView.getShellFolder: f="+f);
 754             e.printStackTrace();
 755             return null;
 756         }
 757     }
 758 
 759     /**
 760      * Creates a new <code>File</code> object for <code>f</code> with correct
 761      * behavior for a file system root directory.
 762      *


 834     public boolean isDrive(File dir) {
 835         return isFloppyDrive(dir);
 836     }
 837 
 838     public boolean isFloppyDrive(File dir) {
 839         // Could be looking at the path for Solaris, but wouldn't be reliable.
 840         // For example:
 841         // return (dir != null && dir.getAbsolutePath().toLowerCase().startsWith("/floppy"));
 842         return false;
 843     }
 844 
 845     public boolean isComputerNode(File dir) {
 846         if (dir != null) {
 847             String parent = dir.getParent();
 848             if (parent != null && parent.equals("/net")) {
 849                 return true;
 850             }
 851         }
 852         return false;
 853     } 
 854 
 855     @Override
 856     public EssentialFolderSection[] getEssentialFolders() {
 857         return new EssentialFolderSection[]{
 858             new EssentialFolderSection(getChooserComboBoxFiles())
 859         };
 860     }
 861 }
 862 
 863 
 864 /**
 865  * FileSystemView that handles some specific windows concepts.
 866  */
 867 class WindowsFileSystemView extends FileSystemView {
 868 
 869     private static final String newFolderString =
 870             UIManager.getString("FileChooser.win32.newFolder");
 871     private static final String newFolderNextString  =
 872             UIManager.getString("FileChooser.win32.newFolder.subsequent");
 873 
 874     public Boolean isTraversable(File f) {
 875         return Boolean.valueOf(isFileSystemRoot(f) || isComputerNode(f) || f.isDirectory());
 876     }
 877 
 878     public File getChild(File parent, String fileName) {
 879         if (fileName.startsWith("\\")
 880             && !fileName.startsWith("\\\\")


 955             public String run() {
 956                 return dir.getAbsolutePath();
 957             }
 958         });
 959 
 960         return path != null && (path.equals("A:\\") || path.equals("B:\\"));
 961     }
 962 
 963     /**
 964      * Returns a File object constructed from the given path string.
 965      */
 966     public File createFileObject(String path) {
 967         // Check for missing backslash after drive letter such as "C:" or "C:filename"
 968         if (path.length() >= 2 && path.charAt(1) == ':' && Character.isLetter(path.charAt(0))) {
 969             if (path.length() == 2) {
 970                 path += "\\";
 971             } else if (path.charAt(2) != '\\') {
 972                 path = path.substring(0, 2) + "\\" + path.substring(2);
 973             }
 974         }
 975         return (File) ShellFolder.get("parseDisplayName " + path);
 976     }
 977 
 978     private static final String CLSID_NETWORK = "{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}";
 979     private static final String CLSID_COMPUTER = "{20d04fe0-3aea-1069-a2d8-08002b30309d}";
 980     private static final String CLSID_HOMEGROUP = "{67CA7650-96E6-4FDD-BB43-A8E774F73A57}";
 981     private static final String CLSID_FAVORITES = "{323CA680-C24D-4099-B94D-446DD2D7249E}";
 982     private static final String CLSID_LIBRARIES = "{031E4825-7B94-4dc3-B131-E946B44C8DD5}";
 983     private static final String CLSID_QUICK_ACCESS = "{679f85cb-0220-4080-b29b-5540cc05aab6}";
 984     private static final String CLSID_HOMEGROUP_WIN10 = "{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}";
 985     
 986     private static final EssentialFolderSection[] ESSENTIAL_FOLDERS = createEssentialFolders();
 987     
 988     private static EssentialFolderSection[] createEssentialFolders() {
 989         List<File> folders = new ArrayList<>();
 990         if (OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_7) <= 0) {
 991             folders.add((File) ShellFolder.get(CLSID_FAVORITES));
 992             folders.add((File) ShellFolder.get(CLSID_LIBRARIES));
 993             folders.add((File) ShellFolder.get(CLSID_HOMEGROUP));
 994             folders.add((File) ShellFolder.get(CLSID_COMPUTER));
 995             folders.add((File) ShellFolder.get(CLSID_NETWORK));
 996         } else {
 997             folders.add((File) ShellFolder.get(CLSID_QUICK_ACCESS));
 998             folders.add((File) ShellFolder.get(CLSID_COMPUTER));
 999             folders.add((File) ShellFolder.get(CLSID_NETWORK));
1000 
1001             // for some unknown reason, adding both Quick Access and Home Group 
1002             // on Windows 10 results in all folders in the FilePane (!) with 
1003             // default icon switched their icon to a green person icon. 
1004         }
1005 
1006         return new EssentialFolderSection[]{
1007           new EssentialFolderSection(folders.toArray(new File[0]))
1008         };
1009     }
1010     
1011     
1012     @Override
1013     public EssentialFolderSection[] getEssentialFolders() {
1014         return Arrays.copyOf(ESSENTIAL_FOLDERS, ESSENTIAL_FOLDERS.length);
1015     }
1016     
1017     @SuppressWarnings("serial") // anonymous class
1018     protected File createFileSystemRoot(File f) {
1019         // Problem: Removable drives on Windows return false on f.exists()
1020         // Workaround: Override exists() to always return true.
1021         return new FileSystemRoot(f) {
1022             public boolean exists() {
1023                 return true;
1024             }
1025         };
1026     }
1027 
1028 }
1029 
1030 /**
1031  * Fallthrough FileSystemView in case we can't determine the OS.
1032  */
1033 class GenericFileSystemView extends FileSystemView {
1034 


1036             UIManager.getString("FileChooser.other.newFolder");
1037 
1038     /**
1039      * Creates a new folder with a default folder name.
1040      */
1041     public File createNewFolder(File containingDir) throws IOException {
1042         if(containingDir == null) {
1043             throw new IOException("Containing directory is null:");
1044         }
1045         // Using NT's default folder name
1046         File newFolder = createFileObject(containingDir, newFolderString);
1047 
1048         if(newFolder.exists()) {
1049             throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
1050         } else {
1051             if(!newFolder.mkdirs()) {
1052                 throw new IOException(newFolder.getAbsolutePath());
1053             }
1054         }
1055         return newFolder;
1056     }
1057 
1058     @Override
1059     public EssentialFolderSection[] getEssentialFolders() {
1060         return new EssentialFolderSection[]{
1061             new EssentialFolderSection(getChooserComboBoxFiles())
1062         };
1063     }
1064 
1065 }
< prev index next >