001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library 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 GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: BackupFileOutputStream.java,v $
023   Revision 1.2  2004/05/05 21:36:35  markl
024   comment block updates
025
026   ----------------------------------------------------------------------------
027*/
028
029package kiwi.io;
030
031import java.io.*;
032
033/** A file output stream that safely overwrites an existing file. When
034 * the stream is created, a temporary file is opened for writing. The name
035 * of the temporary file is simply <b><i>filename</i>.tmp</b>, where
036 * <i>filename</i> is the file to be written. When the stream is closed,
037 * the following steps are taken:
038 *
039 * <ol>
040 * <li>If the original file exists, it is renamed to
041 * <b><i>filename</i>.bak</b>.
042 * <li>The temporary file is renamed to the original filename.
043 * </ol>
044 *
045 * These steps ensure that the original file is not clobbered during the
046 * update, and that a previous version of the file is always available.
047 *
048 * @author Mark Lindner
049 * @since Kiwi 2.0
050 * @see kiwi.io.BackupFileWriter
051 */
052
053public class BackupFileOutputStream extends FileOutputStream
054  {
055  private File tempFile, backupFile;
056  private File file;
057  private boolean closed = false;
058
059  /** Create a new <code>BackupFileOutputStream</code> for the given file.
060   *
061   * @param file The file to write.
062   * @throws java.io.FileNotFoundException If the temporary file could not be
063   * opened for writing.
064   */
065  
066  public BackupFileOutputStream(File file) throws FileNotFoundException
067    {
068    super(getTempFile(file));
069    
070    this.file = file;
071    
072    String path = file.getAbsolutePath();
073    tempFile = new File(path + ".tmp");
074    backupFile = new File(path + ".bak");
075    }
076
077  /** Create a new <code>BackupFileOutputStream</code> for the given file.
078   *
079   * @param file The path of the file to write.
080   * @throws java.io.FileNotFoundException If the temporary file could not be
081   * opened for writing.
082   */
083  
084  public BackupFileOutputStream(String file)  throws FileNotFoundException
085    {
086    this(new File(file));
087    }
088
089  /** Close the output stream.
090   *
091   * @throws java.io.IOException If an I/O error occurs.
092   */
093
094  public final void close() throws IOException
095    {
096    if(closed)
097      return;
098    
099    super.close();
100
101    if(backupFile.exists())
102      backupFile.delete();
103
104    if(file.exists())
105      if(! file.renameTo(backupFile))
106        throw(new IOException("Unable to move file to backup file"));
107
108    if(! tempFile.renameTo(file))
109      throw(new IOException("Unable to move temp file to original file"));
110
111    closed = true;
112    }
113
114  /*
115   */
116
117  private static File getTempFile(File file)
118    {
119    String path = file.getAbsolutePath();
120    return(new File(path + ".tmp"));
121    }
122  
123  }
124
125/* end of source file */