blob: 85a1682fd22c50b89dcbfdeaaae20260c7b656bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 compeople AG 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:
* compeople AG (Stefan Liebig) - initial API and implementation
* IBM Corporation - bug fixes and enhancements
*******************************************************************************/
package org.eclipse.equinox.internal.p2.sar;
import java.io.*;
/**
* The SarOutputStream writes a stream archive as an OutputStream. Methods are
* provided to put entries, and then write their contents by writing to this
* stream using write().
*/
public class SarOutputStream extends OutputStream {
private boolean finished;
private final DataOutputStream dataOutputStream;
private final DirectByteArrayOutputStream entryContent;
/**
* @param outputStream
* @throws IOException
*/
public SarOutputStream(OutputStream outputStream) throws IOException {
dataOutputStream = new DataOutputStream(outputStream);
entryContent = new DirectByteArrayOutputStream(16 * 1024);
writeString(SarConstants.SARFILE_MARKER);
dataOutputStream.writeInt(SarConstants.SARFILE_VERSION);
finished = false;
}
/**
* Ends the SAR archive and closes the underlying OutputStream.
*
* @see java.io.OutputStream#close()
*/
// @Override
public void close() throws IOException {
finish();
super.close();
}
/**
* Finish this SAR archive but does not close the underlying output stream.
*
* @throws IOException
*/
public void finish() throws IOException {
if (finished)
return;
writeEOFRecord();
finished = true;
}
/**
* Put an entry on the output stream. This writes the entry's header record
* and positions the output stream for writing the contents of the entry.
* Once this method is called, the stream is ready for calls to write() to
* write the entry's contents. Once the contents are written, closeEntry()
* <B>MUST </B> be called to ensure that all buffered data is completely
* written to the output stream.
*
* @param entry
* the SarEntry to be written to the archive.
* @throws IOException
*/
public void putNextEntry(SarEntry entry) throws IOException {
entry.writeTo(this);
}
/**
* Close an entry. This method MUST be called for all file entries that
* contain data. The reason is that we must buffer data written to the
* stream in order to satisfy the buffer's record based writes. Thus, there
* may be data fragments still being assembled that must be written to the
* output stream before this entry is closed and the next entry written.
*
* @throws IOException
*/
public void closeEntry() throws IOException {
writeBytes(entryContent.getBuffer(), entryContent.getBufferLength());
entryContent.reset();
}
/**
* @param s
* @throws IOException
*/
void writeString(String s) throws IOException {
byte[] bytes = null;
if (s != null)
bytes = s.getBytes(SarConstants.DEFAULT_ENCODING);
writeBytes(bytes);
}
/**
* @param bytes
* @throws IOException
*/
void writeBytes(byte[] bytes) throws IOException {
writeBytes(bytes, bytes != null ? bytes.length : -1);
}
/**
* @param bytes
* @throws IOException
*/
void writeBytes(byte[] bytes, int length) throws IOException {
if (bytes != null) {
dataOutputStream.writeInt(length);
dataOutputStream.write(bytes, 0, length);
} else {
dataOutputStream.writeInt(-1);
}
}
/**
* @param v
* @throws IOException
*/
void writeInt(int v) throws IOException {
dataOutputStream.writeInt(v);
}
/**
* @param bool
* @throws IOException
*/
public void writeBool(boolean bool) throws IOException {
dataOutputStream.writeBoolean(bool);
}
/**
* @param v
* @throws IOException
*/
void writeLong(long v) throws IOException {
dataOutputStream.writeLong(v);
}
/**
* Writes a byte to the current org.eclipse.equinox.p2.sar archive entry.
*
* @param b
* the byte written.
* @throws IOException
*
* @see java.io.OutputStream#write(int)
*/
public void write(int b) throws IOException {
byte[] bytes = new byte[1];
bytes[0] = (byte) b;
entryContent.write(bytes);
}
/**
* Writes bytes to the current org.eclipse.equinox.p2.sar archive entry.
*
* @param bytes
* The buffer to write to the archive.
* @throws IOException
*
* @see java.io.OutputStream#write(byte[])
*/
public void write(byte[] bytes) throws IOException {
entryContent.write(bytes, 0, bytes.length);
}
/**
* Writes bytes to the current org.eclipse.equinox.p2.sar archive entry.
*
* @param bytes
* The buffer to write to the archive.
* @param offset
* The offset in the buffer from which to get bytes.
* @param numToWrite
* The number of bytes to write.
*
* @throws IOException
*
* @see java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte[] bytes, int offset, int numToWrite) throws IOException {
entryContent.write(bytes, offset, numToWrite);
}
/**
* Write an EOF (end of archive) entry to the org.eclipse.equinox.p2.sar archive.
*
* @throws IOException
*/
private void writeEOFRecord() throws IOException {
SarEntry eofEntry = new SarEntry();
eofEntry.writeTo(this);
}
}