Skip to content

Commit

Permalink
DirectoryChooserUI: reduce reflective win ShellFolder API usage
Browse files Browse the repository at this point in the history
 - some internal methods are now public in FileSystemView and can be
   used instead of using reflection
 - remove calls to ShellFolder.getShellFolder(file) entirely

this hopefully fixes the mysterious NPEs on windows caused by
broken java.io.File instances with null paths.
  • Loading branch information
mbien committed Jan 3, 2025
1 parent 33cdacf commit 12d71f4
Showing 1 changed file with 12 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -272,7 +273,7 @@ private void updateUseShellFolder() {
useShellFolder = false;
File[] roots = fileChooser.getFileSystemView().getRoots();
if (roots != null && roots.length == 1) {
File[] cbFolders = getShellFolderRoots();
File[] cbFolders = fileChooser.getFileSystemView().getChooserComboBoxFiles();
if (cbFolders != null && cbFolders.length > 0 && Arrays.asList(cbFolders).contains(roots[0])) {
useShellFolder = true;
}
Expand Down Expand Up @@ -328,54 +329,15 @@ private JComponent getPlacesBar() {
return null;
}
}

/** Reflection alternative of
* sun.awt.shell.ShellFolder.getShellFolder(file)
*/
private File getShellFolderForFile (File file) {
try {
Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
return (File) clazz.getMethod("getShellFolder", File.class).invoke(null, file);
} catch (Exception exc) {
// reflection not succesfull, just log the exception and return null
Logger.getLogger(DirectoryChooserUI.class.getName()).log(
Level.FINE, "ShellFolder can't be used.", exc);
return null;
}
}

/** Reflection alternative of
* sun.awt.shell.ShellFolder.getShellFolder(dir).getLinkLocation()
*/
private File getShellFolderForFileLinkLoc (File file) {
private File getShellFolderForFileLinkLoc(File file) {
try {
Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
Object sf = clazz.getMethod("getShellFolder", File.class).invoke(null, file);
return (File) clazz.getMethod("getLinkLocation").invoke(sf);
} catch (Exception exc) {
// reflection not succesfull, just log the exception and return null
Logger.getLogger(DirectoryChooserUI.class.getName()).log(
Level.FINE, "ShellFolder can't be used.", exc);
return null;
}

}

/** Reflection alternative of
* sun.awt.shell.ShellFolder.get("fileChooserComboBoxFolders")
*/
private File[] getShellFolderRoots () {
try {
Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
return (File[]) clazz.getMethod("get", String.class).invoke(null, "fileChooserComboBoxFolders");
} catch (Exception exc) {
// reflection not succesfull, just log the exception and return null
Logger.getLogger(DirectoryChooserUI.class.getName()).log(
Level.FINE, "ShellFolder can't be used.", exc);
return fileChooser.getFileSystemView().getLinkLocation(file);
} catch (FileNotFoundException ex) {
return null;
}
}

private void createBottomPanel(JFileChooser fc) {
bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
Expand Down Expand Up @@ -1864,11 +1826,9 @@ public String getName() {
* Data model for a type-face selection combo-box.
*/
private class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
Vector<File> directories = new Vector<>();
int[] depths = null;
File selectedDirectory = null;
JFileChooser chooser = getFileChooser();
FileSystemView fsv = chooser.getFileSystemView();
private final Vector<File> directories = new Vector<>();
private int[] depths = null;
private File selectedDirectory = null;

public DirectoryComboBoxModel() {
// Add the current directory to the model, and make it the
Expand All @@ -1893,7 +1853,7 @@ private void addItem(File directory) {
directories.clear();

if(useShellFolder) {
directories.addAll(Arrays.asList(getShellFolderRoots()));
directories.addAll(Arrays.asList(fileChooser.getFileSystemView().getChooserComboBoxFiles()));
} else {
directories.addAll(Arrays.asList(fileChooser.getFileSystemView().getRoots()));
}
Expand All @@ -1911,8 +1871,7 @@ private void addItem(File directory) {
}

// create File instances of each directory leading up to the top
File sf = useShellFolder? getShellFolderForFile(canonical) : canonical;
File f = sf;
File f = canonical;
Vector<File> path = new Vector<>(10);


Expand Down Expand Up @@ -1940,7 +1899,7 @@ private void addItem(File directory) {
}
}
calculateDepths();
setSelectedItem(sf);
setSelectedItem(canonical);
}

private void calculateDepths() {
Expand Down

0 comments on commit 12d71f4

Please sign in to comment.