It occured to me later on, that I think this interface would be better
if it were focused on describing an Archive, rather than trying to
describe two processes (ie describing the noun rather than all the
verbs). The fall out from this, is that you don't have a member for an
unpack directory, since that is only relevent to the unpacking process.
and I think it makes the interface I went to mock this up and came up
with a couple other issues with the interface.
1) Adding an entry or a file to an archive, you need to be able to
set the entry name, otherwise you can run into problems with getting
just the right relative path in the archive for the files.
2) It is pretty common to want to recursively add directories, we
should provide this in the archive API
I've attached my mock-up so folks can see if they think these thoughts
make sense. I tried to borrow design and parameter conventions from
some of the commons-io methods I use alot.
--Will
will pugh wrote:
Overall, I like the interfaces, but I've got a few issues:
0) Update is mentioned in the Javadoc at the beginning of Archiver,
but is not implemented.
1) You often change method names based on the parameter types, e.g.
Archiver.addFile + Archiver.addFileName, setUnpackDestinationName +
setUnpackDestinationFile, etc. It seems more conventional and less
chaotic to give all the methods the same name, and have them only
differ based on parameter. Examples of this style are constructors
for java.utils.zip.ZipFile, java.io.FileInputStream,
java.io.FileOutputStream, org.apache.commons.io.IOUtils.IOUtils.copy,
org.apache.commons.io.FileUtils.isFileNewer, etc
2) You can only add files to an archive, this makes it more difficult
to add generated entries into an archive. You need to actually write
them to disk before including them in an archive
3) UnpackDestination + Destination should be the same property (on
the both the interface as well as underlying implementation), or you
should split packing and unpacking into two different interfaces (or
force folks to pass a path to pack + unpack, instead of setting
properties on the object).
4) None of your interfaces deal with the case of what to do if the
destination file is already there. Choices are either defining it in
the interface, or adding a property defining what to do. I would
suggest the latter, and would suggest that for Archiver this method
should take a FileFilter (since the unpack behaviour can be
non-trivial) and should default to FalseFileFilter.INSTANCE. For the
Compresser interface a simple boolean is probably sufficient. e.g.
Archiver.setOverwriteFilter(TrueFileFilter.INSTANCE)
Compresser.setOverwrite(true);
5) In AbstractCompressor, I don't understand why you have a copy
method and don't just use IOUtils.copy()
6) In AbstractCompressor, I don't understand why you try to create
your own temp name, rather than just letting File.createTempFile do
it's thing.
--Will
C. Grobmeier wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello all,
here is a new draft for the compress interface:
* http://grobmeier.de/commons-compress-draft-5.zip
I have improved a lot of things, based on the comments of Sandy (thanks
for that).
This draft is not perfect, as you can see in the todo list. But imho we
have a quite good base for future work, everything compiles and works
and is documented. So i would like to propose that someone is comitting
this, except you have reasons not to do this.
If you agree with me, i will open a bugzilla issue and add the link to
the code.
- - Chris.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFEVKMikv8rKBUE/T4RAlxxAKCMYzova2roWDA/skRyoDvFcErE2gCfTjFw
bT2VrGdR8Byt+VjsRo7Cyhw=
=1GRF
-----END PGP SIGNATURE-----
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
package org.apache.commons.compress;
import java.io.*;
import java.util.Iterator;
/**
* Archiver is an interface that defines a generic achive file. This interface
* allows a caller to inspect the entries in an archive, create new ones, add
entries to existing ones
* or to expand an archive.
*
*
* @author christian.grobmeier
*/
public interface MyArchiver {
/**
* If pack is called with this as the <i>overwrite</i> parameter, the method
* will fail if the ArchiveFile exists.
*/
public static final int FAIL_ON_EXISTANCE = 0;
/**
* If pack is called with this as the <i>overwrite</i> parameter, the method
* will overwrite ArchiveFile. The new archive will only contain the
entries
* added via <i>addEntry</i>.
*/
public static final int OVERWRITE_ON_EXISTANCE = 1;
/**
* If pack is called with this as the <i>overwrite</i> parameter, the method
* will add the new entries added via <i>addEntry</i> to the ArchiveFile.
*/
public static final int APPEND_ON_EXISTANCE = 2;
/**
* Adds a file to the internal filelist
* for a possible pack-operation
*
* @param name the name for this entry in the archive
* @param file the file who's contents will be put in the archive
*/
public void addEntry(String name, File file);
/**
* Adds a file to the internal filelist
*
* @param name the name for this entry in the archive. In the case that
recurs is true, all the
* child names will be generated using <i>name</i> as the base.
* @param file the file to add to the archive
* @param recurse whether to recurse into the children of file, in the case
that file is a direcotry
*/
public void addEntry(String name, File file, boolean recurse);
/**
* Adds a file to the internal filelist
*
* @param name the name for this entry in the archive. In the case that
recurs is true, all the
* child names will be generated using <i>name</i> as the base.
* @param fileFilter filter for which children should be included
* @param fileFilter filter for which directory children should be recursed
into
*/
public void addEntry(String name, File file, FileFilter fileFilter,
FileFilter dirFilter);
/**
* Adds a new entry to the archiver, where the contents come in from
* an input stream rather than having to come in from a file.
*
* @param name the name for this entry in the archive
* @param contents the InputStream that contains the contents to put in the
archive
*/
public void addEntry(String name, InputStream contents);
/**
* Iterates through the files in the archive. This will include
* any entries added through the addEntry apis.
*
* @return an interater that will contain objects of type ArchiveEntry
*/
public Iterator getArchiveEntries();
/**
* Returns the file that backs this archive.
* @return the file
*/
public File getArchiveFile();
/**
* Sets the file that will back this archive.
* @param file the file that will back this archive
*/
public void setArchiveFile(File file);
/**
* Unpacks a file to the provided directory
*
* @param destination the directory to unpack the archive to. This
parameter must refer to a directory
* @throws org.apache.commons.compress.UnpackException if an unpack error
occures
* @throws java.lang.IllegalArgumentException if destination is a file
instead of a directory
* @throws java.io.FileNotFoundException if the destination does not exist
*/
public void unpack(File destination) throws IOException;
/**
* Unpacks a file to the provided directory. This method also provides a
parameter to
* define overwrite sematics. It allows you to set a FileFilter to define
when to overwrite existing
* files or not. The filter should return:
* true when it should overwrite a file,
* false if the file should not be overwritten,
* or it throw an exception if this
*
* If you want to always ignore files that already exist, you can use
org.apache.commons.io.filefilter.FalseFileFilter.INSTANCE
* If you want to always overwrite files that already exist, you can use
org.apache.commons.io.filefilter.TrueFileFilter.INSTANCE
* If you want to always throw an error when a file already exists, you can
use org.apache.commons.compress.ErrorFileFilter.INSTANCE
*
* @param destination the directory to unpack the archive to. This
parameter must refer to a directory
* @param overwriteFilter a file filter that gets called when a file
already exists on the filesystem.
* @throws org.apache.commons.compress.UnpackException if an unpack error
occures
* @throws java.lang.IllegalArgumentException if destination is a file
instead of a directory
* @throws java.io.FileNotFoundException if the destination does not exist
*/
public void unpack(File destination, FileFilter overwriteFilter) throws
IOException;
/**
* Writes all the entries to the archive file
* If there is already file that exists with that name, we will overwrite
it.
*
* @throws org.apache.commons.compress.PackException if there is no
destination file or files to be packed
*/
public void pack() throws PackException;
/**
* Writes all the entries to the archive file
* If there is already file that exists with that name, we will overwrite
it.
*
* @param overrideOptions this provides the option for what to do incase a
the ArchiveFile already exists
* @throws org.apache.commons.compress.PackException if there is no
destination file or files to be packed
*/
public void pack(int overrideOptions) throws PackException;
//UNDONE(willpugh) -- This should be it's own top level class, but is
nested currently for
// demonstration purposes
static public interface ArchiveEntry {
String getName();
InputStream getConents();
}
//UNDONE(willpugh) -- This should be it's own top level class, but is
nested currently for
// demonstration purposes
static public class FileOverwriteError extends RuntimeException {
private File file;
public FileOverwriteError(File file) {
this.setFile(file);
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
//UNDONE(willpugh) -- This should be it's own top level class, but is
nested currently for
// demonstration purposes. This will be
org.apache.commons.compress.ErrorFileFilter
static public class ErrorFileFilter implements FileFilter {
public static final FileFilter INSTANCE = new ErrorFileFilter();
public boolean accept(File file) {
throw new FileOverwriteError(file);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]