Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5036988

sun.awt.shell.ShellFolder should be a public class in java.io

    Details

    • Type: Enhancement
    • Status: Closed
    • Priority: P4
    • Resolution: Duplicate
    • Affects Version/s: 1.4.2
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • CPU:
      x86
    • OS:
      windows_2000

      Description

      Name: jl125535 Date: 04/23/2004


      A DESCRIPTION OF THE REQUEST :
      ShellFolder seems to outperform java.io.File by quite a margin. It would be very nice to have this as a public API for general use.

      The inefficiency in java.io.File is from requerying the file system per bit of information asked for (eg exists, isDirectory, isHidden etc..)

      It would be nice to have an API that doesn't guarantee up-to-dateness of this information in exchange for speed. The obvious workaround of writing this yourself isn't as efficient as it could be because caching exists() and isDirectory() individually still queries the filesystem twice, when instead it could get this information once in one go and cache that.

      (FileSnapshot does this below by using the non-public java.io.FileSystem class directly)

      Ideally, on operating systems that allow this (I don't know if there are any) then you could collate *all* information at the same time - ie the boolean attributes accessible via the FileSystem class and things like the last modified time, length of the file etc.. (checksum would be nice if available..)

      JSR203 may cover some of this functionality

      JUSTIFICATION :
      File access is extremely important for lots of applications - especially power tool like applications

      I've put this as "Difficult to make progress" as severity because without it (or the workaround) java is way behind technologies that allow more flexible file access, for this class of application


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      File access is slower than native applications
      ACTUAL -
      File access is comparable to/same as native applications

      CUSTOMER SUBMITTED WORKAROUND :
      You can use reflection to safely gain access to the ShellFolder class on the subclass of JVMs that have sun.awt.shell.ShellFolder in the class pool at run-time, and fall back to normal behaviour otherwise


      import java.io.*;
      import java.lang.reflect.*;

      public final class FileTricks {
         private static Class cShellFolder, cShellFolderManager;
         private static Constructor ctrShellFolderManager;
         private static Method mCreateShellFolder;
         private static Object sfm;

         static {
            try {
               cShellFolder = Class.forName("sun.awt.shell.ShellFolder");
               cShellFolderManager = Class.forName("sun.awt.shell.ShellFolderManager");
               ctrShellFolderManager = cShellFolderManager.getDeclaredConstructor(new Class [] {});
               ctrShellFolderManager.setAccessible(true);
               sfm = ctrShellFolderManager.newInstance(new Object [] {});
               mCreateShellFolder = cShellFolderManager.getDeclaredMethod("createShellFolder",new Class [] {File.class});
               mCreateShellFolder.setAccessible(true);
            } catch(Exception e) {
               e.printStackTrace();
               cShellFolder = cShellFolderManager = null;
               ctrShellFolderManager = null;
               mCreateShellFolder = null;
               sfm = null;
            }
         }

         public static final File attemptReplaceWithShellFolder(File actual) {
            File result = actual;
            if(cShellFolder != null && !cShellFolder.isInstance(actual)) {
               try {
                  result = (File) mCreateShellFolder.invoke(sfm, (new Object [] {actual}));
                  System.out.print(".");
               } catch(Exception e) {
                  System.out.print("#");
               }
            }
            return result;
         }

         public final static class FileSnapshot {
            private static Method mGetBooleanAttributes;
            private static int BA_DIRECTORY, BA_EXISTS, BA_REGULAR, BA_HIDDEN;
            private static Object fs;

            public final boolean isDirectory, exists, isRegular, isHidden;

            public FileSnapshot(File f) {
               boolean e, d, r, h;
               
               try {
                  int ba = ((Integer)mGetBooleanAttributes.invoke(fs, new Object [] {f})).intValue();
                  d = (ba & BA_DIRECTORY)!=0;
                  e = (ba & BA_EXISTS)!=0;
                  r = (ba & BA_REGULAR)!=0;
                  h = (ba & BA_HIDDEN)!=0;
               } catch(Exception x) {
                  d = f.isDirectory();
                  e = d || f.exists();
                  r = f.isFile();
                  h = f.isHidden();
               }
               
               isDirectory = d; exists = e; isRegular = r; isHidden = h;
            }

            static {
               try {
                  Class cFile = Class.forName("java.io.File");
                  Class cFileSystem = Class.forName("java.io.FileSystem");
                  mGetBooleanAttributes = cFileSystem.getDeclaredMethod("getBooleanAttributes", new Class [] {File.class});
                  Field fBA_EXISTS = cFileSystem.getDeclaredField("BA_EXISTS");
                  Field fBA_REGULAR = cFileSystem.getDeclaredField("BA_REGULAR");
                  Field fBA_DIRECTORY = cFileSystem.getDeclaredField("BA_DIRECTORY");
                  Field fBA_HIDDEN = cFileSystem.getDeclaredField("BA_HIDDEN");
                  Field fFs = cFile.getDeclaredField("fs");

                  mGetBooleanAttributes.setAccessible(true);
                  fFs.setAccessible(true);
                  fBA_EXISTS.setAccessible(true);
                  fBA_REGULAR.setAccessible(true);
                  fBA_DIRECTORY.setAccessible(true);
                  fBA_HIDDEN.setAccessible(true);

                  BA_EXISTS = ((Integer)fBA_EXISTS.get(null)).intValue();
                  BA_REGULAR = ((Integer)fBA_REGULAR.get(null)).intValue();
                  BA_DIRECTORY = ((Integer)fBA_DIRECTORY.get(null)).intValue();
                  BA_HIDDEN = ((Integer)fBA_HIDDEN.get(null)).intValue();
                  fs = fFs.get(null);
               } catch(Exception e) {}
            }
         }
      }
      (Incident Review ID: 255591)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                alanb Alan Bateman
                Reporter:
                jleesunw Jon Lee (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: