/*
* Copyright (C) 2014 Jörg Prante
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xbib.io.archive;
import org.xbib.io.BytesProgressWatcher;
import java.io.IOException;
import java.io.OutputStream;
/**
* Archive output stream implementations are expected to override the
* {@link #write(byte[], int, int)} method to improve performance.
* They should also override {@link #close()} to ensure that any necessary
* trailers are added.
* The normal sequence of calls for working with ArchiveOutputStreams is:
* + create ArchiveOutputStream object
* + write header (optional, Zip only)
* + repeat as needed
* - putArchiveEntry() (writes entry header)
* - write() (writes entry data)
* - closeArchiveEntry() (closes entry)
* + finish() (ends the addition of entries)
* + write additional data if format supports it (optional)
* + close()
*/
public abstract class ArchiveOutputStream<E extends ArchiveEntry> extends OutputStream {
private BytesProgressWatcher watcher;
public ArchiveOutputStream setWatcher(BytesProgressWatcher watcher) {
this.watcher = watcher;
return this;
}
public BytesProgressWatcher getWatcher() {
return watcher;
}
/**
* Temporary buffer used for the {@link #write(int)} method
*/
private final byte[] oneByte = new byte[1];
/**
* Creates a new archive entry for this archive output stream
*
* @return the new archive entry
* @throws IOException
*/
public abstract E newArchiveEntry() throws IOException;
/**
* Writes the headers for an archive entry to the output stream.
* The caller must then write the content to the stream and call
* {@link #closeArchiveEntry()} to complete the process.
*
* @param entry describes the entry
* @throws java.io.IOException
*/
public abstract void putArchiveEntry(E entry) throws IOException;
/**
* Closes the archive entry, writing any trailer information that may
* be required.
*
* @throws java.io.IOException
*/
public abstract void closeArchiveEntry() throws IOException;
/**
* Finishes the addition of entries to this stream, without closing it.
* Additional data can be written, if the format supports it.
* <p>
* The finish() method throws an Exception if the user forgets to close the entry
* .
*
* @throws java.io.IOException
*/
public abstract void finish() throws IOException;
/**
* Writes a byte to the current archive entry.
* <p>
* This method simply calls write( byte[], 0, 1 ).
*
* @param b The byte to be written.
* @throws java.io.IOException on error
*/
@Override
public void write(int b) throws IOException {
oneByte[0] = (byte) (b & 0xFF);
write(oneByte, 0, 1);
}
}