blob: 3dd26519756649bb8f218c1d1bd29ca190c10e30 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#ifndef _DECAF_IO_FILTEROUTPUTSTREAM_H_
#define _DECAF_IO_FILTEROUTPUTSTREAM_H_
#include <decaf/io/OutputStream.h>
#include <decaf/io/IOException.h>
#include <decaf/util/concurrent/Mutex.h>
namespace decaf{
namespace io{
/**
* This class is the superclass of all classes that filter output
* streams. These streams sit on top of an already existing output
* stream (the underlying output stream) which it uses as its basic
* sink of data, but possibly transforming the data along the way or
* providing additional functionality.
*
* The class FilterOutputStream itself simply overrides all methods of
* OutputStream with versions that pass all requests to the underlying
* output stream. Subclasses of FilterOutputStream may further override
* some of these methods as well as provide additional methods and
* fields.
*
* Due to the lack of garbage collection in C++ a design decision was
* made to add a boolean parameter to the constructor indicating if the
* wrapped <code>InputStream</code> is owned by this object. That way
* creation of the underlying stream can occur in a Java like way. Ex:
*
* DataOutputStream os = new DataOutputStream( new OutputStream(), true )
*/
class DECAF_API FilterOutputStream : public OutputStream
{
protected:
// The output Stream to wrap
OutputStream* outputStream;
// Synchronization object.
util::concurrent::Mutex mutex;
// Indicates if we own the wrapped stream
bool own;
public:
/**
* Constructor, creates a wrapped output stream
* @param outputStream the OutputStream to wrap
* @param own If true, this object will control the lifetime of the
* output stream that it encapsulates.
*/
FilterOutputStream( OutputStream* outputStream, bool own = false ){
this->outputStream = outputStream;
this->own = own;
}
virtual ~FilterOutputStream() {
try {
if( own == true ) delete outputStream;
}
DECAF_CATCH_NOTHROW( IOException )
DECAF_CATCHALL_NOTHROW( )
}
/**
* Writes a single byte to the output stream. The write method of
* FilterOutputStream calls the write method of its underlying output
* stream, that is, it performs out.write(b).
* @param c the byte.
* @throws IOException thrown if an error occurs.
*/
virtual void write( unsigned char c ) throw ( IOException ) {
try {
outputStream->write( c );
}
DECAF_CATCH_RETHROW( IOException )
DECAF_CATCHALL_THROW( IOException )
}
/**
* Writes an array of bytes to the output stream. The write method of
* FilterOutputStream calls the write method of one argument on each
* byte to output.
* @param buffer The array of bytes to write.
* @param len The number of bytes from the buffer to be written.
* @throws IOException thrown if an error occurs.
*/
virtual void write( const unsigned char* buffer, std::size_t len ) throw ( IOException ) {
try {
for( std::size_t ix = 0; ix < len; ++ix )
{
outputStream->write( buffer[ix] );
}
}
DECAF_CATCH_RETHROW( IOException )
DECAF_CATCHALL_THROW( IOException )
}
/**
* Flushes any pending writes in this output stream.
* The flush method of FilterOutputStream calls the flush method
* of its underlying output stream
* @throws IOException
*/
virtual void flush() throw ( IOException ) {
try {
outputStream->flush();
}
DECAF_CATCH_RETHROW( IOException )
DECAF_CATCHALL_THROW( IOException )
}
/**
* Close the Stream, the FilterOutputStream simply calls the close
* method of the underlying stream
* @throws CMSException
*/
virtual void close() throw ( lang::Exception ) {
try {
outputStream->close();
}
DECAF_CATCH_RETHROW( IOException )
DECAF_CATCHALL_THROW( IOException )
}
public: // Synchronizable
/**
* Waits on a signal from this object, which is generated
* by a call to Notify. Must have this object locked before
* calling.
* @throws Exception
*/
virtual void lock() throw( lang::Exception ){
mutex.lock();
}
/**
* Unlocks the object.
* @throws Exception
*/
virtual void unlock() throw( lang::Exception ){
mutex.unlock();
}
/**
* Waits on a signal from this object, which is generated
* by a call to Notify. Must have this object locked before
* calling.
* @throws Exception
*/
virtual void wait() throw( lang::Exception ){
mutex.wait();
}
/**
* Waits on a signal from this object, which is generated
* by a call to Notify. Must have this object locked before
* calling. This wait will timeout after the specified time
* interval.
* @param millisecs the time in millisecsonds to wait, or WAIT_INIFINITE
* @throws Exception
*/
virtual void wait( unsigned long millisecs ) throw( lang::Exception ){
mutex.wait( millisecs );
}
/**
* Signals a waiter on this object that it can now wake
* up and continue. Must have this object locked before
* calling.
* @throws Exception
*/
virtual void notify() throw( lang::Exception ){
mutex.notify();
}
/**
* Signals the waiters on this object that it can now wake
* up and continue. Must have this object locked before
* calling.
* @throws Exception
*/
virtual void notifyAll() throw( lang::Exception ){
mutex.notifyAll();
}
};
}}
#endif /*_DECAF_IO_FILTEROUTPUTSTREAM_H_*/