I'm currently using ShellFolder.getShellFolder() to determine if a particular path is on a local drive (directly connected to Windows machine) or a remote drive.
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;
}
}
This works fine on Java 8
I am now moving to Java 11, I am using maven to compile the project and if I increase the source parameter for compiler from 8 to 9 (or above)
<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>
I get compile failure (keeping at 8 and setting target to 11 is okay) because of the introduction of the module system
[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
So I am looking for an alternative way to this, either:
- Is there way a way to set src to 11 and allow compile by utilising some module option
- Preferably can I reliably detect if local or remote drive using standard java libs
The reason I need is isLocal() is my program renames files and there is an option for the user to restrict path length to 259 characters because longer lengths cause problems for Windows Explorer, but if they are modifying a remote drive then not usual to enforce this requirement, I will add more detail to question.
For example the application renames music files if they are on local drive to be used by Windows then they may want to enforce that limit. But if it is a networked drive they probably will not because quite often the files are stored on a Nas and they are only accessing the files via Windows because my application can run on Windows but not on the Nas.