# VFS Configuration and Usage

The virtual file system module provides a read-only abstraction for a file system accessed using a root URI/URL.

## Overview

The virtual file system module provides a read-only abstraction for a file system accessed using a root URI/URL. The main VFS classes include:

- org.jboss.virtual.VFS - A factory class for creating and finding VirtualFiles.

- org.jboss.virtual.VirtualFile - the encapsulation of an entry in a virtual file system.

- org.jboss.virtual.VirtualFileFilter/VirtualFileFilterWithAttributes - filters that can be used to restrict the VirtualFiles matching a search.

- org.jboss.virtual.VisitorAttributes - attributes that control how a visitation of a VFS root is performed.

- org.jboss.virtual.VirtualFileVisitor - a callback interface used with the VFS/VirtualFile.vist methods.

- org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter - a VirtualFileFilter implementation that accepts any file that ends with one of the filter suffixes.

### VFS Examples

#### Getting a VFS from a root URL

                   URL rootURL = ...;
                   VFS vfs = VFS.getVFS(rootURL);
                   VirtualFile jar = vfs.findChild("outer.jar");

#### Getting a VFS from a root URI

                   URI rootURI = ...;
                   VFS vfs = VFS.getVFS(rootURI);
                   VirtualFile jar = vfs.findChild("outer.jar");

#### Accessing a jar manifest

                   URI rootURI = ...;
                   VFS vfs = VFS.getVFS(rootURI);
                   VirtualFile jar = vfs.findChild("outer.jar");
                   VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
                   InputStream mfIS = metaInf.openStream();
                   Manifest mf = new Manifest(mfIS);
                   mfIS.close();
                   Attributes mainAttrs = mf.getMainAttributes();
                   String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);

#### Finding all .class files under a VFS root

                   URI rootURI = ...;
                   VFS vfs = VFS.getVFS(rootURI);
                   SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
                   List<VirtualFile> classes = vfs.getChildren(classVisitor);
                   int count = 0;
                   for (VirtualFile cf : classes)
                   {
                   ...
                   }

### org.jboss.virtual Classes

#### org.jboss.virtual.VFS

    public class VFS
    {
       /**
        * Get the virtual file system for a root uri
        *
        * @param rootURI the root URI
        * @return the virtual file system
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL is null
        */
       public static VFS getVFS(URI rootURI) throws IOException
       {
       }

       /**
        * Get the root virtual file
        *
        * @param rootURI the root uri
        * @return the virtual file
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL
        */
       public static VirtualFile getRoot(URI rootURI) throws IOException
       {
       }

       /**
        * Get a virtual file
        *
        * @param rootURI the root uri
        * @param name the path name
        * @return the virtual file
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL or name is null
        */
       public static VirtualFile getVirtualFile(URI rootURI, String name) throws IOException
       {
       }

       /**
        * Get the virtual file system for a root url
        *
        * @param rootURL the root url
        * @return the virtual file system
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL is null
        */
       public static VFS getVFS(URL rootURL) throws IOException
       {
       }

       /**
        * Get the root virtual file
        *
        * @param rootURL the root url
        * @return the virtual file
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL
        */
       public static VirtualFile getRoot(URL rootURL) throws IOException
       {
       }

       /**
        * Get a virtual file
        *
        * @param rootURL the root url
        * @param name the path name
        * @return the virtual file
        * @throws IOException if there is a problem accessing the VFS
        * @throws IllegalArgumentException if the rootURL or name is null
        */
       public static VirtualFile getVirtualFile(URL rootURL, String name) throws IOException
       {
       }

       /**
        * Get the root file of this VFS
        *
        * @return the root
        * @throws IOException for any problem accessing the VFS
        */
       public VirtualFile getRoot() throws IOException
       {
       }

       /**
        * Find a child from the root
        *
        * @param path the child path
        * @return the child
        * @throws IOException for any problem accessing the VFS (including the child does not exist)
        * @throws IllegalArgumentException if the path is null
        */
       public VirtualFile findChild(String path) throws IOException
       {
       }

       /**
        * Find a child from the root
        *
        * @Deprecated use {@link #findChild(String)}
        * @param path the child path
        * @return the child
        * @throws IOException for any problem accessing the VFS (including the child does not exist)
        * @throws IllegalArgumentException if the path is null
        */
       @Deprecated
       public VirtualFile findChildFromRoot(String path) throws IOException
       {
       }

       /**
        * Get the children
        *
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the root is a leaf node
        */
       public List<VirtualFile> getChildren() throws IOException
       {
       }

       /**
        * Get the children
        *
        * @param filter to filter the children
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the root is a leaf node
        */
       public List<VirtualFile> getChildren(VirtualFileFilter filter) throws IOException
       {
       }

       /**
        * Get all the children recursively<p>
        *
        * This always uses {@link VisitorAttributes#RECURSE}
        *
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the root is a leaf node
        */
       public List<VirtualFile> getChildrenRecursively() throws IOException
       {
       }

       /**
        * Get all the children recursively<p>
        *
        * This always uses {@link VisitorAttributes#RECURSE}
        *
        * @param filter to filter the children
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the root is a leaf node
        */
       public List<VirtualFile> getChildrenRecursively(VirtualFileFilter filter) throws IOException
       {
       }

       /**
        * Visit the virtual file system from the root
        *
        * @param visitor the visitor
        * @throws IOException for any problem accessing the VFS
        * @throws IllegalArgumentException if the visitor is null
        * @throws IllegalStateException if the root is a leaf node
        */
       public void visit(VirtualFileVisitor visitor) throws IOException
       {
          ...
       }

    }

#### org.jboss.virtual.VirtualFile

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Serializable;
    import java.net.MalformedURLException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URL;
    import java.util.Collections;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.atomic.AtomicBoolean;

    import org.jboss.util.collection.WeakSet;
    import org.jboss.virtual.plugins.vfs.helpers.FilterVirtualFileVisitor;
    import org.jboss.virtual.plugins.vfs.helpers.MatchAllVirtualFileFilter;
    import org.jboss.virtual.spi.VFSContext;
    import org.jboss.virtual.spi.VirtualFileHandler;

    /**
     * A virtual file as seen by the user
     *
     * @author Scott.Stark@jboss.org
     * @author adrian@jboss.org
     * @version $Revision: 44334 $
     */
    public class VirtualFile implements Serializable
    {
       private static final long serialVersionUID = 1L;

       /** The virtual file handler */
       private final VirtualFileHandler handler;

       /** Whether we are closed */
       private AtomicBoolean closed = new AtomicBoolean(false);

       /** The open streams */
       private transient final Set<InputStream> streams = Collections.synchronizedSet(new WeakSet());

       /**
        * Create a new VirtualFile.
        *
        * @param handler the handler
        * @throws IllegalArgumentException if the handler is null
        */
       public VirtualFile(VirtualFileHandler handler)
       {
    ...
       }

       /**
        * Get the virtual file handler
        *
        * @return the handler
        * @throws IllegalStateException if the file is closed
        */
       public VirtualFileHandler getHandler()
       {
    ...
       }

       /**
        * Get the simple VF name (X.java)
        *
        * @return the simple file name
        * @throws IllegalStateException if the file is closed
        */
       public String getName()
       {
    ...
       }

       /**
        * Get the VFS relative path name (org/jboss/X.java)
        *
        * @return the VFS relative path name
        * @throws IllegalStateException if the file is closed
        */
       public String getPathName()
       {
    ...
       }

       /**
        * Get the VF URL (file://root/org/jboss/X.java)
        *
        * @return the full URL to the VF in the VFS.
        * @throws MalformedURLException if a url cannot be parsed
        * @throws URISyntaxException if a uri cannot be parsed
        * @throws IllegalStateException if the file is closed
        */
       public URL toURL() throws MalformedURLException, URISyntaxException
       {
    ...
       }

       /**
        * Get the VF URI (file://root/org/jboss/X.java)
        *
        * @return the full URI to the VF in the VFS.
        * @throws URISyntaxException if a uri cannot be parsed
        * @throws IllegalStateException if the file is closed
        * @throws MalformedURLException for a bad url
        */
       public URI toURI() throws MalformedURLException, URISyntaxException
       {
    ...
       }

       /**
        * When the file was last modified
        *
        * @return the last modified time
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public long getLastModified() throws IOException
       {
    ...
       }

       /**
        * Returns true if the file has been modified since this method was last called
        * Last modified time is initialized at handler instantiation.
        *
        * @return
        * @throws IOException
        */
       public boolean hasBeenModified() throws IOException
       {
    ...
       }

       /**
        * Get the size
        *
        * @return the size
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public long getSize() throws IOException
       {
    ...
       }

       /**
        * Tests whether the underlying implementation file still exists.
        * @return true if the file exists, false otherwise.
        * @throws IOException - thrown on failure to detect existence.
        */
       public boolean exists() throws IOException
       {
    ...
       }

       /**
        * Whether it is a simple leaf of the VFS,
        * i.e. whether it can contain other files
        *
        * @return true if a simple file.
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public boolean isLeaf() throws IOException
       {
    ...
       }

       /**
        * Whether it is hidden
        *
        * @return true when hidden
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public boolean isHidden() throws IOException
       {
    ...
       }

       /**
        * Access the file contents.
        *
        * @return an InputStream for the file contents.
        * @throws IOException for any error accessing the file system
        * @throws IllegalStateException if the file is closed
        */
       public InputStream openStream() throws IOException
       {
    ...
       }

       /**
        * Close the streams
        */
       public void closeStreams()
       {
    ...
       }

       /**
        * Close the file resources (stream, etc.)
        */
       public void close()
       {
    ...
       }

       /**
        * Get the VFS instance for this virtual file
        *
        * @return the VFS
        * @throws IllegalStateException if the file is closed
        */
       public VFS getVFS()
       {
    ...
       }

       /**
        * Get the parent
        *
        * @return the parent or null if there is no parent
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public VirtualFile getParent() throws IOException
       {
    ...
       }

       /**
        * Get the children
        *
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public List<VirtualFile> getChildren() throws IOException
       {
          return getChildren(null);
       }

       /**
        * Get the children
        *
        * @param filter to filter the children
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed or it is a leaf node
        */
       public List<VirtualFile> getChildren(VirtualFileFilter filter) throws IOException
       {
    ...
       }

       /**
        * Get all the children recursively<p>
        *
        * This always uses {@link VisitorAttributes#RECURSE}
        *
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed
        */
       public List<VirtualFile> getChildrenRecursively() throws IOException
       {
          return getChildrenRecursively(null);
       }

       /**
        * Get all the children recursively<p>
        *
        * This always uses {@link VisitorAttributes#RECURSE}
        *
        * @param filter to filter the children
        * @return the children
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalStateException if the file is closed or it is a leaf node
        */
       public List<VirtualFile> getChildrenRecursively(VirtualFileFilter filter) throws IOException
       {
    ...
       }

       /**
        * Visit the virtual file system
        *
        * @param visitor the visitor
        * @throws IOException for any problem accessing the virtual file system
        * @throws IllegalArgumentException if the visitor is null
        * @throws IllegalStateException if the file is closed or it is a leaf node
        */
       public void visit(VirtualFileVisitor visitor) throws IOException
       {
    ...
       }

       /**
        * Find a child
        *
        * @param path the path
        * @return the child
        * @throws IOException for any problem accessing the VFS (including the child does not exist)
        * @throws IllegalArgumentException if the path is null
        * @throws IllegalStateException if the file is closed or it is a leaf node
        */
       public VirtualFile findChild(String path) throws IOException
       {
    ...
       }

    }

#### org.jboss.virtual.VisitorAttributes

    /**
     * Attributes used when visiting a virtual file system
     *
     * @author <a href="adrian@jboss.com">Adrian Brock</a>
     * @author Scott.Stark@jboss.org
     * @version $Revision: 1.1 $
     */
    public class VisitorAttributes
    {
       /** A VirtualFileFilter than accepts any file */
       public static final AcceptAnyFilter RECURSE_ALL = new AcceptAnyFilter();

       /** The default attributes - visit nothing both leaves, non-leaves, no recursion */
       public static final VisitorAttributes DEFAULT = new ImmutableVisitorAttributes();

       /** Visit leaves only and do not recurse non-leaf files */
       public static final VisitorAttributes LEAVES_ONLY = new ImmutableVisitorAttributes(true, null);

       /** Recurse and visit all non-leaf files */
       public static final VisitorAttributes RECURSE = new ImmutableVisitorAttributes(false, RECURSE_ALL);

       /** Recurse all non-leaf files but only visit leaves */
       public static final VisitorAttributes RECURSE_LEAVES_ONLY = new ImmutableVisitorAttributes(true, RECURSE_ALL);

       /** Whether to include the root */
       private boolean includeRoot;

       /** Whether to only visit leaves */
       private boolean leavesOnly;

       /** Whether to ignore individual file errors */
       private boolean ignoreErrors;

       /** Whether to include hidden files */
       private boolean includeHidden;

       /** A filter used to control whether a non-leaf is recursive visited */
       private VirtualFileFilter recurseFilter;

       /**
        * Whether to visit leaves only<p>
        *
        * Default: false
        *
        * @return the visit leaves only.
        */
       public boolean isLeavesOnly()
       {
          return leavesOnly;
       }

       /**
        * Set the leaves only.
        *
        * @param leavesOnly the leaves only
        * @throws IllegalStateException if you attempt to modify one of the preconfigured static values of this class
        */
       public void setLeavesOnly(boolean leavesOnly)
       {
          this.leavesOnly = leavesOnly;
       }

       /**
        * Whether to recurse into the non-leaf file<p>. If there is a recurse
        * filter then the result will by its accepts(file) value.
        *
        * Default: false
        *
        * @param file the file
        * @return the recurse flag.
        */
       public boolean isRecurse(VirtualFile file)
       {
          boolean recurse = false;
          if( recurseFilter != null )
             recurse = recurseFilter.accepts(file);
          return recurse;
       }

       /**
        * Get the recurse filter.
        * @return the current recurse filter.
        */
       public VirtualFileFilter getRecurseFilter()
       {
          return recurseFilter;
       }

       /**
        * Set the recurse filter.
        *
        * @param filter - the recurse filter.
        * @throws IllegalStateException if you attempt to modify one of the preconfigured static values of this class
        */
       public void setRecurseFilter(VirtualFileFilter filter)
       {
          this.recurseFilter = filter;
       }

       /**
        * Whether to include the root of the visit<p>
        *
        * Default: false
        *
        * @return the includeRoot.
        */
       public boolean isIncludeRoot()
       {
          return includeRoot;
       }

       /**
        * Set the includeRoot.
        *
        * @param includeRoot the includeRoot.
        * @throws IllegalStateException if you attempt to modify one of the preconfigured static values of this class
        */
       public void setIncludeRoot(boolean includeRoot)
       {
          this.includeRoot = includeRoot;
       }

       /**
        * Whether to ignore individual errors<p>
        *
        * Default: false
        *
        * @return the ignoreErrors.
        */
       public boolean isIgnoreErrors()
       {
          return ignoreErrors;
       }

       /**
        * Set the ignoreErrors.
        *
        * @param ignoreErrors the ignoreErrors.
        * @throws IllegalStateException if you attempt to modify one of the preconfigured static values of this class
        */
       public void setIgnoreErrors(boolean ignoreErrors)
       {
          this.ignoreErrors = ignoreErrors;
       }

       /**
        * Whether to include hidden files<p>
        *
        * Default: false
        *
        * @return the includeHidden.
        */
       public boolean isIncludeHidden()
       {
          return includeHidden;
       }

       /**
        * Set the includeHidden.
        *
        * @param includeHidden the includeHidden.
        * @throws IllegalStateException if you attempt to modify one of the preconfigured static values of this class
        */
       public void setIncludeHidden(boolean includeHidden)
       {
          this.includeHidden = includeHidden;
       }

    }

## Configuration

TODO:jboss-vfs.jar ...