United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6430931 : Win L&F:FileChooser Details view under Vista throws an exception

Details
Type:
Bug
Submit Date:
2006-05-26
Status:
Closed
Updated Date:
2011-02-16
Project Name:
JDK
Resolved Date:
2006-08-23
Component:
client-libs
OS:
windows_vista
Sub-Component:
javax.swing
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:

Sub Tasks

Description
reproduced on Vista 5381,Vista 5384 with promoted build mustang b84.
Steps to reproduce:
1)Open SwingSet2 demo and tab to JFileChooser. WIth L&F set to Windows L&F, open file chooser and clickon the details view. THe following exception occurs.
Exception occurred during event dispatching:
java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
        at java.util.Vector.elementAt(Vector.java:431)
        at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:277)
        at sun.swing.FilePane.fixNameColumnWidth(FilePane.java:1097)
        at sun.swing.FilePane.access$2000(FilePane.java:45)
        at sun.swing.FilePane$6.componentResized(FilePane.java:1030)
        at java.awt.Component.processComponentEvent(Component.java:5825)
        at java.awt.Component.processEvent(Component.java:5779)
        at java.awt.Container.processEvent(Container.java:1984)
        at java.awt.Component.dispatchEventImpl(Component.java:4407)
        at java.awt.Container.dispatchEventImpl(Container.java:2042)
        at java.awt.Component.dispatchEvent(Component.java:4237)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:600)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
        at java.awt.Dialog$1.run(Dialog.java:1039)
        at java.awt.Dialog$2.run(Dialog.java:1085)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.awt.Dialog.show(Dialog.java:1083)
        at javax.swing.JFileChooser.showDialog(JFileChooser.java:718)
        at javax.swing.JFileChooser.showOpenDialog(JFileChooser.java:621)
        at FileChooserDemo$2.actionPerformed(FileChooserDemo.java:160)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:377)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:232)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
        at java.awt.Component.processMouseEvent(Component.java:5999)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3240)
        at java.awt.Component.processEvent(Component.java:5764)
        at java.awt.Container.processEvent(Container.java:1984)
        at java.awt.Component.dispatchEventImpl(Component.java:4407)
        at java.awt.Container.dispatchEventImpl(Container.java:2042)
        at java.awt.Component.dispatchEvent(Component.java:4237)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4248)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3912)

        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3842)
        at java.awt.Container.dispatchEventImpl(Container.java:2028)
        at java.awt.Window.dispatchEventImpl(Window.java:2405)
        at java.awt.Component.dispatchEvent(Component.java:4237)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:600)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)

        at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

                                    

Comments
EVALUATION

To get folder details, JFileChooser calls the GetDetailsOf method defined in  IShellFolder2 and IShellDetails interfaces. On Vista this method fails with the error code of 8001010F: CoInitialize has not been called on the current thread. It means that in Vista they changed implementation of this method so that it became to require COM library to be pre-initialized.
                                     
2006-07-13
SUGGESTED FIX

MSDN on CoInitialize states that:

a) "You need to initialize the COM library on a thread before you call any of the library functions"

b) "each successful call to CoInitialize [...] must be balanced by a corresponding call to CoUninitialize"

So there could be several ways to fix it.

1) To initialize COM library on every call to the Win32ShellFolder2's native methods doGetColumnInfo and doGetColumnValue, and uninitialize it on its termination. This was first what I tried and it worked correctly but slowed down performance dramatically: directories with at least 50-60 files were almost impossible to browse in details view mode. It made me to refuse that, but developing it helped me to put all required native code in order.

2) To initialize COM library on the thread where the native Win32ShellFolder's methods are called and uninitialize it on the thread termination. The problem was that this thread was the event dispatch one, and there was no control on when it started and no notifications when it stopped: it's known that AWT can start and stop EDT many times during the application running, so this approach required embbedding my fix into the AWT's EDT management code (since CoUninitialize should be called on the same thread where CoInitialized was called), what was inacceptable on my mind.

3) To create a special thread for calling COM functions that would provide correct initialization/uninitialization of the COM library. So in Win32ShellFolder2, I created two native call wrappers (inner classes ComGetColumnInfo and ComGetColumnValue), and an inner class ComCallWrapper that provides theirs execution on its own thread and transparent COM initialization/uninitialization for that thread. In my opinion, its solves the problem optimally: it allows consecutive calls to perform without reinitializing COM, and doesn't eat resources between series of calls, what fits the typical behavior of JFileChooser: massive file details reading on open or directory change, and then long period of idling while the user observes the shown info.
                                     
2006-07-13



Hardware and Software, Engineered to Work Together