Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 5036988
Votes 1
Synopsis sun.awt.shell.ShellFolder should be a public class in java.io
Category java:classes_io
Reported Against 1.4.2
Release Fixed
State 11-Closed, duplicate of 4313887, request for enhancement
Priority: 4-Low
Related Bugs
Submit Date 23-APR-2004
Description


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  customer " 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) 
======================================================================
Posted Date : 2005-08-25 19:29:56.0
Work Around
N/A
Evaluation
Perhaps this functionality should be considered for JSR203. Not for Tiger.
  xxxxx@xxxxx   2004-04-23
JSR-203 provides for bulk access to file attributes.
Posted Date : 2009-02-16 14:52:59.0
Comments
  
  Include a link with my name & email   

Submitted On 26-APR-2004
asjf
http://forums.java.sun.com/thread.jsp?
forum=32&thread=515993&start=0&range=15#246446
8


Submitted On 21-JUL-2006
UlfZi
See also:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6314708
(File should provide methods to access attributes like archived and created and last-access times)



Submitted On 15-APR-2008
gordan
An even more important reason to make ShellFolder accessible would be to allow the JFileChooser "favorite places" bar on the left customizable.


Submitted On 30-APR-2008
gordan
See also:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6689314


Submitted On 01-MAY-2008
alan.bateman
Note that we there aren't any plans to pull the ShellFolder in the java.io package. However, as part of JSR-203, in works for jdk7, we have a file system API that doesn't the provides the ability to read attributes in bulk. As part of that, support for other attributes (including the DOS attributes requested here) have been added.



PLEASE NOTE: JDK6 is formerly known as Project Mustang