/**
* This file is part of muCommander, http://www.mucommander.com
* Copyright (C) 2002-2016 Maxence Bernard
*
* muCommander is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* muCommander is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.mucommander.commons.file.archive;
import java.io.IOException;
import java.io.OutputStream;
import com.mucommander.commons.file.AbstractFile;
import com.mucommander.commons.file.FileOperation;
import com.mucommander.commons.file.UnsupportedFileOperationException;
/**
* <code>AbstractRWArchiveFile</code> represents a read-write archive file. This class is abstract and implemented by
* all read-write archive files.
* In addition to the read-only operations defined by {@link com.mucommander.commons.file.archive.AbstractArchiveFile}, it provides
* abstract methods for adding and deleting entries from the archive.
*
* The {@link #isWritable()} method impletemented by this class always returns <code>true</code>. However,
* write operations may not always be available depending on the underlying file (e.g. if random file access is
* required). In that case, {@link #isWritable ()} should be overridden to return <code>true</code> only when
* write operations are available.
*
* @author Maxence Bernard
*/
public abstract class AbstractRWArchiveFile extends AbstractArchiveFile {
/**
* Creates an AbstractRWArchiveFile on top of the given file.
*
* @param file the file on top of which to create the archive
*/
protected AbstractRWArchiveFile(AbstractFile file) {
super(file);
}
////////////////////////////////////////
// AbstractArchiveFile implementation //
////////////////////////////////////////
/**
* Returns <code>true</code>: <code>AbstractRWArchiveFile</code> implementations are by definition capable of adding
* or deleting entries. This method should be overridden if the implementation is capable of providing write access
* only under certain conditions, for example if it requires random access to the proxied archive file which may not
* always be available depending on the underlying file. If that is the case, this method should return
* <code>true</code> only when all conditions for providing write operations are met.
*
* @return <code>true</code>, always
*/
@Override
public boolean isWritable() {
return true;
}
//////////////////////
// Abstract methods //
//////////////////////
/**
* Adds the given entry to the archive and returns an <code>OutputStream</code> to write the entry's contents
* if the entry is a regular file, <code>null</code> if the entry is a directory.
* Throws an <code>IOException</code> if the entry already exists in the archive or if an I/O error occurs.
*
* @param entry the entry to add to the archive
* @return an OutputStream to write the entry's contents if the entry is a regular file, null if the entry is a directory
* @throws IOException if the entry already exists in the archive or if an I/O error occurs
* @throws UnsupportedFileOperationException if {@link FileOperation#WRITE_FILE} operations are not supported by
* the underlying file protocol.
*/
public abstract OutputStream addEntry(ArchiveEntry entry) throws IOException, UnsupportedFileOperationException;
/**
* Deletes the specified entry from the archive. Throws an <code>IOException</code> if the entry doesn't exist
* in the archive or if an I/O error occurs.
*
* @param entry the entry to delete from the archive
* @throws IOException if the entry doesn't exist in the archive or if an I/O error occurs
* @throws UnsupportedFileOperationException if {@link FileOperation#WRITE_FILE} operations are not supported by
* the underlying file protocol.
*/
public abstract void deleteEntry(ArchiveEntry entry) throws IOException, UnsupportedFileOperationException;
/**
* Updates the specified entry in the archive with the attributes containted in the {@link ArchiveEntry} object.
* Throws an <code>IOException</code> if the entry doesn't exist in the archive or if an I/O error occurs.
*
* <p>This methods can be used to update the entry's date and permissions for instance.</p>
*
* @param entry the entry to update in the archive
* @throws IOException if the entry doesn't exist in the archive or if an I/O error occurs
* @throws UnsupportedFileOperationException if {@link FileOperation#WRITE_FILE} operations are not supported by
* the underlying file protocol.
*/
public abstract void updateEntry(ArchiveEntry entry) throws IOException, UnsupportedFileOperationException;
/**
* Processes the archive file to leave it in an optimal form. This method should be called after a writable archive
* has been modified (entries added or removed).
*
* <p>The actual effect of this method on the archive file depends on the kind of archive. It may be implemented
* as a no-op if there is no use for it.
* To illustrate, in the case of a {@link com.mucommander.commons.file.archive.zip.ZipArchiveFile}, this method removes chunks
* of free space that are left when entries are deleted.</p>
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedFileOperationException if {@link FileOperation#WRITE_FILE} operations are not supported by
* the underlying file protocol.
*/
public abstract void optimizeArchive() throws IOException, UnsupportedFileOperationException;
}