/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.localstore;
import java.io.*;
/**
* Appends data, in chunks, to a file. Each chunk is defined by the moment the stream is opened
* (created) and a call to #succeed is made. It is necessary to use the
* <code>SafeChunkyInputStream</code> to read its contents back. The user of this class does not
* need to know explicitly about its chunk implementation. It is only an implementation detail. What
* really matters to the outside world is that it tries to keep the file data consistent. If some
* data becomes corrupted while writing or later, upon reading the file, the chunk that contains the
* corrupted data is skipped.
* <p>
* Because of this class purpose (keep data consistent), it is important that the user only calls
* <code>#succeed</code> when the chunk of data is successfully written. After this call, the user
* can continue writing data to the file and it will not be considered related to the previous
* chunk. So, if this data is corrupted, the previous one is still safe.
*
* @see SafeChunkyInputStream
*/
public class SafeChunkyOutputStream extends FilterOutputStream {
protected String filePath;
protected boolean isOpen;
public SafeChunkyOutputStream(File target) throws IOException {
this(target.getAbsolutePath());
}
public SafeChunkyOutputStream(String filePath) throws IOException {
super(new BufferedOutputStream(new FileOutputStream(filePath, true)));
this.filePath= filePath;
isOpen= true;
beginChunk();
}
protected void beginChunk() throws IOException {
write(ILocalStoreConstants.BEGIN_CHUNK);
}
protected void endChunk() throws IOException {
write(ILocalStoreConstants.END_CHUNK);
}
protected void open() throws IOException {
out= new BufferedOutputStream(new FileOutputStream(filePath, true));
isOpen= true;
beginChunk();
}
public void succeed() throws IOException {
try {
endChunk();
} finally {
isOpen= false;
close();
}
}
public void write(int b) throws IOException {
if (!isOpen)
open();
super.write(b);
}
}