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

    1   /*
    2    * Copyright (c) 2003, 2010, 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 java.awt;
   29   import java.awt.image.BufferedImage;
   30   
   31   import java.io.File;
   32   import java.io.FileNotFoundException;
   33   import java.io.IOException;
   34   import java.security.AccessController;
   35   import java.security.PrivilegedAction;
   36   import java.util;
   37   import java.util.List;
   38   import java.util.concurrent;
   39   
   40   import sun.security.action.LoadLibraryAction;
   41   
   42   import static sun.awt.shell.Win32ShellFolder2.*;
   43   import sun.awt.OSInfo;
   44   
   45   // NOTE: This class supersedes Win32ShellFolderManager, which was removed
   46   //       from distribution after version 1.4.2.
   47   
   48   /**
   49    * @author Michael Martak
   50    * @author Leif Samuelsson
   51    * @author Kenneth Russell
   52    * @since 1.4
   53    */
   54   
   55   public class Win32ShellFolderManager2 extends ShellFolderManager {
   56   
   57       static {
   58           // Load library here
   59           AccessController.doPrivileged(new LoadLibraryAction("awt"));
   60       }
   61   
   62       public ShellFolder createShellFolder(File file) throws FileNotFoundException {
   63           try {
   64               return createShellFolder(getDesktop(), file);
   65           } catch (InterruptedException e) {
   66               throw new FileNotFoundException("Execution was interrupted");
   67           }
   68       }
   69   
   70       static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, File file)
   71               throws FileNotFoundException, InterruptedException {
   72           long pIDL;
   73           try {
   74               pIDL = parent.parseDisplayName(file.getCanonicalPath());
   75           } catch (IOException ex) {
   76               pIDL = 0;
   77           }
   78           if (pIDL == 0) {
   79               // Shouldn't happen but watch for it anyway
   80               throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found");
   81           }
   82   
   83           try {
   84               return createShellFolderFromRelativePIDL(parent, pIDL);
   85           } finally {
   86               Win32ShellFolder2.releasePIDL(pIDL);
   87           }
   88       }
   89   
   90       static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, long pIDL)
   91               throws InterruptedException {
   92           // Walk down this relative pIDL, creating new nodes for each of the entries
   93           while (pIDL != 0) {
   94               long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL);
   95               if (curPIDL != 0) {
   96                   parent = new Win32ShellFolder2(parent, curPIDL);
   97                   pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL);
   98               } else {
   99                   // The list is empty if the parent is Desktop and pIDL is a shortcut to Desktop
  100                   break;
  101               }
  102           }
  103           return parent;
  104       }
  105   
  106       private static final int VIEW_LIST = 2;
  107       private static final int VIEW_DETAILS = 3;
  108       private static final int VIEW_PARENTFOLDER = 8;
  109       private static final int VIEW_NEWFOLDER = 11;
  110   
  111       private static final Image[] STANDARD_VIEW_BUTTONS = new Image[12];
  112   
  113       private static Image getStandardViewButton(int iconIndex) {
  114           Image result = STANDARD_VIEW_BUTTONS[iconIndex];
  115   
  116           if (result != null) {
  117               return result;
  118           }
  119   
  120           BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
  121   
  122           img.setRGB(0, 0, 16, 16, Win32ShellFolder2.getStandardViewButton0(iconIndex), 0, 16);
  123   
  124           STANDARD_VIEW_BUTTONS[iconIndex] = img;
  125   
  126           return img;
  127       }
  128   
  129       // Special folders
  130       private static Win32ShellFolder2 desktop;
  131       private static Win32ShellFolder2 drives;
  132       private static Win32ShellFolder2 recent;
  133       private static Win32ShellFolder2 network;
  134       private static Win32ShellFolder2 personal;
  135   
  136       static Win32ShellFolder2 getDesktop() {
  137           if (desktop == null) {
  138               try {
  139                   desktop = new Win32ShellFolder2(DESKTOP);
  140               } catch (IOException e) {
  141                   // Ignore error
  142               } catch (InterruptedException e) {
  143                   // Ignore error
  144               }
  145           }
  146           return desktop;
  147       }
  148   
  149       static Win32ShellFolder2 getDrives() {
  150           if (drives == null) {
  151               try {
  152                   drives = new Win32ShellFolder2(DRIVES);
  153               } catch (IOException e) {
  154                   // Ignore error
  155               } catch (InterruptedException e) {
  156                   // Ignore error
  157               }
  158           }
  159           return drives;
  160       }
  161   
  162       static Win32ShellFolder2 getRecent() {
  163           if (recent == null) {
  164               try {
  165                   String path = Win32ShellFolder2.getFileSystemPath(RECENT);
  166                   if (path != null) {
  167                       recent = createShellFolder(getDesktop(), new File(path));
  168                   }
  169               } catch (InterruptedException e) {
  170                   // Ignore error
  171               } catch (IOException e) {
  172                   // Ignore error
  173               }
  174           }
  175           return recent;
  176       }
  177   
  178       static Win32ShellFolder2 getNetwork() {
  179           if (network == null) {
  180               try {
  181                   network = new Win32ShellFolder2(NETWORK);
  182               } catch (IOException e) {
  183                   // Ignore error
  184               } catch (InterruptedException e) {
  185                   // Ignore error
  186               }
  187           }
  188           return network;
  189       }
  190   
  191       static Win32ShellFolder2 getPersonal() {
  192           if (personal == null) {
  193               try {
  194                   String path = Win32ShellFolder2.getFileSystemPath(PERSONAL);
  195                   if (path != null) {
  196                       Win32ShellFolder2 desktop = getDesktop();
  197                       personal = desktop.getChildByPath(path);
  198                       if (personal == null) {
  199                           personal = createShellFolder(getDesktop(), new File(path));
  200                       }
  201                       if (personal != null) {
  202                           personal.setIsPersonal();
  203                       }
  204                   }
  205               } catch (InterruptedException e) {
  206                   // Ignore error
  207               } catch (IOException e) {
  208                   // Ignore error
  209               }
  210           }
  211           return personal;
  212       }
  213   
  214   
  215       private static File[] roots;
  216   
  217       /**
  218        * @param key a <code>String</code>
  219        *  "fileChooserDefaultFolder":
  220        *    Returns a <code>File</code> - the default shellfolder for a new filechooser
  221        *  "roots":
  222        *    Returns a <code>File[]</code> - containing the root(s) of the displayable hierarchy
  223        *  "fileChooserComboBoxFolders":
  224        *    Returns a <code>File[]</code> - an array of shellfolders representing the list to
  225        *    show by default in the file chooser's combobox
  226        *   "fileChooserShortcutPanelFolders":
  227        *    Returns a <code>File[]</code> - an array of shellfolders representing well-known
  228        *    folders, such as Desktop, Documents, History, Network, Home, etc.
  229        *    This is used in the shortcut panel of the filechooser on Windows 2000
  230        *    and Windows Me.
  231        *  "fileChooserIcon <icon>":
  232        *    Returns an <code>Image</code> - icon can be ListView, DetailsView, UpFolder, NewFolder or
  233        *    ViewMenu (Windows only).
  234        *  "optionPaneIcon iconName":
  235        *    Returns an <code>Image</code> - icon from the system icon list
  236        *
  237        * @return An Object matching the key string.
  238        */
  239       public Object get(String key) {
  240           if (key.equals("fileChooserDefaultFolder")) {
  241               File file = getPersonal();
  242               if (file == null) {
  243                   file = getDesktop();
  244               }
  245               return file;
  246           } else if (key.equals("roots")) {
  247               // Should be "History" and "Desktop" ?
  248               if (roots == null) {
  249                   File desktop = getDesktop();
  250                   if (desktop != null) {
  251                       roots = new File[] { desktop };
  252                   } else {
  253                       roots = (File[])super.get(key);
  254                   }
  255               }
  256               return roots;
  257           } else if (key.equals("fileChooserComboBoxFolders")) {
  258               Win32ShellFolder2 desktop = getDesktop();
  259   
  260               if (desktop != null) {
  261                   ArrayList<File> folders = new ArrayList<File>();
  262                   Win32ShellFolder2 drives = getDrives();
  263   
  264                   Win32ShellFolder2 recentFolder = getRecent();
  265                   if (recentFolder != null && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_2000) >= 0) {
  266                       folders.add(recentFolder);
  267                   }
  268   
  269                   folders.add(desktop);
  270                   // Add all second level folders
  271                   File[] secondLevelFolders = desktop.listFiles();
  272                   Arrays.sort(secondLevelFolders);
  273                   for (File secondLevelFolder : secondLevelFolders) {
  274                       Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder;
  275                       if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) {
  276                           folders.add(folder);
  277                           // Add third level for "My Computer"
  278                           if (folder.equals(drives)) {
  279                               File[] thirdLevelFolders = folder.listFiles();
  280                               if (thirdLevelFolders != null && thirdLevelFolders.length > 0) {
  281                                   List<File> thirdLevelFoldersList = Arrays.asList(thirdLevelFolders);
  282   
  283                                   folder.sortChildren(thirdLevelFoldersList);
  284                                   folders.addAll(thirdLevelFoldersList);
  285                               }
  286                           }
  287                       }
  288                   }
  289                   return folders.toArray(new File[folders.size()]);
  290               } else {
  291                   return super.get(key);
  292               }
  293           } else if (key.equals("fileChooserShortcutPanelFolders")) {
  294               Toolkit toolkit = Toolkit.getDefaultToolkit();
  295               ArrayList<File> folders = new ArrayList<File>();
  296               int i = 0;
  297               Object value;
  298               do {
  299                   value = toolkit.getDesktopProperty("win.comdlg.placesBarPlace" + i++);
  300                   try {
  301                       if (value instanceof Integer) {
  302                           // A CSIDL
  303                           folders.add(new Win32ShellFolder2((Integer)value));
  304                       } else if (value instanceof String) {
  305                           // A path
  306                           folders.add(createShellFolder(new File((String)value)));
  307                       }
  308                   } catch (IOException e) {
  309                       // Skip this value
  310                   } catch (InterruptedException e) {
  311                       // Return empty result
  312                       return new File[0];
  313                   }
  314               } while (value != null);
  315   
  316               if (folders.size() == 0) {
  317                   // Use default list of places
  318                   for (File f : new File[] {
  319                       getRecent(), getDesktop(), getPersonal(), getDrives(), getNetwork()
  320                   }) {
  321                       if (f != null) {
  322                           folders.add(f);
  323                       }
  324                   }
  325               }
  326               return folders.toArray(new File[folders.size()]);
  327           } else if (key.startsWith("fileChooserIcon ")) {
  328               String name = key.substring(key.indexOf(" ") + 1);
  329   
  330               int iconIndex;
  331   
  332               if (name.equals("ListView") || name.equals("ViewMenu")) {
  333                   iconIndex = VIEW_LIST;
  334               } else if (name.equals("DetailsView")) {
  335                   iconIndex = VIEW_DETAILS;
  336               } else if (name.equals("UpFolder")) {
  337                   iconIndex = VIEW_PARENTFOLDER;
  338               } else if (name.equals("NewFolder")) {
  339                   iconIndex = VIEW_NEWFOLDER;
  340               } else {
  341                   return null;
  342               }
  343   
  344               return getStandardViewButton(iconIndex);
  345           } else if (key.startsWith("optionPaneIcon ")) {
  346               Win32ShellFolder2.SystemIcon iconType;
  347               if (key == "optionPaneIcon Error") {
  348                   iconType = Win32ShellFolder2.SystemIcon.IDI_ERROR;
  349               } else if (key == "optionPaneIcon Information") {
  350                   iconType = Win32ShellFolder2.SystemIcon.IDI_INFORMATION;
  351               } else if (key == "optionPaneIcon Question") {
  352                   iconType = Win32ShellFolder2.SystemIcon.IDI_QUESTION;
  353               } else if (key == "optionPaneIcon Warning") {
  354                   iconType = Win32ShellFolder2.SystemIcon.IDI_EXCLAMATION;
  355               } else {
  356                   return null;
  357               }
  358               return Win32ShellFolder2.getSystemIcon(iconType);
  359           } else if (key.startsWith("shell32Icon ") || key.startsWith("shell32LargeIcon ")) {
  360               String name = key.substring(key.indexOf(" ") + 1);
  361               try {
  362                   int i = Integer.parseInt(name);
  363                   if (i >= 0) {
  364                       return Win32ShellFolder2.getShell32Icon(i, key.startsWith("shell32LargeIcon "));
  365                   }
  366               } catch (NumberFormatException ex) {
  367               }
  368           }
  369           return null;
  370       }
  371   
  372       /**
  373        * Does <code>dir</code> represent a "computer" such as a node on the network, or
  374        * "My Computer" on the desktop.
  375        */
  376       public boolean isComputerNode(final File dir) {
  377           if (dir != null && dir == getDrives()) {
  378               return true;
  379           } else {
  380               String path = AccessController.doPrivileged(new PrivilegedAction<String>() {
  381                   public String run() {
  382                       return dir.getAbsolutePath();
  383                   }
  384               });
  385   
  386               return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0);      //Network path
  387           }
  388       }
  389   
  390       public boolean isFileSystemRoot(File dir) {
  391           //Note: Removable drives don't "exist" but are listed in "My Computer"
  392           if (dir != null) {
  393               Win32ShellFolder2 drives = getDrives();
  394               if (dir instanceof Win32ShellFolder2) {
  395                   Win32ShellFolder2 sf = (Win32ShellFolder2)dir;
  396                   if (sf.isFileSystem()) {
  397                       if (sf.parent != null) {
  398                           return sf.parent.equals(drives);
  399                       }
  400                       // else fall through ...
  401                   } else {
  402                       return false;
  403                   }
  404               }
  405               String path = dir.getPath();
  406   
  407               if (path.length() != 3 || path.charAt(1) != ':') {
  408                   return false;
  409               }
  410   
  411               File[] files = drives.listFiles();
  412   
  413               return files != null && Arrays.asList(files).contains(dir);
  414           }
  415           return false;
  416       }
  417   
  418       private static List topFolderList = null;
  419       static int compareShellFolders(Win32ShellFolder2 sf1, Win32ShellFolder2 sf2) {
  420           boolean special1 = sf1.isSpecial();
  421           boolean special2 = sf2.isSpecial();
  422   
  423           if (special1 || special2) {
  424               if (topFolderList == null) {
  425                   ArrayList tmpTopFolderList = new ArrayList();
  426                   tmpTopFolderList.add(Win32ShellFolderManager2.getPersonal());
  427                   tmpTopFolderList.add(Win32ShellFolderManager2.getDesktop());
  428                   tmpTopFolderList.add(Win32ShellFolderManager2.getDrives());
  429                   tmpTopFolderList.add(Win32ShellFolderManager2.getNetwork());
  430                   topFolderList = tmpTopFolderList;
  431               }
  432               int i1 = topFolderList.indexOf(sf1);
  433               int i2 = topFolderList.indexOf(sf2);
  434               if (i1 >= 0 && i2 >= 0) {
  435                   return (i1 - i2);
  436               } else if (i1 >= 0) {
  437                   return -1;
  438               } else if (i2 >= 0) {
  439                   return 1;
  440               }
  441           }
  442   
  443           // Non-file shellfolders sort before files
  444           if (special1 && !special2) {
  445               return -1;
  446           } else if (special2 && !special1) {
  447               return  1;
  448           }
  449   
  450           return compareNames(sf1.getAbsolutePath(), sf2.getAbsolutePath());
  451       }
  452   
  453       static int compareNames(String name1, String name2) {
  454           // First ignore case when comparing
  455           int diff = name1.compareToIgnoreCase(name2);
  456           if (diff != 0) {
  457               return diff;
  458           } else {
  459               // May differ in case (e.g. "mail" vs. "Mail")
  460               // We need this test for consistent sorting
  461               return name1.compareTo(name2);
  462           }
  463       }
  464   
  465       @Override
  466       protected Invoker createInvoker() {
  467           return new ComInvoker();
  468       }
  469   
  470       private static class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker {
  471           private static Thread comThread;
  472   
  473           private ComInvoker() {
  474               super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>());
  475               allowCoreThreadTimeOut(false);
  476               setThreadFactory(this);
  477               final Runnable shutdownHook = new Runnable() {
  478                   public void run() {
  479                       AccessController.doPrivileged(new PrivilegedAction<Void>() {
  480                           public Void run() {
  481                               shutdownNow();
  482                               return null;
  483                           }
  484                       });
  485                   }
  486               };
  487               AccessController.doPrivileged(new PrivilegedAction<Void>() {
  488                   public Void run() {
  489                       Runtime.getRuntime().addShutdownHook(
  490                           new Thread(shutdownHook)
  491                       );
  492                       return null;
  493                   }
  494               });
  495           }
  496   
  497           public synchronized Thread newThread(final Runnable task) {
  498               final Runnable comRun = new Runnable() {
  499                   public void run() {
  500                       try {
  501                           initializeCom();
  502                           task.run();
  503                       } finally {
  504                           uninitializeCom();
  505                       }
  506                   }
  507               };
  508               comThread =
  509                   AccessController.doPrivileged(
  510                       new PrivilegedAction<Thread>() {
  511                           public Thread run() {
  512                               /* The thread must be a member of a thread group
  513                                * which will not get GCed before VM exit.
  514                                * Make its parent the top-level thread group.
  515                                */
  516                               ThreadGroup tg = Thread.currentThread().getThreadGroup();
  517                               for (ThreadGroup tgn = tg;
  518                                    tgn != null;
  519                                    tg = tgn, tgn = tg.getParent());
  520                               Thread thread = new Thread(tg, comRun, "Swing-Shell");
  521                               thread.setDaemon(true);
  522                               return thread;
  523                           }
  524                       }
  525                   );
  526               return comThread;
  527           }
  528   
  529           public <T> T invoke(Callable<T> task) throws Exception {
  530               if (Thread.currentThread() == comThread) {
  531                   // if it's already called from the COM
  532                   // thread, we don't need to delegate the task
  533                   return task.call();
  534               } else {
  535                   final Future<T> future;
  536   
  537                   try {
  538                       future = submit(task);
  539                   } catch (RejectedExecutionException e) {
  540                       throw new InterruptedException(e.getMessage());
  541                   }
  542   
  543                   try {
  544                       return future.get();
  545                   } catch (InterruptedException e) {
  546                       AccessController.doPrivileged(new PrivilegedAction<Void>() {
  547                           public Void run() {
  548                               future.cancel(true);
  549   
  550                               return null;
  551                           }
  552                       });
  553   
  554                       throw e;
  555                   } catch (ExecutionException e) {
  556                       Throwable cause = e.getCause();
  557   
  558                       if (cause instanceof Exception) {
  559                           throw (Exception) cause;
  560                       }
  561   
  562                       if (cause instanceof Error) {
  563                           throw (Error) cause;
  564                       }
  565   
  566                       throw new RuntimeException("Unexpected error", cause);
  567                   }
  568               }
  569           }
  570       }
  571   
  572       static native void initializeCom();
  573   
  574       static native void uninitializeCom();
  575   }

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