Create hidden files in Apache VFS with the RAM filesystem type

Apache VFS is a great way to access different file systems in the same way. I particularly like the custom RAM filesystem in my unit tests in order to check code that eventually accesses the actual file system.

For example:

StandardFileSystemManager manager = new StandardFileSystemManager();
manager.init();
manager.resolveFile("ram://root/file.txt").createFile(); // prepare test harness
...
manager.resolveFile("ram://root/file.txt").getName(); // do something useful

Annoyingly, Apache VFS API provides a way to check if a file/folder is hidden, but, although it is always possible to manually create hidden files on your system, there is no way to mark a file as hidden in the RAM filesystem.

manager.resolveFile("ram://root/file.txt").isHidden(); // returns false
manager.resolveFile("ram://root/.file.txt").isHidden(); // also returns false

The solution is to modify the RAM filesystem and customize its checking of the hidden attribute. This means that we need a new RamFileProvider, a new RamFileSystem and finally a new RamFileObject.

In this example, all files and folders whose names start with a dot will be considered hidden:

public class RamFileProvider extends org.apache.commons.vfs2.provider.ram.RamFileProvider {
  @Override
  protected FileSystem doCreateFileSystem(FileName name, FileSystemOptions fileSystemOptions) throws FileSystemException {
    return new RamFileSystem(name, fileSystemOptions);
  }

  private static class RamFileSystem extends org.apache.commons.vfs2.provider.ram.RamFileSystem {
    public RamFileSystem(FileName rootName, FileSystemOptions fileSystemOptions) {
      super(rootName, fileSystemOptions);
    }

    @Override
    protected FileObject createFile(AbstractFileName name) throws Exception {
      return new RamFileObject(name, this);
    }
  }

  private static class RamFileObject extends org.apache.commons.vfs2.provider.ram.RamFileObject {
    public RamFileObject(AbstractFileName name, RamFileSystem ramFileSystemWithHiddenSupport) {
      super(name, ramFileSystemWithHiddenSupport);
    }

    @Override
    public boolean isHidden() throws FileSystemException {
      // this is the important part
      if (getName().getBaseName().startsWith(".")) {
        return true;
      }
      return super.isHidden(); // in practice, this always return false
    }
  }
}

Finally, this new RamFileProvider must be registered with your existing FileSystemManager. In my case, I get something like that:

StandardFileSystemManager manager = new StandardFileSystemManager();
manager.init();
manager.addProvider("ram-ext", new RamFileProvider());
manager.resolveFile("ram-ext:///root/file.txt").createFile();
manager.resolveFile("ram-ext:///root/.file.txt").createFile();
...
manager.resolveFile("ram-ext://root/file.txt").isHidden(); // returns false
manager.resolveFile("ram-ext://root/.file.txt").isHidden(); // returns true

Note that I did not replace the “ram” filesystem entirely. Although that would have been my preferred option, that would have taken too much time in my little experiment.

About Eric Lefevre-Ardant

Independent technical consultant.
This entry was posted in java, test. Bookmark the permalink.