ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From adammurd...@apache.org
Subject cvs commit: jakarta-ant/proposal/myrmidon/src/testcases/org/apache/aut/vfs AbstractFileSystemTest.java
Date Sat, 02 Mar 2002 04:07:51 GMT
adammurdoch    02/03/01 20:07:51

  Modified:    proposal/myrmidon/src/java/org/apache/aut/vfs FileName.java
                        FileObject.java NameScope.java
               proposal/myrmidon/src/java/org/apache/aut/vfs/provider
                        DefaultFileName.java Resources.properties
                        UriParser.java
               proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local
                        LocalFile.java LocalFileNameParser.java
                        LocalFileSystem.java LocalFileSystemProvider.java
                        ParsedFileUri.java
               proposal/myrmidon/src/testcases/org/apache/aut/vfs
                        AbstractFileSystemTest.java
  Added:       proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local
                        GenericFileNameParser.java
                        WindowsFileNameParser.java
  Log:
  * Added 'descendent' name scope.
  * Changed semantics of FileName.resolveName() with 'child' scope.
  * Fixed a couple of problems in UriParser.normalise().
  * Split up LocalFileNameParser into a Windows specifc parser and a generic
    parser.
  * More test cases.
  
  Revision  Changes    Path
  1.2       +2 -3      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java
  
  Index: FileName.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FileName.java	2 Feb 2002 03:29:07 -0000	1.1
  +++ FileName.java	2 Mar 2002 04:07:51 -0000	1.2
  @@ -67,9 +67,8 @@
       FileName resolveName( String path ) throws FileSystemException;
   
       /**
  -     * Resolves a name, relative to the file.  Refer to {@link NameScope#CHILD}
  -     * and {@link NameScope#FILE_SYSTEM} for a description of how names are
  -     * resolved.
  +     * Resolves a name, relative to the file.  Refer to {@link NameScope}
  +     * for a description of how names are resolved.
        *
        * @param name
        *      The path to resolve.
  
  
  
  1.2       +3 -4      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java
  
  Index: FileObject.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FileObject.java	2 Feb 2002 03:29:07 -0000	1.1
  +++ FileObject.java	2 Mar 2002 04:07:51 -0000	1.2
  @@ -123,9 +123,8 @@
       FileObject[] getChildren() throws FileSystemException;
   
       /**
  -     * Finds a file, relative to this file.  Refer to {@link NameScope#CHILD}
  -     * and {@link NameScope#FILE_SYSTEM} for a description of how names
  -     * are resolved in the different scopes.
  +     * Finds a file, relative to this file.  Refer to {@link NameScope}
  +     * for a description of how names are resolved in the different scopes.
        *
        * @param name
        *      The name to resolve.
  @@ -207,7 +206,7 @@
        *
        * @see FileContent#close
        *
  -     * @throws FileSystemEception
  +     * @throws FileSystemException
        *      On error closing the file.
        */
       void close() throws FileSystemException;
  
  
  
  1.4       +10 -5     jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java
  
  Index: NameScope.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- NameScope.java	9 Feb 2002 22:49:56 -0000	1.3
  +++ NameScope.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -16,13 +16,18 @@
   public final class NameScope
   {
       /**
  -     * Resolve against the children of the base file.
  -     *
  -     * <p>The supplied name must be a valid element name.  That is, it may
  -     * not be empty, or <code>.</code>, or <code>..</code>, or contain any
  -     * separator characters.
  +     * Resolve against the children of the base file.  The name is resolved
  +     * as described by {@link #FILE_SYSTEM}.  However, an exception is
  +     * thrown if the resolved file is not a direct child of the base file.
        */
       public final static NameScope CHILD = new NameScope( "child" );
  +
  +    /**
  +     * Resolve against the descendents of the base file.  The name is resolved
  +     * as described by {@link #FILE_SYSTEM}.  However, an exception is thrown
  +     * if the resolved file is not a descendent of the base file.
  +     */
  +    public final static NameScope DESCENDENT = new NameScope( "descendent" );
   
       /**
        * Resolve against files in the same file system as the base file.
  
  
  
  1.2       +29 -22    jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java
  
  Index: DefaultFileName.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultFileName.java	2 Feb 2002 03:29:08 -0000	1.1
  +++ DefaultFileName.java	2 Mar 2002 04:07:51 -0000	1.2
  @@ -18,22 +18,39 @@
    */
   public class DefaultFileName implements FileName
   {
  -    private UriParser m_parser;
  -    private String m_rootPrefix;
  -    private String m_absPath;
  +    private final UriParser m_parser;
  +    private final String m_rootPrefix;
  +    private final String m_absPath;
   
       // Cached stuff
       private String m_uri;
       private String m_baseName;
   
  -    public DefaultFileName( UriParser parser, String rootPrefix, String absPath )
  +    public DefaultFileName( final UriParser parser,
  +                            final String rootPrefix,
  +                            final String absPath )
       {
           m_parser = parser;
           m_rootPrefix = rootPrefix;
           m_absPath = absPath;
       }
   
  -    // TODO - make these usable as hash keys
  +    /**
  +     * Returns the hashcode for this name.
  +     */
  +    public int hashCode()
  +    {
  +        return ( m_rootPrefix.hashCode() ^ m_absPath.hashCode() );
  +    }
  +
  +    /**
  +     * Determines if this object is equal to another.
  +     */
  +    public boolean equals( final Object obj )
  +    {
  +        final DefaultFileName name = (DefaultFileName)obj;
  +        return ( m_rootPrefix.equals( name.m_rootPrefix ) && m_absPath.equals( m_absPath ) );
  +    }
   
       /**
        * Returns the URI of the file.
  @@ -67,22 +84,12 @@
       /**
        * Returns the name of a child of the file.
        */
  -    public FileName resolveName( String name, NameScope scope ) throws FileSystemException
  +    public FileName resolveName( final String name,
  +                                 final NameScope scope )
  +        throws FileSystemException
       {
  -        if( scope == NameScope.CHILD )
  -        {
  -            String childPath = m_parser.getChildPath( m_absPath, name );
  -            return new DefaultFileName( m_parser, m_rootPrefix, childPath );
  -        }
  -        else if( scope == NameScope.FILE_SYSTEM )
  -        {
  -            String absPath = m_parser.resolvePath( m_absPath, name );
  -            return new DefaultFileName( m_parser, m_rootPrefix, absPath );
  -        }
  -        else
  -        {
  -            throw new IllegalArgumentException();
  -        }
  +        final String absPath = m_parser.resolvePath( m_absPath, name, scope );
  +        return new DefaultFileName( m_parser, m_rootPrefix, absPath );
       }
   
       /**
  @@ -90,7 +97,7 @@
        */
       public FileName getParent()
       {
  -        String parentPath = m_parser.getParentPath( m_absPath );
  +        final String parentPath = m_parser.getParentPath( m_absPath );
           if( parentPath == null )
           {
               return null;
  @@ -104,7 +111,7 @@
        * file system that the file belongs to.  If a relative name is supplied,
        * then it is resolved relative to this file name.
        */
  -    public FileName resolveName( String path ) throws FileSystemException
  +    public FileName resolveName( final String path ) throws FileSystemException
       {
           return resolveName( path, NameScope.FILE_SYSTEM );
       }
  
  
  
  1.3       +1 -0      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Resources.properties	3 Feb 2002 00:06:37 -0000	1.2
  +++ Resources.properties	2 Mar 2002 04:07:51 -0000	1.3
  @@ -37,3 +37,4 @@
   missing-port.error=Port number is missing from URI "{0}".
   missing-hostname-path-sep.error=Expecting / to follow the hostname in URI "{0}".
   invalid-childname.error=Invalid file base-name "{0}".
  +invalid-descendent-name.error=Invalid descendent file name "{0}".
  
  
  
  1.4       +95 -83    jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java
  
  Index: UriParser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- UriParser.java	9 Feb 2002 22:49:55 -0000	1.3
  +++ UriParser.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -10,6 +10,7 @@
   import java.util.HashSet;
   import java.util.Iterator;
   import org.apache.aut.vfs.FileSystemException;
  +import org.apache.aut.vfs.NameScope;
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   
  @@ -24,14 +25,14 @@
           ResourceManager.getPackageResources( UriParser.class );
   
       /** The normalised separator to use. */
  -    private char m_separatorChar;
  -    private String m_separator;
  +    private final char m_separatorChar;
  +    private final String m_separator;
   
       /**
        * The set of valid separators.  These are all converted to the normalised one.
        * Does <i>not</i> contain the normalised separator
        */
  -    private char[] m_separators;
  +    private final char[] m_separators;
   
       /**
        * Creates a parser, using '/' and '\' as the path separators.
  @@ -49,12 +50,12 @@
        *          Additional legal separator characters.  Any occurrences of
        *          these in paths are replaced with the separator char.
        */
  -    protected UriParser( char[] separators )
  +    protected UriParser( final char[] separators )
       {
           m_separatorChar = '/';
   
           // Remove the separator char from the separators array
  -        HashSet set = new HashSet();
  +        final HashSet set = new HashSet();
           set.add( new Character( '\\' ) );
           if( separators != null )
           {
  @@ -69,10 +70,10 @@
               }
           }
           m_separators = new char[ set.size() ];
  -        Iterator iter = set.iterator();
  +        final Iterator iter = set.iterator();
           for( int i = 0; i < m_separators.length; i++ )
           {
  -            Character ch = (Character)iter.next();
  +            final Character ch = (Character)iter.next();
               m_separators[ i ] = ch.charValue();
           }
   
  @@ -86,9 +87,9 @@
        *
        * <p>Sub-classes should override this method.
        */
  -    public ParsedUri parseUri( String uriStr ) throws FileSystemException
  +    public ParsedUri parseUri( final String uriStr ) throws FileSystemException
       {
  -        ParsedUri retval = new ParsedUri();
  +        final ParsedUri retval = new ParsedUri();
           parseGenericUri( uriStr, retval );
           return retval;
       }
  @@ -109,9 +110,11 @@
        * @param uri
        *          Used to return the parsed components of the URI.
        */
  -    protected void parseGenericUri( String uriStr, ParsedUri uri ) throws FileSystemException
  +    protected void parseGenericUri( final String uriStr,
  +                                    final ParsedUri uri )
  +        throws FileSystemException
       {
  -        StringBuffer name = new StringBuffer();
  +        final StringBuffer name = new StringBuffer();
   
           // Extract the scheme and authority parts
           extractToPath( uriStr, name, uri );
  @@ -121,7 +124,7 @@
           uri.setPath( name.toString() );
   
           // Build the root uri
  -        StringBuffer rootUri = new StringBuffer();
  +        final StringBuffer rootUri = new StringBuffer();
           rootUri.append( uri.getScheme() );
           rootUri.append( "://" );
           rootUri.append( uri.getHostName() );
  @@ -141,11 +144,13 @@
        * @parsedUri
        *          Used to return the extracted components.
        */
  -    protected void extractToPath( String uri, StringBuffer name, ParsedUri parsedUri )
  +    protected void extractToPath( final String uri,
  +                                  final StringBuffer name,
  +                                  final ParsedUri parsedUri )
           throws FileSystemException
       {
           // Extract the scheme
  -        String scheme = extractScheme( uri, name );
  +        final String scheme = extractScheme( uri, name );
           parsedUri.setScheme( scheme );
   
           // Expecting "//"
  @@ -157,11 +162,11 @@
           name.delete( 0, 2 );
   
           // Extract userinfo
  -        String userInfo = extractUserInfo( name );
  +        final String userInfo = extractUserInfo( name );
           parsedUri.setUserInfo( userInfo );
   
           // Extract hostname
  -        String hostName = extractHostName( name );
  +        final String hostName = extractHostName( name );
           if( hostName == null )
           {
               final String message = REZ.getString( "missing-hostname.error", uri );
  @@ -170,7 +175,7 @@
           parsedUri.setHostName( hostName );
   
           // Extract port
  -        String port = extractPort( name );
  +        final String port = extractPort( name );
           if( port != null && port.length() == 0 )
           {
               final String message = REZ.getString( "missing-port.error", uri );
  @@ -190,12 +195,12 @@
        * Extracts the user info from a URI.  The <scheme>:// part has been removed
        * already.
        */
  -    protected String extractUserInfo( StringBuffer name )
  +    protected String extractUserInfo( final StringBuffer name )
       {
  -        int maxlen = name.length();
  +        final int maxlen = name.length();
           for( int pos = 0; pos < maxlen; pos++ )
           {
  -            char ch = name.charAt( pos );
  +            final char ch = name.charAt( pos );
               if( ch == '@' )
               {
                   // Found the end of the user info
  @@ -218,13 +223,13 @@
        * Extracts the hostname from a URI.  The <scheme>://<userinfo>@ part has
        * been removed.
        */
  -    protected String extractHostName( StringBuffer name )
  +    protected String extractHostName( final StringBuffer name )
       {
  -        int maxlen = name.length();
  +        final int maxlen = name.length();
           int pos = 0;
           for( ; pos < maxlen; pos++ )
           {
  -            char ch = name.charAt( pos );
  +            final char ch = name.charAt( pos );
               if( ch == '/' || ch == ';' || ch == '?' || ch == ':'
                   || ch == '@' || ch == '&' || ch == '=' || ch == '+'
                   || ch == '$' || ch == ',' )
  @@ -237,7 +242,7 @@
               return null;
           }
   
  -        String hostname = name.substring( 0, pos );
  +        final String hostname = name.substring( 0, pos );
           name.delete( 0, pos );
           return hostname;
       }
  @@ -246,23 +251,25 @@
        * Extracts the port from a URI.  The <scheme>://<userinfo>@<hostname>
        * part has been removed.
        */
  -    protected String extractPort( StringBuffer name )
  +    protected String extractPort( final StringBuffer name )
       {
           if( name.length() < 1 || name.charAt( 0 ) != ':' )
           {
               return null;
           }
  -        int maxlen = name.length();
  +
  +        final int maxlen = name.length();
           int pos = 1;
           for( ; pos < maxlen; pos++ )
           {
  -            char ch = name.charAt( pos );
  +            final char ch = name.charAt( pos );
               if( ch < '0' || ch > '9' )
               {
                   break;
               }
           }
  -        String port = name.substring( 1, pos );
  +
  +        final String port = name.substring( 1, pos );
           name.delete( 0, pos );
           return port;
       }
  @@ -270,9 +277,9 @@
       /**
        * Extracts the first element of a path.
        */
  -    protected String extractFirstElement( StringBuffer name )
  +    protected String extractFirstElement( final StringBuffer name )
       {
  -        int len = name.length();
  +        final int len = name.length();
           if( len < 1 )
           {
               return null;
  @@ -287,14 +294,14 @@
               if( name.charAt( pos ) == m_separatorChar )
               {
                   // Found a separator
  -                String elem = name.substring( startPos, pos );
  +                final String elem = name.substring( startPos, pos );
                   name.delete( startPos, pos + 1 );
                   return elem;
               }
           }
   
           // No separator
  -        String elem = name.substring( startPos );
  +        final String elem = name.substring( startPos );
           name.setLength( 0 );
           return elem;
       }
  @@ -308,10 +315,11 @@
        * @param path
        *          A <i>normalised</i> path.
        */
  -    public String getUri( String rootUri, String path )
  +    public String getUri( final String rootUri,
  +                          final String path )
       {
  -        StringBuffer uri = new StringBuffer( rootUri );
  -        int len = uri.length();
  +        final StringBuffer uri = new StringBuffer( rootUri );
  +        final int len = uri.length();
           if( uri.charAt( len - 1 ) == m_separatorChar )
           {
               uri.delete( len - 1, len );
  @@ -330,9 +338,9 @@
        * @param path
        *          A <i>normalised</i> path.
        */
  -    public String getBaseName( String path )
  +    public String getBaseName( final String path )
       {
  -        int idx = path.lastIndexOf( m_separatorChar );
  +        final int idx = path.lastIndexOf( m_separatorChar );
           if( idx == -1 )
           {
               return path;
  @@ -353,9 +361,11 @@
        *          does need to be a path (i.e. not an absolute URI).
        *
        */
  -    public String resolvePath( String basePath, String path ) throws FileSystemException
  +    public String resolvePath( final String basePath,
  +                               final String path )
  +        throws FileSystemException
       {
  -        StringBuffer buffer = new StringBuffer( path );
  +        final StringBuffer buffer = new StringBuffer( path );
   
           // Adjust separators
           fixSeparators( buffer );
  @@ -374,47 +384,52 @@
       }
   
       /**
  -     * Returns a child path.
  +     * Resolved a name, relative to a base file.
        *
  -     * @param parent
  +     * @param baseFile
        *          A <i>normalised</i> path.
        *
  -     * @param name
  -     *          The child name.  Must be a valid element name (i.e. no separators, etc).
  +     * @param path
  +     *          The path to resolve.
  +     *
  +     * @param scope
  +     *          The scope to resolve and validate the name in.
        */
  -    public String getChildPath( String parent, String name ) throws FileSystemException
  +    public String resolvePath( final String baseFile,
  +                               final String path,
  +                               final NameScope scope )
  +        throws FileSystemException
       {
  -        // Validate the child name
  -        if( name.length() == 0
  -            || name.equals( "." )
  -            || name.equals( ".." ) )
  +        final String resolvedPath = resolvePath( baseFile, path );
  +        if( scope == NameScope.CHILD )
           {
  -            final String message = REZ.getString( "invalid-childname.error", name );
  -            throw new FileSystemException( message );
  -        }
  -
  -        // Check for separators
  -        if( name.indexOf( m_separatorChar ) != -1 )
  -        {
  -            final String message = REZ.getString( "invalid-childname.error", name );
  -            throw new FileSystemException( message );
  +            final int baseLen = baseFile.length();
  +            if( ! resolvedPath.startsWith( baseFile )
  +                || resolvedPath.length() == baseLen
  +                || resolvedPath.charAt( baseLen ) != m_separatorChar
  +                || resolvedPath.indexOf( m_separatorChar, baseLen + 1 ) != -1 )
  +            {
  +                final String message = REZ.getString( "invalid-childname.error", path );
  +                throw new FileSystemException( message );
  +            }
           }
  -        for( int i = 0; i < m_separators.length; i++ )
  +        else if( scope == NameScope.DESCENDENT )
           {
  -            char separator = m_separators[ i ];
  -            if( name.indexOf( separator ) != -1 )
  +            final int baseLen = baseFile.length();
  +            if( ! resolvedPath.startsWith( baseFile )
  +                || resolvedPath.length() == baseLen
  +                || resolvedPath.charAt( baseLen ) != m_separatorChar )
               {
  -                final String message = REZ.getString( "invalid-childname.error", name );
  +                final String message = REZ.getString( "invalid-descendent-name.error", path );
                   throw new FileSystemException( message );
               }
           }
  -
  -        if( parent.endsWith( m_separator ) )
  +        else if( scope != NameScope.FILE_SYSTEM )
           {
  -            // Either root, or the parent name already ends with the separator
  -            return parent + name;
  +            throw new IllegalArgumentException();
           }
  -        return parent + m_separatorChar + name;
  +
  +        return resolvedPath;
       }
   
       /**
  @@ -423,9 +438,9 @@
        * @param path
        *          A <i>normalised</i> path.
        */
  -    public String getParentPath( String path )
  +    public String getParentPath( final String path )
       {
  -        int idx = path.lastIndexOf( m_separatorChar );
  +        final int idx = path.lastIndexOf( m_separatorChar );
           if( idx == -1 || idx == path.length() - 1 )
           {
               // No parent
  @@ -448,7 +463,7 @@
        * <li>Removes trailing separator.
        * </ul>
        */
  -    public void normalisePath( StringBuffer path ) throws FileSystemException
  +    public void normalisePath( final StringBuffer path ) throws FileSystemException
       {
           if( path.length() == 0 )
           {
  @@ -480,7 +495,7 @@
               {
               }
   
  -            int elemLen = endElem - startElem;
  +            final int elemLen = endElem - startElem;
               if( elemLen == 0 )
               {
                   // An empty element - axe it
  @@ -503,11 +518,8 @@
                   if( startElem > startFirstElem )
                   {
                       int pos = startElem - 2;
  -                    char ch = path.charAt( pos );
  -                    while( ch != m_separatorChar )
  +                    for( ; pos >= 0 && path.charAt( pos ) != m_separatorChar; pos -- )
                       {
  -                        pos--;
  -                        ch = path.charAt( pos );
                       }
                       startElem = pos + 1;
                   }
  @@ -521,7 +533,7 @@
           }
   
           // Remove trailing separator
  -        if( path.charAt( maxlen - 1 ) == m_separatorChar && maxlen > 1 )
  +        if( maxlen > 0 && path.charAt( maxlen - 1 ) == m_separatorChar && maxlen > 1 )
           {
               path.delete( maxlen - 1, maxlen );
           }
  @@ -530,7 +542,7 @@
       /**
        * Adjusts the separators in a name.
        */
  -    protected boolean fixSeparators( StringBuffer name )
  +    protected boolean fixSeparators( final StringBuffer name )
       {
           if( m_separators.length == 0 )
           {
  @@ -539,10 +551,10 @@
           }
   
           boolean changed = false;
  -        int maxlen = name.length();
  +        final int maxlen = name.length();
           for( int i = 0; i < maxlen; i++ )
           {
  -            char ch = name.charAt( i );
  +            final char ch = name.charAt( i );
               for( int j = 0; j < m_separators.length; j++ )
               {
                   char separator = m_separators[ j ];
  @@ -566,7 +578,7 @@
        * @return
        *          The scheme name.  Returns null if there is no scheme.
        */
  -    public static String extractScheme( String uri )
  +    public static String extractScheme( final String uri )
       {
           return extractScheme( uri, null );
       }
  @@ -583,7 +595,7 @@
        * @return
        *          The scheme name.  Returns null if there is no scheme.
        */
  -    protected static String extractScheme( String uri, StringBuffer buffer )
  +    protected static String extractScheme( final String uri, final StringBuffer buffer )
       {
           if( buffer != null )
           {
  @@ -591,15 +603,15 @@
               buffer.append( uri );
           }
   
  -        int maxPos = uri.length();
  +        final int maxPos = uri.length();
           for( int pos = 0; pos < maxPos; pos++ )
           {
  -            char ch = uri.charAt( pos );
  +            final char ch = uri.charAt( pos );
   
               if( ch == ':' )
               {
                   // Found the end of the scheme
  -                String scheme = uri.substring( 0, pos );
  +                final String scheme = uri.substring( 0, pos );
                   if( buffer != null )
                   {
                       buffer.delete( 0, pos + 1 );
  
  
  
  1.4       +3 -2      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java
  
  Index: LocalFile.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LocalFile.java	9 Feb 2002 02:51:50 -0000	1.3
  +++ LocalFile.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -23,7 +23,8 @@
   /**
    * A file object implementation which uses direct file access.
    *
  - * @author Adam Murdoch
  + * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  + * @version $Revision: 1.4 $ $Date: 2002/03/02 04:07:51 $
    */
   final class LocalFile
       extends AbstractFileObject
  @@ -33,7 +34,7 @@
           ResourceManager.getPackageResources( LocalFile.class );
   
       private File m_file;
  -    private String m_fileName;
  +    private final String m_fileName;
   
       /**
        * Creates a non-root file.
  
  
  
  1.4       +6 -146    jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileNameParser.java
  
  Index: LocalFileNameParser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileNameParser.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LocalFileNameParser.java	9 Feb 2002 02:51:50 -0000	1.3
  +++ LocalFileNameParser.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -11,26 +11,19 @@
   import org.apache.aut.vfs.FileSystemException;
   import org.apache.aut.vfs.provider.ParsedUri;
   import org.apache.aut.vfs.provider.UriParser;
  -import org.apache.avalon.excalibur.i18n.ResourceManager;
  -import org.apache.avalon.excalibur.i18n.Resources;
   
   /**
    * A name parser.
    *
  - * @author Adam Murdoch
  + * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  + * @version $Revision: 1.4 $ $Date: 2002/03/02 04:07:51 $
    */
  -class LocalFileNameParser
  +abstract class LocalFileNameParser
       extends UriParser
   {
  -    private final static Resources REZ =
  -        ResourceManager.getPackageResources( LocalFileNameParser.class );
  -
  -    private boolean m_windowsNames;
  -
       public LocalFileNameParser()
       {
           super( new char[]{File.separatorChar, '/', '\\'} );
  -        m_windowsNames = ( System.getProperty( "os.name" ).toLowerCase().indexOf( "windows" ) != -1 );
       }
   
       /**
  @@ -91,141 +84,8 @@
       /**
        * Pops the root prefix off a URI, which has had the scheme removed.
        */
  -    private String extractRootPrefix( final String uri,
  -                                      final StringBuffer name )
  -        throws FileSystemException
  -    {
  -        // TODO - split this into sub-classes
  -        if( m_windowsNames )
  -        {
  -            return extractWindowsRootPrefix( uri, name );
  -        }
  -        else
  -        {
  -            // Looking for <sep>
  -            if( name.length() == 0 || name.charAt( 0 ) != '/' )
  -            {
  -                final String message = REZ.getString( "not-absolute-file-name.error", uri );
  -                throw new FileSystemException( message );
  -            }
  -
  -            // TODO - this isn't always true
  -            return "/";
  -        }
  -    }
  -
  -    /**
  -     * Extracts a Windows root prefix from a name.
  -     */
  -    private String extractWindowsRootPrefix( final String uri,
  -                                             final StringBuffer name )
  -        throws FileSystemException
  -    {
  -        // Looking for:
  -        // ('/'){0, 3} <letter> ':' '/'
  -        // ['/'] '//' <name> '/' <name> ( '/' | <end> )
  -
  -        // Skip over first 3 leading '/' chars
  -        int startPos = 0;
  -        int maxlen = Math.min( 3, name.length() );
  -        for( ; startPos < maxlen && name.charAt( startPos ) == '/'; startPos++ )
  -        {
  -        }
  -        if( startPos == maxlen )
  -        {
  -            // Too many '/'
  -            final String message = REZ.getString( "not-absolute-file-name.error", uri );
  -            throw new FileSystemException( message );
  -        }
  -        name.delete( 0, startPos );
  -
  -        // Look for drive name
  -        String driveName = extractDrivePrefix( name );
  -        if( driveName != null )
  -        {
  -            return driveName;
  -        }
  -
  -        // Look for UNC name
  -        if( startPos < 2 )
  -        {
  -            final String message = REZ.getString( "not-absolute-file-name.error", uri );
  -            throw new FileSystemException( message );
  -        }
  -
  -        return "//" + extractUNCPrefix( uri, name );
  -    }
  -
  -    /**
  -     * Extracts a drive prefix from a path.  Leading '/' chars have been removed.
  -     */
  -    private String extractDrivePrefix( final StringBuffer name )
  -        throws FileSystemException
  -    {
  -        // Looking for <letter> ':' '/'
  -        if( name.length() < 3 )
  -        {
  -            // Too short
  -            return null;
  -        }
  -        char ch = name.charAt( 0 );
  -        if( ch == '/' || ch == ':' )
  -        {
  -            // Missing drive letter
  -            return null;
  -        }
  -        if( name.charAt( 1 ) != ':' )
  -        {
  -            // Missing ':'
  -            return null;
  -        }
  -        if( name.charAt( 2 ) != '/' )
  -        {
  -            // Missing separator
  -            return null;
  -        }
  +    protected abstract String extractRootPrefix( final String uri,
  +                                                 final StringBuffer name )
  +        throws FileSystemException;
   
  -        String prefix = name.substring( 0, 2 );
  -        name.delete( 0, 2 );
  -        return prefix;
  -    }
  -
  -    /**
  -     * Extracts a UNC name from a path.  Leading '/' chars have been removed.
  -     */
  -    private String extractUNCPrefix( final String uri,
  -                                     final StringBuffer name )
  -        throws FileSystemException
  -    {
  -        // Looking for <name> '/' <name> ( '/' | <end> )
  -
  -        // Look for first separator
  -        int maxpos = name.length();
  -        int pos = 0;
  -        for( ; pos < maxpos && name.charAt( pos ) != '/'; pos++ )
  -        {
  -        }
  -        pos++;
  -        if( pos >= maxpos )
  -        {
  -            final String message = REZ.getString( "missing-share-name.error", uri );
  -            throw new FileSystemException( message );
  -        }
  -
  -        // Now have <name> '/'
  -        int startShareName = pos;
  -        for( ; pos < maxpos && name.charAt( pos ) != '/'; pos++ )
  -        {
  -        }
  -        if( pos == startShareName )
  -        {
  -            final String message = REZ.getString( "missing-share-name.error", uri );
  -            throw new FileSystemException( message );
  -        }
  -
  -        // Now have <name> '/' <name> ( '/' | <end> )
  -        String prefix = name.substring( 0, pos );
  -        name.delete( 0, pos );
  -        return prefix;
  -    }
   }
  
  
  
  1.2       +2 -1      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java
  
  Index: LocalFileSystem.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LocalFileSystem.java	2 Feb 2002 03:29:08 -0000	1.1
  +++ LocalFileSystem.java	2 Mar 2002 04:07:51 -0000	1.2
  @@ -17,7 +17,8 @@
   /**
    * A local file system.
    *
  - * @author Adam Murdoch
  + * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  + * @version $Revision: 1.2 $ $Date: 2002/03/02 04:07:51 $
    */
   class LocalFileSystem extends AbstractFileSystem implements FileSystem
   {
  
  
  
  1.4       +16 -2     jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystemProvider.java
  
  Index: LocalFileSystemProvider.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystemProvider.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LocalFileSystemProvider.java	1 Mar 2002 08:54:19 -0000	1.3
  +++ LocalFileSystemProvider.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -8,6 +8,7 @@
   package org.apache.aut.vfs.provider.local;
   
   import java.io.File;
  +import org.apache.aut.nativelib.Os;
   import org.apache.aut.vfs.FileObject;
   import org.apache.aut.vfs.FileSystemException;
   import org.apache.aut.vfs.provider.AbstractFileSystemProvider;
  @@ -19,12 +20,25 @@
   /**
    * A file system provider, which uses direct file access.
    *
  - * @author Adam Murdoch
  + * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  + * @version $Revision: 1.4 $ $Date: 2002/03/02 04:07:51 $
    */
   public class LocalFileSystemProvider extends AbstractFileSystemProvider
       implements FileSystemProvider
   {
  -    private final LocalFileNameParser m_parser = new LocalFileNameParser();
  +    private final LocalFileNameParser m_parser;
  +
  +    public LocalFileSystemProvider()
  +    {
  +        if( Os.isFamily( Os.OS_FAMILY_WINDOWS ) )
  +        {
  +            m_parser = new WindowsFileNameParser();
  +        }
  +        else
  +        {
  +            m_parser = new GenericFileNameParser();
  +        }
  +    }
   
       /**
        * Determines if a name is an absolute file name.
  
  
  
  1.2       +4 -3      jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/ParsedFileUri.java
  
  Index: ParsedFileUri.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/ParsedFileUri.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ParsedFileUri.java	2 Feb 2002 03:29:08 -0000	1.1
  +++ ParsedFileUri.java	2 Mar 2002 04:07:51 -0000	1.2
  @@ -12,9 +12,10 @@
   /**
    * A parsed file URI.
    *
  - * @author Adam Murdoch
  + * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  + * @version $Revision: 1.2 $ $Date: 2002/03/02 04:07:51 $
    */
  -public class ParsedFileUri extends ParsedUri
  +class ParsedFileUri extends ParsedUri
   {
       private String m_rootFile;
   
  @@ -23,7 +24,7 @@
           return m_rootFile;
       }
   
  -    public void setRootFile( String rootPrefix )
  +    public void setRootFile( final String rootPrefix )
       {
           m_rootFile = rootPrefix;
       }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/GenericFileNameParser.java
  
  Index: GenericFileNameParser.java
  ===================================================================
  /*
  * Copyright (C) The Apache Software Foundation. All rights reserved.
  *
  * This software is published under the terms of the Apache Software License
  * version 1.1, a copy of which has been included  with this distribution in
  * the LICENSE.txt file.
  */
  package org.apache.aut.vfs.provider.local;
  
  import org.apache.aut.vfs.FileSystemException;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  
  /**
   * A general-purpose file name parser.
   *
   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/02 04:07:51 $
   */
  class GenericFileNameParser
      extends LocalFileNameParser
  {
      private final static Resources REZ
          = ResourceManager.getPackageResources( GenericFileNameParser.class );
  
      /**
       * Pops the root prefix off a URI, which has had the scheme removed.
       */
      protected String extractRootPrefix( final String uri,
                                          final StringBuffer name )
          throws FileSystemException
      {
          // TODO - this class isn't generic at all.  Need to fix this
  
          // Looking for <sep>
          if( name.length() == 0 || name.charAt( 0 ) != '/' )
          {
              final String message = REZ.getString( "not-absolute-file-name.error", uri );
              throw new FileSystemException( message );
          }
  
          return "/";
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/WindowsFileNameParser.java
  
  Index: WindowsFileNameParser.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.aut.vfs.provider.local;
  
  import org.apache.aut.vfs.FileSystemException;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  
  /**
   * A parser for Windows file names.
   *
   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/02 04:07:51 $
   */
  class WindowsFileNameParser
      extends LocalFileNameParser
  {
      private final static Resources REZ
          = ResourceManager.getPackageResources( WindowsFileNameParser.class );
  
      /**
       * Pops the root prefix off a URI, which has had the scheme removed.
       */
      protected String extractRootPrefix( final String uri,
                                          final StringBuffer name )
          throws FileSystemException
      {
          return extractWindowsRootPrefix( uri, name );
      }
  
      /**
       * Extracts a Windows root prefix from a name.
       */
      private String extractWindowsRootPrefix( final String uri,
                                               final StringBuffer name )
          throws FileSystemException
      {
          // Looking for:
          // ('/'){0, 3} <letter> ':' '/'
          // ['/'] '//' <name> '/' <name> ( '/' | <end> )
  
          // Skip over first 3 leading '/' chars
          int startPos = 0;
          int maxlen = Math.min( 3, name.length() );
          for( ; startPos < maxlen && name.charAt( startPos ) == '/'; startPos++ )
          {
          }
          if( startPos == maxlen )
          {
              // Too many '/'
              final String message = REZ.getString( "not-absolute-file-name.error", uri );
              throw new FileSystemException( message );
          }
          name.delete( 0, startPos );
  
          // Look for drive name
          String driveName = extractDrivePrefix( name );
          if( driveName != null )
          {
              return driveName;
          }
  
          // Look for UNC name
          if( startPos < 2 )
          {
              final String message = REZ.getString( "not-absolute-file-name.error", uri );
              throw new FileSystemException( message );
          }
  
          return "//" + extractUNCPrefix( uri, name );
      }
  
      /**
       * Extracts a drive prefix from a path.  Leading '/' chars have been removed.
       */
      private String extractDrivePrefix( final StringBuffer name )
          throws FileSystemException
      {
          // Looking for <letter> ':' '/'
          if( name.length() < 3 )
          {
              // Too short
              return null;
          }
          char ch = name.charAt( 0 );
          if( ch == '/' || ch == ':' )
          {
              // Missing drive letter
              return null;
          }
          if( name.charAt( 1 ) != ':' )
          {
              // Missing ':'
              return null;
          }
          if( name.charAt( 2 ) != '/' )
          {
              // Missing separator
              return null;
          }
  
          String prefix = name.substring( 0, 2 );
          name.delete( 0, 2 );
          return prefix;
      }
  
      /**
       * Extracts a UNC name from a path.  Leading '/' chars have been removed.
       */
      private String extractUNCPrefix( final String uri,
                                       final StringBuffer name )
          throws FileSystemException
      {
          // Looking for <name> '/' <name> ( '/' | <end> )
  
          // Look for first separator
          int maxpos = name.length();
          int pos = 0;
          for( ; pos < maxpos && name.charAt( pos ) != '/'; pos++ )
          {
          }
          pos++;
          if( pos >= maxpos )
          {
              final String message = REZ.getString( "missing-share-name.error", uri );
              throw new FileSystemException( message );
          }
  
          // Now have <name> '/'
          int startShareName = pos;
          for( ; pos < maxpos && name.charAt( pos ) != '/'; pos++ )
          {
          }
          if( pos == startShareName )
          {
              final String message = REZ.getString( "missing-share-name.error", uri );
              throw new FileSystemException( message );
          }
  
          // Now have <name> '/' <name> ( '/' | <end> )
          String prefix = name.substring( 0, pos );
          name.delete( 0, pos );
          return prefix;
      }
  }
  
  
  
  1.4       +183 -83   jakarta-ant/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java
  
  Index: AbstractFileSystemTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractFileSystemTest.java	1 Mar 2002 08:54:34 -0000	1.3
  +++ AbstractFileSystemTest.java	2 Mar 2002 04:07:51 -0000	1.4
  @@ -15,6 +15,9 @@
   import java.util.List;
   import java.util.Map;
   import org.apache.aut.vfs.impl.DefaultFileSystemManager;
  +import org.apache.aut.vfs.provider.AbstractFileObject;
  +import org.apache.avalon.excalibur.i18n.ResourceManager;
  +import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.myrmidon.AbstractMyrmidonTest;
   
   /**
  @@ -29,6 +32,9 @@
   public abstract class AbstractFileSystemTest
       extends AbstractMyrmidonTest
   {
  +    private final static Resources REZ
  +        = ResourceManager.getPackageResources( AbstractFileObject.class );
  +
       protected FileObject m_baseFolder;
       protected DefaultFileSystemManager m_manager;
   
  @@ -46,12 +52,12 @@
       private FileInfo buildExpectedStructure()
       {
           // Build the expected structure
  -        FileInfo base = new FileInfo( "test", FileType.FOLDER );
  +        final FileInfo base = new FileInfo( "test", FileType.FOLDER );
           base.addChild( new FileInfo( "file1.txt", FileType.FILE ) );
           base.addChild( new FileInfo( "empty.txt", FileType.FILE ) );
           base.addChild( new FileInfo( "emptydir", FileType.FOLDER ) );
   
  -        FileInfo dir = new FileInfo( "dir1", FileType.FOLDER );
  +        final FileInfo dir = new FileInfo( "dir1", FileType.FOLDER );
           base.addChild( dir );
           dir.addChild( new FileInfo( "file1.txt", FileType.FILE ) );
           dir.addChild( new FileInfo( "file2.txt", FileType.FILE ) );
  @@ -76,7 +82,7 @@
           m_baseFolder = m_manager.resolveFile( getBaseFolderURI() );
   
           // Build the expected content of "file1.txt"
  -        String eol = System.getProperty( "line.separator" );
  +        final String eol = System.getProperty( "line.separator" );
           m_charContent = "This is a test file." + eol + "With 2 lines in it." + eol;
       }
   
  @@ -86,8 +92,8 @@
       public void testAbsoluteURI() throws Exception
       {
           // Try fetching base folder again by its URI
  -        String uri = m_baseFolder.getName().getURI();
  -        FileObject file = m_manager.resolveFile( uri );
  +        final String uri = m_baseFolder.getName().getURI();
  +        final FileObject file = m_manager.resolveFile( uri );
   
           assertSame( "file object", m_baseFolder, file );
       }
  @@ -123,7 +129,7 @@
       public void testRootFileName() throws Exception
       {
           // Locate the root file
  -        FileName rootName = m_baseFolder.getRoot().getName();
  +        final FileName rootName = m_baseFolder.getRoot().getName();
   
           // Test that the root path is "/"
           assertEquals( "root path", "/", rootName.getPath() );
  @@ -140,9 +146,9 @@
        */
       public void testChildName() throws Exception
       {
  -        FileName baseName = m_baseFolder.getName();
  -        String basePath = baseName.getPath();
  -        FileName name = baseName.resolveName( "some-child", NameScope.CHILD );
  +        final FileName baseName = m_baseFolder.getName();
  +        final String basePath = baseName.getPath();
  +        final FileName name = baseName.resolveName( "some-child", NameScope.CHILD );
   
           // Test path is absolute
           assertTrue( "is absolute", basePath.startsWith( "/" ) );
  @@ -157,76 +163,95 @@
           assertEquals( "parent absolute path", basePath, name.getParent().getPath() );
   
           // Try using a compound name to find a child
  -        try
  -        {
  -            name.resolveName( "a/b", NameScope.CHILD );
  -            assertTrue( false );
  -        }
  -        catch( FileSystemException e )
  -        {
  -        }
  +        assertBadName( name, "a/b", NameScope.CHILD );
   
  -        // Try using a empty name to find a child
  -        try
  -        {
  -            name.resolveName( "", NameScope.CHILD );
  -            assertTrue( false );
  -        }
  -        catch( FileSystemException e )
  -        {
  -        }
  +        // Check other invalid names
  +        checkDescendentNames( name, NameScope.CHILD );
  +    }
   
  -        // Try using '.' to find a child
  -        try
  -        {
  -            name.resolveName( ".", NameScope.CHILD );
  -            assertTrue( false );
  -        }
  -        catch( FileSystemException e )
  -        {
  -        }
  +    /**
  +     * Name resolution tests that are common for CHILD or DESCENDENT scope.
  +     */
  +    private void checkDescendentNames( final FileName name,
  +                                       final NameScope scope )
  +        throws Exception
  +    {
  +        // Make some assumptions about the name explicit
  +        assertTrue( !name.getPath().equals( "/" ) );
  +        assertTrue( !name.getPath().endsWith( "/a" ) );
  +        assertTrue( !name.getPath().endsWith( "/a/b" ) );
   
  -        // Try using '..' to find a child
  -        try
  -        {
  -            name.resolveName( "..", NameScope.CHILD );
  -            assertTrue( false );
  -        }
  -        catch( FileSystemException e )
  -        {
  -        }
  +        // Test names with the same prefix
  +        String path = name.getPath() + "/a";
  +        assertSameName( path, name, path, scope );
  +        assertSameName( path, name, "../" + name.getBaseName() + "/a", scope );
  +
  +        // Test an empty name
  +        assertBadName( name, "", scope );
  +
  +        // Test . name
  +        assertBadName( name, ".", scope );
  +        assertBadName( name, "./", scope );
  +
  +        // Test ancestor names
  +        assertBadName( name, "..", scope );
  +        assertBadName( name, "../a", scope );
  +        assertBadName( name, "../" + name.getBaseName() + "a", scope );
  +        assertBadName( name, "a/..", scope );
  +
  +        // Test absolute names
  +        assertBadName( name, "/", scope );
  +        assertBadName( name, "/a", scope );
  +        assertBadName( name, "/a/b", scope );
  +        assertBadName( name, name.getPath(), scope );
  +        assertBadName( name, name.getPath() + "a", scope );
       }
   
       /**
        * Checks that a relative name resolves to the expected absolute path.
  +     * Tests both forward and back slashes.
        */
  -    private void assertSameName( String expectedPath,
  -                                 FileName baseName,
  -                                 String relName ) throws Exception
  +    private void assertSameName( final String expectedPath,
  +                                 final FileName baseName,
  +                                 final String relName,
  +                                 final NameScope scope )
  +        throws Exception
       {
  -        FileName name = baseName.resolveName( relName );
  +        // Try the supplied name
  +        FileName name = baseName.resolveName( relName, scope );
           assertEquals( expectedPath, name.getPath() );
   
           // Replace the separators
           relName.replace( '\\', '/' );
  -        name = baseName.resolveName( relName );
  +        name = baseName.resolveName( relName, scope );
           assertEquals( expectedPath, name.getPath() );
   
           // And again
           relName.replace( '/', '\\' );
  -        name = baseName.resolveName( relName );
  +        name = baseName.resolveName( relName, scope );
           assertEquals( expectedPath, name.getPath() );
       }
   
       /**
  +     * Checks that a relative name resolves to the expected absolute path.
  +     * Tests both forward and back slashes.
  +     */
  +    private void assertSameName( String expectedPath,
  +                                 FileName baseName,
  +                                 String relName ) throws Exception
  +    {
  +        assertSameName( expectedPath, baseName, relName, NameScope.FILE_SYSTEM );
  +    }
  +
  +    /**
        * Tests relative name resolution, relative to the base folder.
        */
       public void testNameResolution() throws Exception
       {
  -        FileName baseName = m_baseFolder.getName();
  -        String parentPath = baseName.getParent().getPath();
  -        String path = baseName.getPath();
  -        String childPath = path + "/some-child";
  +        final FileName baseName = m_baseFolder.getName();
  +        final String parentPath = baseName.getParent().getPath();
  +        final String path = baseName.getPath();
  +        final String childPath = path + "/some-child";
   
           // Test empty relative path
           assertSameName( path, baseName, "" );
  @@ -280,23 +305,78 @@
       }
   
       /**
  -     * Walks the folder structure, asserting it contains exactly the
  +     * Tests descendent name resolution.
  +     */
  +    public void testDescendentName()
  +        throws Exception
  +    {
  +        final FileName baseName = m_baseFolder.getName();
  +
  +        // Test direct child
  +        String path = baseName.getPath() + "/some-child";
  +        assertSameName( path, baseName, "some-child", NameScope.DESCENDENT );
  +
  +        // Test compound name
  +        path = path + "/grand-child";
  +        assertSameName( path, baseName, "some-child/grand-child", NameScope.DESCENDENT );
  +
  +        // Test relative names
  +        assertSameName( path, baseName, "./some-child/grand-child", NameScope.DESCENDENT );
  +        assertSameName( path, baseName, "./nada/../some-child/grand-child", NameScope.DESCENDENT );
  +        assertSameName( path, baseName, "some-child/./grand-child", NameScope.DESCENDENT );
  +
  +        // Test badly formed descendent names
  +        checkDescendentNames( baseName, NameScope.DESCENDENT );
  +    }
  +
  +    /**
  +     * Asserts that a particular relative name is invalid for a particular
  +     * scope.
  +     */
  +    private void assertBadName( final FileName name,
  +                                final String relName,
  +                                final NameScope scope )
  +    {
  +        try
  +        {
  +            name.resolveName( relName, scope );
  +            fail();
  +        }
  +        catch( FileSystemException e )
  +        {
  +            // TODO - should check error message
  +        }
  +    }
  +
  +    /**
  +     * Walks the base folder structure, asserting it contains exactly the
        * expected files and folders.
        */
       public void testStructure() throws Exception
       {
  +        final FileInfo baseInfo = buildExpectedStructure();
  +        assertSameStructure( m_baseFolder, baseInfo );
  +    }
  +
  +    /**
  +     * Walks a folder structure, asserting it contains exactly the
  +     * expected files and folders.
  +     */
  +    protected void assertSameStructure( final FileObject folder,
  +                                        final FileInfo expected )
  +        throws Exception
  +    {
           // Setup the structure
  -        List queueExpected = new ArrayList();
  -        FileInfo baseInfo = buildExpectedStructure();
  -        queueExpected.add( baseInfo );
  +        final List queueExpected = new ArrayList();
  +        queueExpected.add( expected );
   
  -        List queueActual = new ArrayList();
  -        queueActual.add( m_baseFolder );
  +        final List queueActual = new ArrayList();
  +        queueActual.add( folder );
   
           while( queueActual.size() > 0 )
           {
  -            FileObject file = (FileObject)queueActual.remove( 0 );
  -            FileInfo info = (FileInfo)queueExpected.remove( 0 );
  +            final FileObject file = (FileObject)queueActual.remove( 0 );
  +            final FileInfo info = (FileInfo)queueExpected.remove( 0 );
   
               // Check the type is correct
               assertSame( file.getType(), info._type );
  @@ -307,7 +387,7 @@
               }
   
               // Check children
  -            FileObject[] children = file.getChildren();
  +            final FileObject[] children = file.getChildren();
   
               // Make sure all children were found
               assertNotNull( children );
  @@ -316,8 +396,8 @@
               // Recursively check each child
               for( int i = 0; i < children.length; i++ )
               {
  -                FileObject child = children[ i ];
  -                FileInfo childInfo = (FileInfo)info._children.get( child.getName().getBaseName() );
  +                final FileObject child = children[ i ];
  +                final FileInfo childInfo = (FileInfo)info._children.get( child.getName().getBaseName() );
   
                   // Make sure the child is expected
                   assertNotNull( childInfo );
  @@ -366,16 +446,16 @@
   
           // Test an unknown file
           file = m_baseFolder.resolveFile( "unknown-child" );
  -        FileSystemException exc = null;
           try
           {
               file.getType();
  +            fail();
           }
           catch( FileSystemException e )
           {
  -            exc = e;
  +            final String message = REZ.getString( "get-type-no-exist.error", file );
  +            assertSameMessage( message, e );
           }
  -        assertNotNull( exc );
       }
   
       /**
  @@ -419,10 +499,12 @@
           try
           {
               file.getChildren();
  -            assertTrue( false );
  +            fail();
           }
           catch( FileSystemException e )
           {
  +            final String message = REZ.getString( "list-children-not-folder.error", file );
  +            assertSameMessage( message, e );
           }
   
           // Should be able to get child by name
  @@ -435,10 +517,12 @@
           try
           {
               file.getChildren();
  -            assertTrue( false );
  +            fail();
           }
           catch( FileSystemException e )
           {
  +            final String message = REZ.getString( "list-children-no-exist.error", file );
  +            assertSameMessage( message, e );
           }
   
           // Should be able to get child by name
  @@ -468,23 +552,33 @@
        * a byte stream, and as a char stream, and compares the result with
        * the expected content.  Assumes files are encoded using UTF-8.
        */
  -    public void assertSameContent( String expected, FileContent content ) throws Exception
  +    protected void assertSameContent( final String expected,
  +                                      final FileContent content )
  +        throws Exception
       {
           // Get file content as a binary stream
  -        byte[] expectedBin = expected.getBytes( "utf-8" );
  +        final byte[] expectedBin = expected.getBytes( "utf-8" );
   
           // Check lengths
           assertEquals( "same content length", expectedBin.length, content.getSize() );
   
           // Read content into byte array
  -        InputStream instr = content.getInputStream();
  -        ByteArrayOutputStream outstr = new ByteArrayOutputStream();
  -        byte[] buffer = new byte[ 256 ];
  -        int nread = 0;
  -        while( nread >= 0 )
  +        final InputStream instr = content.getInputStream();
  +        final ByteArrayOutputStream outstr;
  +        try
  +        {
  +            outstr = new ByteArrayOutputStream();
  +            final byte[] buffer = new byte[ 256 ];
  +            int nread = 0;
  +            while( nread >= 0 )
  +            {
  +                outstr.write( buffer, 0, nread );
  +                nread = instr.read( buffer );
  +            }
  +        }
  +        finally
           {
  -            outstr.write( buffer, 0, nread );
  -            nread = instr.read( buffer );
  +            instr.close();
           }
   
           // Compare
  @@ -501,10 +595,12 @@
           try
           {
               folder.getContent();
  -            assertTrue( false );
  +            fail();
           }
           catch( FileSystemException e )
           {
  +            final String message = REZ.getString( "get-folder-content.error", folder );
  +            assertSameMessage( message, e );
           }
   
           // Try getting the content of an unknown file
  @@ -513,18 +609,22 @@
           try
           {
               content.getInputStream();
  -            assertTrue( false );
  +            fail();
           }
           catch( FileSystemException e )
           {
  +            final String message = REZ.getString( "read-no-exist.error", unknownFile );
  +            assertSameMessage( message, e );
           }
           try
           {
               content.getSize();
  -            assertTrue( false );
  +            fail();
           }
           catch( FileSystemException e )
           {
  +            final String message = REZ.getString( "get-size-no-exist.error", unknownFile );
  +            assertSameMessage( message, e );
           }
       }
   
  @@ -557,7 +657,7 @@
       /**
        * Info about a file.
        */
  -    private static final class FileInfo
  +    protected static final class FileInfo
       {
           String _baseName;
           FileType _type;
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message