Замена или способ использования ShellFolder.getShellFolder () на Java 11 - PullRequest
0 голосов
/ 10 апреля 2020

В настоящее время я использую ShellFolder.getShellFolder () , чтобы определить, находится ли конкретный путь на локальном диске (напрямую подключенном к Windows машине) или на удаленном диске.

package com.jthink.songkong.analyse.analyser;

import com.jthink.songkong.analyse.filename.WindowsFileSystem;
import com.jthink.songkong.ui.MainWindow;
import sun.awt.shell.ShellFolder;
import sun.awt.shell.ShellFolderColumnInfo;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;

/**
 * Only Windows can load these methods because of reliance on sun classes
 *
 */
public class WindowsFilesystemType
{

    public static final String WINDOWS_SHELL_ATTRIBUTES = "Attributes";
    public static final String WINDOWS_SHELL_ITEM_TYPE = "Item type";
    public static final String WINDOWS_SHELL_SIZE = "Size";
    /**
     * Is Windows NTFS or FAT32
     *
     * @param newPath
     * @return
     */
    public static boolean isNTFSOrFAT32(String newPath)
    {
        Path root = Paths.get(newPath).getRoot();
        if (root == null)
        {
            return false;
        }
        try
        {
            FileStore fs = Files.getFileStore(root);
            if (fs.type().equals(WindowsFileSystem.NTFS)
                    || fs.type().equals(WindowsFileSystem.FAT)
                    || fs.type().equals(WindowsFileSystem.FAT32)
                    || fs.type().equals(WindowsFileSystem.EX_FAT))
            {
                return true;
            }
            return false;
        }
        catch (IOException ex)
        {
            MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
            return false;
        }
    }

    /**
     * Is this a remote drive, only works for Windows because relies on underlying Windows code
     *
     * @param newPath
     *
     * @return true if this a remote (Network) drive
     */
    public static boolean isRemote(String newPath)
    {
        try
        {
            Path root = Paths.get(newPath).getRoot();
            ShellFolder shellFolder = ShellFolder.getShellFolder(root.toFile());
            ShellFolderColumnInfo[] cols = shellFolder.getFolderColumns();
            for (int i = 0; i < cols.length; i++)
            {
                if (cols[i].getTitle().equals(WINDOWS_SHELL_SIZE)
                        &&  ((String) shellFolder.getFolderColumnValue(i)).startsWith(WindowsShellFileSystemType.NETWORK_DRIVE))
                {
                    return true;
                }
                else if (cols[i].getTitle().equals(WINDOWS_SHELL_ATTRIBUTES)
                        &&  ((String) shellFolder.getFolderColumnValue(i)).startsWith("\\"))
                {
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            return false;
        }
        return false;
    }

    /**
     * Is this a local drive, only works for Windows because relies on underlying Windows code
     *
     * @param newPath
     *
     * @return true if this a local drive
     */
    public static boolean isLocal(String newPath)
    {
        try
        {
            Path root = Paths.get(newPath).getRoot();
            ShellFolder shellFolder = ShellFolder.getShellFolder(root.toFile());
            ShellFolderColumnInfo[] cols = shellFolder.getFolderColumns();
            for (int i = 0; i < cols.length; i++)
            {
                if (cols[i].getTitle().equals(WINDOWS_SHELL_SIZE)
                        &&  ((String) shellFolder.getFolderColumnValue(i)).startsWith(WindowsShellFileSystemType.LOCAL_DISK))
                {
                    return true;
                }
                else if (cols[i].getTitle().equals(WINDOWS_SHELL_ATTRIBUTES)
                        &&  ((String) shellFolder.getFolderColumnValue(i)).startsWith("\\"))
                {
                    return false;
                }
            }
        }
        catch (Exception ex)
        {
            return true;
        }
        return true;
    }

}

Это прекрасно работает на Java 8

. Сейчас я перехожу на Java 11, я использую maven для компиляции проекта и, если я увеличу исходный код параметр для компилятора от 8 до 9 (или выше)

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <compilerVersion>11</compilerVersion>
                    <source>8</source>
                    <target>11</target>
                    <verbose>true</verbose>
                    <fork>true</fork>
                </configuration>
            </plugin>

Я получаю ошибку компиляции (сохранение на 8 и установка целевого значения на 11 в порядке ) из-за введения системы модулей

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] c:\Code\jthink\SongKong\src\main\java\com\jthink\songkong\analyse\analyser\WindowsFilesystemType.java:[5,14] error: package sun.awt.shell is not visible
  (package sun.awt.shell is declared in module java.desktop, which does not export it)
[ERROR] c:\Code\jthink\SongKong\src\main\java\com\jthink\songkong\analyse\analyser\WindowsFilesystemType.java:[6,14] error: package sun.awt.shell is not visible
  (package sun.awt.shell is declared in module java.desktop, which does not export it)
[INFO] 2 errors

Так что я ищу альтернативный путь к этому, либо:

  1. Есть ли способ установить sr c до 11 и разрешить компиляцию с использованием некоторой опции модуля
  2. Предпочтительно я могу надежно определить, использует ли локальный или удаленный диск стандартные java libs

1 Ответ

0 голосов
/ 13 апреля 2020

Кажется, на данный момент нет замены функциональности, которая мне требуется в стандартном Java API (определение на Windows, если путь удаленный или локальный).

Так что выбор между продолжением использования класса non-publi c, который может отсутствовать в будущем, или написанием хакерского кода для взаимодействия с командой операционной системы (net), которая может измениться в будущем.

Так что прагматическое c решение для меня - продолжать использовать класс non publi c и надеяться, что что-то будет добавлено в apli publi c, если это не так и не Класс publi c удален, и мне нужно будет написать код, чтобы поговорить с net на этом этапе.

Чтобы разрешить доступ к этому неопубликованному классу c во время компиляции с использованием Maven, я добавил следующее к плагину компилятора

 <compilerArgs>
     <arg>--add-exports=java.desktop/sun.awt.shell=ALL-UNNAMED</arg>
 </compilerArgs>

например

   <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
            <encoding>UTF-8</encoding>
            <compilerVersion>11</compilerVersion>
            <source>11</source>
            <target>11</target>
            <verbose>true</verbose>
            <fork>true</fork>
            <compilerArgs>
                <arg>--add-exports=java.desktop/sun.awt.shell=ALL-UNNAMED</arg>
            </compilerArgs>
        </configuration>
    </plugin>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...