From dfa0c6e159416ba22df942ba98e496d99d53d07f Mon Sep 17 00:00:00 2001 From: adammurdoch Date: Sun, 7 Apr 2002 02:27:58 +0000 Subject: [PATCH] VFS Additions: * Added FileSelector, which allows files to be chosen when doing recursive operations. Added a couple of implementations. Added a selector parameter to FileObject.delete() and copy(). * Added FileObject.replicateFile(), which converts a FileObject into a local File. * Moved replication code out of the Zip provider, into a shared FileReplicator component. The implemenation is pretty brain-dead, but at very least should properly clean up temporary files in ant_vfs_cache. Also, local files will no longer be replicated, but used directly. * Added FileName.getRelativeName(), and NameScope.DESCENDENT_OR_SELF. * Now handles providers which are LogEnabled and Disposable. * Made the local file provider pluggable. * Providers are now responsible for thier own caching. * FTP and Zip providers clean up properly. Fixed FTP directory delete. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272262 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/myrmidon/build.xml | 2 +- .../apache/antlib/vfile/CopyFilesTask.java | 5 +- .../org/apache/aut/vfs/AllFileSelector.java | 36 +++ .../org/apache/aut/vfs/FileConstants.java | 46 ++++ .../java/org/apache/aut/vfs/FileContent.java | 3 +- .../org/apache/aut/vfs/FileDepthSelector.java | 46 ++++ .../src/java/org/apache/aut/vfs/FileName.java | 47 ++-- .../java/org/apache/aut/vfs/FileObject.java | 49 +++- .../org/apache/aut/vfs/FileSelectInfo.java | 33 +++ .../java/org/apache/aut/vfs/FileSelector.java | 38 +++ .../apache/aut/vfs/FileSystemException.java | 3 +- .../org/apache/aut/vfs/FileSystemManager.java | 6 +- .../src/java/org/apache/aut/vfs/FileType.java | 3 +- .../java/org/apache/aut/vfs/NameScope.java | 13 +- .../aut/vfs/impl/DefaultFileReplicator.java | 98 ++++++++ .../vfs/impl/DefaultFileSystemManager.java | 113 ++++++--- .../aut/vfs/impl/DefaultProviderContext.java | 27 +-- .../apache/aut/vfs/impl/Resources.properties | 5 +- .../aut/vfs/provider/AbstractFileObject.java | 224 ++++++++++++++---- .../aut/vfs/provider/AbstractFileSystem.java | 54 +++-- .../provider/AbstractFileSystemProvider.java | 40 +++- .../aut/vfs/provider/DefaultFileContent.java | 3 +- .../aut/vfs/provider/DefaultFileName.java | 11 +- .../vfs/provider/DefaultFileSelectorInfo.java | 55 +++++ .../aut/vfs/provider/FileReplicator.java | 36 +++ .../apache/aut/vfs/provider/FileSystem.java | 3 +- .../aut/vfs/provider/FileSystemProvider.java | 3 + .../provider/FileSystemProviderContext.java | 9 +- .../vfs/provider/LocalFileSystemProvider.java | 43 ++++ .../apache/aut/vfs/provider/ParsedUri.java | 3 +- .../aut/vfs/provider/Resources.properties | 2 + .../apache/aut/vfs/provider/UriParser.java | 75 +++++- .../vfs/provider/ftp/FtpFileNameParser.java | 3 +- .../aut/vfs/provider/ftp/FtpFileObject.java | 16 +- .../aut/vfs/provider/ftp/FtpFileSystem.java | 53 +++-- .../provider/ftp/FtpFileSystemProvider.java | 5 +- .../aut/vfs/provider/ftp/ParsedFtpUri.java | 3 +- .../aut/vfs/provider/ftp/Resources.properties | 3 +- ...va => DefaultLocalFileSystemProvider.java} | 14 +- .../aut/vfs/provider/local/LocalFile.java | 12 +- .../vfs/provider/local/LocalFileSystem.java | 11 +- .../aut/vfs/provider/smb/ParsedSmbUri.java | 3 +- .../vfs/provider/smb/SmbFileNameParser.java | 3 +- .../aut/vfs/provider/smb/SmbFileObject.java | 3 +- .../aut/vfs/provider/smb/SmbFileSystem.java | 13 +- .../provider/smb/SmbFileSystemProvider.java | 5 +- .../aut/vfs/provider/zip/ParsedZipUri.java | 3 +- .../aut/vfs/provider/zip/Resources.properties | 1 + .../vfs/provider/zip/ZipFileNameParser.java | 5 +- .../aut/vfs/provider/zip/ZipFileObject.java | 3 +- .../aut/vfs/provider/zip/ZipFileSystem.java | 30 ++- .../provider/zip/ZipFileSystemProvider.java | 24 +- .../framework/factories/VfsManager.java | 13 +- .../vfs/test/AbstractFileSystemTestCase.java | 122 ++++++++-- .../AbstractWritableFileSystemTestCase.java | 29 ++- .../apache/myrmidon/AbstractMyrmidonTest.java | 6 - .../apache/myrmidon/AbstractProjectTest.java | 40 ++-- .../DefaultClassLoaderManagerTestCase.java | 2 +- 58 files changed, 1254 insertions(+), 305 deletions(-) create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/AllFileSelector.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/FileConstants.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/FileDepthSelector.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelectInfo.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelector.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileReplicator.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileSelectorInfo.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileReplicator.java create mode 100644 proposal/myrmidon/src/java/org/apache/aut/vfs/provider/LocalFileSystemProvider.java rename proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/{LocalFileSystemProvider.java => DefaultLocalFileSystemProvider.java} (89%) diff --git a/proposal/myrmidon/build.xml b/proposal/myrmidon/build.xml index 8aafc6d8f..297d3c998 100644 --- a/proposal/myrmidon/build.xml +++ b/proposal/myrmidon/build.xml @@ -682,7 +682,7 @@ Legal: - + diff --git a/proposal/myrmidon/src/java/org/apache/antlib/vfile/CopyFilesTask.java b/proposal/myrmidon/src/java/org/apache/antlib/vfile/CopyFilesTask.java index 798f31f0b..5bcb2fd0b 100644 --- a/proposal/myrmidon/src/java/org/apache/antlib/vfile/CopyFilesTask.java +++ b/proposal/myrmidon/src/java/org/apache/antlib/vfile/CopyFilesTask.java @@ -13,6 +13,7 @@ import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.FileType; import org.apache.aut.vfs.NameScope; +import org.apache.aut.vfs.FileConstants; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.myrmidon.api.AbstractTask; @@ -114,7 +115,7 @@ public class CopyFilesTask } getContext().verbose( "copy " + m_srcFile + " to " + m_destFile ); - m_destFile.copy( m_srcFile ); + m_destFile.copyFrom( m_srcFile, FileConstants.SELECT_SELF ); } // Copy the contents of the filesets across @@ -142,7 +143,7 @@ public class CopyFilesTask // Copy the file across getContext().verbose( "copy " + srcFile + " to " + destFile ); - destFile.copy( srcFile ); + destFile.copyFrom( srcFile, FileConstants.SELECT_SELF ); } } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/AllFileSelector.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/AllFileSelector.java new file mode 100644 index 000000000..4ed50e373 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/AllFileSelector.java @@ -0,0 +1,36 @@ +/* + * 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; + +/** + * A {@link FileSelector} which selects everything. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class AllFileSelector + implements FileSelector +{ + /** + * Determines if a file or folder should be selected. + */ + public boolean includeFile( final FileSelectInfo fileInfo ) + throws FileSystemException + { + return true; + } + + /** + * Determines whether a folder should be traversed. + */ + public boolean traverseDescendents( final FileSelectInfo fileInfo ) + throws FileSystemException + { + return true; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileConstants.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileConstants.java new file mode 100644 index 000000000..dd4c461bc --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileConstants.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * Several constants for use in the VFS API. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface FileConstants +{ + /** + * A {@link FileSelector} which selects only the base file/folder. + */ + FileSelector SELECT_SELF = new FileDepthSelector( 0, 0 ); + + /** + * A {@link FileSelector} which selects the base file/folder and its + * direct children. + */ + FileSelector SELECT_SELF_AND_CHILDREN = new FileDepthSelector( 0, 1 ); + + /** + * A {@link FileSelector} which selects only the direct children + * of the base folder. + */ + FileSelector SELECT_CHILDREN = new FileDepthSelector( 1, 1 ); + + /** + * A {@link FileSelector} which selects all the descendents of the + * base folder, but does not select the base folder itself. + */ + FileSelector EXCLUDE_SELF = new FileDepthSelector( 1, Integer.MAX_VALUE ); + + /** + * A {@link FileSelector} which selects the base file/folder, plus all + * its descendents. + */ + FileSelector SELECT_ALL = new AllFileSelector(); +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileContent.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileContent.java index ec684c794..dcada8398 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileContent.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileContent.java @@ -25,7 +25,8 @@ import java.io.OutputStream; * * @see FileObject#getContent * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public interface FileContent { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileDepthSelector.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileDepthSelector.java new file mode 100644 index 000000000..e1baefdfb --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileDepthSelector.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * A {@link FileSelector} which selects all files in a particular depth range. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class FileDepthSelector + implements FileSelector +{ + private final int m_minDepth; + private final int m_maxDepth; + + public FileDepthSelector( int minDepth, int maxDepth ) + { + m_minDepth = minDepth; + m_maxDepth = maxDepth; + } + + /** + * Determines if a file or folder should be selected. + */ + public boolean includeFile( final FileSelectInfo fileInfo ) + throws FileSystemException + { + final int depth = fileInfo.getDepth(); + return m_minDepth <= depth && depth <= m_maxDepth; + } + + /** + * Determines whether a folder should be traversed. + */ + public boolean traverseDescendents( final FileSelectInfo fileInfo ) + throws FileSystemException + { + return fileInfo.getDepth() < m_maxDepth; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java index a265c0f4b..3caee29a6 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileName.java @@ -13,13 +13,14 @@ package org.apache.aut.vfs; * * @see FileObject * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public interface FileName { /** - * Returns the base name of the file. The base name of a file is the - * last element of its name. For example the base name of + * Returns the base name of this file. The base name is the last element + * of the file name. For example the base name of * /somefolder/somefile is somefile. * *

The root file of a file system has an empty base name. @@ -27,23 +28,23 @@ public interface FileName String getBaseName(); /** - * Returns the absolute path of the file, within its file system. This + * Returns the absolute path of this file, within its file system. This * path is normalised, so that . and .. elements * have been removed. Also, the path only contains / as its * separator character. The path always starts with / * - *

The root of a file system has / as its path. + *

The root of a file system has / as its absolute path. */ String getPath(); /** - * Returns the absolute URI of the file. + * Returns the absolute URI of this file. */ String getURI(); /** - * Returns the name of the parent of the file. The root of a file system - * has no parent. + * Returns the file name of the parent of this file. The root of a + * file system has no parent. * * @return * A {@link FileName} object representing the parent name. Returns @@ -52,35 +53,49 @@ public interface FileName FileName getParent(); /** - * Resolves a name, relative to the file. Equivalent to calling + * Resolves a name, relative to this file name. Equivalent to calling * resolveName( path, NameScope.FILE_SYSTEM ). * - * @param path - * The path to resolve. + * @param name + * The name to resolve. * * @return - * A {@link FileName} object representing the resolved name. + * A {@link FileName} object representing the resolved file name. * * @throws FileSystemException * If the name is invalid. */ - FileName resolveName( String path ) throws FileSystemException; + FileName resolveName( String name ) throws FileSystemException; /** - * Resolves a name, relative to the file. Refer to {@link NameScope} + * Resolves a name, relative to this file name. Refer to {@link NameScope} * for a description of how names are resolved. * * @param name - * The path to resolve. + * The name to resolve. * * @param scope * The scope to use when resolving the name. * * @return - * A {@link FileName} object representing the resolved name. + * A {@link FileName} object representing the resolved file name. * * @throws FileSystemException * If the name is invalid. */ FileName resolveName( String name, NameScope scope ) throws FileSystemException; + + /** + * Converts a file name to a relative name, relative to this file name. + * + * @param name + * The name to convert to a relative path. + * + * @return + * The relative name. + * + * @throws FileSystemException + * On error. + */ + String getRelativeName( FileName name ) throws FileSystemException; } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java index 42210e513..f36b02f2a 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileObject.java @@ -7,6 +7,8 @@ */ package org.apache.aut.vfs; +import java.io.File; + /** * This interface represents a file, and is used to access the content and * structure of the file. @@ -53,7 +55,8 @@ package org.apache.aut.vfs; * @see FileContent * @see FileName * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public interface FileObject { @@ -154,17 +157,19 @@ public interface FileObject FileObject resolveFile( String path ) throws FileSystemException; /** - * Deletes this file, and all children. Does nothing if the file + * Deletes this file, and all descendents. Does nothing if the file * does not exist. * *

This method is not transactional. If it fails and throws an - * exception, some of this file's descendents may have been deleted. + * exception, this file will potentially only be partially deleted. + * + * @param selector The selector to use to select which files to delete. * * @throws FileSystemException * If this file or one of its descendents is read-only, or on error * deleting this file or one of its descendents. */ - void delete() throws FileSystemException; + void delete( FileSelector selector ) throws FileSystemException; /** * Creates this file, if it does not exist. Also creates any ancestor @@ -182,18 +187,42 @@ public interface FileObject void create( FileType type ) throws FileSystemException; /** - * Copies the content of another file to this file. + * Copies another file, and all its descendents, to this file. * * If this file does not exist, it is created. Its parent folder is also - * created, if necessary. If this file does exist, its content is replaced. + * created, if necessary. If this file does exist, it is deleted first. + * + *

This method is not transactional. If it fails and throws an + * exception, this file will potentially only be partially copied. + * + * @param srcFile The source file to copy. + * @param selector The selector to use to select which files to copy. + * + * @throws FileSystemException + * If this file is read-only, or if the source file does not exist, + * or on error copying the file. + */ + void copyFrom( FileObject srcFile, FileSelector selector ) throws FileSystemException; + + /** + * Creates a temporary local copy of this file, and its descendents. If + * this file is a local file, a copy is not made. + * + *

Note that the local copy may include additonal files, that were + * not selected by the given selector. + * + * @todo Add options to indicate whether the caller is happy to deal with + * extra files being present locally (eg if the file has been + * replicated previously), or whether the caller expects only + * the selected files to be present. * - * @param file The file to copy the content from. + * @param selector the selector to use to select the files to replicate. + * @return The local copy of this file. * * @throws FileSystemException - * If this file is read-only, or is a folder, or if the supplied file - * is not a file, or on error copying the content. + * If this file does not exist, or on error replicating the file. */ - void copy( FileObject file ) throws FileSystemException; + File replicateFile( FileSelector selector ) throws FileSystemException; /** * Returns this file's content. The {@link FileContent} returned by this diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelectInfo.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelectInfo.java new file mode 100644 index 000000000..a31508be8 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelectInfo.java @@ -0,0 +1,33 @@ +/* + * 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; + +/** + * Information about a file, that is used to select files during the + * traversal of a hierarchy. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface FileSelectInfo +{ + /** + * Returns the base folder of the traversal. + */ + FileObject getBaseFolder(); + + /** + * Returns the file (or folder) to be considered. + */ + FileObject getFile(); + + /** + * Returns the depth of the file relative to the base folder. + */ + int getDepth(); +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelector.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelector.java new file mode 100644 index 000000000..25cacc8b8 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSelector.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * This interface is used to select files when traversing a file hierarchy. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface FileSelector +{ + /** + * Determines if a file or folder should be selected. + * + * @param fileInfo the file or folder to select. + * @return true if the file should be selected. + */ + boolean includeFile( FileSelectInfo fileInfo ) + throws FileSystemException; + + /** + * Determines whether a folder should be traversed. If this method returns + * true, {@link #includeFile} is called for each of the children of + * the folder, and each of the child folders is recursively traversed. + * + * @param fileInfo the file or folder to select. + * + * @return true if the folder should be traversed. + */ + boolean traverseDescendents( FileSelectInfo fileInfo ) + throws FileSystemException; +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemException.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemException.java index 63cb711ef..10e8e4e35 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemException.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemException.java @@ -10,7 +10,8 @@ package org.apache.aut.vfs; /** * Thrown for file system errors. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class FileSystemException extends Exception diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemManager.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemManager.java index 19768527c..e8679a008 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemManager.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileSystemManager.java @@ -49,7 +49,9 @@ import java.io.File; * * * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ + * * @ant:role shorthand="file-system-manager" */ public interface FileSystemManager @@ -128,7 +130,7 @@ public interface FileSystemManager /** * Creates a layered file system. A layered file system is a file system - * that is created from the contents of another file file, such as a zip + * that is created from the contents of another file, such as a zip * or tar file. * * @param provider diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileType.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileType.java index 69b2b31c2..ce2355e4e 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/FileType.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/FileType.java @@ -5,7 +5,8 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ package org.apache.aut.vfs; diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java index e730a4c73..2280219db 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/NameScope.java @@ -11,7 +11,8 @@ package org.apache.aut.vfs; * An enumerated type for file name scope, used when resolving a name relative * to a file. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public final class NameScope { @@ -29,6 +30,14 @@ public final class NameScope */ public static final NameScope DESCENDENT = new NameScope( "descendent" ); + /** + * 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, or the base + * files itself. + */ + public static final NameScope DESCENDENT_OR_SELF = new NameScope( "descendent_or_self" ); + /** * Resolve against files in the same file system as the base file. * @@ -46,7 +55,7 @@ public final class NameScope */ public static final NameScope FILE_SYSTEM = new NameScope( "filesystem" ); - private String m_name; + private final String m_name; private NameScope( final String name ) { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileReplicator.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileReplicator.java new file mode 100644 index 000000000..13d83276b --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileReplicator.java @@ -0,0 +1,98 @@ +/* + * 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.impl; + +import java.io.File; +import java.util.ArrayList; +import org.apache.aut.vfs.FileConstants; +import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSelector; +import org.apache.aut.vfs.FileSystemException; +import org.apache.aut.vfs.provider.FileReplicator; +import org.apache.avalon.excalibur.i18n.ResourceManager; +import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.logger.AbstractLogEnabled; + +/** + * A simple file replicator. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class DefaultFileReplicator + extends AbstractLogEnabled + implements FileReplicator, Disposable +{ + private static final Resources REZ = + ResourceManager.getPackageResources( DefaultFileReplicator.class ); + + private final DefaultFileSystemManager m_manager; + private final File m_tempDir; + private final ArrayList m_copies = new ArrayList(); + private long m_filecount; + + public DefaultFileReplicator( final DefaultFileSystemManager manager ) + { + m_manager = manager; + m_tempDir = new File( "ant_vfs_cache" ).getAbsoluteFile(); + } + + /** + * Deletes the temporary files. + */ + public void dispose() + { + while( m_copies.size() > 0 ) + { + final FileObject file = (FileObject)m_copies.remove( 0 ); + try + { + file.delete( FileConstants.SELECT_ALL ); + } + catch( final FileSystemException e ) + { + final String message = REZ.getString( "delete-temp.warn", file.getName() ); + getLogger().warn( message, e ); + } + } + } + + /** + * Creates a local copy of the file, and all its descendents. + */ + public File replicateFile( final FileObject srcFile, + final FileSelector selector ) + throws FileSystemException + { + // TODO - this is awful + + // Create a unique-ish file name + final String basename = m_filecount + "_" + srcFile.getName().getBaseName(); + m_filecount++; + final File file = new File( m_tempDir, basename ); + + try + { + // Copy from the source file + final FileObject destFile = m_manager.convert( file ); + destFile.copyFrom( srcFile, selector ); + + // Keep track of the copy + m_copies.add( destFile ); + } + catch( final FileSystemException e ) + { + final String message = REZ.getString( "replicate-file.error", srcFile.getName(), file ); + throw new FileSystemException( message, e ); + } + + return file; + } + +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileSystemManager.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileSystemManager.java index 7bed643da..5cb43cc67 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileSystemManager.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultFileSystemManager.java @@ -9,48 +9,50 @@ package org.apache.aut.vfs.impl; import java.io.File; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.FileSystemManager; +import org.apache.aut.vfs.provider.FileReplicator; import org.apache.aut.vfs.provider.FileSystemProvider; +import org.apache.aut.vfs.provider.LocalFileSystemProvider; import org.apache.aut.vfs.provider.UriParser; -import org.apache.aut.vfs.provider.local.LocalFileSystemProvider; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.logger.Logger; /** * A default file system manager implementation. * + * @todo - Extract an AbstractFileSystemManager super-class from this class. + * * @author Adam Murdoch * @version $Revision$ $Date$ */ public class DefaultFileSystemManager - implements FileSystemManager + extends AbstractLogEnabled + implements FileSystemManager, Disposable { private static final Resources REZ = ResourceManager.getPackageResources( DefaultFileSystemManager.class ); - /** The default provider. */ - private final LocalFileSystemProvider m_localFileProvider; + /** The provider for local files. */ + private LocalFileSystemProvider m_localFileProvider; + + /** The file replicator to use. */ + private final DefaultFileReplicator m_fileReplicator = new DefaultFileReplicator( this ); /** Mapping from URI scheme to FileSystemProvider. */ private final Map m_providers = new HashMap(); - /** The provider context. */ - private final DefaultProviderContext m_context = new DefaultProviderContext( this ); - /** The base file to use for relative URI. */ private FileObject m_baseFile; - public DefaultFileSystemManager() - { - // Create the local provider - m_localFileProvider = new LocalFileSystemProvider(); - m_providers.put( "file", m_localFileProvider ); - m_localFileProvider.setContext( m_context ); - } - /** * Registers a file system provider. */ @@ -58,7 +60,7 @@ public class DefaultFileSystemManager final FileSystemProvider provider ) throws FileSystemException { - addProvider( new String[] { urlScheme }, provider ); + addProvider( new String[]{urlScheme}, provider ); } /** @@ -71,7 +73,7 @@ public class DefaultFileSystemManager // Check for duplicates for( int i = 0; i < urlSchemes.length; i++ ) { - final String scheme = urlSchemes[i ]; + final String scheme = urlSchemes[ i ]; if( m_providers.containsKey( scheme ) ) { final String message = REZ.getString( "multiple-providers-for-scheme.error", scheme ); @@ -80,7 +82,8 @@ public class DefaultFileSystemManager } // Contextualise - provider.setContext( m_context ); + setupLogger( provider ); + provider.setContext( new DefaultProviderContext( this ) ); // Add to map for( int i = 0; i < urlSchemes.length; i++ ) @@ -88,14 +91,55 @@ public class DefaultFileSystemManager final String scheme = urlSchemes[ i ]; m_providers.put( scheme, provider ); } + + if( provider instanceof LocalFileSystemProvider ) + { + m_localFileProvider = (LocalFileSystemProvider)provider; + } } /** - * Closes all file systems created by this file system manager. + * Returns the file replicator. + * + * @return The file replicator. Never returns null. */ - public void close() + public FileReplicator getReplicator() + throws FileSystemException { - // TODO - implement this + return m_fileReplicator; + } + + /** + * Enable logging. + */ + public void enableLogging( final Logger logger ) + { + super.enableLogging( logger ); + setupLogger( m_fileReplicator ); + } + + /** + * Closes all files created by this manager, and cleans up any temporary + * files. + */ + public void dispose() + { + // Dispose the providers (making sure we only dispose each provider + // once + final Set providers = new HashSet(); + providers.addAll( m_providers.values() ); + for( Iterator iterator = providers.iterator(); iterator.hasNext(); ) + { + Object provider = iterator.next(); + if( provider instanceof Disposable ) + { + Disposable disposable = (Disposable)provider; + disposable.dispose(); + } + } + m_providers.clear(); + + m_fileReplicator.dispose(); } /** @@ -111,7 +155,7 @@ public class DefaultFileSystemManager */ public void setBaseFile( final File baseFile ) throws FileSystemException { - m_baseFile = m_localFileProvider.findLocalFile( baseFile.getAbsolutePath() ); + m_baseFile = getLocalFileProvider().findLocalFile( baseFile ); } /** @@ -136,7 +180,7 @@ public class DefaultFileSystemManager public FileObject resolveFile( final File baseFile, final String uri ) throws FileSystemException { - final FileObject baseFileObj = m_localFileProvider.findLocalFile( baseFile ); + final FileObject baseFileObj = getLocalFileProvider().findLocalFile( baseFile ); return resolveFile( baseFileObj, uri ); } @@ -162,19 +206,20 @@ public class DefaultFileSystemManager final String decodedUri = UriParser.decode( uri ); // Handle absolute file names - if( m_localFileProvider.isAbsoluteLocalName( decodedUri ) ) + if( m_localFileProvider != null + && m_localFileProvider.isAbsoluteLocalName( decodedUri ) ) { return m_localFileProvider.findLocalFile( decodedUri ); } - // Assume a bad scheme if( scheme != null ) { + // Assume a bad scheme final String message = REZ.getString( "unknown-scheme.error", scheme, uri ); throw new FileSystemException( message ); } - // Use the supplied base file + // Assume a relative name - use the supplied base file if( baseFile == null ) { final String message = REZ.getString( "find-rel-file.error", uri ); @@ -189,7 +234,7 @@ public class DefaultFileSystemManager public FileObject convert( final File file ) throws FileSystemException { - return m_localFileProvider.findLocalFile( file ); + return getLocalFileProvider().findLocalFile( file ); } /** @@ -207,4 +252,18 @@ public class DefaultFileSystemManager } return provider.createFileSystem( scheme, file ); } + + /** + * Locates the local file provider. + */ + private LocalFileSystemProvider getLocalFileProvider() + throws FileSystemException + { + if( m_localFileProvider == null ) + { + final String message = REZ.getString( "no-local-file-provider.error" ); + throw new FileSystemException( message ); + } + return m_localFileProvider; + } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultProviderContext.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultProviderContext.java index 9cb6ac6b8..e2a04b238 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultProviderContext.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/DefaultProviderContext.java @@ -7,11 +7,9 @@ */ package org.apache.aut.vfs.impl; -import java.util.HashMap; -import java.util.Map; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; -import org.apache.aut.vfs.provider.FileSystem; +import org.apache.aut.vfs.provider.FileReplicator; import org.apache.aut.vfs.provider.FileSystemProviderContext; /** @@ -25,12 +23,6 @@ final class DefaultProviderContext { private final DefaultFileSystemManager m_manager; - /** - * The cached file systems. This is a mapping from root URI to - * FileSystem object. - */ - private final Map m_fileSystems = new HashMap(); - public DefaultProviderContext( final DefaultFileSystemManager manager ) { m_manager = manager; @@ -46,21 +38,10 @@ final class DefaultProviderContext } /** - * Locates a cached file system by root URI. + * Locates a file replicator for the provider to use. */ - public FileSystem getFileSystem( final String rootURI ) - { - // TODO - need to have a per-fs uri comparator - return (FileSystem)m_fileSystems.get( rootURI ); - } - - /** - * Registers a file system for caching. - */ - public void putFileSystem( final String rootURI, final FileSystem fs ) - throws FileSystemException + public FileReplicator getReplicator() throws FileSystemException { - // TODO - should really check that there's not one already cached - m_fileSystems.put( rootURI, fs ); + return m_manager.getReplicator(); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/Resources.properties b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/Resources.properties index 6d9077083..b75e74ebf 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/impl/Resources.properties @@ -2,4 +2,7 @@ unknown-scheme.error=Unknown scheme "{0}" in URI "{1}". find-rel-file.error=Could not find file with URI "{0}" because it is a relative path, and no base URI was provided. multiple-providers-for-scheme.error=Multiple file system providers registered for URL scheme "{0}". -unknown-provider.error=Unknown file system provider "{0}". \ No newline at end of file +unknown-provider.error=No file system provider is registered for URI scheme "{0}". +no-local-file-provider.error=Could not find a file system provider which can handle local files. +replicate-file.error=Could not replicate "{0}" to "{1}". +delete-temp.warn=Could not clean up temporary file "{0}". \ No newline at end of file diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileObject.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileObject.java index 103a8883a..18c9a2780 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileObject.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileObject.java @@ -7,15 +7,16 @@ */ package org.apache.aut.vfs.provider; +import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import org.apache.aut.vfs.FileConstants; import org.apache.aut.vfs.FileContent; import org.apache.aut.vfs.FileName; import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSelector; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.FileType; import org.apache.aut.vfs.NameScope; @@ -26,7 +27,11 @@ import org.apache.avalon.excalibur.io.IOUtil; /** * A partial file object implementation. * - * @author Adam Murdoch + * @todo Chop this class up - move all the protected methods to several + * interfaces, so that structure and content can be separately overridden. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public abstract class AbstractFileObject implements FileObject @@ -98,7 +103,7 @@ public abstract class AbstractFileObject *

    *
  • {@link #isReadOnly} returns false. *
  • {@link #doGetType} does not return null. - *
  • If this file is a folder, it has no children. + *
  • This file has no children. *
*/ protected void doDelete() throws Exception @@ -122,6 +127,15 @@ public abstract class AbstractFileObject throw new FileSystemException( message ); } + /** + * Creates a local copy of this file. + */ + protected File doReplicateFile( final FileSelector selector ) throws FileSystemException + { + final FileReplicator replicator = m_fs.getContext().getReplicator(); + return replicator.replicateFile( this, selector ); + } + /** * Called when the children of this file change. */ @@ -321,9 +335,9 @@ public abstract class AbstractFileObject * absolute path, which is resolved relative to the file system * that contains this file. */ - public FileObject resolveFile( String path ) throws FileSystemException + public FileObject resolveFile( final String path ) throws FileSystemException { - FileName name = m_name.resolveName( path ); + final FileName name = m_name.resolveName( path ); return m_fs.findFile( name ); } @@ -356,7 +370,7 @@ public abstract class AbstractFileObject /** * Deletes this file, and all children. */ - public void delete() throws FileSystemException + public void delete( final FileSelector selector ) throws FileSystemException { attach(); if( m_type == null ) @@ -365,51 +379,27 @@ public abstract class AbstractFileObject return; } - // Recursively delete this file and all its children - List queue = new ArrayList(); - Set expanded = new HashSet(); - queue.add( this ); + // Locate all the files to delete + ArrayList files = new ArrayList(); + findFiles( selector, true, files ); - // Recursively delete each file - // TODO - recover from errors - while( queue.size() > 0 ) + // Delete 'em + final int count = files.size(); + for( int i = 0; i < count; i++ ) { - AbstractFileObject file = (AbstractFileObject)queue.get( 0 ); + final AbstractFileObject file = (AbstractFileObject)files.get( i ); file.attach(); - if( file.m_type == null ) - { - // Shouldn't happen - queue.remove( 0 ); - } - else if( file.m_type == FileType.FILE ) - { - // Delete the file - file.deleteSelf(); - queue.remove( 0 ); - } - else if( expanded.contains( file ) ) + // If the file is a folder, make sure all its children have been deleted + if( file.m_type == FileType.FOLDER && file.getChildren().length != 0 ) { - // Have already deleted all the children of this folder - - // delete it - file.deleteSelf(); - queue.remove( 0 ); + // Skip + continue; } - else - { - // Delete the folder's children - FileObject[] children = file.getChildren(); - for( int i = 0; i < children.length; i++ ) - { - FileObject child = children[ i ]; - queue.add( 0, child ); - } - expanded.add( file ); - } - } - // Update parent's child list - notifyParent(); + // Delete the file + file.deleteSelf(); + } } /** @@ -467,19 +457,88 @@ public abstract class AbstractFileObject updateType(); } + /** + * Copies another file to this file. + */ + public void copyFrom( final FileObject file, final FileSelector selector ) + throws FileSystemException + { + if( !file.exists() ) + { + final String message = REZ.getString( "copy-missing-file.error", file.getName() ); + throw new FileSystemException( message ); + } + if( isReadOnly() ) + { + final String message = REZ.getString( "copy-read-only.error", file.getType(), file.getName(), m_name ); + throw new FileSystemException( message ); + } + + // Locate the files to copy across + final ArrayList files = new ArrayList(); + ( (AbstractFileObject)file ).findFiles( selector, false, files ); + + // Copy everything across + final int count = files.size(); + for( int i = 0; i < count; i++ ) + { + final FileObject srcFile = (FileObject)files.get( i ); + + // Determine the destination file + final String relPath = file.getName().getRelativeName( srcFile.getName() ); + final FileObject destFile = resolveFile( relPath, NameScope.DESCENDENT_OR_SELF ); + + // Clean up the destination file, if necessary + if( destFile.exists() && destFile.getType() != srcFile.getType() ) + { + // The destination file exists, and is not of the same type, + // so delete it + // TODO - add a pluggable policy for deleting and overwriting existing files + destFile.delete( FileConstants.SELECT_ALL ); + } + + // Copy across + if( srcFile.getType() == FileType.FILE ) + { + copyContent( srcFile, destFile ); + } + else + { + destFile.create( FileType.FOLDER ); + } + } + } + + /** + * Creates a temporary local copy of this file, and its descendents. + */ + public File replicateFile( final FileSelector selector ) + throws FileSystemException + { + if( !exists() ) + { + final String message = REZ.getString( "copy-missing-file.error", m_name ); + throw new FileSystemException( message ); + } + + return doReplicateFile( selector ); + } + /** * Copies the content of another file to this file. */ - public void copy( final FileObject file ) throws FileSystemException + private static void copyContent( final FileObject srcFile, + final FileObject destFile ) + throws FileSystemException { try { - final InputStream instr = file.getContent().getInputStream(); + final InputStream instr = srcFile.getContent().getInputStream(); try { - // Create the output strea via getContent(), to pick up the + // Create the output stream via getContent(), to pick up the // validation it does - final OutputStream outstr = getContent().getOutputStream(); + final OutputStream outstr = destFile.getContent().getOutputStream(); try { IOUtil.copy( instr, outstr ); @@ -496,7 +555,7 @@ public abstract class AbstractFileObject } catch( final Exception exc ) { - final String message = REZ.getString( "copy-file.error", file.getName(), m_name ); + final String message = REZ.getString( "copy-file.error", srcFile.getName(), destFile.getName() ); throw new FileSystemException( message, exc ); } } @@ -678,4 +737,69 @@ public abstract class AbstractFileObject m_children = null; onChildrenChanged(); } + + /** + * Traverses the descendents of this file, and builds a list of selected + * files. + */ + void findFiles( final FileSelector selector, + final boolean depthwise, + final List selected ) throws FileSystemException + { + if( exists() ) + { + // Traverse starting at this file + final DefaultFileSelectorInfo info = new DefaultFileSelectorInfo(); + info.setBaseFolder( this ); + info.setDepth( 0 ); + info.setFile( this ); + traverse( info, selector, depthwise, selected ); + } + } + + /** + * Traverses a file. + */ + private void traverse( final DefaultFileSelectorInfo fileInfo, + final FileSelector selector, + final boolean depthwise, + final List selected ) + throws FileSystemException + { + // Check the file itself + final boolean includeFile = selector.includeFile( fileInfo ); + final FileObject file = fileInfo.getFile(); + + // Add the file if not doing depthwise traversal + if( !depthwise && includeFile ) + { + selected.add( file ); + } + + // If the file is a folder, traverse it + if( file.getType() == FileType.FOLDER && selector.traverseDescendents( fileInfo ) ) + { + final int curDepth = fileInfo.getDepth(); + fileInfo.setDepth( curDepth + 1 ); + + // Traverse the children + final FileObject[] children = file.getChildren(); + for( int i = 0; i < children.length; i++ ) + { + final FileObject child = children[ i ]; + fileInfo.setFile( child ); + traverse( fileInfo, selector, depthwise, selected ); + } + + fileInfo.setFile( file ); + fileInfo.setDepth( curDepth ); + } + + // Add the file if doing depthwise traversal + if( depthwise && includeFile ) + { + selected.add( file ); + } + } + } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystem.java index a72cad269..35741dea1 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystem.java @@ -12,45 +12,67 @@ import java.util.Map; import org.apache.aut.vfs.FileName; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.logger.AbstractLogEnabled; /** * A partial file system implementation. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ -public abstract class AbstractFileSystem implements FileSystem +public abstract class AbstractFileSystem + extends AbstractLogEnabled + implements FileSystem, Disposable { private FileObject m_root; - private FileName m_rootName; + private final FileName m_rootName; + private final FileSystemProviderContext m_context; - /** Map from absolute file path to FileObject. */ - private Map m_files = new HashMap(); + /** Map from FileName to FileObject. */ + private final Map m_files = new HashMap(); - protected AbstractFileSystem( FileName rootName ) + protected AbstractFileSystem( final FileSystemProviderContext context, + final FileName rootName ) { m_rootName = rootName; + m_context = context; + } + + public void dispose() + { + // Clean-up + m_files.clear(); } /** * Creates a file object. This method is called only if the requested * file is not cached. */ - protected abstract FileObject createFile( FileName name ) throws FileSystemException; + protected abstract FileObject createFile( final FileName name ) throws FileSystemException; /** * Adds a file object to the cache. */ - protected void putFile( FileObject file ) + protected void putFile( final FileObject file ) { - m_files.put( file.getName().getPath(), file ); + m_files.put( file.getName(), file ); } /** * Returns a cached file. */ - protected FileObject getFile( FileName name ) + protected FileObject getFile( final FileName name ) + { + return (FileObject)m_files.get( name ); + } + + /** + * Returns the context fir this file system. + */ + public FileSystemProviderContext getContext() { - return (FileObject)m_files.get( name.getPath() ); + return m_context; } /** @@ -68,24 +90,24 @@ public abstract class AbstractFileSystem implements FileSystem /** * Finds a file in this file system. */ - public FileObject findFile( String nameStr ) throws FileSystemException + public FileObject findFile( final String nameStr ) throws FileSystemException { // Resolve the name, and create the file - FileName name = m_rootName.resolveName( nameStr ); + final FileName name = m_rootName.resolveName( nameStr ); return findFile( name ); } /** * Finds a file in this file system. */ - public FileObject findFile( FileName name ) throws FileSystemException + public FileObject findFile( final FileName name ) throws FileSystemException { // TODO - assert that name is from this file system - FileObject file = (FileObject)m_files.get( name.getPath() ); + FileObject file = (FileObject)m_files.get( name ); if( file == null ) { file = createFile( name ); - m_files.put( name.getPath(), file ); + m_files.put( name, file ); } return file; } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystemProvider.java index ea143b2e5..1643b0b8a 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/AbstractFileSystemProvider.java @@ -7,24 +7,37 @@ */ package org.apache.aut.vfs.provider; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.logger.AbstractLogEnabled; /** * A partial file system provider implementation. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public abstract class AbstractFileSystemProvider - implements FileSystemProvider + extends AbstractLogEnabled + implements FileSystemProvider, Disposable { private static final Resources REZ = ResourceManager.getPackageResources( AbstractFileSystemProvider.class ); private FileSystemProviderContext m_context; + /** + * The cached file systems. This is a mapping from root URI to + * FileSystem object. + */ + private final Map m_fileSystems = new HashMap(); + /** * Returns the context for this provider. */ @@ -42,6 +55,23 @@ public abstract class AbstractFileSystemProvider m_context = context; } + /** + * Closes the file systems created by this provider. + */ + public void dispose() + { + for( Iterator iterator = m_fileSystems.values().iterator(); iterator.hasNext(); ) + { + FileSystem fileSystem = (FileSystem)iterator.next(); + if( fileSystem instanceof Disposable ) + { + Disposable disposable = (Disposable)fileSystem; + disposable.dispose(); + } + } + m_fileSystems.clear(); + } + /** * Locates a file object, by absolute URI. * @@ -65,7 +95,6 @@ public abstract class AbstractFileSystemProvider // Locate the file return findFile( parsedUri ); - } /** @@ -76,12 +105,13 @@ public abstract class AbstractFileSystemProvider { // Check in the cache for the file system final String rootUri = parsedUri.getRootUri(); - FileSystem fs = m_context.getFileSystem( rootUri ); + FileSystem fs = (FileSystem)m_fileSystems.get( rootUri ); if( fs == null ) { // Need to create the file system, and cache it fs = createFileSystem( parsedUri ); - m_context.putFileSystem( rootUri, fs ); + setupLogger( fs ); + m_fileSystems.put( rootUri, fs ); } // Locate the file diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileContent.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileContent.java index fed48eed6..52720f5ef 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileContent.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileContent.java @@ -21,7 +21,8 @@ import org.apache.avalon.excalibur.i18n.Resources; /** * The content of a file. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class DefaultFileContent implements FileContent diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java index abb9a174b..45ce49e6c 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileName.java @@ -14,7 +14,8 @@ import org.apache.aut.vfs.NameScope; /** * A default file name implementation. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class DefaultFileName implements FileName { @@ -127,4 +128,12 @@ public class DefaultFileName implements FileName } return m_uri; } + + /** + * Converts a file name to a relative name, relative to this file name. + */ + public String getRelativeName( final FileName name ) throws FileSystemException + { + return m_parser.makeRelative( m_absPath, name.getPath() ); + } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileSelectorInfo.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileSelectorInfo.java new file mode 100644 index 000000000..efa62c8f7 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/DefaultFileSelectorInfo.java @@ -0,0 +1,55 @@ +/* + * 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; + +import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSelectInfo; + +/** + * A default {@link FileSelectInfo} implementation. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +class DefaultFileSelectorInfo + implements FileSelectInfo +{ + private FileObject m_baseFolder; + private FileObject m_file; + private int m_depth; + + public FileObject getBaseFolder() + { + return m_baseFolder; + } + + public void setBaseFolder( final FileObject baseFolder ) + { + m_baseFolder = baseFolder; + } + + public FileObject getFile() + { + return m_file; + } + + public void setFile( final FileObject file ) + { + m_file = file; + } + + public int getDepth() + { + return m_depth; + } + + public void setDepth( final int depth ) + { + m_depth = depth; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileReplicator.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileReplicator.java new file mode 100644 index 000000000..b283bd956 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileReplicator.java @@ -0,0 +1,36 @@ +/* + * 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; + +import java.io.File; +import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSelector; +import org.apache.aut.vfs.FileSystemException; + +/** + * Responsible for making local replicas of files. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface FileReplicator +{ + /** + * Creates a local copy of the file, and all its descendents. + * + * @param srcFile The file to copy. + * @param selector Selects the files to copy. + * + * @return The local copy of the source file. + * + * @throws FileSystemException + * If the source files does not exist, or on error copying. + */ + File replicateFile( FileObject srcFile, FileSelector selector ) + throws FileSystemException; +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystem.java index 8c9d53c84..2fe00e41a 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystem.java @@ -14,7 +14,8 @@ import org.apache.aut.vfs.FileSystemException; /** * A file system. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public interface FileSystem { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProvider.java index 37f61209c..1d9f2c4f4 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProvider.java @@ -25,6 +25,9 @@ public interface FileSystemProvider /** * Sets the context for this file system provider. This method is called * before any of the other provider methods. + * + * @todo - move this to a lifecycle interface (this interface is accessable to + * other providers, so need to prevent this being called). */ void setContext( FileSystemProviderContext context ); diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProviderContext.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProviderContext.java index 1fb092d11..fd3ce1b91 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProviderContext.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/FileSystemProviderContext.java @@ -29,12 +29,7 @@ public interface FileSystemProviderContext throws FileSystemException; /** - * Locates a cached file system by root URI. + * Locates a file replicator for the provider to use. */ - FileSystem getFileSystem( String rootURI ); - - /** - * Registers a file system for caching. - */ - void putFileSystem( String rootURI, FileSystem fs ) throws FileSystemException; + FileReplicator getReplicator() throws FileSystemException; } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/LocalFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/LocalFileSystemProvider.java new file mode 100644 index 000000000..07cfccecb --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/LocalFileSystemProvider.java @@ -0,0 +1,43 @@ +/* + * 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; + +import java.io.File; +import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSystemException; + +/** + * A file system provider which handles local file systems. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface LocalFileSystemProvider + extends FileSystemProvider +{ + /** + * Determines if a name is an absolute file name. + * + * @todo Move this to a general file name parser interface. + * + * @param name The name to test. + */ + boolean isAbsoluteLocalName( final String name ); + + /** + * Finds a local file, from its local name. + */ + FileObject findLocalFile( final String name ) + throws FileSystemException; + + /** + * Finds a local file. + */ + FileObject findLocalFile( final File file ) + throws FileSystemException; +} diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ParsedUri.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ParsedUri.java index 70b7efd66..ecf6950e3 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ParsedUri.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ParsedUri.java @@ -10,7 +10,8 @@ package org.apache.aut.vfs.provider; /** * A data container for information parsed from an absolute URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class ParsedUri { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties index 16911ce1a..c32e60b18 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/Resources.properties @@ -18,6 +18,8 @@ write-folder.error=Could not write to "{0}" because it is a folder. write-in-use.error=Could not write to "{0}" because it is already in use. write.error=Could not write to "{0}". copy-file.error=Could not copy "{0}" to "{1}". +copy-read-only.error=Could not copy {0} "{1}" to "{2}" because the destination file is read-only. +copy-missing-file.error=Could not copy "{0}" because is does not exist. # DefaultFileContent get-size-no-exist.error=Could not determine the size of file "{0}" because it does not exist. diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java index 298b1fca2..74912c20d 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/UriParser.java @@ -17,7 +17,8 @@ import org.apache.avalon.excalibur.i18n.Resources; /** * A name parser which parses absolute URIs. See RFC 2396 for details. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class UriParser { @@ -452,6 +453,17 @@ public class UriParser throw new FileSystemException( message ); } } + else if( scope == NameScope.DESCENDENT_OR_SELF ) + { + final int baseLen = baseFile.length(); + if( !resolvedPath.startsWith( baseFile ) + || ( resolvedPath.length() != baseLen + && resolvedPath.charAt( baseLen ) != m_separatorChar ) ) + { + final String message = REZ.getString( "invalid-descendent-name.error", path ); + throw new FileSystemException( message ); + } + } else if( scope != NameScope.FILE_SYSTEM ) { throw new IllegalArgumentException(); @@ -482,6 +494,67 @@ public class UriParser return path.substring( 0, idx ); } + /** + * Converts an absolute path into a relative path. + * + * @param basePath The base path. + * @param path The path to convert. + */ + public String makeRelative( final String basePath, final String path ) + { + // Calculate the common prefix + final int basePathLen = basePath.length(); + final int pathLen = path.length(); + + // Deal with root + if( basePathLen == 1 && pathLen == 1 ) + { + return "."; + } + else if( basePathLen == 1 ) + { + return path.substring( 1 ); + } + + final int maxlen = Math.min( basePathLen, pathLen ); + int pos = 0; + for( ; pos < maxlen && basePath.charAt( pos ) == path.charAt( pos ); pos++ ) + { + } + + if( pos == basePathLen && pos == pathLen ) + { + // Same names + return "."; + } + else if( pos == basePathLen && pos < pathLen && path.charAt( pos ) == m_separatorChar ) + { + // A descendent of the base path + return path.substring( pos + 1 ); + } + + // Strip the common prefix off the path + final StringBuffer buffer = new StringBuffer(); + if( pathLen > 1 && ( pos < pathLen || basePath.charAt( pos ) != m_separatorChar ) ) + { + // Not a direct ancestor, need to back up + pos = basePath.lastIndexOf( m_separatorChar, pos ); + buffer.append( path.substring( pos ) ); + } + + // Prepend a '../' for each element in the base path past the common + // prefix + buffer.insert( 0, ".." ); + pos = basePath.indexOf( m_separatorChar, pos + 1 ); + while( pos != -1 ) + { + buffer.insert( 0, "../" ); + pos = basePath.indexOf( m_separatorChar, pos + 1 ); + } + + return buffer.toString(); + } + /** * Normalises a path. Does the following: *
    diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileNameParser.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileNameParser.java index 5b2f4f12e..41e0c5763 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileNameParser.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileNameParser.java @@ -13,7 +13,8 @@ import org.apache.aut.vfs.provider.UriParser; /** * A parser for FTP URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class FtpFileNameParser extends UriParser { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileObject.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileObject.java index 7c71fc1f3..fba668fe7 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileObject.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileObject.java @@ -7,6 +7,7 @@ */ package org.apache.aut.vfs.provider.ftp; +import com.oroinc.net.ftp.FTPClient; import com.oroinc.net.ftp.FTPFile; import java.io.InputStream; import java.io.OutputStream; @@ -20,7 +21,8 @@ import org.apache.avalon.excalibur.i18n.Resources; /** * An FTP file. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ class FtpFileObject extends AbstractFileObject @@ -160,7 +162,17 @@ class FtpFileObject */ protected void doDelete() throws Exception { - if( !m_ftpFs.getClient().deleteFile( getName().getPath() ) ) + final FTPClient ftpClient = m_ftpFs.getClient(); + boolean ok; + if( m_fileInfo.isDirectory() ) + { + ok = ftpClient.removeDirectory( getName().getPath() ); + } + else + { + ok = ftpClient.deleteFile( getName().getPath() ); + } + if( !ok ) { final String message = REZ.getString( "delete-file.error", getName() ); throw new FileSystemException( message ); diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystem.java index dd4cf4c9f..880d82353 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystem.java @@ -15,13 +15,15 @@ import org.apache.aut.vfs.FileName; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystem; +import org.apache.aut.vfs.provider.FileSystemProviderContext; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; /** * An FTP file system. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ class FtpFileSystem extends AbstractFileSystem @@ -31,13 +33,14 @@ class FtpFileSystem private FTPClient m_client; - public FtpFileSystem( final FileName rootName, + public FtpFileSystem( final FileSystemProviderContext context, + final FileName rootName, final String hostname, final String username, final String password ) throws FileSystemException { - super( rootName ); + super( context, rootName ); try { m_client = new FTPClient(); @@ -64,26 +67,39 @@ class FtpFileSystem throw new FileSystemException( message ); } } - catch( Exception exc ) + catch( final Exception exc ) { - try - { - // Clean up - if( m_client.isConnected() ) - { - m_client.disconnect(); - } - } - catch( IOException e ) - { - // Ignore - } - + closeConnection(); final String message = REZ.getString( "connect.error", hostname ); throw new FileSystemException( message, exc ); } + } - // TODO - close connection + public void dispose() + { + // Clean up the connection + super.dispose(); + closeConnection(); + } + + /** + * Cleans up the connection to the server. + */ + private void closeConnection() + { + try + { + // Clean up + if( m_client.isConnected() ) + { + m_client.disconnect(); + } + } + catch( final IOException e ) + { + final String message = REZ.getString( "close-connection.error" ); + getLogger().warn( message, e ); + } } /** @@ -91,6 +107,7 @@ class FtpFileSystem */ public FTPClient getClient() { + // TODO - connect on demand, and garbage collect connections return m_client; } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystemProvider.java index 0369c6d5f..ef0105123 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/FtpFileSystemProvider.java @@ -18,7 +18,8 @@ import org.apache.aut.vfs.provider.ParsedUri; /** * A provider for FTP file systems. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ * * @ant.type type="file-system" name="ftp" */ @@ -60,6 +61,6 @@ public class FtpFileSystemProvider extends AbstractFileSystemProvider } // Create the file system - return new FtpFileSystem( rootName, ftpUri.getHostName(), username, password ); + return new FtpFileSystem( getContext(), rootName, ftpUri.getHostName(), username, password ); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/ParsedFtpUri.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/ParsedFtpUri.java index 03616ec27..d9c8befa2 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/ParsedFtpUri.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/ParsedFtpUri.java @@ -12,7 +12,8 @@ import org.apache.aut.vfs.provider.ParsedUri; /** * A parsed FTP URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class ParsedFtpUri extends ParsedUri { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/Resources.properties b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/Resources.properties index d2c712051..eaa64d0a2 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/ftp/Resources.properties @@ -6,4 +6,5 @@ finish-put.error=Could not put FTP file "{0}". connect-rejected.error=Connection to FTP server on "{0}" rejected. login.error=Could not login to FTP server on "{0}" as user "{1}". set-binary.error=Could not switch to binary transfer mode. -connect.error=Could not connect to FTP server on "{0}". \ No newline at end of file +connect.error=Could not connect to FTP server on "{0}". +close-connection.error=Could not close connection to FTP server. \ No newline at end of file diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/DefaultLocalFileSystemProvider.java similarity index 89% rename from proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystemProvider.java rename to proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/DefaultLocalFileSystemProvider.java index be00f376d..d81e830d0 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/DefaultLocalFileSystemProvider.java @@ -14,7 +14,7 @@ import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystemProvider; import org.apache.aut.vfs.provider.DefaultFileName; import org.apache.aut.vfs.provider.FileSystem; -import org.apache.aut.vfs.provider.FileSystemProvider; +import org.apache.aut.vfs.provider.LocalFileSystemProvider; import org.apache.aut.vfs.provider.ParsedUri; /** @@ -22,13 +22,17 @@ import org.apache.aut.vfs.provider.ParsedUri; * * @author Adam Murdoch * @version $Revision$ $Date$ + * + * @ant.type type="file-system" name="file" + * */ -public class LocalFileSystemProvider extends AbstractFileSystemProvider - implements FileSystemProvider +public class DefaultLocalFileSystemProvider + extends AbstractFileSystemProvider + implements LocalFileSystemProvider { private final LocalFileNameParser m_parser; - public LocalFileSystemProvider() + public DefaultLocalFileSystemProvider() { if( Os.isFamily( Os.OS_FAMILY_WINDOWS ) ) { @@ -96,6 +100,6 @@ public class LocalFileSystemProvider extends AbstractFileSystemProvider // Create the file system final DefaultFileName rootName = new DefaultFileName( m_parser, fileUri.getRootUri(), "/" ); - return new LocalFileSystem( rootName, rootFile ); + return new LocalFileSystem( getContext(), rootName, rootFile ); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java index a0d04cfc5..8cb0fc90d 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFile.java @@ -14,6 +14,7 @@ import java.io.InputStream; import java.io.OutputStream; import org.apache.aut.vfs.FileName; import org.apache.aut.vfs.FileObject; +import org.apache.aut.vfs.FileSelector; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.FileType; import org.apache.aut.vfs.provider.AbstractFileObject; @@ -94,7 +95,7 @@ final class LocalFile /** * Deletes this file, and all children. */ - public void doDelete() + protected void doDelete() throws Exception { if( !m_file.delete() ) @@ -143,4 +144,13 @@ final class LocalFile { return m_file.length(); } + + /** + * Creates a temporary local copy of this file, and its descendents. + */ + protected File doReplicateFile( final FileSelector selector ) + throws FileSystemException + { + return m_file; + } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java index 2c8712f0a..88bfb996b 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/local/LocalFileSystem.java @@ -13,6 +13,7 @@ import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystem; import org.apache.aut.vfs.provider.DefaultFileName; import org.apache.aut.vfs.provider.FileSystem; +import org.apache.aut.vfs.provider.FileSystemProviderContext; /** * A local file system. @@ -24,19 +25,21 @@ class LocalFileSystem extends AbstractFileSystem implements FileSystem { private String m_rootFile; - public LocalFileSystem( DefaultFileName rootName, String rootFile ) + public LocalFileSystem( final FileSystemProviderContext context, + final DefaultFileName rootName, + final String rootFile ) { - super( rootName ); + super( context, rootName ); m_rootFile = rootFile; } /** * Creates a file object. */ - protected FileObject createFile( FileName name ) throws FileSystemException + protected FileObject createFile( final FileName name ) throws FileSystemException { // Create the file - String fileName = m_rootFile + name.getPath(); + final String fileName = m_rootFile + name.getPath(); return new LocalFile( this, fileName, name ); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/ParsedSmbUri.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/ParsedSmbUri.java index 6ee462f94..597a5a086 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/ParsedSmbUri.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/ParsedSmbUri.java @@ -12,7 +12,8 @@ import org.apache.aut.vfs.provider.ParsedUri; /** * A parsed SMB URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class ParsedSmbUri extends ParsedUri { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileNameParser.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileNameParser.java index d5bef9099..48f5ac6ae 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileNameParser.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileNameParser.java @@ -16,7 +16,8 @@ import org.apache.avalon.excalibur.i18n.Resources; /** * A parser for SMB URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class SmbFileNameParser extends UriParser diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileObject.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileObject.java index ed7dfe26d..d68dfeb6c 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileObject.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileObject.java @@ -23,7 +23,8 @@ import org.apache.avalon.excalibur.i18n.Resources; /** * A file in an SMB file system. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class SmbFileObject extends AbstractFileObject diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystem.java index 9c7e3b098..4cd9797d9 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystem.java @@ -12,25 +12,28 @@ import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystem; import org.apache.aut.vfs.provider.FileSystem; +import org.apache.aut.vfs.provider.FileSystemProviderContext; /** * A SMB file system. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class SmbFileSystem extends AbstractFileSystem implements FileSystem { - public SmbFileSystem( FileName rootName ) + public SmbFileSystem( final FileSystemProviderContext context, + final FileName rootName ) { - super( rootName ); + super( context, rootName ); } /** * Creates a file object. */ - protected FileObject createFile( FileName name ) throws FileSystemException + protected FileObject createFile( final FileName name ) throws FileSystemException { - String fileName = name.getURI(); + final String fileName = name.getURI(); return new SmbFileObject( fileName, name, this ); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystemProvider.java index a6b60bfec..4f851d785 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/smb/SmbFileSystemProvider.java @@ -19,7 +19,8 @@ import org.apache.aut.vfs.provider.ParsedUri; /** * A provider for SMB (Samba, Windows share) file systems. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ * * @ant.type type="file-system" name="smb" */ @@ -45,6 +46,6 @@ public class SmbFileSystemProvider extends AbstractFileSystemProvider implements { final ParsedSmbUri smbUri = (ParsedSmbUri)uri; final FileName rootName = new DefaultFileName( m_parser, smbUri.getRootUri(), "/" ); - return new SmbFileSystem( rootName ); + return new SmbFileSystem( getContext(), rootName ); } } diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ParsedZipUri.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ParsedZipUri.java index 9bc36d0c8..d6dcb0b20 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ParsedZipUri.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ParsedZipUri.java @@ -13,7 +13,8 @@ import org.apache.aut.vfs.provider.ParsedUri; /** * A parsed Zip URI. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class ParsedZipUri extends ParsedUri { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/Resources.properties b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/Resources.properties index 4885c50ca..41efc2e72 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/Resources.properties @@ -1 +1,2 @@ open-zip-file.error=Could not open Zip file "{0}". +close-zip-file.error=Could not close Zip file "{0}". diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileNameParser.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileNameParser.java index caeab439c..131a2f821 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileNameParser.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileNameParser.java @@ -13,12 +13,13 @@ import org.apache.aut.vfs.provider.UriParser; /** * A parser for Zip file names. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ public class ZipFileNameParser extends UriParser { - private static final char[] ZIP_URL_RESERVED_CHARS = { '!' }; + private static final char[] ZIP_URL_RESERVED_CHARS = {'!'}; /** * Parses an absolute URI, splitting it into its components. diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileObject.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileObject.java index 9bbf7e484..d79131843 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileObject.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileObject.java @@ -19,7 +19,8 @@ import org.apache.aut.vfs.provider.AbstractFileObject; /** * A file in a Zip file system. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ class ZipFileObject extends AbstractFileObject implements FileObject { diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystem.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystem.java index c10d2a9ab..a376e440b 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystem.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystem.java @@ -18,15 +18,19 @@ import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystem; import org.apache.aut.vfs.provider.DefaultFileName; import org.apache.aut.vfs.provider.FileSystem; +import org.apache.aut.vfs.provider.FileSystemProviderContext; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; /** * A read-only file system for Zip/Jar files. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ */ -public class ZipFileSystem extends AbstractFileSystem implements FileSystem +public class ZipFileSystem + extends AbstractFileSystem + implements FileSystem { private static final Resources REZ = ResourceManager.getPackageResources( ZipFileSystem.class ); @@ -34,9 +38,11 @@ public class ZipFileSystem extends AbstractFileSystem implements FileSystem private File m_file; private ZipFile m_zipFile; - public ZipFileSystem( DefaultFileName rootName, File file ) throws FileSystemException + public ZipFileSystem( final FileSystemProviderContext context, + final DefaultFileName rootName, + final File file ) throws FileSystemException { - super( rootName ); + super( context, rootName ); m_file = file; // Open the Zip file @@ -101,6 +107,22 @@ public class ZipFileSystem extends AbstractFileSystem implements FileSystem } } + public void dispose() + { + super.dispose(); + + // Release the zip file + try + { + m_zipFile.close(); + } + catch( final IOException e ) + { + final String message = REZ.getString( "close-zip-file.error", m_file ); + getLogger().warn( message, e ); + } + } + /** * Creates a file object. */ diff --git a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystemProvider.java b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystemProvider.java index 6c3c91a1d..fa5e7a39c 100644 --- a/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystemProvider.java +++ b/proposal/myrmidon/src/java/org/apache/aut/vfs/provider/zip/ZipFileSystemProvider.java @@ -8,7 +8,7 @@ package org.apache.aut.vfs.provider.zip; import java.io.File; -import java.io.IOException; +import org.apache.aut.vfs.FileConstants; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileSystemException; import org.apache.aut.vfs.provider.AbstractFileSystemProvider; @@ -21,7 +21,8 @@ import org.apache.aut.vfs.provider.ParsedUri; * A file system provider for Zip/Jar files. Provides read-only file * systems, for local Zip files only. * - * @author Adam Murdoch + * @author Adam Murdoch + * @version $Revision$ $Date$ * * @ant.type type="file-system" name="zip" */ @@ -80,25 +81,12 @@ public class ZipFileSystemProvider final ParsedZipUri zipUri = (ParsedZipUri)uri; final FileObject file = zipUri.getZipFile(); - // TODO - temporary hack; need to use a converter - File destFile = null; - try - { - final File cacheDir = new File( "ant_vfs_cache" ); - cacheDir.mkdirs(); - destFile = File.createTempFile( "cache_", "_" + file.getName().getBaseName(), cacheDir ); - destFile.deleteOnExit(); - } - catch( IOException e ) - { - throw new FileSystemException( "Could not replicate file", e ); - } - FileObject destFileObj = getContext().resolveFile( null, destFile.getAbsolutePath() ); - destFileObj.copy( file ); + // Make a local copy of the file + final File zipFile = file.replicateFile( FileConstants.SELECT_SELF ); // Create the file system DefaultFileName name = new DefaultFileName( m_parser, zipUri.getRootUri(), "/" ); - return new ZipFileSystem( name, destFile ); + return new ZipFileSystem( getContext(), name, zipFile ); } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factories/VfsManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factories/VfsManager.java index 2042f0bd0..f4690d716 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factories/VfsManager.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factories/VfsManager.java @@ -12,7 +12,6 @@ import org.apache.aut.vfs.impl.DefaultFileSystemManager; import org.apache.aut.vfs.provider.FileSystemProvider; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; -import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; @@ -28,7 +27,7 @@ import org.apache.myrmidon.interfaces.type.TypeManager; */ public class VfsManager extends DefaultFileSystemManager - implements Serviceable, Initializable, Disposable + implements Serviceable, Initializable { private static final Resources REZ = ResourceManager.getPackageResources( VfsManager.class ); @@ -53,6 +52,7 @@ public class VfsManager // TODO - make this list configurable // Required providers + addProvider( factory, new String[]{"file"}, "file", false ); addProvider( factory, new String[]{"zip", "jar"}, "zip", false ); // Optional providers @@ -60,15 +60,6 @@ public class VfsManager addProvider( factory, new String[]{"ftp"}, "ftp", true ); } - /** - * Disposes this service. - */ - public void dispose() - { - // Clean-up - close(); - } - /** * Registers a file system provider. */ diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractFileSystemTestCase.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractFileSystemTestCase.java index 61dc091ff..a92748c21 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractFileSystemTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractFileSystemTestCase.java @@ -16,6 +16,8 @@ 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.aut.vfs.provider.LocalFileSystemProvider; +import org.apache.aut.vfs.provider.local.DefaultLocalFileSystemProvider; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileType; import org.apache.aut.vfs.FileSystemException; @@ -59,15 +61,15 @@ public abstract class AbstractFileSystemTestCase { // Build the expected structure 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 ) ); + base.addChild( "file1.txt", FileType.FILE ); + base.addChild( "empty.txt", FileType.FILE ); + base.addChild( "emptydir", 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 ) ); - dir.addChild( new FileInfo( "file3.txt", FileType.FILE ) ); + dir.addChild( "file1.txt", FileType.FILE ); + dir.addChild( "file2.txt", FileType.FILE ); + dir.addChild( "file3.txt", FileType.FILE ); return base; } @@ -83,6 +85,8 @@ public abstract class AbstractFileSystemTestCase { // Create the file system manager m_manager = new DefaultFileSystemManager(); + m_manager.enableLogging( getLogger() ); + m_manager.addProvider( "file", new DefaultLocalFileSystemProvider() ); // Locate the base folder m_baseFolder = getBaseFolder(); @@ -100,7 +104,7 @@ public abstract class AbstractFileSystemTestCase */ protected void tearDown() throws Exception { - m_manager.close(); + m_manager.dispose(); } /** @@ -465,6 +469,70 @@ public abstract class AbstractFileSystemTestCase } } + /** + * Tests conversion from absolute to relative names. + */ + public void testAbsoluteNameConvert() throws Exception + { + final FileName baseName = m_baseFolder.getName(); + + String path = "/test1/test2"; + FileName name = baseName.resolveName( path ); + assertEquals( path, name.getPath() ); + + // Try child and descendent names + testRelName( name, "child" ); + testRelName( name, "child1/child2" ); + + // Try own name + testRelName( name, "." ); + + // Try parent, and root + testRelName( name, ".." ); + testRelName( name, "../.." ); + + // Try sibling and descendent of sibling + testRelName( name, "../sibling" ); + testRelName( name, "../sibling/child" ); + + // Try siblings with similar names + testRelName( name, "../test2_not" ); + testRelName( name, "../test2_not/child" ); + testRelName( name, "../test" ); + testRelName( name, "../test/child" ); + + // Try unrelated + testRelName( name, "../../unrelated" ); + testRelName( name, "../../test" ); + testRelName( name, "../../test/child" ); + + // Test against root + path = "/"; + name = baseName.resolveName( path ); + assertEquals( path, name.getPath() ); + + // Try child and descendent names (against root) + testRelName( name, "child" ); + testRelName( name, "child1/child2" ); + + // Try own name (against root) + testRelName( name, "." ); + } + + /** + * Checks that a file name converts to an expected relative path + */ + private void testRelName( final FileName baseName, + final String relPath ) + throws Exception + { + final FileName expectedName = baseName.resolveName( relPath ); + + // Convert to relative path, and check + final String actualRelPath = baseName.getRelativeName( expectedName ); + assertEquals( relPath, actualRelPath ); + } + /** * Walks the base folder structure, asserting it contains exactly the * expected files and folders. @@ -496,9 +564,9 @@ public abstract class AbstractFileSystemTestCase final FileInfo info = (FileInfo)queueExpected.remove( 0 ); // Check the type is correct - assertSame( file.getType(), info._type ); + assertSame( file.getType(), info.m_type ); - if( info._type == FileType.FILE ) + if( info.m_type == FileType.FILE ) { continue; } @@ -508,13 +576,13 @@ public abstract class AbstractFileSystemTestCase // Make sure all children were found assertNotNull( children ); - assertEquals( "count children of \"" + file.getName() + "\"", info._children.size(), children.length ); + assertEquals( "count children of \"" + file.getName() + "\"", info.m_children.size(), children.length ); // Recursively check each child for( int i = 0; i < children.length; i++ ) { final FileObject child = children[ i ]; - final FileInfo childInfo = (FileInfo)info._children.get( child.getName().getBaseName() ); + final FileInfo childInfo = (FileInfo)info.m_children.get( child.getName().getBaseName() ); // Make sure the child is expected assertNotNull( childInfo ); @@ -776,20 +844,36 @@ public abstract class AbstractFileSystemTestCase */ protected static final class FileInfo { - String _baseName; - FileType _type; - Map _children = new HashMap(); + String m_baseName; + FileType m_type; + Map m_children = new HashMap(); + + public FileInfo( final String name, final FileType type ) + { + m_baseName = name; + m_type = type; + } - public FileInfo( String name, FileType type ) + /** Adds a child. */ + public void addChild( final FileInfo child ) { - _baseName = name; - _type = type; + m_children.put( child.m_baseName, child ); } /** Adds a child. */ - public void addChild( FileInfo child ) + public void addChild( final String baseName, final FileType type ) + { + addChild( new FileInfo( baseName, type ) ); + } + + /** Adds a bunch of children. */ + public void addChildren( final String[] baseNames, final FileType type ) { - _children.put( child._baseName, child ); + for( int i = 0; i < baseNames.length; i++ ) + { + String baseName = baseNames[i ]; + addChild( new FileInfo( baseName, type ) ); + } } } } diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractWritableFileSystemTestCase.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractWritableFileSystemTestCase.java index 06a73c132..f08e0edfe 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractWritableFileSystemTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/test/AbstractWritableFileSystemTestCase.java @@ -14,6 +14,7 @@ import org.apache.aut.vfs.test.AbstractFileSystemTestCase; import org.apache.aut.vfs.FileObject; import org.apache.aut.vfs.FileType; import org.apache.aut.vfs.FileSystemException; +import org.apache.aut.vfs.FileConstants; /** * File system test that check that a file system can be modified. @@ -41,7 +42,7 @@ public abstract class AbstractWritableFileSystemTestCase FileObject scratchFolder = getWriteFolder(); // Make sure the test folder is empty - scratchFolder.delete(); + scratchFolder.delete( FileConstants.EXCLUDE_SELF ); scratchFolder.create( FileType.FOLDER ); return scratchFolder; @@ -59,6 +60,7 @@ public abstract class AbstractWritableFileSystemTestCase assertTrue( !folder.exists() ); folder.create( FileType.FOLDER ); assertTrue( folder.exists() ); + assertSame( FileType.FOLDER, folder.getType() ); assertEquals( 0, folder.getChildren().length ); // Create a descendant, where the intermediate folders don't exist @@ -68,11 +70,13 @@ public abstract class AbstractWritableFileSystemTestCase assertTrue( !folder.getParent().getParent().exists() ); folder.create( FileType.FOLDER ); assertTrue( folder.exists() ); + assertSame( FileType.FOLDER, folder.getType() ); assertEquals( 0, folder.getChildren().length ); assertTrue( folder.getParent().exists() ); assertTrue( folder.getParent().getParent().exists() ); // Test creating a folder that already exists + assertTrue( folder.exists() ); folder.create( FileType.FOLDER ); } @@ -88,6 +92,7 @@ public abstract class AbstractWritableFileSystemTestCase assertTrue( !file.exists() ); file.create( FileType.FILE ); assertTrue( file.exists() ); + assertSame( FileType.FILE, file.getType() ); assertEquals( 0, file.getContent().getSize() ); // Create a descendant, where the intermediate folders don't exist @@ -97,11 +102,13 @@ public abstract class AbstractWritableFileSystemTestCase assertTrue( !file.getParent().getParent().exists() ); file.create( FileType.FILE ); assertTrue( file.exists() ); + assertSame( FileType.FILE, file.getType() ); assertEquals( 0, file.getContent().getSize() ); assertTrue( file.getParent().exists() ); assertTrue( file.getParent().getParent().exists() ); // Test creating a file that already exists + assertTrue( file.exists() ); file.create( FileType.FILE ); } @@ -125,7 +132,7 @@ public abstract class AbstractWritableFileSystemTestCase try { folder.create( FileType.FILE ); - assertTrue( false ); + fail(); } catch( FileSystemException exc ) { @@ -135,7 +142,7 @@ public abstract class AbstractWritableFileSystemTestCase try { file.create( FileType.FOLDER ); - assertTrue( false ); + fail(); } catch( FileSystemException exc ) { @@ -146,7 +153,7 @@ public abstract class AbstractWritableFileSystemTestCase try { folder2.create( FileType.FOLDER ); - assertTrue( false ); + fail(); } catch( FileSystemException exc ) { @@ -168,13 +175,13 @@ public abstract class AbstractWritableFileSystemTestCase // Delete a file FileObject file = folder.resolveFile( "file1.txt" ); assertTrue( file.exists() ); - file.delete(); + file.delete( FileConstants.SELECT_ALL ); assertTrue( !file.exists() ); // Delete an empty folder file = folder.resolveFile( "emptydir" ); assertTrue( file.exists() ); - file.delete(); + file.delete( FileConstants.SELECT_ALL ); assertTrue( !file.exists() ); // Recursive delete @@ -182,14 +189,14 @@ public abstract class AbstractWritableFileSystemTestCase FileObject file2 = file.resolveFile( "dir2/file2.txt" ); assertTrue( file.exists() ); assertTrue( file2.exists() ); - file.delete(); + file.delete( FileConstants.SELECT_ALL ); assertTrue( !file.exists() ); assertTrue( !file2.exists() ); // Delete a file that does not exist file = folder.resolveFile( "some-folder/some-file" ); assertTrue( !file.exists() ); - file.delete(); + file.delete( FileConstants.SELECT_ALL ); assertTrue( !file.exists() ); } @@ -226,17 +233,17 @@ public abstract class AbstractWritableFileSystemTestCase assertSameFileSet( names, folder.getChildren() ); // Delete a child folder - folder.resolveFile( "dir1" ).delete(); + folder.resolveFile( "dir1" ).delete( FileConstants.SELECT_ALL ); names.remove( "dir1" ); assertSameFileSet( names, folder.getChildren() ); // Delete a child file - folder.resolveFile( "file1.html" ).delete(); + folder.resolveFile( "file1.html" ).delete( FileConstants.SELECT_ALL ); names.remove( "file1.html" ); assertSameFileSet( names, folder.getChildren() ); // Recreate the folder - folder.delete(); + folder.delete( FileConstants.SELECT_ALL ); folder.create( FileType.FOLDER ); assertEquals( 0, folder.getChildren().length ); } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java index 490d8b253..26b2035bf 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java @@ -174,12 +174,6 @@ public abstract class AbstractMyrmidonTest */ protected void assertSameMessage( final String[] messages, final Throwable throwable ) { - //System.out.println( "exception:" ); - //for( Throwable t = throwable; t != null; t = ExceptionUtil.getCause( t, true ) ) - //{ - // System.out.println( " " + t.getMessage() ); - //} - Throwable current = throwable; for( int i = 0; i < messages.length; i++ ) { diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractProjectTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractProjectTest.java index 2eed07523..11469badb 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractProjectTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractProjectTest.java @@ -10,6 +10,7 @@ package org.apache.myrmidon; import java.io.File; import org.apache.myrmidon.frontends.EmbeddedAnt; import org.apache.myrmidon.listeners.ProjectListener; +import org.apache.avalon.framework.ExceptionUtil; /** * A base class for test cases which need to execute projects. @@ -72,28 +73,35 @@ public class AbstractProjectTest final ProjectListener listener ) throws Exception { - // Create the project and workspace final EmbeddedAnt embeddor = new EmbeddedAnt(); - embeddor.setHomeDirectory( getInstallDirectory() ); - embeddor.enableLogging( getLogger() ); - embeddor.setSharedClassLoader( getClass().getClassLoader() ); - embeddor.setProjectFile( projectFile.getAbsolutePath() ); - embeddor.setProjectListener( null ); - - // Add a listener to make sure all is good final TrackingProjectListener tracker = new TrackingProjectListener(); - embeddor.addProjectListener( tracker ); - // Add supplied listener - if( listener != null ) + try { - embeddor.addProjectListener( listener ); - } + // Configure embeddor + embeddor.setHomeDirectory( getInstallDirectory() ); + embeddor.enableLogging( getLogger() ); + embeddor.setSharedClassLoader( getClass().getClassLoader() ); + embeddor.setProjectFile( projectFile.getAbsolutePath() ); + embeddor.setProjectListener( null ); + + // Add a listener to make sure all is good + embeddor.addProjectListener( tracker ); - // Now execute the target - embeddor.executeTargets( new String[] { targetName } ); + // Add supplied listener + if( listener != null ) + { + embeddor.addProjectListener( listener ); + } + + // Now execute the target + embeddor.executeTargets( new String[] { targetName } ); + } + finally + { + embeddor.stop(); + } - embeddor.stop(); // Make sure all expected events were delivered tracker.assertComplete(); diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/classloader/test/DefaultClassLoaderManagerTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/classloader/test/DefaultClassLoaderManagerTestCase.java index 8ac769f02..0cb96c077 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/classloader/test/DefaultClassLoaderManagerTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/classloader/test/DefaultClassLoaderManagerTestCase.java @@ -335,7 +335,7 @@ public class DefaultClassLoaderManagerTestCase * add some classes to common loader only. * * unknown extension - * multiple versions of extensions + * multiple versions of the same extension * extn with requirement on itself * * jar with 1 and 2 extns: