Git Product home page Git Product logo

jimfs's Introduction

Jimfs

Jimfs is an in-memory file system for Java 8 and above, implementing the java.nio.file abstract file system APIs.

Build Status Maven Central

Getting started

The latest release is 1.3.0.

It is available in Maven Central as com.google.jimfs:jimfs:1.3.0:

<dependency>
  <groupId>com.google.jimfs</groupId>
  <artifactId>jimfs</artifactId>
  <version>1.3.0</version>
</dependency>

Basic use

The simplest way to use Jimfs is to just get a new FileSystem instance from the Jimfs class and start using it:

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
...

// For a simple file system with Unix-style paths and behavior:
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path foo = fs.getPath("/foo");
Files.createDirectory(foo);

Path hello = foo.resolve("hello.txt"); // /foo/hello.txt
Files.write(hello, ImmutableList.of("hello world"), StandardCharsets.UTF_8);

What's supported?

Jimfs supports almost all the APIs under java.nio.file. It supports:

  • Creating, deleting, moving and copying files and directories.
  • Reading and writing files with FileChannel or SeekableByteChannel, InputStream, OutputStream, etc.
  • Symbolic links.
  • Hard links to regular files.
  • SecureDirectoryStream, for operations relative to an open directory.
  • Glob and regex path filtering with PathMatcher.
  • Watching for changes to a directory with a WatchService.
  • File attributes. Built-in attribute views that can be supported include "basic", "owner", "posix", "unix", "dos", "acl" and "user". Do note, however, that not all attribute views provide useful attributes. For example, while setting and reading POSIX file permissions is possible with the "posix" view, those permissions will not actually affect the behavior of the file system.

Jimfs also supports creating file systems that, for example, use Windows-style paths and (to an extent) behavior. In general, however, file system behavior is modeled after UNIX and may not exactly match any particular real file system or platform.

License

Copyright 2013 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

jimfs's People

Contributors

ascopes avatar asiekierka avatar bhamiltoncx avatar cgdecker avatar cgruber avatar chaoren avatar cpovirk avatar cushon avatar dependabot[bot] avatar dimo414 avatar godin avatar jasontedor avatar java-team-github-bot avatar jiangji avatar kluever avatar mbarbero avatar nick-someone avatar ronshapiro avatar sahmed10315 avatar scordio avatar sullis avatar szpak avatar tianyin avatar turbanoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jimfs's Issues

JimfsFileStore.getUsableSpace() returning .getTotalSpace()

FileStore.getUsableSpace() should be at most equal to FileStore.getUnallocatedSpace(). Here's a code sample that shows otherwise in the case of JimfsFileStore:

final FileSystem filesystem = Jimfs.newFileSystem(
        Configuration.unix().toBuilder().setMaxSize(100000).build());
final Path file = filesystem.getPath("/somefile");
final FileStore filestore = Files.getFileStore(file);
System.out.println("Before: total space = " + filestore.getTotalSpace());
System.out.println("Before: usable space = " + filestore.getUsableSpace());
System.out.println("Before: unallocated space = " + filestore.getUnallocatedSpace());

Files.write(file, new byte[50000]);
System.out.println("After: total space = " + filestore.getTotalSpace());
System.out.println("After: usable space = " + filestore.getUsableSpace());
System.out.println("After: unallocated space = " + filestore.getUnallocatedSpace());

Here's the output I get:

Before: total space = 98304
Before: usable space = 98304
Before: unallocated space = 98304
After: total space = 98304
After: usable space = 98304
After: unallocated space = 40960

Allow mutable File Size attribute and/or overriding Attribute providers

Hey guys,

I'm looking to use JimFS to test some logic around a File system visitor I've written thats very sensitive to both the timestamp that a file is modified (โœ“ -- BasicAttributeProvider supports setLastModifiedTime) and how large that file is (โœ— -- BasicAttributeProvider throws unsettable for any attemps to set the size).

There are a couple of workarounds I can currently employ:

  • our domain logic involves looking at files that are many megabytes big --making creation of these files in an in-memory file system distasteful, but I can probably inject these size & threshold values into our service components to have our logic trigger on much smaller files, and then simply create files on the order of a few kilobytes in memory.
  • I can wrap all of our length testing operations in an interface and simply have that interface supply me with the setLength operation I need in a testing environment. This has a little bit of a tricky life cycle requirement --I need to make sure the right objects get the right instances, but it would do the job.

That said, support from JimFS for setting the size attribute would allow me to write code that is a step closer to what is actually running in deployment.

Any chance you guys would consider making the file size settable? I understand that this leads to a number of logical inconsistencies (the most obvious: what do we do if we open a stream to a file whose length was programmatically set?)

One solution might be to allow users to write custom AttributeProvider objects and register them with JimFS. This would require exposing the File instances you guys keep to programmers, and would require that JimFS use some kind of hierarchical search scheme when looking up which Attribute provider to use, but would allow for a great deal of flexibility.

WatchService drops all changes after the first event

When running a reasonably simple test with the watch service, I simply cant get it to post a second event, regardless of the changes made to the file.

    @Test(timeout = 5000) fun `when using jimfs should properly see multiple changes to file`(){
        val pollTimeMillis: Long = 20

        val config = Configuration
                .windows()
                .toBuilder()
                //speed things up for the sake of testing, for in-memory changes a delay of 20ms should suffice.
                .setWatchServiceConfiguration(WatchServiceConfiguration.polling(pollTimeMillis, TimeUnit.MILLISECONDS))
                .build()
        val fs = Jimfs.newFileSystem(config)

        val folder = fs.getPath("dir")
        val testFile = folder.resolve("asdf.txt")
        Files.createDirectory(folder)
        Files.createFile(testFile)

        val watch = fs.newWatchService()

        folder.register(watch, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY)

        print("writing first change...")
        Files.write(testFile, "first".toByteArray())
        // I saw from source code that jimFS was looking at file time changes
        // and I'm not sure if its NTFS+win32 or the JVM thats responsible for those changes,
        // so I figured I'd make them myself.
        // Doesnt seem to have any impact
        Files.setLastModifiedTime(testFile, FileTime.from(Instant.now()))
        println("done")
        println("waiting for notification of first change...")
        watch.take()
        println("done")

        println("sleeping to let polling finish")
        Thread.sleep(pollTimeMillis * 5)

        println("writing second change...")
        Files.write(testFile, "second".toByteArray())
        Files.setLastModifiedTime(testFile, FileTime.from(Instant.now()))
        println("done")
        println("waiting for notification of second change...")
        val secondChange = watch.take()
        println("done")

        println("test passed!")
    }

actual test times out
expected: more println statements, namely "waiting for notification of second change... done"

Unexpected behaviour of Path.resolve where other path does not yet exist

Is this expected behaviour? Similar behaviour on real filesystems are able to invoke Path.resolve(otherPath), where otherPath does not exist.

final FileSystem posixCompliantFs = Jimfs.newFileSystem(Configuration.unix().toBuilder().setAttributeViews("posix").build());
final Path rootPath = Files.createFile(posixCompliantFs.getPath("/root-path"));
final Path relativePath = Files.createFile(rootPath.resolve("x"));
java.nio.file.NoSuchFileException: /root-path/x
    at com.google.common.jimfs.FileTree.lookUp(FileTree.java:91)
    at com.google.common.jimfs.JimfsFileStore.lookUp(JimfsFileStore.java:138)
    at com.google.common.jimfs.FileSystemView.lookUp(FileSystemView.java:123)
    at com.google.common.jimfs.FileSystemView.createFile(FileSystemView.java:270)
    at com.google.common.jimfs.FileSystemView.getOrCreateRegularFileWithWriteLock(FileSystemView.java:349)
    at com.google.common.jimfs.FileSystemView.getOrCreateRegularFile(FileSystemView.java:312)
    at com.google.common.jimfs.JimfsFileSystemProvider.newJimfsFileChannel(JimfsFileSystemProvider.java:232)
    at com.google.common.jimfs.JimfsFileSystemProvider.newByteChannel(JimfsFileSystemProvider.java:240)
    at java.nio.file.Files.newByteChannel(Files.java:361)
    at java.nio.file.Files.createFile(Files.java:632)

Using jimfs when not loaded by application server

It was discovered a problem regarding use of jimfs (and other FileSystemProviders in general) on Wildfly/JBoss when developing our software. The related issue may be found here:
anskaffelser/vefa-validator#9

As of version 1.1 is our fix not supported any more, so I'm wondering if I could please have some help on how to implement this in such a way that I can upgrade to use version 1.1 and later versions.

Calling Path.toUri() on a directory should return a URI with a trailing slash

The default file system provider returns URI's with trailing slashes if the URI is known to refer to a directory. This only way to know for sure if a URI refers to a directory or a file is if the directory actually exists on disk. For example:

    Path rootPath = Paths.get(URI.create("file:/"));
    System.out.println(rootPath.toUri());
    Path dir1 = rootPath.resolve("dir1");
    System.out.println(dir1.toUri());
    Path dir1Path = Files.createDirectory(dir1);
    System.out.println(dir1.toUri());
    System.out.println(dir1Path.toUri());

If C:\dir1\ does not exist before running this code, the result will be:

file:///C:/
file:///C:/dir1
file:///C:/dir1/
file:///C:/dir1/

Notice that dir1.toUri() does not contain a trailing slash before the directory is created, but it does contain a trailing slash afterward.

I have verified this same behavior on OSX as well.

Add OSGi headers to generated manifest

Currently the generated manifest does not contain any OSGi-headers. This can be fixed easily by using the maven-bundle-plugin (see http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html) for packaging instead of the default jar plugin. Latest version of that plugin is currently 2.4.0.

Note: This change makes Jimfs fully work in an OSGi environment when you instantiate JimfsFileSystemProvider directly. If you go the official way through the Jimfs facade you will face classloading issues.

Make polling frequency in PollingWatchService configurable

The WatchService implementation in PollingWatchService uses a hard coded polling frequency (5 seconds). Currently I need to sleep relatively long in my tests in order to receive the event. It would be nice if this could be configured at file system creation time (e.g. by adding something to Configuration.builder()).

Obtaining a URL from a jimfs Path

A framework I'm testing internally needs to obtain an URL from a passed in path. For testing, I'd like to use jimfs, but obtaining a URL from a jimfs path seems not to be possible. Calling path.toUri().toURL() throws a MalformedURLException with message: java.net.MalformedURLException: unknown protocol: jimfs. Is this something fixable or something to live with? Here is a simpe test case to reproduce:

import java.net.MalformedURLException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.Path;

import org.junit.Test;

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;

public class JimFSTest {

    @Test
    public void testGetURL() throws MalformedURLException {
        final FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
        final Path path = fs.getPath("foo", "bar");
        final URI uri = path.toUri();
        uri.toURL();
    }
}

Edit: I just found out that one can implement a URLStreamHandlerFactory to accomplish this. You might consider to ship a suitable implementation for jimfs.

Cannot use with apache sshd/sftp

Hi, I'd like to use this with apache sshd/sftp but, alas, it barfs out trying to set a permission:

DEBUG [2016-09-19 20:39:19,637] sshd-SftpSubsystem-thread-1 - org.apache.sshd.server.subsystem.sftp.SftpSubsystem doOpen(ServerSessionImpl[dball@/0:0:0:0:0:0:0:1:60555])[id=2] SSH_FXP_OPEN (path=/project.clj, access=0x102, pflags=0x1, attrs={permissions=[OWNER_READ, OWNER_WRITE, GROUP_READ, OTHERS_READ]})
TRACE [2016-09-19 20:39:19,637] sshd-SftpSubsystem-thread-1 - org.apache.sshd.server.subsystem.sftp.SftpSubsystem resolveFile(ServerSessionImpl[dball@/0:0:0:0:0:0:0:1:60555]) /project.clj => /project.clj
TRACE [2016-09-19 20:39:19,638] sshd-SftpSubsystem-thread-1 - org.apache.sshd.server.subsystem.sftp.SftpSubsystem generateFileHandle(ServerSessionImpl[dball@/0:0:0:0:0:0:0:1:60555])[/project.clj] 1d31de562edf35d4c1bfe97865ddb206
DEBUG [2016-09-19 20:39:19,639] sshd-SftpSubsystem-thread-1 - org.apache.sshd.server.subsystem.sftp.SftpSubsystem doSendStatus(ServerSessionImpl[dball@/0:0:0:0:0:0:0:1:60555])[id=2] SSH_FXP_STATUS (substatus=SSH_FX_INVALID_PARAMETER, lang=, msg=java.lang.IllegalArgumentException: cannot set attribute 'basic:permissions')

It's unusual to my untrained eye that the sftp subsystem is trying to set a basic:permissions attribute. I would have guessed it should try to set a posix:permissions attribute.

Do you think the bug is in sshd or in jimfs?

JimFS doesn't handle file locks in documented way (OverlappingFileLockException)

If I try to lock regular file then locking it the second time will raise OverlappingFileLockException as described in FileChannel documentation

JimFS allows to lock the same file multiple times. Here is a test code

    public void testJimfsLock() throws IOException {

        FileSystem jimFs = Jimfs.newFileSystem();
        FileSystem fs = FileSystems.getDefault();

        checkLock(jimFs.getPath("/lockfile"));
        checkLock(fs.getPath("/tmp/lockfile"));

    }

    private void checkLock(Path lockFilePath) throws IOException {
        System.out.println("lockFilePath=" + lockFilePath);
        FileChannel fileChannel = FileChannel.open(lockFilePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
        FileLock lock1 = fileChannel.lock();
        FileLock lock2 = null;
        try {
            lock2 = fileChannel.tryLock();
        } catch (OverlappingFileLockException e) {
            System.out.println("got OverlappingFileLockException");
        }

        System.out.println("lock1=" + lock1);
        System.out.println("lock2=" + lock2);
    }

It will print the following output:

lockFilePath=/lockfile
lock1=com.google.common.jimfs.JimfsFileChannel$FakeFileLock[0:9223372036854775807 exclusive valid]
lock2=com.google.common.jimfs.JimfsFileChannel$FakeFileLock[0:9223372036854775807 exclusive valid]
lockFilePath=/tmp/lockfile
got OverlappingFileLockException
lock1=sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]
lock2=null

As you see attempting to lock file for the second time on regular file system leads to OverlappingFileLockException.

Create extra tools to help know the internal status of the file system

Is there any way to have tools that work like unix commands but on Jimfs? I think about ls -l, find, etc.

Usually when tests are developed on a physical file system, we use directly commands like ls and find to understand the current status. That solution is the pragmatic way of working. This is also why there are no library that does it already (to my knowledge, and after a thorough search).

With Jimfs, the fs is not persistent and therefore I cannot use external tools. This is why I specifically request this for Jimfs.

The goal here is mostly to know what is the current status of the memory fs. For instance when you work with several files and some give errors I want to be able to know exactly what I have on my fs.

Currently, my workaround is to develop tests on an actual fs and then switch to Jimfs when the test is stable so that I don't need to use the CI actual hard drive.

PathMatcher does not respect pathEqualityUsesCanonicalForm setting

I'm writing a test by emulating a windows file system like so:

Configuration.windows().toBuilder().setRoots("C:\\").build()

The built-in windows configuration has the right settings for case sensitivity:

.setNameCanonicalNormalization(CASE_FOLD_ASCII)
.setPathEqualityUsesCanonicalForm(true) // matches real behavior of WindowsPath

However, the following matcher does not accept files having a TXT extension: fileSystem.getPathMatcher("glob:**.txt")

Looking into the implementation, it seems like the GlobToRegex class should check the actual normalization settings.

Transitive deps not resolved in non OSGi build

When depending on jimfs with without specifying the type, i.e. it defaults to:

<type>jar</type>

... Guava (as a 'required' transitive dependency) is not being resolved. I suspect this has something to do with jimfs being published as an OSGi bundle, i.e.:

<type>bundle</type

Explicitly pulling in Guava works as a work-around:

<dependency>
    <groupId>com.google.jimfs</groupId>
        <artifactId>jimfs</artifactId>
    <version>1.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
    <scope>test</scope>
</dependency>

Never have used OSGi packaging with Maven, does this have something to do with the way jimfs is being published to Maven Central?

Interrupt behaviour deviations

The methods bellow deviate from the default FileSystem implementation in their behaviour to interrupts. If a thread is interrupted when or "while" calling these methods, then the method must throw a ClosedByInterruptException and the channel must be closed:

  • FileChannel.position(long)
  • FileChannel.position()
  • FileChannel.size()
  • FileChannel.force(boolean)

There might be other methods that deviate besides these, but these are the ones that my tests caught. Correct interrupt behaviour is important to me, because my code needs to correctly cope with stray interrupts, which I obviously have to test for.

Support assertion that all resources are closed

I really like jimfs for testing. However there are a few things that I cannot easily test at the moment, especially checking if all resources have been closed. It seems FileSystemState already contains a list of open resources, but I can't find a way to access this list.

Having a method like getOpenResources() or assertNoOpenResources() would be really nice and easy to implement.

Cant compile the project

Ii checked out the project using eclipse and egit , but getting this error. Any help ??

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] Jimfs Parent
[INFO] Jimfs
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Jimfs Parent 1.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ jimfs-parent ---
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Jimfs 1.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ jimfs ---
[INFO]
[INFO] --- maven-resources-plugin:2.7:resources (default-resources) @ jimfs ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\MK------\Eclipse\Eclipse Projects\JavaPractice\jimfs-parent\jimfs\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ jimfs ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 57 source files to E:\MK------\Eclipse\Eclipse Projects\JavaPractice\jimfs-parent\jimfs\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Jimfs Parent ....................................... SUCCESS [ 1.039 s]
[INFO] Jimfs .............................................. FAILURE [ 0.915 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.881 s
[INFO] Finished at: 2015-12-12T14:54:26+05:30
[INFO] Final Memory: 8M/21M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project jimfs: Execution default-compile of goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile failed: A required class was missing while executing org.apache.maven.plugins:maven-compiler-plugin:3.1:compile: com/sun/tools/javac/main/JavaCompiler
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>org.apache.maven.plugins:maven-compiler-plugin:3.1
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/Windows%207/.m2/repository/org/apache/maven/plugins/maven-compiler-plugin/3.1/maven-compiler-plugin-3.1.jar
[ERROR] urls[1] = file:/C:/Users/Windows%207/.m2/repository/com/google/errorprone/error_prone_core/1.1.1/error_prone_core-1.1.1.jar
[ERROR] urls[2] = file:/C:/Users/Windows%207/.m2/repository/com/google/errorprone/error_prone_annotation/1.1.1/error_prone_annotation-1.1.1.jar
[ERROR] urls[3] = file:/C:/Users/Windows%207/.m2/repository/com/google/code/findbugs/jFormatString/2.0.2/jFormatString-2.0.2.jar
[ERROR] urls[4] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-compiler-javac/2.4/plexus-compiler-javac-2.4.jar
[ERROR] urls[5] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-utils/3.0.10/plexus-utils-3.0.10.jar
[ERROR] urls[6] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-compiler-javac-errorprone/2.4/plexus-compiler-javac-errorprone-2.4.jar
[ERROR] urls[7] = file:/C:/Users/Windows%207/.m2/repository/org/apache/maven/shared/maven-shared-utils/0.1/maven-shared-utils-0.1.jar
[ERROR] urls[8] = file:/C:/Users/Windows%207/.m2/repository/com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.jar
[ERROR] urls[9] = file:/C:/Users/Windows%207/.m2/repository/org/apache/maven/shared/maven-shared-incremental/1.1/maven-shared-incremental-1.1.jar
[ERROR] urls[10] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar
[ERROR] urls[11] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-compiler-api/2.2/plexus-compiler-api-2.2.jar
[ERROR] urls[12] = file:/C:/Users/Windows%207/.m2/repository/org/codehaus/plexus/plexus-compiler-manager/2.2/plexus-compiler-manager-2.2.jar
[ERROR] urls[13] = file:/C:/Users/Windows%207/.m2/repository/org/apache/xbean/xbean-reflect/3.4/xbean-reflect-3.4.jar
[ERROR] urls[14] = file:/C:/Users/Windows%207/.m2/repository/log4j/log4j/1.2.12/log4j-1.2.12.jar
[ERROR] urls[15] = file:/C:/Users/Windows%207/.m2/repository/commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.jar
[ERROR] urls[16] = file:/C:/Users/Windows%207/.m2/repository/com/google/collections/google-collections/1.0/google-collections-1.0.jar
[ERROR] urls[17] = file:/C:/Users/Windows%207/.m2/repository/junit/junit/3.8.2/junit-3.8.2.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import from realm ClassRealm[project>com.google.jimfs:jimfs:1.1-SNAPSHOT, parent: ClassRealm[maven.api, parent: null]]]
[ERROR]
[ERROR] -----------------------------------------------------: com.sun.tools.javac.main.JavaCompiler
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn -rf :jimfs

support system.setProperty style overriding of default provider

As a user writing a suite of unit tests against a file-IO heavy application, I would like to simply set the default file system provider via a call similar to System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "com.google.common.jimfs.SystemJimfsFileSystemProvider"), so that I can more easily apply JimFS as the systems file system.

So this is hopefully a fairly minor request:

the system property "java.nio.file.spi.DefaultFileSystemProvider" controls which FileSystemProvider is to be used as the default one. It works by specifying a fully-qualified class name as the value, which will be loaded on a call to java.nio.file.FileSystems.DefaultFileSystemHolder#getDefaultProvider. It does this by looking for a constructor that takes a FileSystemProvider as its single argument, effectively allowing you to chain-wrap file system providers.

So, if you guys could add another constructor to the SystemFileSystemProvider, that takes a provider as an argument and simply ignores it, I would be much appreciative.

Regarding

I'd strongly recommend not using Paths.get to get a Path in your production code. It's convenient as a quick replacement for new File(String) when migrating from the old API, but that's about it. When using java.nio.file, methods that tie you to the default FileSystem are generally an anti-pattern.

I agree with the general principal but I'd appreciate a little trust in navigating this space myself. I think this is better expressed as a line in documentation rather than a hard requirement within your library.

In my particular case, some of my libraries are calling Paths.get() and the application I'm building is quite small, so I'm OK with using statics for testing here.

This issue relates to:

ClassLoader issues with Jimfs.newFileSystem

It looks like there are problems using Jimfs in an environment where user and system code are loaded by separate classloaders. In that case, JimfsFileSystemProvider will be loaded and initialized by the system classloader (because of the META-INF/services entry), while a user who wants to create a file system by calling Jimfs.newFileSystem will be using classes loaded by a different classloader.

The problem is that to create a FileSystem instance, Jimfs calls FileSystems.newFileSystem(...), passing it an environment map containing the Configuration object to be used to configure the file system. When the JimfsFileSystemProvider instance loaded by the system classloader gets this object, it doesn't recognize it as an instance of Configuration, because it was loaded by a different classloader. This leads to an error like:

env map ({config=com.google.common.jimfs.Configuration@15b71125}) must contain key 'config' mapped to an instance of Jimfs.Configuration

Why do we do it this way in the first place? We want to call FileSystems.newFileSystem so that the canonical (system-loaded) JimfsFileSystemProvider instance is used to create (and more importantly, cache) the file system. This is necessary for methods like Paths.get(URI) to work, as it will go to that FileSystemProvider instance and ask it to resolve the URI to a Path. If it doesn't have the FileSystem instance cached, it won't be able to find it and get a Path from it.

Some possible solutions (and the problems with them):

  1. Change the environment map that's passed to FileSystems.newFileSystem to only contain standard JDK types. This should solve the classloader issues.
    • Problem: While most of the Configuration object could be converted to a map of standard JDK types, there are a couple things that cannot, specifically the PathType and the set of AttributeProviders the file system should use. It's possible (though it would require changing the API) that we could change the configuration from storing instances of these types to storing only the classes (requiring a default constructor or some such), in which case we could put the names of the classes into the map to be loaded and instantiated by the FileSystemProvider.
    • Even if we did this, though, there are still potential problems if, say, an AttributeProvider deals with attributes whose values are not standard JDK classes--the could be problems when a user tries to set an attribute value on a file and the AttributeProvider doesn't see it as the same class (due to the classloader issues).
  2. Stop using FileSystems.newFileSystem to create Jimfs file systems. Use a locally initialized instance of JimfsFileSystemProvider instead. This solves the problem because only the user code classloader should be involved.
    • Problem: It's no longer possible to get a Jimfs Path or FileSystem by its URI using the standard methods in the java.nio.file API. This also prevents things like the recently-added support for Jimfs URLs from working.
  3. Try to work around this by making the system-loaded FileSystemProvider for Jimfs not be the real JimfsFileSystemProvider.
    • Rather, it would just be used for caching FileSystem instances as needed for URI-based methods to work.
    • The real JimfsFileSystemProvider would be a singleton, and Jimfs would use that to create a FileSystem instance when Jimfs.newFileSystem is called. It would then pass the created FileSystem itself as a value in the environment map to FileSystems.newFileSystem, allowing the new FileSystem to be cached. Since FileSystem is a JDK type and since the system-loaded FileSystemProvider has no reason to care about any details beyond that, it should have no problem with the FileSystem coming from a different classloader.
    • Since the FileSystemProvider that created the FileSystem will be the one that handles implementing all the methods for it, there should be no issues with the FileSystem functionality.

I think approach 3 should work, but still need to confirm that. It's fairly gross, but should be transparent as long as people are using the API as expected.

Add a means to convert a URI to a JimfsPath

There is no obvious way to convert a URI into a JimfsPath. Normally, one could use fs.provider().getPath(uri), but this is not implemented by JimfsFileSystemProvider; instead, it throws an exception stating:

This method should not be called directly; use Paths.get(URI) instead.

Which is funny, since on #12 @cgdecker (main contributor to the project?)

strongly recommends not using Paths.get

I would've used JimfsFileSystem.toPath(URI), but the entire class is set to the package-private access modifier (why the hell?).

Use mocks to provide MappedByteBuffers.

When called, FileChannel.map throws an UnsupportedOperationException, but the Javadoc doesn't mention any such Exception:

Example code to reproduce the error:

FileSystem fs = Jimfs.newFileSystem();
Path file = fs.getPath("MyFile.data");
FileChannel channel = FileChannel.open(file, READ, WRITE, CREATE, DSYNC);
MappedByteBuffer buffer = channel.map(READ_WRITE, 0L, 1024L);

Okay, I read the code of the method, which is relatively simple:

  @Override
  public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
    // would like this to pretend to work, but can't create an implementation of MappedByteBuffer
    // well, a direct buffer could be cast to MappedByteBuffer, but it couldn't work in general
    throw new UnsupportedOperationException();
}

However, I have to say that I successfully mocked MappedByteBuffer using Mockito (latest version). Wouldn't it be possible to create such a mock (using either Mockito or your own bytecode manipulator) so that we can properly test our usage of FileChannel.map?

Cannot compile via Maven

I can't compile jimfs (v1.0) via Maven. I cloned the repository and checked out tag v1.0.

Here's the stack trace I get when I run mvn install:

$ mvn install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] Jimfs Parent
[INFO] Jimfs
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Jimfs Parent 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ jimfs-parent ---
[INFO]
[INFO] --- maven-gpg-plugin:1.4:sign (sign-artifacts) @ jimfs-parent ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ jimfs-parent ---

[INFO] Installing c:\Dev\JVM\jimfs\pom.xml to C:\Users\Paul\.m2\repository\com\g
oogle\jimfs\jimfs-parent\1.0\jimfs-parent-1.0.pom
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Jimfs 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ jimfs ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ jimfs ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Dev\JVM\jimfs\jimfs\src\main\resou
rces
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ jimfs ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 54 source files to C:\Dev\JVM\jimfs\jimfs\target\classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] FATAL ERROR: java.lang.IllegalArgumentException: Invalid relative name:
META-INF\services\java.nio.file.spi.FileSystemProvider
        at com.sun.tools.javac.file.JavacFileManager.getFileForOutput(JavacFileM
anager.java:737)
        at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java
:467)
        at com.google.auto.service.processor.AutoServiceProcessor.generateConfig
Files(AutoServiceProcessor.java:171)
        at com.google.auto.service.processor.AutoServiceProcessor.processImpl(Au
toServiceProcessor.java:116)
        at com.google.auto.service.processor.AutoServiceProcessor.process(AutoSe
rviceProcessor.java:104)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcess
or(JavacProcessingEnvironment.java:794)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$200(
JavacProcessingEnvironment.java:91)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredP
rocessors$ProcessorStateIterator.runContributingProcs(JavacProcessingEnvironment
.java:627)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(J
avacProcessingEnvironment.java:1033)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessin
g(JavacProcessingEnvironment.java:1198)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler
.java:1170)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
        at com.sun.tools.javac.main.Main.compile(Main.java:523)
        at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
        at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
        at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProces
s(JavaxToolsCompiler.java:126)
        at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(Javac
Compiler.java:169)
        at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(Abstrac
tCompilerMojo.java:785)
        at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.ja
va:129)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(Default
BuildPluginManager.java:134)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:208)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProje
ct(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProje
ct(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThre
adedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(Lifecycl
eStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Laun
cher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.jav
a:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(La
uncher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:
356)
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Jimfs Parent ....................................... SUCCESS [  0.656 s]
[INFO] Jimfs .............................................. FAILURE [  1.812 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.592 s
[INFO] Finished at: 2015-09-25T01:24:37+02:00
[INFO] Final Memory: 18M/219M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:compile (default-compile) on project jimfs: Compilation failure
[ERROR] FATAL ERROR: java.lang.IllegalArgumentException: Invalid relative name:
META-INF\services\java.nio.file.spi.FileSystemProvider
[ERROR] at com.sun.tools.javac.file.JavacFileManager.getFileForOutput(JavacFileM
anager.java:737)
[ERROR] at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java
:467)
[ERROR] at com.google.auto.service.processor.AutoServiceProcessor.generateConfig
Files(AutoServiceProcessor.java:171)
[ERROR] at com.google.auto.service.processor.AutoServiceProcessor.processImpl(Au
toServiceProcessor.java:116)
[ERROR] at com.google.auto.service.processor.AutoServiceProcessor.process(AutoSe
rviceProcessor.java:104)
[ERROR] at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcess
or(JavacProcessingEnvironment.java:794)
[ERROR] at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$200(
JavacProcessingEnvironment.java:91)
[ERROR] at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredP
rocessors$ProcessorStateIterator.runContributingProcs(JavacProcessingEnvironment
.java:627)
[ERROR] at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(J
avacProcessingEnvironment.java:1033)
[ERROR] at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessin
g(JavacProcessingEnvironment.java:1198)
[ERROR] at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler
.java:1170)
[ERROR] at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
[ERROR] at com.sun.tools.javac.main.Main.compile(Main.java:523)
[ERROR] at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
[ERROR] at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
[ERROR] at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProces
s(JavaxToolsCompiler.java:126)
[ERROR] at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(Javac
Compiler.java:169)
[ERROR] at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(Abstrac
tCompilerMojo.java:785)
[ERROR] at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.ja
va:129)
[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(Default
BuildPluginManager.java:134)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:208)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:153)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor
.java:145)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProje
ct(LifecycleModuleBuilder.java:116)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProje
ct(LifecycleModuleBuilder.java:80)
[ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThre
adedBuilder.build(SingleThreadedBuilder.java:51)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(Lifecycl
eStarter.java:128)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
[ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
[ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862)
[ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286)
[ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:62)
[ERROR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:43)
[ERROR] at java.lang.reflect.Method.invoke(Method.java:497)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Laun
cher.java:289)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.jav
a:229)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(La
uncher.java:415)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:
356)
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
ch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please rea
d the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureExc
eption
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command

[ERROR]   mvn <goals> -rf :jimfs

My environment:

$ mvn -v
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T13:57:3
7+02:00)
Maven home: c:\Dev\Programs\Maven
Java version: 1.8.0_45, vendor: Oracle Corporation
Java home: c:\Program Files\Java\jdk8\jre
Default locale: de_DE, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "amd64", family: "dos"

Don't use polling for WatchService

Google policy forbids unit tests from calling sleep. If sleep is used, they have to be categorized as medium tests.

It would be nice if PollingWatchService was replaced with an implementation that uses mutex conditions, e.g. wait() and notify().

Allow creation of Links from other File Systems

Hi all, we are trying to use JimFS as a Virtual File System, using it to create a directory structure, and store Symbolic Links to Files that reside on other File Systems.

We work with very large files and don't have the memory capacity to store these files in memory unfortunately.

Trying to do this, we receive the error "path is not associated with a Jimfs file system"
at com.google.common.jimfs.JimfsFileSystemProvider.checkPath(JimfsFileSystemProvider.java:130)
at com.google.common.jimfs.JimfsFileSystemProvider.createLink(JimfsFileSystemProvider.java:231)
at java.nio.file.Files.createLink(Files.java:1086)

Empty filesystem contains a "work" dir (that shouldn't be there)

Hi,
first of all, thanks for this library. I'm trying to use it, but the following code (in Kotlin)...

val fs = Jimfs.newFileSystem(Configuration.unix())
val rootDir = fs.getPath("/")
Files.newDirectoryStream(rootDir).forEach { println(it) }

...prints...

/work

Am I doing something wrong? As far as I can understand, that dir shouldn't be there.

Thanks again for your work!

testAsyncClose_write is flaky

In our build process, we also run the jimfs tests on our CI.

We've just noticed that testAsyncClose_write is flaky (in com.google.common.jimfs.JimfsAsynchronousFileChannelTest)

I guess it's due to the Uninterruptibles.sleepUninterruptibly(10, MILLISECONDS);.

Is it possible to improve this test so that it's not flaky anymore?

Slower than regular file system?

Running my integration tests (which write and read back a couple hundred small-ish HTML files) with jimfs takes about twice as long as running them with the regular file system (MacBook Pro 2015, SSD).

Is this expected? More generally, are there any good reasons for using jimfs for tests that need a file system?

Put the Javadoc online

Currently the javadoc is not online (no reference about it in the readme) and the top search result for "jimfs javadoc" is some third party website with ads.

The javadoc is indeed available on Maven and all IDEs can use it to show the documentation of a class or method, but to discover all the functionalities, it's way easier to check it online, hence this request.

Allow to set JimfsFileSystemProvider as DefaultFileSystemProvider

In production code I use the static factory methods of nio.file.Paths to create Path objects. The nio.file.Paths utility class uses the default Filesystem.

In my test code I would like to change the default file system, which can be done by setting the system property java.nio.file.spi.DefaultFileSystemProvider. However, in order for this to work, the provider class needs to have a one argument constructor whose formal parameter type is FileSystemProvider. Since JimfsFileSystemProvider doesn't have such a constructor and I can't extend the class (marked as final), I can't make FileSystems.getDefault() return a Jimfs file system.

closing a filesystem does not close its ByteChannels

e.g.

FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix());
Path path = jimfs.getPath( "/foo" );
SeekableByteChannle readChannel = Files.newByteChannel( path, StandardOpenOption.READ );
jimfs.close();
readChannel.read() // should throw ClosedChannelException

i.e. the channel is still open

Consider a separate file system "environment"

Brain dump:
It occurs to me that it may be useful to separate the file system from the environment it's operating in. Things that seem like environment:

  • Info on users and (for POSIX) group memberships, where needed.
  • Current user... mutable! Possibly per-thread?
  • Permission checking, using the above user/group info, plus knowledge of permissions, etc. (see #11).
  • Default attributes to set when creating a new file. There are a number of issues with this:
    • The default owner of a new file should probably always be the current user, meaning the value for that particular attribute probably needs to be handled differently than other attributes.
    • The environment and file system need to be consistent about attributes: should the environment be the canonical thing that understands attributes...? This kind of makes sense, but it seems easy to expand this to say that the environment also includes things like disks for storing data, etc. until the environment is basically just the file system as it is now.

The environment should also be responsible for, as indicated above, for things like checking permissions. This likely means that:

  • There need to be multiple implementations of environment, such as a POSIX environment that understands POSIX groups, permissions, etc. and a Windows environment that understands DOS things like readonly, plus ACLs, etc.
  • If we want to support creating in-memory file systems that are similar to file systems other than Unix, Windows, etc. (as we've already tried to do with file attributes), the environment needs to be extensible.

It seems pretty clear to me now that given what the environment needs to do, it should be responsible for attributes in general. This could also simplify things a bit from the current "combine whatever attribute views you want", making it instead "use one of these prepackaged environments", which could include a basic environment (no permission checking, just a basic attribute view, etc.) a POSIX environment, a Windows environment, etc.

Of course, then there's a further issue of how to deal with, say, the possibility of creating a file system with a POSIX environment but using Windows-style paths, etc., which would be really weird.

Difference in behavior for pathMatcher when run between Linux/Windows

I'm creating a jimfs FileSystem object with configuration Unix and noticed a slight difference in how the PathMatcher object is handling single star globs. In the code below, the assertion passes when run on Windows and fails when run on Linux. Based on the documentation for getPathMatcher:
https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)
I would expect the assertion to fail, since the single star glob shouldn't cross directory boundaries. Is this expected behavior? If so, is there a way I can tell the jimfs FileSystem object to not cross directory bounds for single star globs, regardless of the OS I run the code on?

import com.google.common.jimfs.Jimfs;
import org.junit.Assert;
import org.junit.Test;

import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;

public class JimfsTest {

    @Test
    public void testSingleStarMatching() {
        String pattern = "*.cpp";
        Path path = Paths.get("first/second/third.cpp");
        FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
        PathMatcher pathMatcher = fileSystem.getPathMatcher("glob:" + pattern);

        Assert.assertTrue(pathMatcher.matches(path));
    }
}

Consider actual support for file permissions

Saw a StackOverflow question about this.

It could be useful to have POSIX permissions for files in a file system actually affect behavior. For that to work, there'd also need to be some way to set a current user/group.

There are a variety of difficulties with this, though, such as:

  • Do we try to make this work for Windows-like file systems as well?
  • If there are other forms of authorization other file systems might use, is there some way to make this extensible so that a fake of one of those file systems can work properly?
  • Management of context (e.g. user/group for current thread or other context) seems pretty unrelated to the file system and as such isn't something I really wanted to do.

When is next release?

This projects has received multiple updates during the last two years, and in my case have I been waiting for a release containing changes done almost two years ago as a result of #31.

When may we expect to see the next release of jimfs?

Provide toString() for Configuration/FileSystem

This would be a minor cosmetic improvement.

I'm using this code:

@Parameters(name = "{0}")
public static ImmutableList<Configuration> fileSystemConfigurations() {
    return ImmutableList.of(Configuration.unix(), Configuration.windows(), Configuration.osX());
}

with JUnit parameterized runner to make my test suite run with all possible file systems. The obvious problem here is that neither Configuration nor Jimfs's FileSystem instances provide a useful toString(). Therefore, when a test fails on one of the configurations, I do not immediately see which "system" is to blame: http://i.imgur.com/7E3dTjR.png

How can I create a zip FileSystem for a zip in a jimfs FileSystem?

I found this, so I think it's supported, but I don't know how to use it.

Attempt 1

FileSystems.newFileSystem(
    pathToZipFile.toUri(),
    Collections.singletonMap("create", "true"));
java.lang.IllegalArgumentException: 
  uri (jimfs://814e6cd3-0d35-4c8f-a93d-62f44ffd3825/work/stuff.zip) 
  may not have a path, query or fragment

Attempt 2

FileSystems.newFileSystem(pathToZipFile, null)
java.nio.file.ProviderNotFoundException: Provider not found

Any ideas?

WatchService registered directory gets deleted, but nothing happens.

FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path data = fs.getPath("/data");
Files.createDirectory(data);
 
 watcher = data.getFileSystem().newWatchService();
Thread watcherThread = new Thread(() -> {
	WatchKey key;
			try {
				key = watcher.take(); // will be stuck here
				while (key != null) {
					for (WatchEvent<?> event : key.pollEvents()) {
						System.out.printf("event of type: %s received for file: %s\n", event.kind(), event.context());
					}
					boolean isValid = key.reset();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	}, "CustomWatcher");
watcherThread.start();
data.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
 
Files.deleteIfExists(data);

When the registered directory gets deleted nothing happens at all but when using the default file system WatchService.take() actually stops waiting and the WatchKey for the registered directory gets invalidated.

Allow configuration that has "\" and "/" as separator

I want to create a virtual FileSystem similar to Configuration.unix() that is able to handle both / and \ as separators, like the default Java filesystem.

I regularly read relative file paths from default FileSystem or configuration and need to convert them to relative JimFs paths. Those paths happily mix / and \ if the program is executed on windows, and i do not want to manually replace the separators at every occation since actually JimFs has this functionality built in, but I don't see a way to use it.

A PathType for this would be nice. Or the possibility to configure this somehow. The only way I see to do this is to create my own PathType adapter class that forwards all methods to UnixPathType but has a different constructor that specified additional separators.

Edit:
Implementing adapter is somewhat cumbersome because toUriPath(...) and parseUriPath(...) are protected, so i cannot call them unless i put my adapter into the same package as UnixPathType, but thats only nitpicking.

Edit2:
I need to implement parsePath(String path) as well so it uses the custom Splitter. This solution is not great.

code

package com.google.common.jimfs;

import static com.google.common.jimfs.Feature.FILE_CHANNEL;
import static com.google.common.jimfs.Feature.LINKS;
import static com.google.common.jimfs.Feature.SECURE_DIRECTORY_STREAM;
import static com.google.common.jimfs.Feature.SYMBOLIC_LINKS;

import java.nio.file.InvalidPathException;

/**
 * Very similar to normal Configuration.unix(), but is able to parse windows separators in
 * addition to unix separator.
 * 
 */
public class UnixCompatible {
	
	public static Configuration config() {
		return Configuration.builder(new CompatiblePathType())
	            .setRoots("/")
	            .setWorkingDirectory("/work")
	            .setAttributeViews("basic")
	            .setSupportedFeatures(LINKS, SYMBOLIC_LINKS, SECURE_DIRECTORY_STREAM, FILE_CHANNEL)
	            .build();
	}
	
	static class CompatiblePathType extends PathType {

		final PathType unix;
		
		public CompatiblePathType() {
			super(false, '/', '\\');
			unix = PathType.unix();
		}
		
		/** Copied from UnixPathType, custom splitter */
		@Override
		public ParseResult parsePath(String path) {
			if (path.isEmpty()) {
				return emptyPath();
			}

			checkValid(path);

			final String root = path.startsWith("/") ? "/" : null;
			return new ParseResult(root, splitter().split(path));
		}
		
		/** Copied from UnixPathType */
		private static void checkValid(String path) {
			final int nulIndex = path.indexOf('\0');
			if (nulIndex != -1) {
				throw new InvalidPathException(path, "nul character not allowed", nulIndex);
			}
		}

		@Override
		public String toString(String root, Iterable<String> names) {
			return unix.toString(root, names);
		}

		@Override
		public String toString() {
			return unix.toString();
		}

		@Override
		protected String toUriPath(String root, Iterable<String> names, boolean directory) {
			return unix.toUriPath(root, names, directory);
		}

		@Override
		protected ParseResult parseUriPath(String uriPath) {
			return unix.parseUriPath(uriPath);
		}
	}
}

Make it throw!

I always find it difficult to test I/O error handling. Jimfs immensely simplifies writing unit tests for code that interacts with the file system, but it doesn't help with testing the 'bad' path.

I would like to be able to set expectations on a Path, e.g. to throw an IOException if someone tries to open a channel for it. I was thinking of a new method Jimfs.newMockFileSystem() that returns a specialized MockFileSystem, which in turn can be used to build Path objects that behave how I want.

As I understand it, the goal of Jimfs is to simplify unit testing, so I hope this feature request is not too much out of scope?!

IllegalAccessException in OSGi.

If I try to call the Jimfs via Paths.get of a Jimfs URI inside an OSGi bundle, I get an illegal access exception from the reflection code in the file system provider. I'm not sure what the fuss is about: this is a pax-exam osgi test that uses Jimfs, and it so all the Jimfs stuff should be in one class loader: the class loader for the jimfs bundle.

In the debugger, toPath.getClass().getClassLoader() is null. fileSystem.getClass().getClassLoader() is org.eclipse.osgi.internal.loader.EquinoxClassLoader@1437268e[com.google.jimfs:1.1.0(id=37)] -- the jimfs bundle.

I see; the collection of file systems in the main 'Paths' class are all loaded by the app class loader, so we're using SystemJimfsClassLoader from the wrong class loader.

Perhaps this is just a typical 'OSGi versus SPI' problem?


Class sun.reflect.Reflection can not access a member of class com.google.common.jimfs.JimfsFileSystem with modifiers "public"

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:109)
      at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261)
      at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253)
      at java.lang.reflect.Method.invoke(Method.java:599)
      at com.google.common.jimfs.SystemJimfsFileSystemProvider.toPath(SystemJimfsFileSystemProvider.java:179)
      at com.google.common.jimfs.SystemJimfsFileSystemProvider.getPath(SystemJimfsFileSystemProvider.java:144)
      at java.nio.file.Paths.get(Paths.java:143)
      at com.basistech.rosette.osgi.util.NioPathDeserializer.deserialize(NioPathDeserializer.java:42)
      at com.basistech.rosette.osgi.util.NioPathDeserializer.deserialize(NioPathDeserializer.java:31)
      at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:490)
      at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:260)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2798)
      at com.basistech.rosette.osgi.util.OsgiUtils.deserializeYamlConfiguration(OsgiUtils.java:116)
      at com.basistech.rosette.osgi.util.AbstractComponentService.createFactory(AbstractComponentService.java:47)

Any way to mount this filesystem in the OS?

Admittedly, it is a bit inside out. Is there any way to run this in a process that is then mountable in an OS? I'd like to run the java app, somehow "mount" it in the OS, then be able to "cd, ls, cp, mv" the "files" in this virtual file system from the command line.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.