// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.core.util; import java.io.File; import org.openstreetmap.osmosis.core.OsmosisRuntimeException; /** * Supports the creation of files in an atomic fashion. Internally it creates files using a * temporary filename, then renames them to the final file name. */ public class AtomicFileCreator { private File file; private File tmpFile; /** * Creates a new instance. * * @param file * The file to be created. */ public AtomicFileCreator(File file) { this.file = file; this.tmpFile = new File(file.getPath() + ".tmp"); } /** * Checks if either one of the main or temporary files currently exists. * * @return True if a file exists, false otherwise. */ public boolean exists() { // We're checking both files because there is a small window where only the new file exists // after the main state file is deleted before the new file being renamed. // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4017593 for more details. return file.exists() || tmpFile.exists(); } /** * Renames the new temporary file to the current file deleting the current file if it exists. */ public void renameTmpFileToCurrent() { // Make sure we have a new file. if (!tmpFile.exists()) { throw new OsmosisRuntimeException("Can't rename non-existent file " + tmpFile + "."); } // Delete the existing file if it exists. if (file.exists()) { if (!file.delete()) { throw new OsmosisRuntimeException("Unable to delete file " + file + "."); } } // Rename the new file to the existing file. if (!tmpFile.renameTo(file)) { throw new OsmosisRuntimeException( "Unable to rename file " + tmpFile + " to " + file + "."); } } /** * Returns the temporary file used during file generation. This file is written first, and then * renamed to the real file name when complete. * * @return The temporary file name. */ public File getTmpFile() { return tmpFile; } /** * Returns the file represented by this class. This file is not written directly, instead a * temporary file is created and then renamed to this file. * * @return The file name. */ public File getFile() { return file; } }