001    /*
002     * This file is part of muCommander, http://www.mucommander.com
003     * Copyright (C) 2002-2008 Maxence Bernard
004     *
005     * muCommander is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation; either version 3 of the License, or
008     * (at your option) any later version.
009     *
010     * muCommander is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    
019    package com.mucommander.file;
020    
021    import java.io.IOException;
022    import java.io.OutputStream;
023    
024    /**
025     * <code>AbstractRWArchiveFile</code> represents a read-write archive file. This class is abstract and implemented by
026     * all read-write archive files.
027     * In addition to the read-only operations defined by {@link com.mucommander.file.AbstractArchiveFile}, it provides
028     * abstract methods for adding and deleting entries from the archive.
029     *
030     * The {@link #isWritableArchive()} method impletemented by this class always returns <code>true</code>. However,
031     * write operations may not always be available depending on the underlying file (e.g. if random file access is
032     * required). In that case, {@link #isWritableArchive()} should be overridden to return <code>true</code> only when
033     * write operations are available.
034     *
035     * @author Maxence Bernard
036     */
037    public abstract class AbstractRWArchiveFile extends AbstractArchiveFile {
038    
039        /**
040         * Creates an AbstractRWArchiveFile on top of the given file.
041         *
042         * @param file the file on top of which to create the archive
043         */
044        protected AbstractRWArchiveFile(AbstractFile file) {
045            super(file);
046        }
047    
048    
049        ////////////////////////////////////////
050        // AbstractArchiveFile implementation //
051        ////////////////////////////////////////
052    
053        /**
054         * Returns <code>true</code>: <code>AbstractRWArchiveFile</code> implementations are capable of adding or deleting
055         * entries. This method should be overridden if the implementation is capable of providing write access only under
056         * certain conditions, for example if it requires random access to the proxied archive file which may not
057         * always be available depending on the udnderlying file. If that is the case, this method should return
058         * <code>true</code> only when all conditions for providing write operations are met.
059         *
060         * @return true
061         */
062        public boolean isWritableArchive() {
063            return true;
064        }
065    
066    
067        //////////////////////
068        // Abstract methods //
069        //////////////////////
070    
071        /**
072         * Adds the given entry to the archive and returns an <code>OutputStream</code> to write the entry's contents
073         * if the entry is a regular file, <code>null</code> if the entry is a directory.
074         * Throws an <code>IOException</code> if the entry already exists in the archive or if an I/O error occurs.
075         *
076         * @param entry the entry to add to the archive
077         * @return an OutputStream to write the entry's contents if the entry is a regular file, null if the entry is a directory
078         * @throws IOException if the entry already exists in the archive or if an I/O error occurs
079         */
080        public abstract OutputStream addEntry(ArchiveEntry entry) throws IOException;
081    
082        /**
083         * Deletes the specified entry from the archive. Throws an <code>IOException</code> if the entry doesn't exist
084         * in the archive or if an I/O error occurs.
085         *
086         * @param entry the entry to delete from the archive
087         * @throws IOException if the entry doesn't exist in the archive or if an I/O error occurs
088         */
089        public abstract void deleteEntry(ArchiveEntry entry) throws IOException;
090    
091        /**
092         * Updates the specified entry in the archive with the attributes containted in the {@link ArchiveEntry} object.
093         * Throws an <code>IOException</code> if the entry doesn't exist in the archive or if an I/O error occurs.
094         *
095         * <p>This methods can be used to update the entry's date and permissions for instance.</p>
096         *
097         * @param entry the entry to update in the archive
098         * @throws IOException if the entry doesn't exist in the archive or if an I/O error occurs
099         */
100        public abstract void updateEntry(ArchiveEntry entry) throws IOException;
101    
102        /**
103         * Processes the archive file to leave it in an optimal form. This method should be called after a writable archive
104         * has been modified (entries added or removed).
105         *
106         * <p>The actual effect of this method on the archive file depends on the kind of archive. It may be implemented
107         * as a no-op if there is no use for it.
108         * To illustrate, in the case of a {@link com.mucommander.file.impl.zip.ZipArchiveFile}, this method removes chunks
109         * of free space that are left when entries are deleted.</p>
110         *
111         * @throws IOException if an I/O error occurs
112         */
113        public abstract void optimizeArchive() throws IOException;
114    }