Michael Lipp a écrit le 16/05/2017 à 23:39 :
> Hi,
> 
> I searched to no avail. Does anybody know of an implementation of
> FileSystemProvider
> (https://docs.oracle.com/javase/7/docs/api/java/nio/file/spi/FileSystemProvider.html)
> that supports the "bundle:" scheme (similar to the Zip File System
> Provider:
> https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html)?
> 
> I have code that relies on a directory tree of resources to be available
> as NIO FileSystem. This is no problem when the using the "ordinary"
> class loading. The "root" is found using a resource lookup (URI resSrc =
> this.getClass().getResource("").toURI();). This returns a URI with
> scheme "jar", which can be passed to FileSystems.newFileSystem. When
> running in the OSGi environment, I get a URI with the "bundle" scheme...

Hi,

I have searched before and did not find any. Here's a summary of my
previous exploration on the topic:

My conclusion is that there is no proper way to do it without being the
system bundle. The thing is Nio Filesystems have non-blocking IO methods
(eg AsynchronousFileChannels) and Bundles are opaque, might be stored in
memory (e.g installing/updating a bundle from an InputStream). A partial
solution for bundles only stored in disk is not reliable either, because
the bundle "location" can be anything, and is rarely if ever an absolute
path... recomposing an absolute path from the workingDir + the location
might work in some cases, but that's super hackish.  Then, the only way
to work with them is blocking (reading a resource can only be done
through URL#openStream())

Blocking methods from the NIO filesystem provider could be implemented
on top of those, but the non-blocking ones would have to be backed by a
thread-pool, read extra bytes (it's possible with an
AsyncFileChannel/RandomAccessFile to start reading at a random position)
and in that case you might as well go for blocking methods and be "fake
non-blocking" with your own thread-pool. Or they could throw
UnsupportedOperationException, but that would probably break your
consumer code, and it's a bit sad considering that's a big part of what
Nio filesystems add to the File API!

Because this probably requires a significant refactor of existing system
bundles, my quick solution has been to lazily copy Bundle resources,
when asked for, to the bundle storage area, and then use the regular
filesystem API (since the bundle storage area is on disk). You can see
how it's used there [1] (I happen to wrap it in reactive streams [2] for
composition)

Why go through all the trouble? First benefit is using nio.Files/Path
API to abstract over different file-systems, another is to be able to
have back-pressure with non-blocking consumers.

The good news is, because those URLs are of the form
bundle://<bundleId>.<bundleRevision>/resource, it does not need an
update of the OSGi APIs, the system bundle can implement it, however as
far as I know there are no implementation for open source frameworks,
maybe there are on some proprietary ones ; and maybe it should be part
of a future OSGi core spec, because that code is going to break on
frameworks not implementing the extension!

While it does not seem too hard to implement for bundles that stored on
a file system (default filesystem provider), or as a jar file (zip
filesystem), it is probably trickier for in memory-bundles: however
there are existing open source in-memory filesystems like jimfs that
could be used as a back-end, and the current Bundle IO/resource methods
could wrap Jimfs newInputStream() calls.

Hope this helps,

Simon

[1]
https://github.com/primeval-io/primeval-codex/blob/master/src/test/java/io/primeval/codex/io/impl/ResourceFinderReaderImplTest.java
[2] http://www.reactive-streams.org/



_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to