/******************************************************************************* * 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); } }