Home » openjdk-7 » sun » awt » shell » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2009, 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 sun.awt.shell;
   27   
   28   import javax.swing;
   29   import java.awt.Image;
   30   import java.awt.Toolkit;
   31   import java.io;
   32   import java.io.FileNotFoundException;
   33   import java.util;
   34   import java.util.concurrent.Callable;
   35   
   36   /**
   37    * @author Michael Martak
   38    * @since 1.4
   39    */
   40   
   41   public abstract class ShellFolder extends File {
   42       private static final String COLUMN_NAME = "FileChooser.fileNameHeaderText";
   43       private static final String COLUMN_SIZE = "FileChooser.fileSizeHeaderText";
   44       private static final String COLUMN_DATE = "FileChooser.fileDateHeaderText";
   45   
   46       protected ShellFolder parent;
   47   
   48       /**
   49        * Create a file system shell folder from a file
   50        */
   51       ShellFolder(ShellFolder parent, String pathname) {
   52           super((pathname != null) ? pathname : "ShellFolder");
   53           this.parent = parent;
   54       }
   55   
   56       /**
   57        * @return Whether this is a file system shell folder
   58        */
   59       public boolean isFileSystem() {
   60           return (!getPath().startsWith("ShellFolder"));
   61       }
   62   
   63       /**
   64        * This method must be implemented to make sure that no instances
   65        * of <code>ShellFolder</code> are ever serialized. If <code>isFileSystem()</code> returns
   66        * <code>true</code>, then the object should be representable with an instance of
   67        * <code>java.io.File</code> instead. If not, then the object is most likely
   68        * depending on some internal (native) state and cannot be serialized.
   69        *
   70        * @returns a <code>java.io.File</code> replacement object, or <code>null</code>
   71        * if no suitable replacement can be found.
   72        */
   73       protected abstract Object writeReplace() throws java.io.ObjectStreamException;
   74   
   75       /**
   76        * Returns the path for this object's parent,
   77        * or <code>null</code> if this object does not name a parent
   78        * folder.
   79        *
   80        * @return  the path as a String for this object's parent,
   81        * or <code>null</code> if this object does not name a parent
   82        * folder
   83        *
   84        * @see java.io.File#getParent()
   85        * @since 1.4
   86        */
   87       public String getParent() {
   88           if (parent == null && isFileSystem()) {
   89               return super.getParent();
   90           }
   91           if (parent != null) {
   92               return (parent.getPath());
   93           } else {
   94               return null;
   95           }
   96       }
   97   
   98       /**
   99        * Returns a File object representing this object's parent,
  100        * or <code>null</code> if this object does not name a parent
  101        * folder.
  102        *
  103        * @return  a File object representing this object's parent,
  104        * or <code>null</code> if this object does not name a parent
  105        * folder
  106        *
  107        * @see java.io.File#getParentFile()
  108        * @since 1.4
  109        */
  110       public File getParentFile() {
  111           if (parent != null) {
  112               return parent;
  113           } else if (isFileSystem()) {
  114               return super.getParentFile();
  115           } else {
  116               return null;
  117           }
  118       }
  119   
  120       public File[] listFiles() {
  121           return listFiles(true);
  122       }
  123   
  124       public File[] listFiles(boolean includeHiddenFiles) {
  125           File[] files = super.listFiles();
  126   
  127           if (!includeHiddenFiles) {
  128               Vector v = new Vector();
  129               int nameCount = (files == null) ? 0 : files.length;
  130               for (int i = 0; i < nameCount; i++) {
  131                   if (!files[i].isHidden()) {
  132                       v.addElement(files[i]);
  133                   }
  134               }
  135               files = (File[])v.toArray(new File[v.size()]);
  136           }
  137   
  138           return files;
  139       }
  140   
  141   
  142       /**
  143        * @return Whether this shell folder is a link
  144        */
  145       public abstract boolean isLink();
  146   
  147       /**
  148        * @return The shell folder linked to by this shell folder, or null
  149        * if this shell folder is not a link
  150        */
  151       public abstract ShellFolder getLinkLocation() throws FileNotFoundException;
  152   
  153       /**
  154        * @return The name used to display this shell folder
  155        */
  156       public abstract String getDisplayName();
  157   
  158       /**
  159        * @return The type of shell folder as a string
  160        */
  161       public abstract String getFolderType();
  162   
  163       /**
  164        * @return The executable type as a string
  165        */
  166       public abstract String getExecutableType();
  167   
  168       /**
  169        * Compares this ShellFolder with the specified ShellFolder for order.
  170        *
  171        * @see #compareTo(Object)
  172        */
  173       public int compareTo(File file2) {
  174           if (file2 == null || !(file2 instanceof ShellFolder)
  175               || ((file2 instanceof ShellFolder) && ((ShellFolder)file2).isFileSystem())) {
  176   
  177               if (isFileSystem()) {
  178                   return super.compareTo(file2);
  179               } else {
  180                   return -1;
  181               }
  182           } else {
  183               if (isFileSystem()) {
  184                   return 1;
  185               } else {
  186                   return getName().compareTo(file2.getName());
  187               }
  188           }
  189       }
  190   
  191       /**
  192        * @param getLargeIcon whether to return large icon (ignored in base implementation)
  193        * @return The icon used to display this shell folder
  194        */
  195       public Image getIcon(boolean getLargeIcon) {
  196           return null;
  197       }
  198   
  199   
  200       // Static
  201   
  202       private static ShellFolderManager shellFolderManager;
  203   
  204       private static Invoker invoker;
  205   
  206       static {
  207           String managerClassName = (String)Toolkit.getDefaultToolkit().
  208                                         getDesktopProperty("Shell.shellFolderManager");
  209           Class managerClass = null;
  210           try {
  211               managerClass = Class.forName(managerClassName);
  212           // swallow the exceptions below and use default shell folder
  213           } catch(ClassNotFoundException e) {
  214           } catch(NullPointerException e) {
  215           }
  216   
  217           if (managerClass == null) {
  218               managerClass = ShellFolderManager.class;
  219           }
  220           try {
  221               shellFolderManager =
  222                   (ShellFolderManager)managerClass.newInstance();
  223           } catch (InstantiationException e) {
  224               throw new Error("Could not instantiate Shell Folder Manager: "
  225               + managerClass.getName());
  226           } catch (IllegalAccessException e) {
  227               throw new Error ("Could not access Shell Folder Manager: "
  228               + managerClass.getName());
  229           }
  230   
  231           invoker = shellFolderManager.createInvoker();
  232       }
  233   
  234       /**
  235        * Return a shell folder from a file object
  236        * @exception FileNotFoundException if file does not exist
  237        */
  238       public static ShellFolder getShellFolder(File file) throws FileNotFoundException {
  239           if (file instanceof ShellFolder) {
  240               return (ShellFolder)file;
  241           }
  242           if (!file.exists()) {
  243               throw new FileNotFoundException();
  244           }
  245           return shellFolderManager.createShellFolder(file);
  246       }
  247   
  248       /**
  249        * @param key a <code>String</code>
  250        * @return An Object matching the string <code>key</code>.
  251        * @see ShellFolderManager#get(String)
  252        */
  253       public static Object get(String key) {
  254           return shellFolderManager.get(key);
  255       }
  256   
  257       /**
  258        * Does <code>dir</code> represent a "computer" such as a node on the network, or
  259        * "My Computer" on the desktop.
  260        */
  261       public static boolean isComputerNode(File dir) {
  262           return shellFolderManager.isComputerNode(dir);
  263       }
  264   
  265       /**
  266        * @return Whether this is a file system root directory
  267        */
  268       public static boolean isFileSystemRoot(File dir) {
  269           return shellFolderManager.isFileSystemRoot(dir);
  270       }
  271   
  272       /**
  273        * Canonicalizes files that don't have symbolic links in their path.
  274        * Normalizes files that do, preserving symbolic links from being resolved.
  275        */
  276       public static File getNormalizedFile(File f) throws IOException {
  277           File canonical = f.getCanonicalFile();
  278           if (f.equals(canonical)) {
  279               // path of f doesn't contain symbolic links
  280               return canonical;
  281           }
  282   
  283           // preserve symbolic links from being resolved
  284           return new File(f.toURI().normalize());
  285       }
  286   
  287       // Override File methods
  288   
  289       public static void sort(final List<? extends File> files) {
  290           if (files == null || files.size() <= 1) {
  291               return;
  292           }
  293   
  294           // To avoid loads of synchronizations with Invoker and improve performance we
  295           // synchronize the whole code of the sort method once
  296           invoke(new Callable<Void>() {
  297               public Void call() {
  298                   // Check that we can use the ShellFolder.sortChildren() method:
  299                   //   1. All files have the same non-null parent
  300                   //   2. All files is ShellFolders
  301                   File commonParent = null;
  302   
  303                   for (File file : files) {
  304                       File parent = file.getParentFile();
  305   
  306                       if (parent == null || !(file instanceof ShellFolder)) {
  307                           commonParent = null;
  308   
  309                           break;
  310                       }
  311   
  312                       if (commonParent == null) {
  313                           commonParent = parent;
  314                       } else {
  315                           if (commonParent != parent && !commonParent.equals(parent)) {
  316                               commonParent = null;
  317   
  318                               break;
  319                           }
  320                       }
  321                   }
  322   
  323                   if (commonParent instanceof ShellFolder) {
  324                       ((ShellFolder) commonParent).sortChildren(files);
  325                   } else {
  326                       Collections.sort(files, FILE_COMPARATOR);
  327                   }
  328   
  329                   return null;
  330               }
  331           });
  332       }
  333   
  334       public void sortChildren(final List<? extends File> files) {
  335           // To avoid loads of synchronizations with Invoker and improve performance we
  336           // synchronize the whole code of the sort method once
  337           invoke(new Callable<Void>() {
  338               public Void call() {
  339                   Collections.sort(files, FILE_COMPARATOR);
  340   
  341                   return null;
  342               }
  343           });
  344       }
  345   
  346       public boolean isAbsolute() {
  347           return (!isFileSystem() || super.isAbsolute());
  348       }
  349   
  350       public File getAbsoluteFile() {
  351           return (isFileSystem() ? super.getAbsoluteFile() : this);
  352       }
  353   
  354       public boolean canRead() {
  355           return (isFileSystem() ? super.canRead() : true);       // ((Fix?))
  356       }
  357   
  358       /**
  359        * Returns true if folder allows creation of children.
  360        * True for the "Desktop" folder, but false for the "My Computer"
  361        * folder.
  362        */
  363       public boolean canWrite() {
  364           return (isFileSystem() ? super.canWrite() : false);     // ((Fix?))
  365       }
  366   
  367       public boolean exists() {
  368           // Assume top-level drives exist, because state is uncertain for
  369           // removable drives.
  370           return (!isFileSystem() || isFileSystemRoot(this) || super.exists()) ;
  371       }
  372   
  373       public boolean isDirectory() {
  374           return (isFileSystem() ? super.isDirectory() : true);   // ((Fix?))
  375       }
  376   
  377       public boolean isFile() {
  378           return (isFileSystem() ? super.isFile() : !isDirectory());      // ((Fix?))
  379       }
  380   
  381       public long lastModified() {
  382           return (isFileSystem() ? super.lastModified() : 0L);    // ((Fix?))
  383       }
  384   
  385       public long length() {
  386           return (isFileSystem() ? super.length() : 0L);  // ((Fix?))
  387       }
  388   
  389       public boolean createNewFile() throws IOException {
  390           return (isFileSystem() ? super.createNewFile() : false);
  391       }
  392   
  393       public boolean delete() {
  394           return (isFileSystem() ? super.delete() : false);       // ((Fix?))
  395       }
  396   
  397       public void deleteOnExit() {
  398           if (isFileSystem()) {
  399               super.deleteOnExit();
  400           } else {
  401               // Do nothing       // ((Fix?))
  402           }
  403       }
  404   
  405       public boolean mkdir() {
  406           return (isFileSystem() ? super.mkdir() : false);
  407       }
  408   
  409       public boolean mkdirs() {
  410           return (isFileSystem() ? super.mkdirs() : false);
  411       }
  412   
  413       public boolean renameTo(File dest) {
  414           return (isFileSystem() ? super.renameTo(dest) : false); // ((Fix?))
  415       }
  416   
  417       public boolean setLastModified(long time) {
  418           return (isFileSystem() ? super.setLastModified(time) : false); // ((Fix?))
  419       }
  420   
  421       public boolean setReadOnly() {
  422           return (isFileSystem() ? super.setReadOnly() : false); // ((Fix?))
  423       }
  424   
  425       public String toString() {
  426           return (isFileSystem() ? super.toString() : getDisplayName());
  427       }
  428   
  429       public static ShellFolderColumnInfo[] getFolderColumns(File dir) {
  430           ShellFolderColumnInfo[] columns = null;
  431   
  432           if (dir instanceof ShellFolder) {
  433               columns = ((ShellFolder) dir).getFolderColumns();
  434           }
  435   
  436           if (columns == null) {
  437               columns = new ShellFolderColumnInfo[]{
  438                       new ShellFolderColumnInfo(COLUMN_NAME, 150,
  439                               SwingConstants.LEADING, true, null,
  440                               FILE_COMPARATOR),
  441                       new ShellFolderColumnInfo(COLUMN_SIZE, 75,
  442                               SwingConstants.RIGHT, true, null,
  443                               DEFAULT_COMPARATOR, true),
  444                       new ShellFolderColumnInfo(COLUMN_DATE, 130,
  445                               SwingConstants.LEADING, true, null,
  446                               DEFAULT_COMPARATOR, true)
  447               };
  448           }
  449   
  450           return columns;
  451       }
  452   
  453       public ShellFolderColumnInfo[] getFolderColumns() {
  454           return null;
  455       }
  456   
  457       public static Object getFolderColumnValue(File file, int column) {
  458           if (file instanceof ShellFolder) {
  459               Object value = ((ShellFolder)file).getFolderColumnValue(column);
  460               if (value != null) {
  461                   return value;
  462               }
  463           }
  464   
  465           if (file == null || !file.exists()) {
  466               return null;
  467           }
  468   
  469           switch (column) {
  470               case 0:
  471                   // By default, file name will be rendered using getSystemDisplayName()
  472                   return file;
  473   
  474               case 1: // size
  475                   return file.isDirectory() ? null : Long.valueOf(file.length());
  476   
  477               case 2: // date
  478                   if (isFileSystemRoot(file)) {
  479                       return null;
  480                   }
  481                   long time = file.lastModified();
  482                   return (time == 0L) ? null : new Date(time);
  483   
  484               default:
  485                   return null;
  486           }
  487       }
  488   
  489       public Object getFolderColumnValue(int column) {
  490           return null;
  491       }
  492   
  493       /**
  494        * Invokes the {@code task} which doesn't throw checked exceptions
  495        * from its {@code call} method. If invokation is interrupted then Thread.currentThread().isInterrupted() will
  496        * be set and result will be {@code null}
  497        */
  498       public static <T> T invoke(Callable<T> task) {
  499           try {
  500               return invoke(task, RuntimeException.class);
  501           } catch (InterruptedException e) {
  502               return null;
  503           }
  504       }
  505   
  506       /**
  507        * Invokes the {@code task} which throws checked exceptions from its {@code call} method.
  508        * If invokation is interrupted then Thread.currentThread().isInterrupted() will
  509        * be set and InterruptedException will be thrown as well.
  510        */
  511       public static <T, E extends Throwable> T invoke(Callable<T> task, Class<E> exceptionClass)
  512               throws InterruptedException, E {
  513           try {
  514               return invoker.invoke(task);
  515           } catch (Exception e) {
  516               if (e instanceof RuntimeException) {
  517                   // Rethrow unchecked exceptions
  518                   throw (RuntimeException) e;
  519               }
  520   
  521               if (e instanceof InterruptedException) {
  522                   // Set isInterrupted flag for current thread
  523                   Thread.currentThread().interrupt();
  524   
  525                   // Rethrow InterruptedException
  526                   throw (InterruptedException) e;
  527               }
  528   
  529               if (exceptionClass.isInstance(e)) {
  530                   throw exceptionClass.cast(e);
  531               }
  532   
  533               throw new RuntimeException("Unexpected error", e);
  534           }
  535       }
  536   
  537       /**
  538        * Interface allowing to invoke tasks in different environments on different platforms.
  539        */
  540       public static interface Invoker {
  541           /**
  542            * Invokes a callable task.
  543            *
  544            * @param task a task to invoke
  545            * @throws Exception {@code InterruptedException} or an exception that was thrown from the {@code task}
  546            * @return the result of {@code task}'s invokation
  547            */
  548           <T> T invoke(Callable<T> task) throws Exception;
  549       }
  550   
  551       /**
  552        * Provides a default comparator for the default column set
  553        */
  554       private static final Comparator DEFAULT_COMPARATOR = new Comparator() {
  555           public int compare(Object o1, Object o2) {
  556               int gt;
  557   
  558               if (o1 == null && o2 == null) {
  559                   gt = 0;
  560               } else if (o1 != null && o2 == null) {
  561                   gt = 1;
  562               } else if (o1 == null && o2 != null) {
  563                   gt = -1;
  564               } else if (o1 instanceof Comparable) {
  565                   gt = ((Comparable) o1).compareTo(o2);
  566               } else {
  567                   gt = 0;
  568               }
  569   
  570               return gt;
  571           }
  572       };
  573   
  574       private static final Comparator<File> FILE_COMPARATOR = new Comparator<File>() {
  575           public int compare(File f1, File f2) {
  576               ShellFolder sf1 = null;
  577               ShellFolder sf2 = null;
  578   
  579               if (f1 instanceof ShellFolder) {
  580                   sf1 = (ShellFolder) f1;
  581                   if (sf1.isFileSystem()) {
  582                       sf1 = null;
  583                   }
  584               }
  585               if (f2 instanceof ShellFolder) {
  586                   sf2 = (ShellFolder) f2;
  587                   if (sf2.isFileSystem()) {
  588                       sf2 = null;
  589                   }
  590               }
  591   
  592               if (sf1 != null && sf2 != null) {
  593                   return sf1.compareTo(sf2);
  594               } else if (sf1 != null) {
  595                   // Non-file shellfolders sort before files
  596                   return -1;
  597               } else if (sf2 != null) {
  598                   return 1;
  599               } else {
  600                   String name1 = f1.getName();
  601                   String name2 = f2.getName();
  602   
  603                   // First ignore case when comparing
  604                   int diff = name1.compareToIgnoreCase(name2);
  605                   if (diff != 0) {
  606                       return diff;
  607                   } else {
  608                       // May differ in case (e.g. "mail" vs. "Mail")
  609                       // We need this test for consistent sorting
  610                       return name1.compareTo(name2);
  611                   }
  612               }
  613           }
  614       };
  615   }

Home » openjdk-7 » sun » awt » shell » [javadoc | source]