Show FileBackup.java syntax highlighted
/*
* Copyright (C) 2000-2004 Roger Butenuth, Andreas Gampe,
* Stefan Goetz, Sebastian Pappert,
* Klaas Prause, Enno Rehling,
* Sebastian Tusk, Ulrich Kuester,
* Ilja Pavkovic
*
* This file is part of the Eressea Java Code Base, see the
* file LICENSING for the licensing information applying to
* this file.
*
*/
package com.eressea.io.file;
import java.io.File;
import java.io.IOException;
import com.eressea.demo.Client;
import com.eressea.util.logging.Logger;
/**
* Handles backup generation for files.
*/
public class FileBackup {
private static final Logger log = Logger.getInstance(FileBackup.class);
/** this is normally a bad idea, but we allow this global */
private static int DEFAULT_BACKUP_LEVEL = 5;
/**
* Disable instantiation of class
*/
private FileBackup() {
}
/**
* Returns the new backup file for the given file. Uses a backup level of <code>5</code>.
*
* @param file the file to back up. The directory is the parent directory of the given file.
*
* @return the created backup file.
*
* @throws IOException if an I/O error occured.
*/
public static synchronized File create(File file) throws IOException {
return create(file, file.getParentFile());
}
/**
* Returns the new backup file for the given file and backup level
*
* @param file the file to back up. The directory is the parent directory of the given file.
* @param backuplevel number of revisions to hold, ignored for the{@link #SIMPLE} backup type.
*
* @return the created backup file.
*
* @throws IOException if an I/O error occured.
*/
public static synchronized File create(File file, int backuplevel) throws IOException {
return create(file, file.getParentFile(), backuplevel);
}
/**
* Returns the new backup file for the given file. Uses a backup level of <code>5</code>.
*
* @param file the file to back up.
* @param directory the directory to copy the backup to. If the directory doesn't exist, it
* will be created.
*
* @return the created backup file.
*
* @throws IOException if an I/O error occured.
*/
public static synchronized File create(File file, File directory) throws IOException {
return create(file, directory, DEFAULT_BACKUP_LEVEL);
}
/**
* Returns the new backup file for the given file.
*
* @param file the file to back up.
* @param directory the directory to copy the backup to. If the directory doesn't exist, it
* will be created.
* @param backupLevel number of revisions to hold, ignored for the {@link #SIMPLE} backup
* type.
*
* @return the created backup file or null if target file does not exist
*
* @throws IOException if an I/O error occured.
*/
public static synchronized File create(File file, File directory, int backupLevel)
throws IOException
{
// ensure that file exists. If not, stop execution to create backup file
if(!(file.exists())) {
return null;
}
if (directory==null){
log.error("error getting dir for file " + file.toString());
log.error("the returned directory is null - failed to create backup!");
return null;
}
// ensure that target directory exists
if(!directory.exists()) {
if(!directory.mkdirs()) {
throw new IOException("Could not create directory " + directory);
}
}
File backup = null;
int highestBackup = getLatestRevision(file.getName(), directory);
backup = new File(directory + File.separator +
getVersionName(file.getName(), highestBackup + 1));
copy(file, backup);
removeObsoleteRevisions(highestBackup + 1, backupLevel, file.getName(), directory);
return backup;
}
/**
* Returns the revision number of the latest revision found for the given filename.
*
* @param filename filename to check for revision numbers.
* @param dir directory to search.
*
* @return revision number of the latest backup; returns <code>0</code> if no backup could be
* found.
*/
private static int getLatestRevision(String filename, File dir) {
if(dir == null) {
return 0;
}
File files[] = dir.listFiles();
int result = 0;
for(int i = 0; i < files.length; i++) {
String name = files[i].getName();
if(name.startsWith(filename)) {
int revision = getRevision(name);
if(revision > result) {
result = revision;
}
}
}
return result;
}
/**
* Returns the revision number of the filename.
*
* @param filename filename to check for a revision number.
*
* @return the found revision number; returns <code>0</code> if no revision number could be
* found.
*/
private static int getRevision(String filename) {
int startOffset = filename.indexOf('~');
int endOffset = filename.indexOf('~', startOffset + 1);
while((startOffset < endOffset) && (startOffset > -1) && (endOffset > -1)) {
String result = filename.substring(startOffset + 1, endOffset);
startOffset = filename.indexOf('~', endOffset);
endOffset = filename.indexOf('~', startOffset + 1);
try {
int revision = Integer.parseInt(result);
if(revision > 0) {
return revision;
}
} catch(NumberFormatException nfe) {
}
}
return 0;
}
/**
* Concatenates the filename plus the revision string.
*
* @param filename the filename to use.
* @param revision the revision number.
*
* @return the resulting string.
*/
private static String getVersionName(String filename, int revision) {
StringBuffer buf = new StringBuffer(15);
buf.append(filename);
buf.append('~');
buf.append(revision);
buf.append('~');
return buf.toString();
}
/**
* Copies the given source file to the given destination.
*
* @param source source file.
* @param target destination target file.
*
* @throws IOException if an I/O error occured.
*/
private static void copy(File source, File target) throws IOException {
CopyFile.copy(source, target);
}
/**
* Removes all obsolete revisions for the given filename in the given directory.
*
* @param currentRevision revision number of the latest revision.
* @param backupLevel number of revisions to hold.
* @param filename filename to check for revision numbers.
* @param directory directory which holds the backups.
*/
private static void removeObsoleteRevisions(int currentRevision, int backupLevel,
String filename, File directory) {
File files[] = directory.listFiles();
if(backupLevel > 0) {
// delete old revisions
for(int i = 0; i < files.length; i++) {
String name = files[i].getName();
if(name.startsWith(filename)) {
if(getRevision(name) <= (currentRevision - backupLevel)) {
files[i].delete();
}
}
}
}
}
}
See more files for this project here