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>
>>>> 
>> 
>> 

Reply via email to