I have created the following function which now gives me the required feedback independently of Commons IO, so I will now be able to migrate to 2.18.0
The function below is actually giving me more feedback about various scenarios which can go wrong so maybe this was a blessing in disguise. Dave import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributes; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.util.Set; public class RemoteShareChecker { private String errorMessage = ""; private void setErrorMessage(String message) { this.errorMessage = message; } public String getErrorMessage() { return this.errorMessage; } public boolean isValidPath(String path) { boolean result = true; Path remotePath = Paths.get(path); try { Files.readAttributes(remotePath, BasicFileAttributes.class); setErrorMessage("File is accessible: " + remotePath); if (Files.isRegularFile(remotePath)) { if (canDelete(remotePath)) { setErrorMessage("The file can be deleted."); } else { setErrorMessage("The file cannot be deleted due to permission or other restrictions."); result = false; } } if (Files.isRegularFile(remotePath)) { if (isFileLocked(remotePath)) { setErrorMessage("The file is locked by another process."); result = false; } else { setErrorMessage("The file is not locked."); } } } catch (NoSuchFileException e) { setErrorMessage("The file or directory does not exist: " + e.getFile()); result = false; } catch (AccessDeniedException e) { setErrorMessage("Access denied to the path: " + e.getFile()); result = false; } catch (FileSystemException e) { setErrorMessage("File system error: " + e.getMessage()); result = false; } catch (IOException e) { setErrorMessage("An I/O error occurred: " + e.getMessage()); result = false; } return result; } private boolean canDelete(Path path) { try { Path parentDir = path.getParent(); // Check if the parent directory is writable if (!Files.isWritable(parentDir)) { setErrorMessage("Parent directory is not writable: " + parentDir); return false; } // Platform-specific writable check if (!System.getProperty("os.name").toLowerCase().contains("win")) { PosixFileAttributes posixAttributes = Files.readAttributes(path, PosixFileAttributes.class); Set<PosixFilePermission> permissions = posixAttributes.permissions(); if (!permissions.contains(PosixFilePermission.OWNER_WRITE)) { setErrorMessage("File is not writable according to POSIX permissions: " + path); return false; } } else { DosFileAttributes dosAttributes = Files.readAttributes(path, DosFileAttributes.class); if (dosAttributes.isReadOnly()) { setErrorMessage("File is read-only: " + path); return false; } } return true; } catch (IOException e) { setErrorMessage("Error checking delete permissions: " + e.getMessage()); return false; } } private boolean isFileLocked(Path path) { // Attempt to open the file with exclusive access try (FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE)) { // File is not locked if we successfully open it return false; } catch (IOException e) { setErrorMessage("Error: Unable to open the file for write access. It may be locked."); return true; } } } > On 30 Dec 2024, at 22:43, Gary Gregory <garydgreg...@gmail.com> wrote: > > We had a unit test missing for this specific use case it seems. Maybe check > your test coverage (JaCoCo for example). > > Gary > > On Mon, Dec 30, 2024, 5:22 PM Dave Garratt <davegarratt1...@gmail.com> > wrote: > >> Well yes I suppose that would suffice - I’m just a little worried about >> how much code might be broken in my dependencies as well as my own code. >> >> Dave >> >>> On 30 Dec 2024, at 21:28, Ruby Paasche <r.paas...@pripares.com> wrote: >>> >>> How about `dir.exists()` maybe in combination with `dir.isDirectory()`? >>> >>> Dave Garratt <davegarratt1...@gmail.com <mailto: >> davegarratt1...@gmail.com>> schrieb am Mo., 30. Dez. 2024, 22:21: >>>> I’m not sure if I understand if the usefulness of the behaviour in all >> versions up to and including 2.17.0 is a bug unless something else is >> happening which I’m unaware of. >>>> >>>> Assuming the ability to detect a path / network url is no longer valid >> has gone it begs the question- is there some other mechanism within commons >> io which can be used to detect the same issue. >>>> >>>> The application which I develop runs as a middleware solution and as a >> service. When a network url is no longer available I generate an alert via >> an email. >>>> >>>> My code simply loops around check for the presence of files in a folder >> constantly. >>>> >>>> With the new behaviour I won’t be able to detect and report on a >> failure of this kind. >>>> >>>> Thanks >>>> >>>> Dave >>>> >>>> >>>> ‑‑ >>>> Ruby Paasche >>>> Senior Entwicklerin >>>> <image493809.png> <https://www.linkedin.com/company/pripares-gmbh> >>>> PRIPARES Software Solutions GmbH >>>> Ridlerstraße 57 >>>> 80339 München >>>> Tel: >>>> +49 (0)89 45 22 808 ‑ 30 >>>> Email: >>>> r.paas...@pripares.com >>>> Web: >>>> https://pripares.com <https://pripares.com/> >>>> Handelsregister: Registergericht München HRB 138701 >>>> Sitz der Gesellschaft: München >>>> Geschäftsführer: Aßmann Christoph, Ertl Andreas >>>> >>>> Diese E‑Mail enthält vertrauliche und/oder rechtlich geschützte >> Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E‑Mail >> irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und >> löschen Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte >> Weitergabe dieser Mail und der darin enthaltenen Informationen sind nicht >> gestattet. >>>> >>>> This e‑mail may contain confidential and/or privileged information. If >> you are not the intended recipient (or have received this e‑mail in error) >>>> please notify the sender immediately and delete this e‑mail. Any >> unauthorized copying, disclosure or distribution of the material in this >> e‑mail is strictly forbidden. >>>>> On 30 Dec 2024, at 19:49, Gary D. Gregory <ggreg...@apache.org >> <mailto:ggreg...@apache.org>> wrote: >>>>> >>>>> It looks like this change with by design for >> https://issues.apache.org/jira/browse/IO-856 >>>>> >>>>> Gary >>>>> >>>>>> On 2024/12/30 17:54:17 "Gary D. Gregory" wrote: >>>>>> Hm, we'll have to look into that one. In the meantime, I added >>>>>> >>>>>> org.apache.commons.io <http://org.apache.commons.io/ >>> .FileUtilsListFilesTest.testListFilesMissing() >>>>>> >>>>>> which asserts the current behavior in git master. >>>>>> >>>>>> TY, >>>>>> Gary >>>>>> >>>>>>> On 2024/12/30 17:00:17 Dave Garratt wrote: >>>>>>> >>>>>>> I have recently tried updating from Commons IO 2.16.1 to Commons IO >> 2.18.0 >>>>>>> >>>>>>> My java program constantly polls a folder for the presence of >> files. Normally this will be a remote folder on a windows share. >>>>>>> >>>>>>> In Commons IO 2.16.1 when I use FileUtils.listFiles it would >> trigger an exception if the folder being polled became unavailable and I >> would use this to trigger an action. >>>>>>> >>>>>>> In Commons IO 2.18.0 the error does not occur. >>>>>>> >>>>>>> I have created a very simple test program to illustrate this. >>>>>>> >>>>>>> Running this code with Commons IO 2.16.1 and passing an invalid >> (non existent) path to it gives me the following exception (which in my >> case is desirable): >>>>>>> >>>>>>> import java.io.File; >>>>>>> >>>>>>> import org.apache.commons.io <http://org.apache.commons.io/ >>> .FileUtils; >>>>>>> >>>>>>> public class Test2161 >>>>>>> { >>>>>>> >>>>>>> public static void main(String[] args) >>>>>>> { >>>>>>> File dir = new File("/Users/dave/Downloads/nonexistent"); >>>>>>> >>>>>>> try >>>>>>> { >>>>>>> FileUtils.listFiles(dir, args, false); >>>>>>> } >>>>>>> catch (Exception ex) >>>>>>> { >>>>>>> System.out.println(ex.getMessage()); >>>>>>> ex.printStackTrace(); >>>>>>> } >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> java.nio.file.NoSuchFileException: /Users/dave/Downloads/nonexistent >>>>>>> java.io.UncheckedIOException: java.nio.file.NoSuchFileException: >> /Users/dave/Downloads/nonexistent >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .function.Uncheck.wrap(Uncheck.java:339) >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .function.Uncheck.get(Uncheck.java:199) >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .FileUtils.listFiles(FileUtils.java:2313) >>>>>>> at Test2161.main(Test2161.java:14) >>>>>>> Caused by: java.nio.file.NoSuchFileException: >> /Users/dave/Downloads/nonexistent >>>>>>> at >> java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) >>>>>>> at >> java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) >>>>>>> at >> java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) >>>>>>> at >> java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55) >>>>>>> at >> java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:148) >>>>>>> at java.base/java.nio.file.Files.readAttributes(Files.java:1851) >>>>>>> at >> java.base/java.nio.file.FileTreeWalker.getAttributes(FileTreeWalker.java:226) >>>>>>> at >> java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:277) >>>>>>> at >> java.base/java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:323) >>>>>>> at >> java.base/java.nio.file.FileTreeIterator.<init>(FileTreeIterator.java:71) >>>>>>> at java.base/java.nio.file.Files.walk(Files.java:3918) >>>>>>> at org.apache.commons.io.file.PathUtils.walk(PathUtils.java:1847) >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .FileUtils.streamFiles(FileUtils.java:2952) >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .FileUtils.lambda$listFiles$10(FileUtils.java:2313) >>>>>>> at org.apache.commons.io <http://org.apache.commons.io/ >>> .function.Uncheck.get(Uncheck.java:197) >>>>>>> ... 2 more >>>>>>> >>>>>>> >>>>>>> >>>>>>> If however I run the same code with Commons IO 2.18.0 I get >> nothing, no indication that the path is not valid which make it difficult >> to determine if the folder is empty or the remote file server is shutdown. >>>>>>> >>>>>>> Am I supposed to use a different way to accomplish the same error >> condition now ? >>>>>>> >>>>>>> Thanks >>>>>>> >>>>>>> Dave >>>>>>> >>>>>>> >>>>>>> >> --------------------------------------------------------------------- >>>>>>> To unsubscribe, e-mail: user-unsubscr...@commons.apache.org >> <mailto:user-unsubscr...@commons.apache.org> >>>>>>> For additional commands, e-mail: user-h...@commons.apache.org >> <mailto:user-h...@commons.apache.org> >>>>>>> >>>>>>> >>>>>> >>>>>> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: user-unsubscr...@commons.apache.org <mailto: >> user-unsubscr...@commons.apache.org> >>>>>> For additional commands, e-mail: user-h...@commons.apache.org >> <mailto:user-h...@commons.apache.org> >>>>>> >>>>>> >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: user-unsubscr...@commons.apache.org <mailto: >> user-unsubscr...@commons.apache.org> >>>>> For additional commands, e-mail: user-h...@commons.apache.org >> <mailto:user-h...@commons.apache.org> >>>>> >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: user-unsubscr...@commons.apache.org <mailto: >> user-unsubscr...@commons.apache.org> >>>> For additional commands, e-mail: user-h...@commons.apache.org <mailto: >> user-h...@commons.apache.org> >>>> >> >>