Copyright (c) 2000, 2014 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM Corporation - initial API and implementation
James Blackburn (Broadcom Corp.) - ongoing development
/*******************************************************************************
* Copyright (c) 2000, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.internal.localstore;
import java.io.*;
import org.eclipse.core.internal.utils.FileUtil;
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 SafeChunkyInputStream
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.
Because of this class purpose (keep data consistent), it is important that the
user only calls #succeed
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 Also: - SafeChunkyInputStream
/**
* 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();
close();
} finally {
isOpen = false;
FileUtil.safeClose(this);
}
}
Overrides super implementation to allow multiple calls on Java 9+.
See https://bugs.eclipse.org/bugs/show_bug.cgi?id=530330
{@inheritDoc}
/**
* Overrides super implementation to allow multiple calls on Java 9+.
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=530330
*
* {@inheritDoc}
*/
@Override
public void close() throws IOException {
try (OutputStream ostream = out) {
flush();
}
}
@Override
public void write(int b) throws IOException {
if (!isOpen)
open();
super.write(b);
}
}