|
|
AbstractThis draft introduces the streaming interfaces (package com.sun.star.uno.io) and gives some examples about how they can be used. Note: In some pictures there is a ignoreable 2 in the interface names (e.g. XInputStream2). ContentsIntroduction Introduction
The interfaces
The 1st level : XInputStream/XOutputStream
//simple scenario : 200 bytes shall be transfered from source to target
//active sink, passive source scenario.
class source : public XInputStream, public ....
{
...
// set the actual position to zero
source() { index = 0; }
// XinputStream.readBytes()
INT32 readBytes( Sequence<unsigned char> &seq , INT32 nBytes )
{
// beware eof !
INT32 nCopy = min( nBytes, 200-index );
// allocate memory for the requested number of bytes
seq.realloc( nCopy );
// put the data into the sequence
memcpy( seq.getArray() , &acData[index] , nCopy );
// increase actual position
index += nCopy;
return nCopy;
}
// XInputStream.skipBytes()
INT32 skipBytes( INT32 nBytes )
{
// beware eof !
INT32 nCopy = min( nBytes, 200-index );
// increase actual position
index += nCopy;
return nCopy;
}
// XInputStream.available()
INT32 available()
{
return 200-index;
}
// XInputStream.closeInput()
void closeInput()
{
// no special closing procedure in this simple example
}
...
private:
unsigned char acData[200];
INT32 index;
};
// the active datasink
// No error or exception handling for simplicity
class sink : public XXXXXXX, .....
{
// method of interface XXXXXXX
void readFromStream( const Reference< XInputStream > &r )
{
Sequence<unsigned char> seq(10);
BOOL bContinue = TRUE;
// number of bytes that have been read
INT32 nRead;
while( bContinue ) {
// read from the inputstream in 10 byte steps
nRead = r->readBytes( seq , 10 )
// ... do something with seq
// check, if eof has been reached
bContinue = ( 10 == nRead );
}
// close the stream
r->closeInput();
}
}
///in main :
{
Reference< XInterface > source;
Reference< XInterface > sink;
// instantiate source and sink through some service.
....
// query the inputstream
Reference< XInputStream > input_stream( source , UNO_QUERY );
// query the sink
Reference< XXXXXXX > some_interface( sink , UNO_QUERY );
// do the reading
some_interface->readFromStream( input_stream );
}
The 2nd level : XActiveDataSink2/XActiveDataSource2
2.2.1 Chaining
The following code samples show how plugging is done.
/// Plugging for Fig 6b (without error handling)
{
Reference<XInterface > application;
Reference<XInterface > OConverter;
Reference<XInterface > OFile;
// instantiate the three objects via services, put them into the above references
.....
// query the interfaces
Reference< XInputStream > aFileInputStream( OFile , UNO_QUERY );
Reference< XInputStream > aConverterInputStream( OConverter , UNO_QUERY );
Reference< XActiveDataSink > aConverterSink( OConverter , UNO_QUERY );
Reference< XActiveDataSink > aApplicationSink( application , UNO_QUERY );
// plug the connection
aConverterSink.setInputStream( aFileInputStream );
aApplicationSink.setInputStream( aConverterInputStream );
// start data transfer
...
}
{
// plug the connection
aConverterSink.setInputStream( aFileInputStream ); // first connect passive parts.
aApplicationSink.setInputStream( aConverterInputStream ); // active player is connected last,
// no problems can arise
}
b)
{
// plug the connection
aApplicationSink.setInputStream( aConverterInputStream ); // application starts to read but OConverter
// is not connected to anything.
aConverterSink.setInputStream( aFileInputStream );
}
The problem can be avoided :
2.2.2 Piping
{
Reference< XInterface > OFileWriter, OPipe, OFileReader;
// instantiate them via a standard service
....
// get the interfaces
Reference< XActiveDataSink > sink( OFileWriter, UNO_QUERY );
Reference< XOutputStream > pipeOut( OPipe , UNO_QUERY );
Reference< XInputStream > pipeIn( OPipe , UNO_QUERY );
Reference< XActiveDataSource > source( OFileReader , UNO_QUERY );
// do the plugging
sink.setInputStream( pipeIn );
source.setOutputStream( pipeOut );
// now work with the connection ( sink and source )
}
The 3rd level : XActiveDataControl
To startup the above sample pipe, the following code is necessary :
{
Reference< XInterface > OFileWriter, OPipe, OFileReader;
// instantiate them via a standard service
....
// get the interfaces for plugging
Reference< XActiveDataSink > sink( OFileWriter, UNO_QUERY );
Reference< XOutputStream > pipeOut( OPipe , UNO_QUERY );
Reference< XInputStream > pipeIn( OPipe , UNO_QUERY );
Reference< XActiveDataSource > source( OFileReader , UNO_QUERY );
// plug ( data transfer is not started )
sink.setInputStream( pipeIn );
source.setOutputStream( pipeOut );
// get the interfaces for starting
Reference< XActiveDataControl > controlSink( OFileWriter );
Reference< XActiveDataControl > controlSource( OFileReader );
// start
controlSink.start(); // order of starting is not important, the whole connection already exists.
controlSource.start(); // it may be less expensive to start sink first, because OPipe
// may need less resources for buffering.
}
XActiveDataControl also offers a listener administration. The 4th level : XConnectable
OFileWriter::setInputStream( const Reference< XInputStream > &r )
{
/// store the inputstream reference for later use
m_in = r;
/// does the instance provide a XDataSourceRef ?
Reference< XConnectable > predecessor( r , UNO_QUERY );
setPredecessor( predecessor );
}
application::setPredecessor( const Reference< XConnectable > &r )
{
/// if the references match, nothing needs to be done
if( m_pred != r ) {
/// store the reference for later use
m_pred = r;
if( m_pred.is() ) {
/// set this instance as the sink !
m_pred.setSuccessor( this );
}
}
}
{
/// send the close to the chained partner
getInputStream()->closeInput();
//.... do some tiding up, that is necessary when closing.
/// release all references
setPredecessor( Reference< XConnectable >() );
setSource( Reference< XConnectable >() );
setInputStream( Reference< XInputStream >() );
}
Note that any object, which does not support this XConnectable mechanism will interrupt the connection.
2.5 Errorhandling
Standard servicesThe following standard services have been implemented . Implementations can be found in udk/io/source/stm. The dll is stm.dll. All implementations are thread safe. However it is probably not very meaningful, if two threads read the same input stream at the same time which thread gets which data is then arbitrary. Note: All streams must be explicitly closed in order to free their resources and release their ring references. com.sun.star.uno.io.Pipe : implements XOutputStream, XInputStream and XConnectable Basic implementation (see fig 12) to connect input stream and output stream. In general one thread is writing data into the pipe and another is reading from the pipe. The pipe does the necessary buffering in memory. com.sun.star.uno.io.DataInputStream : implements XDataInputStream, XActiveDataSink and XConnectable Provides the XDataInputStream functionality. Must be chained to another XInputStream (e.g. a pipe) to be meaningful. com.sun.star.uno.io.DataOutputStream : implements XDataOutputStream, XActiveDataSource and XConnectable Provides the XDataOutputStream functionality. Must be chained to another XOutputStream (e.g. a pipe) to be meaningful. com.sun.star.uno.io.MarkableInputStream : implements XMarkableStream, XInputStream, XActiveDataSink and XConnectable Provides the XMarkableStream functionality. When a mark is created, the implementations buffers all further read data. Must be chained to another inputstream to be meaningful. com.sun.star.uno.io.MarkableOutputStream : implements XMarkableStream, XOutputStream, XActiveDataSource and XConnectable Provides the XMarkableStream functionality. When a mark is created, the implementations buffers all further written data. The data is written further through the chain, when the mark is deleted. Even a flush will not have any effect. Must be chained to another outputstream to be meaningful. com.sun.star.uno.io.ObjectInputStream : implements XObjectInputStream, XActiveDataSink and XConnectable Provides XObjectInputStream functionality. All services of instances, that shall be read, must be registered with the global service manager. All services must implement XPersistObject. Must be chained to another XInputStream. Somewhere in the chain must exist an XMarkableStream. Be careful that all elements between this and XMarkableStream must not buffer data ( otherwise the markable stream becomes meaningless ) and one receives coincident results. com.sun.star.uno.io.ObjectOutputStream : implements XObjectOutputStream, XActiveDataSource and XConnectable Provides XObjectOutputStream functionality. All services, that shall be serialized, must implement XPersistObject. Must be chained to another XOutputStream. Somewhere in the chain must exist a XMarkableStream. Be careful that all elements between this and XMarkableStream must not buffer data ( otherwise the markable stream becomes meaningless) and one receives coincident results.
|





