/** * */ package fr.cedrik.email.fs; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.channels.FileLock; import java.util.Iterator; import java.util.zip.GZIPOutputStream; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.cedrik.email.spi.Message; import fr.cedrik.util.Charsets; /** * Usage: * <ul><li>{@link #openFolder(boolean)}</li> * <li>{@link #openFile(Message, boolean)}</li> * <li>{@link #write(Message, Iterator)}</li> * <li>{@link #closeFile(Message)} (in {@code finally} block!)</li> * <li>{@link #closeFolder()} (in {@code finally} block!)</li></ul> * * @author Cédrik LIME */ public abstract class BaseFileWriter { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); protected File outFile = null; protected Writer outWriter = null; protected FileLock outFileLock = null; public BaseFileWriter() { } public abstract boolean exists(); public abstract void openFolder(boolean append) throws IOException; public abstract void openFile(Message message, boolean append) throws IOException; protected void openWriter(Message message, boolean append) throws IOException { outFile = getMBoxFile(message); OutputStream outStream = new FileOutputStream(outFile, append); outFileLock = ((FileOutputStream)outStream).getChannel().tryLock(); if (outFileLock == null) { logger.error("Can not acquire a lock on file " + outFile + ". Aborting."); IOUtils.closeQuietly(outStream); throw new IOException("Can not acquire a lock on file " + outFile + ". Aborting."); } if (canCompress() /* || iNotes.isCompressExports() */) { outStream = new GZIPOutputStream(outStream, 8*1024); } outWriter = new BufferedWriter(new OutputStreamWriter(outStream, Charsets.US_ASCII), 32*1024); } protected abstract boolean canCompress(); protected abstract File getMBoxFile(Message message); public final void write(Message message, Iterator<String> mime) throws IOException { logger.debug("Writing message {}", message); writeMIME(outWriter, message, mime); } public void flush() throws IOException { if (outWriter != null) { outWriter.flush(); } } public abstract void closeFile(Message message) throws IOException; public abstract void closeFolder() throws IOException; protected void closeWriter() throws IOException { if (outWriter != null) { outWriter.flush(); } if (outFileLock != null) { outFileLock.release(); outFileLock = null; } IOUtils.closeQuietly(outWriter); outWriter = null; // Do not set outFile to null, as it may be used by sub-classes! } protected abstract void writeMIME(Writer mbox, Message message, Iterator<String> mime) throws IOException;//FIXME replace BaseINotesMessage with "extraHeaders"? /** * @return RFC-compliant new-line char */ protected String newLine() { return "\n"; } /** * @return RFC-compliant new-line char */ protected Writer newLine(Writer out) throws IOException { return out.append(newLine()); } }