Как отобразить сетевые ресурсы с помощью JFileChooser в Java 9+? - PullRequest
0 голосов
/ 07 ноября 2018

Пользователям нашего программного обеспечения необходимо просматривать сетевые ресурсы в Windows 10 в нашем приложении Java Swing, однако JFileChooser Swing по умолчанию не имеет этой возможности.

В этом посте Как перейти к сетевому узлу в JFileChooser? Приличное решение представлено с использованием ShellFolder (sun private API) для установки текущего каталога JFileChooser, и мы использовали этот подход с некоторыми изменениями за последние пару лет без проблем.

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException {
  final File file = new NonCanonicalizingFile( folder.getPath() );
  if( isNetworkShareFolder( file ) ) { // assume Win32ShellFolderManager2 will be present
     try {
        // JRE-13272 -PRIVATE API that must eventually be swapped for Java 9 alternative
        // Using reflection because Win32ShellFolderManager2 may not exist in rt.jar on Linux build server
        final Class win32ShellMgr = Class.forName( "sun.awt.shell.Win32ShellFolderManager2" );
        // get static creation method from class, execute it
        final Method cfMethod = win32ShellMgr.getMethod( "createShellFolder", File.class );
        return (ShellFolder) cfMethod.invoke( win32ShellMgr.newInstance(), file );
     } catch( final Exception xx ) {
        xx.printStackTrace();
     }
  }
  throw new IllegalArgumentException( "Given path is not a Windows network share folder." ); 
} 

Однако мы переходим на Java 11, а в Java 9 и далее частные API-интерфейсы инкапсулируются, и нам было поручено больше их не использовать. Не беспокойтесь, API замены в OpenJDK вошли в FileSystemView, в подпакет Swing Filechooser.

sun.awt.shell.ShellFolder.isComputerNode (Файл) -> javax.swing.filechooser.FileSystemView.getFileSystemView (). IsComputerNode (Файл) sun.awt.shell.ShellFolder.getShellFolder (Файл) -> javax.swing .filechooser.FileSystemView.getFileSystemView (). getLinkLocation (File)

поэтому предыдущий код теперь становится

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException {
   final File file = new NonCanonicalizingFile( folder.getPath() );
   if( isNetworkShareFolder( file ) ) { 
      try {
         return FileSystemView.getFileSystemView().getLinkLocation( file );
      } catch( final Exception xx ) {
         xx.printStackTrace();
      }
   }
   throw new IllegalArgumentException( "Given path is not a Windows network share folder." );
}

public static boolean isNetworkShareFolder( final File folder ) {
   return FileSystemView.getFileSystemView().isComputerNode( new NonCanonicalizingFile( folder.getPath() ) );
}

Это было бы здорово, но, к сожалению, ОБА getShellFolder () и getLinkLocation () генерируют исключение под Java 11, которое не было сгенерировано под Java 8.

java.nio.file.InvalidPathException: UNC-путь отсутствует имя_ресурса: \ 100.212.51.37 в java.base / sun.nio.fs.WindowsPathParser.parse (WindowsPathParser.java:118) в java.base / sun.nio.fs.WindowsPathParser.parse (WindowsPathParser.java:77) в java.base / sun.nio.fs.WindowsPath.parse (WindowsPath.java:92) в java.base / sun.nio.fs.WindowsFileSystem.getPath (WindowsFileSystem.java:229) в java.base / java.nio.file.Path.of (Path.java:147) в java.base / java.nio.file.Paths.get (Paths.java:69) в java.desktop / sun.awt.shell.ShellFolder.getShellFolder (ShellFolder.java:247) в java.desktop / javax.swing.filechooser.FileSystemView.getLinkLocation (FileSystemView.java:641)

Похоже, что теперь он считает UNC-пути недействительными, если у него нет действительного имени общего ресурса, то есть "\\ 100.212.51.37 \" недопустимо, но "\\ 100.212.51.37 \ myShare" в порядке.

Теперь, если вы получите папку оболочки для UNC-пути "\\ 100.212.51.37 \ myShare" и затем getParent (), вы получите папку оболочки для "\\ 100.212.51.37 \", которую мы хотели в первую очередь , К сожалению, этот обходной путь не подходит для наших клиентов из-за проблемы с курицей и яйцом - пользователи часто еще не знают ни одного из реальных имен общих ресурсов, это то, что они хотели просмотреть в первую очередь!

Argh - это хорошо работало в Java 8, но в Java 11, даже если вы нарушаете инкапсуляцию для использования оригинального частного API ShellFolder с помощью

'--add-exports', 'java.desktop/sun.awt.shell=ALL-UNNAMED'

Это не помогает, потому что предыдущее решение теперь выдает то же исключение в Java 11 (9+).

Другое решение, которое мы видели в StackOverflow, - это использование класса SmbFile в JCIFS , но из-за ограничений безопасности нам очень трудно использовать сторонний код. Особенно, если он не обновлен для Java 11 JPMS без использования частных API.

Интересно, что DirectoryChooser в JavaFX НЕ имеет этой проблемы. Если пользователь вручную вводит сетевой хост, он с удовольствием отобразит все имена общих ресурсов для этого хоста. Мы пойдем по этому пути, если придется, но иметь дело с модальностью между FX Stage над свинг-приложением - уродливо и потенциально очень много работы.

Все еще надеемся на более простой обходной путь, чтобы JFileChooser отображал сетевые ресурсы в Java 11 (Java 9+)! Может быть, кто-то знает хитрость, которую использует FX DirectoryChooser, и ее можно применить к JFileChooser?

1 Ответ

0 голосов
/ 10 апреля 2019

Все еще ищем лучшее решение, но в то же время мы решили заменить JFileChooser на JavaFX DirectoryChooser в Java 11 из-за сетевых ресурсов. DirectoryChooser более чем рад разрешить пользователю вводить общий сетевой ресурс, и он будет отображать все имена сетевых ресурсов. Пользовательский интерфейс, который запускает DirectoryChooser, все еще не изменен, но у нас нет проблем с модальностью или фокусировкой, по крайней мере, в Windows 10.

Однако у нас есть существенные недостатки, помимо необходимости тщательно управлять потоками между JavaFX Platform.runLater () и SwingUtilities.invokeLater ()

1) DirectoryChooser не допускает множественный выбор. JFileChooser делает.

2) DirectoryChooser ТОЛЬКО позволяет выбирать каталоги, а не файлы. Пожимает плечами Кому нужно было бы разрешить выбрать ЛИБО каталог или файл? Глупо. Только это именно то, что нужно нашим клиентам более чем в одном случае. JFileChooser поддерживает это.

3) DirectoryChooser не позволяет вводить недопустимый путь. А? Да, на самом деле, у одного из наших клиентов есть конкретное требование ввести путь, который еще не существует (предварительно сконфигурирован), но будет введен, как только целевой диск будет подключен к сети. JFileChooser позволяет это и может быть очень удобным для перехода к нужному корневому каталогу, а затем просто введите последнюю часть пути (имя каталога или общего ресурса).

4) DirectoryChooser не соответствует стилю приложения. В JavaFX вы можете установить свой собственный CSS в корневом узле вашей сцены, но не в DirectoryChooser. Кажется, что DirectoryChooser на самом деле вызывает собственный инструмент выбора файлов, который должен использовать цветовую схему системы. К сожалению, для наших пилотов, работающих ночью в «темном режиме», Windows 10 File Explorer НЕ учитывает настройки «темного режима» до версии 1809, которой почти никто из наших клиентов не обладает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...