package com.limegroup.gnutella.downloader.serial;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.io.IOUtils;
import org.limewire.util.ConverterObjectInputStream;
import org.limewire.util.FileUtils;
import org.limewire.util.GenericsUtils;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class DownloadSerializerImpl implements DownloadSerializer {
private static final Log LOG = LogFactory.getLog(DownloadSerializerImpl.class);
private final DownloadSerializeSettings downloadSerializeSettings;
@Inject
public DownloadSerializerImpl(DownloadSerializeSettings downloadSerializeSettings) {
this.downloadSerializeSettings = downloadSerializeSettings;
}
/**
* Reads all saved downloads from disk.
* <p>
* This works by first attempting to read from the save file described in the settings,
* and then attempting to read from the backup file if there were any errors while
* reading the normal file. If both files fail, this returns an empty list.
*/
public List<DownloadMemento> readFromDisk() throws IOException {
if(!downloadSerializeSettings.getSaveFile().exists() && !downloadSerializeSettings.getSaveFile().exists())
return Collections.emptyList();
Throwable exception;
ObjectInputStream in = null;
try {
in = new ConverterObjectInputStream(new BufferedInputStream(new FileInputStream(downloadSerializeSettings.getSaveFile())));
return GenericsUtils.scanForList(in.readObject(), DownloadMemento.class, GenericsUtils.ScanMode.REMOVE);
} catch(Throwable ignored) {
exception = ignored;
LOG.warn("Error reading normal file.", ignored);
} finally {
IOUtils.close(in);
}
// Falls through to here only on error with normal file.
try {
in = new ConverterObjectInputStream(new BufferedInputStream(new FileInputStream(downloadSerializeSettings.getBackupFile())));
return GenericsUtils.scanForList(in.readObject(), DownloadMemento.class, GenericsUtils.ScanMode.REMOVE);
} catch(Throwable ignored) {
LOG.warn("Error reading normal file.", ignored);
} finally {
IOUtils.close(in);
}
if(exception instanceof IOException)
throw (IOException)exception;
else
throw (IOException)new IOException().initCause(exception);
}
/**
* Writes the mementos to disk. This works by first writing to the backup
* file and then renaming the backup file to the save file. If the backup
* file cannot be written, this fails.
*/
// synchronized to prevent more than one person at a time from possibly writing
public synchronized boolean writeToDisk(List<? extends DownloadMemento> mementos) {
return FileUtils.writeWithBackupFile(mementos, downloadSerializeSettings.getBackupFile(),
downloadSerializeSettings.getSaveFile(), LOG);
}
}