I am using the spring Resource API and using a ResourcePatternResolver to scan my classpath for files.
In one situation the scan is picking up some directories and files that are in a pre-built jar and some that are on the file system.
In either case a 'resource' will either be a file or a directory. How can I reliably detect whether a resource points to a directory or file, whether in a jar file or not? Calling getFile()
on a Resource inside a jar throws an Exception so I can't use that plus isFile()
as I initially tried.
Spring’s
Resource
interface is meant to be a more capable interface for abstracting access to low-level resources.It wraps File sometimes while sometimes not.
It has six built-in implements:
UrlResource
,ClassPathResource
,FileSystemResource
,ServletContextResource
,InputStreamResource
,ByteArrayResource
.You can implement yourself resource form.
The
UrlResource
wraps ajava.net.URL
, and may be used to access any Object that is normally accessible via a URL. If you usehttp:
prefix ,the resource is a URL.The
ClassPathResource
represents a resource which should be obtained from the classpath. ThisResource
implementation supports resolution asjava.io.File
if the class path resource resides in the file system, but not for classpath resources which reside in a jar and have not been expanded (by the servlet engine, or whatever the environment is) to the filesystem. To address this the variousResource
implementations always support resolution as ajava.net.URL
.FileSystemResource
is an implement forjava.io.File
handles.It obviously supports resolution as aFile
and as aURL
.InputStreamResource
is a resource implements for a givenInputStream
. Do not use it if you need to keep the resource descriptor somewhere, or if you need read a stream multiple times.ByteArrayResource
is aResource
implement for a given byte array. It creates a ByteArrayInputStream for the given byte array.So you should not always use
getFile()
as Spring'sResource
doesn't always represent a file system resource.For this reason, we recommend that you usegetInputStream()
to access resource contents because it is likely to function for all possible resource types.Refer to: Resources
I had a similar requirement, and solved it by excluding directories from my search pattern. Then for each resource found I lookup the parent item in the path, and ensure the directory has been created before writing the file.
In my case the file could be in the filesystem, or in the classpath, so I check the scheme of the URI first..
Although my search pattern may still pickup dirs if they have a dot in the name, so it would be better to catch the exception in that case -
search pattern -
classpath*:/**/sprout/plugins/**/*.*
Example code -
Using it in this project -
https://github.com/savantly-net/sprout-platform/blob/master/sprout-core/src/main/java/net/savantly/sprout/core/ui/UiLoader.java
I think you can just surround the code checking for file by a try catch block: