-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
1.4.0
-
x86
-
windows_nt
Name: sv35042 Date: 10/09/2002
FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION : NT 4.0 (SP6)
ADDITIONAL OPERATING SYSTEMS : All other OSs for which JDK
is available (linux, solaris, hp, ...)
A DESCRIPTION OF THE PROBLEM :
This issue is similar to the one reported in Bug #4493369,
except that it concerns the
javax.swing.plaf.metal.MetalFileChooserUI class instead of
the com.sun.java.swing.plaf.windows.WindowsFileChooserUI
class. I assume the issue affects more people as metal plaf
is used more widely than windows plaf.
Similar to the reporter of Bug #4493369, I use JFileChooser
to view remote files in any cross-platform client/server
fashion by using a custom FileSystemView. Before 1.4, the
custom class only needs to override the FileSystemView
interface (9 methods). My implementation stops working in
1.4 because:
1) 12 more public methods are added to FileSystemView,
which JFileChooser can potential call
2) sun.awt.shell.ShellFolder class is heavily used in the
filechooser UI component and FileSystemView. Because
ShellFolder class extends from java.io.File, it's local-
system-dependent. (plus, there is no javadoc for
this "secret" class)
Issues concerning FileSystemView can be worked around by
overriding the new interface methods, and overriding any
FSV methods that makes use of ShellFolder.
However, the filechooser UI component (in this case
MetalFileChooserUI class) is quite beyond reach. The source
code shows that MetalFileChooserUI uses ShellFolder in 3
places. Two of them happen in the private addItem(File dir)
method (the first protected by "if (useShellFolder)", the
other not), and the third one occurs in an actionPerformed
() concerning changing the "useShellFolder" flag from false
to true.
For the two occurrences in addItem(File), both should be
protected by "if (useShellFolder)" so that as long
as "useShellFolder" is never set, we can avoid dealing with
ShellFolder class of the local file system.
The condition under which "useShellFolder" could be set
should also be reexamined. Here's a direct quote of code
comment from the source:
// Use ShellFolder class to populate combobox only if
// FileSystemView.getRoots() returns one folder and that is
// the same as the first item in the ShellFolder combobox
list.
Note that if my custom FSV's first root returned happened
to have the same name as the first root from the local
ShellFolder, it does not mean we should start using the
local file system!
Anyway, the bottom line is, if you decide to continue
allowing the UI component to interact with local file
system (ShellFolder) like this, then at least fix the
MetalFileChooserUI to condition all such interactions on
the "useShellFolder" flag, and to bullet-proof condition
when "useShellFolder" will be set.
A more desired solution is to re-evaluate the
implementation. JavaDoc for FileSystemView starts
with "FileSystemView is JFileChooser's gateway to the file
system." FileChooserUI component, which is part of
JFileChooser, should "honor" this statement by not by-
passing FSV and directly talking to local file system
(ShellFolder). Any dealing with local file system should go
through FSV.
Despite some UI bugs, the JFileChooser-FSV relation in Java
1.3 and earlier is much cleaner than what's in 1.4, and we
want it back!
REGRESSION. Last worked in version 1.3.1
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. write a custom file system view class to simulate a non-
local file system. (this does not have to be a remote file
system, it could be a fictitious file system you conjured
up in memory. this way, you don't need a client/server
program like I have.) Also, to see "useShellFolder" flag of
MetalFileChooserUI can be incorrectly set, make the first
element the FSV's getRoots() method returns the same as
that of the ShellFolder.get("fileChooserComboBoxFolders"),
while the rest of the roots differ. This should switch you
midway from not using local ShellFolder to using local
ShellFolder.
2. construct a JFileChooser using this custom FSV
3. navigate via all the buttons in the JFileChooser GUI.
EXPECTED VERSUS ACTUAL BEHAVIOR :
you may see some local system roots in the "Look In:"
directory combobox that are not in your custom non-local
file system.
currentDirectory will not show in the "Look In:" directory
combobox when navigating to various directories on the non-
local file system.
if your custom FileSystemView class failed to override
certain method in the
javax.swing.filechooser.FileSystemView class, (esp. those
using the ShellFolder class), then you may enounter various
exceptions at runtime such as "NoSuchFile", or "unable to
parse path" if the nonlocal file system uses different file
separator character than the local FS.
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
My app is a client/server via RMI containing at least 10 modules. I don't want
to clutter up the space here by pasting all the source code, especially when it
won't be very useful anyways. For the MetalFileChooserUI problem, the best
place is to look at the java source code. (I am quoting relavant snippets
below.) To decouple FileChooserUI from ShellFolder, some redesign is needed.
MetalFileChooserUI.java
========================
class ViewButtonListener ... {
public void actionPerformed(..) {
...
// Use ShellFolder class to populate combobox only if
// FileSystemView.getRoots() returns one folder and that is
// the same as the first item in the ShellFolder combobox list.
{
useShellFolder = false;
File[] roots = fsv.getRoots();
if (roots != null && roots.length == 1) {//<<<--- can be problematic
File[] cbFolders = (File[])ShellFolder.get
("fileChooserComboBoxFolders");
if (cbFolders != null && cbFolders.length > 0 && roots[0] == cbFolders
[0]) { //<<<-- can be problematic
useShellFolder = true;
}
}
}
}
...
private void addItem(File directory) {
...
// create File instances of each directory leading up to the top
try {
File sf = ShellFolder.getShellFolder(canonical); //<<<-- sf
should be retrieved from ShellFolder on condition that if (useShellFolder)
File f = sf;
Vector path = new Vector(10);
do {
path.addElement(f);
} while ((f = f.getParentFile()) != null);
int pathCount = path.size();
// Insert chain at appropriate place in vector
for (int i = 0; i < pathCount; i++) {
f = (File)path.get(i);
if (directories.contains(f)) {
int topIndex = directories.indexOf(f);
for (int j = i-1; j >= 0; j--) {
directories.insertElementAt(path.get(j), topIndex+i-j);
}
break;
}
}
calculateDepths();
setSelectedItem(sf);
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Can't rip out and replace the FileChooserUI component used
by JFileChooser from UIManager.
Can't override static methods of ShellFolder used by (Metal)
FileChooserUI.
Only option left i can think of is to modify the
MetalFileChooserUI.java and protecting all uses of
ShellFolder methods with "useShellFolder" flag.
Have not figured out a way to prevent "useShellFolder" flag
from being set incorrectly.
(Review ID: 144901)
======================================================================
- duplicates
-
JDK-4723745 1.4 REGRESSION: Metal & Windows FileChooserUI classes cannot be used without She
-
- Resolved
-