xref: /aoo41x/main/io/source/stm/odata.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_io.hxx"
30 
31 
32 // streams
33 #include <hash_map>
34 #include <vector>
35 
36 #include <com/sun/star/io/XObjectInputStream.hpp>
37 #include <com/sun/star/io/XObjectOutputStream.hpp>
38 #include <com/sun/star/io/XActiveDataSource.hpp>
39 #include <com/sun/star/io/XActiveDataSink.hpp>
40 #include <com/sun/star/io/XMarkableStream.hpp>
41 #include <com/sun/star/io/XConnectable.hpp>
42 #include <com/sun/star/io/UnexpectedEOFException.hpp>
43 #include <com/sun/star/io/WrongFormatException.hpp>
44 #include <com/sun/star/lang/XServiceInfo.hpp>
45 
46 #include <cppuhelper/weak.hxx>      // OWeakObject
47 #include <cppuhelper/factory.hxx>
48 #include <cppuhelper/implbase4.hxx>
49 #include <cppuhelper/typeprovider.hxx>
50 #include <cppuhelper/queryinterface.hxx>
51 
52 #include <osl/mutex.hxx>
53 
54 #include <string.h>
55 
56 
57 using namespace ::cppu;
58 using namespace ::osl;
59 using namespace ::std;
60 using namespace ::rtl;
61 using namespace ::com::sun::star::io;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::lang;
64 
65 #include "factreg.hxx"
66 
67 namespace io_stm {
68 
69 class ODataInputStream :
70 	public WeakImplHelper4 <
71                               XDataInputStream,
72 	                          XActiveDataSink,
73                               XConnectable,
74 			                  XServiceInfo
75                            >
76 {
77 public:
78 	ODataInputStream( )
79 		: m_bValidStream( sal_False )
80 		{
81 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
82 		}
83 
84 	~ODataInputStream();
85 public: // XInputStream
86     virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
87     														throw (	NotConnectedException,
88     																	BufferSizeExceededException,
89     																	RuntimeException);
90     virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
91     														throw (	NotConnectedException,
92     																	BufferSizeExceededException,
93     																	RuntimeException);
94     virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) 				throw (	NotConnectedException,
95     																	BufferSizeExceededException,
96     																	RuntimeException);
97     virtual sal_Int32 SAL_CALL available(void) 							throw (	NotConnectedException,
98     																	RuntimeException);
99     virtual void SAL_CALL closeInput(void) 							throw (	NotConnectedException,
100     																	RuntimeException);
101 
102 public: // XDataInputStream
103     virtual sal_Int8 SAL_CALL readBoolean(void) throw (IOException, RuntimeException);
104     virtual sal_Int8 SAL_CALL readByte(void) throw (IOException, RuntimeException);
105     virtual sal_Unicode SAL_CALL readChar(void) throw (IOException, RuntimeException);
106     virtual sal_Int16 SAL_CALL readShort(void) throw (IOException, RuntimeException);
107     virtual sal_Int32 SAL_CALL readLong(void) throw (IOException, RuntimeException);
108     virtual sal_Int64 SAL_CALL readHyper(void) throw (IOException, RuntimeException);
109     virtual float SAL_CALL readFloat(void) throw (IOException, RuntimeException);
110     virtual double SAL_CALL readDouble(void) throw (IOException, RuntimeException);
111     virtual OUString SAL_CALL readUTF(void) throw (IOException, RuntimeException);
112 
113 
114 
115 public: // XActiveDataSink
116     virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream)
117 		throw (RuntimeException);
118     virtual Reference< XInputStream > SAL_CALL getInputStream(void) throw (RuntimeException);
119 
120 public: // XConnectable
121     virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) throw (RuntimeException);
122     virtual Reference < XConnectable > SAL_CALL getPredecessor(void) throw (RuntimeException);
123     virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) throw (RuntimeException);
124     virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException) ;
125 
126 
127 public: // XServiceInfo
128     OUString                     SAL_CALL getImplementationName() throw ();
129     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
130 	sal_Bool                        SAL_CALL supportsService(const OUString& ServiceName) throw ();
131 
132 protected:
133 
134 	Reference < XConnectable > 	m_pred;
135 	Reference < XConnectable > 	m_succ;
136 	Reference < XInputStream > 	m_input;
137 	sal_Bool m_bValidStream;
138 };
139 
140 ODataInputStream::~ODataInputStream()
141 {
142 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
143 }
144 
145 // XInputStream
146 sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
147 	throw (	NotConnectedException,
148 			BufferSizeExceededException,
149 			RuntimeException)
150 {
151  	sal_Int32 nRead;
152 
153  	if( m_bValidStream )
154 	{
155  		nRead = m_input->readBytes( aData , nBytesToRead );
156  	}
157  	else
158 	{
159  		throw NotConnectedException( );
160  	}
161 
162  	return nRead;
163 }
164 
165 sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
166 	throw (	NotConnectedException,
167 			BufferSizeExceededException,
168 			RuntimeException)
169 {
170  	sal_Int32 nRead;
171  	if( m_bValidStream ) {
172  		nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
173  	}
174  	else {
175  		throw NotConnectedException( );
176  	}
177 
178  	return nRead;
179 }
180 void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
181 	throw (	NotConnectedException,
182 			BufferSizeExceededException,
183 			RuntimeException)
184 {
185  	if( m_bValidStream ) {
186  		m_input->skipBytes( nBytesToSkip );
187  	}
188  	else
189 	{
190  		throw NotConnectedException( );
191  	}
192 }
193 
194 
195 sal_Int32 ODataInputStream::available(void)
196 	throw (	NotConnectedException,
197 			RuntimeException)
198 {
199  	sal_Int32 nAvail;
200 
201  	if( m_bValidStream )
202 	{
203  		nAvail = m_input->available( );
204  	}
205  	else
206 	{
207  		throw NotConnectedException( );
208  	}
209  	return nAvail;
210 }
211 
212 void ODataInputStream::closeInput(void )
213 	throw (	NotConnectedException,
214 			RuntimeException)
215 {
216  	if( m_bValidStream ) {
217  		m_input->closeInput( );
218  		setInputStream( Reference< XInputStream > () );
219  		setPredecessor( Reference < XConnectable >() );
220  		setSuccessor( Reference < XConnectable >() );
221  		m_bValidStream = sal_False;
222  	}
223  	else
224 	{
225  		throw NotConnectedException( );
226  	}
227 }
228 
229 
230 
231 
232 //== XDataInputStream ===========================================
233 
234 // XDataInputStream
235 sal_Int8 ODataInputStream::readBoolean(void) throw (IOException, RuntimeException)
236 {
237 	return readByte();
238 }
239 
240 sal_Int8 ODataInputStream::readByte(void)	 throw (IOException, RuntimeException)
241 {
242 	Sequence<sal_Int8> aTmp(1);
243 	if( 1 != readBytes( aTmp, 1 ) )
244 	{
245 		throw UnexpectedEOFException();
246 	}
247 	return aTmp.getArray()[0];
248 }
249 
250 sal_Unicode ODataInputStream::readChar(void) throw (IOException, RuntimeException)
251 {
252 	Sequence<sal_Int8> aTmp(2);
253 	if( 2 != readBytes( aTmp, 2 ) )
254 	{
255 		throw UnexpectedEOFException();
256 	}
257 
258 	const sal_uInt8 * pBytes = ( const sal_uInt8 * )aTmp.getConstArray();
259 	return ((sal_Unicode)pBytes[0] << 8) + pBytes[1];
260 }
261 
262 sal_Int16 ODataInputStream::readShort(void) throw (IOException, RuntimeException)
263 {
264 	Sequence<sal_Int8> aTmp(2);
265 	if( 2 != readBytes( aTmp, 2 ) )
266 	{
267 		throw UnexpectedEOFException();
268 	}
269 
270 	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
271 	return ((sal_Int16)pBytes[0] << 8) + pBytes[1];
272 }
273 
274 
275 sal_Int32 ODataInputStream::readLong(void) throw (IOException, RuntimeException)
276 {
277 	Sequence<sal_Int8> aTmp(4);
278 	if( 4 != readBytes( aTmp, 4 ) )
279 	{
280 		throw UnexpectedEOFException( );
281 	}
282 
283 	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
284 	return ((sal_Int32)pBytes[0] << 24) + ((sal_Int32)pBytes[1] << 16) + ((sal_Int32)pBytes[2] << 8) + pBytes[3];
285 }
286 
287 
288 sal_Int64 ODataInputStream::readHyper(void) throw (IOException, RuntimeException)
289 {
290 	Sequence<sal_Int8> aTmp(8);
291 	if( 8 != readBytes( aTmp, 8 ) )
292 	{
293 		throw UnexpectedEOFException( );
294 	}
295 
296 	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
297 	return
298 		(((sal_Int64)pBytes[0]) << 56) +
299 		(((sal_Int64)pBytes[1]) << 48) +
300 		(((sal_Int64)pBytes[2]) << 40) +
301 		(((sal_Int64)pBytes[3]) << 32) +
302 		(((sal_Int64)pBytes[4]) << 24) +
303 		(((sal_Int64)pBytes[5]) << 16) +
304 		(((sal_Int64)pBytes[6]) << 8) +
305 		pBytes[7];
306 }
307 
308 float ODataInputStream::readFloat(void) throw (IOException, RuntimeException)
309 {
310 	union { float f; sal_uInt32 n; } a;
311 	a.n = readLong();
312 	return a.f;
313 }
314 
315 double ODataInputStream::readDouble(void) throw (IOException, RuntimeException)
316 {
317 	sal_uInt32 n = 1;
318 	union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
319 	if( *(sal_uInt8 *)&n == 1 )
320 	{
321 		// little endian
322 		a.ad.n2 = readLong();
323 		a.ad.n1 = readLong();
324 	}
325 	else
326 	{
327 		// big endian
328 		a.ad.n1 = readLong();
329 		a.ad.n2 = readLong();
330 	}
331 	return a.d;
332 }
333 
334 OUString ODataInputStream::readUTF(void) throw (IOException, RuntimeException)
335 {
336 	sal_uInt16				nShortLen = (sal_uInt16)readShort();
337 	sal_Int32				nUTFLen;
338 
339 	if( ((sal_uInt16)0xffff) == nShortLen )
340 	{
341 		// is interpreted as a sign, that string is longer than 64k
342 		// incompatible to older XDataInputStream-routines, when strings are exactly 64k
343 		nUTFLen = readLong();
344 	}
345 	else
346 	{
347 		nUTFLen = ( sal_Int32 ) nShortLen;
348 	}
349 
350 	Sequence<sal_Unicode>	aBuffer( nUTFLen );
351 	sal_Unicode *			pStr = aBuffer.getArray();
352 
353 	sal_Int32 nCount = 0;
354 	sal_Int32 nStrLen = 0;
355 	while( nCount < nUTFLen )
356 	{
357 	    sal_uInt8 c = (sal_uInt8)readByte();
358 	    sal_uInt8 char2, char3;
359 	    switch( c >> 4 )
360 		{
361 	        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
362 				// 0xxxxxxx
363 				nCount++;
364 				pStr[nStrLen++] = c;
365 				break;
366 
367 	        case 12: case 13:
368 				// 110x xxxx   10xx xxxx
369 				nCount += 2;
370 				if( ! ( nCount <= nUTFLen ) )
371 				{
372 					throw WrongFormatException( );
373 				}
374 
375 				char2 = (sal_uInt8)readByte();
376 				if( ! ( (char2 & 0xC0) == 0x80 ) )
377 				{
378 					throw WrongFormatException( );
379 				}
380 
381 				pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
382 				break;
383 
384 	        case 14:
385 		    // 1110 xxxx  10xx xxxx  10xx xxxx
386 				nCount += 3;
387 				if( !( nCount <= nUTFLen) )
388 				{
389 					throw WrongFormatException( );
390 				}
391 
392 				char2 = (sal_uInt8)readByte();
393 				char3 = (sal_uInt8)readByte();
394 
395 				if( (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) ) {
396 					throw WrongFormatException( );
397 				}
398 				pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
399 								(sal_Unicode(char2 & 0x3F) << 6) |
400 								(char3 & 0x3F);
401 				break;
402 
403 	        default:
404 				// 10xx xxxx,  1111 xxxx
405 				throw WrongFormatException();
406 				//throw new UTFDataFormatException();
407 		}
408 	}
409 	return OUString( pStr, nStrLen );
410 }
411 
412 
413 
414 // XActiveDataSource
415 void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
416 	throw (RuntimeException)
417 {
418 
419 	if( m_input != aStream ) {
420 		m_input = aStream;
421 
422 		Reference < XConnectable > pred( m_input , UNO_QUERY );
423 		setPredecessor( pred );
424 	}
425 
426 	m_bValidStream = m_input.is();
427 }
428 
429 Reference< XInputStream > ODataInputStream::getInputStream(void) throw (RuntimeException)
430 {
431 	return m_input;
432 }
433 
434 
435 
436 // XDataSink
437 void ODataInputStream::setSuccessor( const Reference < XConnectable > &r ) throw (RuntimeException)
438 {
439      /// if the references match, nothing needs to be done
440      if( m_succ != r ) {
441          /// store the reference for later use
442          m_succ = r;
443 
444          if( m_succ.is() ) {
445               /// set this instance as the sink !
446               m_succ->setPredecessor( Reference< XConnectable > (
447 				  SAL_STATIC_CAST( XConnectable * , this ) ) );
448          }
449      }
450 }
451 
452 Reference < XConnectable > ODataInputStream::getSuccessor() throw (RuntimeException)
453 {
454 	return m_succ;
455 }
456 
457 
458 // XDataSource
459 void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
460 	throw (RuntimeException)
461 {
462 	if( r != m_pred ) {
463 		m_pred = r;
464 		if( m_pred.is() ) {
465 			m_pred->setSuccessor( Reference< XConnectable > (
466 				SAL_STATIC_CAST( XConnectable * , this ) ) );
467 		}
468 	}
469 }
470 Reference < XConnectable > ODataInputStream::getPredecessor() throw (RuntimeException)
471 {
472 	return m_pred;
473 }
474 
475 // XServiceInfo
476 OUString ODataInputStream::getImplementationName() throw ()
477 {
478     return ODataInputStream_getImplementationName();
479 }
480 
481 // XServiceInfo
482 sal_Bool ODataInputStream::supportsService(const OUString& ServiceName) throw ()
483 {
484     Sequence< OUString > aSNL = getSupportedServiceNames();
485     const OUString * pArray = aSNL.getConstArray();
486 
487     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
488         if( pArray[i] == ServiceName )
489             return sal_True;
490 
491     return sal_False;
492 }
493 
494 // XServiceInfo
495 Sequence< OUString > ODataInputStream::getSupportedServiceNames(void) throw ()
496 {
497     return ODataInputStream_getSupportedServiceNames();
498 }
499 
500 /***
501 *
502 * registration information
503 *
504 *
505 ****/
506 
507 Reference< XInterface > SAL_CALL ODataInputStream_CreateInstance( const Reference < XComponentContext > & ) throw( Exception)
508 {
509 	ODataInputStream *p = new ODataInputStream;
510 	return Reference< XInterface > ( (OWeakObject * ) p );
511 }
512 
513 OUString ODataInputStream_getImplementationName()
514 {
515 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.DataInputStream" ) );
516 }
517 
518 Sequence<OUString> ODataInputStream_getSupportedServiceNames(void)
519 {
520 	Sequence<OUString> aRet(1);
521 	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.DataInputStream" ) );
522 	return aRet;
523 }
524 
525 
526 
527 
528 class ODataOutputStream :
529 	public WeakImplHelper4 <
530 			 XDataOutputStream,
531 			 XActiveDataSource,
532 			 XConnectable,
533  	         XServiceInfo >
534 {
535 public:
536 	ODataOutputStream()
537 		: m_bValidStream( sal_False )
538 		{
539 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
540 		}
541 	~ODataOutputStream();
542 
543 public: // XOutputStream
544     virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
545 		throw (	NotConnectedException,
546 				BufferSizeExceededException,
547 				RuntimeException);
548     virtual void SAL_CALL flush(void)
549 		throw (	NotConnectedException,
550 				BufferSizeExceededException,
551 				RuntimeException);
552     virtual void SAL_CALL closeOutput(void)
553 		throw (	NotConnectedException,
554 				BufferSizeExceededException,
555 				RuntimeException);
556 
557 public: // XDataOutputStream
558     virtual void SAL_CALL writeBoolean(sal_Bool Value) throw (IOException, RuntimeException);
559     virtual void SAL_CALL writeByte(sal_Int8 Value) throw (IOException, RuntimeException);
560     virtual void SAL_CALL writeChar(sal_Unicode Value) throw (IOException, RuntimeException);
561     virtual void SAL_CALL writeShort(sal_Int16 Value) throw (IOException, RuntimeException);
562     virtual void SAL_CALL writeLong(sal_Int32 Value) throw (IOException, RuntimeException);
563     virtual void SAL_CALL writeHyper(sal_Int64 Value) throw (IOException, RuntimeException);
564     virtual void SAL_CALL writeFloat(float Value) throw (IOException, RuntimeException);
565     virtual void SAL_CALL writeDouble(double Value) throw (IOException, RuntimeException);
566     virtual void SAL_CALL writeUTF(const OUString& Value) throw (IOException, RuntimeException);
567 
568 public: // XActiveDataSource
569     virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
570 		throw (RuntimeException);
571 	virtual Reference < XOutputStream > SAL_CALL getOutputStream(void) throw (RuntimeException);
572 
573 public: // XConnectable
574     virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor)
575 		throw (RuntimeException);
576 	virtual Reference < XConnectable > SAL_CALL getPredecessor(void)
577 		throw (RuntimeException);
578 	virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor)
579 		throw (RuntimeException);
580     virtual Reference < XConnectable > SAL_CALL getSuccessor(void)
581 		throw (RuntimeException);
582 
583 public: // XServiceInfo
584     OUString                     SAL_CALL getImplementationName() throw ();
585     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
586     sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) throw ();
587 
588 protected:
589 	Reference < XConnectable > 	m_succ;
590 	Reference < XConnectable >	m_pred;
591 	Reference<  XOutputStream > m_output;
592 	sal_Bool m_bValidStream;
593 };
594 
595 ODataOutputStream::~ODataOutputStream()
596 {
597 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
598 }
599 
600 
601 // XOutputStream
602 void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
603 	throw (	NotConnectedException,
604 			BufferSizeExceededException,
605 			RuntimeException)
606 {
607 	if( m_bValidStream )
608 	{
609 		m_output->writeBytes( aData );
610 	}
611 	else {
612 		throw NotConnectedException( );
613 	}
614 }
615 
616 void ODataOutputStream::flush(void)
617 	throw (	NotConnectedException,
618 			BufferSizeExceededException,
619 			RuntimeException)
620 {
621 	if( m_bValidStream )
622 	{
623 		m_output->flush();
624 	}
625 	else
626 	{
627 		throw NotConnectedException();
628 	}
629 
630 }
631 
632 
633 void ODataOutputStream::closeOutput(void)
634 	throw (	NotConnectedException,
635 			BufferSizeExceededException,
636 			RuntimeException)
637 {
638 	if( m_bValidStream )
639 	{
640 		m_output->closeOutput();
641 		setOutputStream( Reference< XOutputStream > () );
642 		setPredecessor( Reference < XConnectable >() );
643 		setSuccessor( Reference < XConnectable >() );
644 	}
645 	else
646 	{
647 		throw NotConnectedException();
648 	}
649 }
650 
651 // XDataOutputStream
652 void ODataOutputStream::writeBoolean(sal_Bool Value)
653 	throw (	IOException,
654 			RuntimeException)
655 {
656 	if( Value )
657 	{
658 		writeByte( 1 );
659 	}
660 	else
661 	{
662 		writeByte( 0 );
663 	}
664 }
665 
666 
667 void ODataOutputStream::writeByte(sal_Int8 Value)
668 	throw (	IOException,
669 			RuntimeException)
670 {
671 	Sequence<sal_Int8> aTmp( 1 );
672 	aTmp.getArray()[0] = Value;
673 	writeBytes( aTmp );
674 }
675 
676 void ODataOutputStream::writeChar(sal_Unicode Value)
677 	throw (	IOException,
678 			RuntimeException)
679 {
680 	Sequence<sal_Int8> aTmp( 2 );
681 	sal_Int8 * pBytes = ( sal_Int8 * ) aTmp.getArray();
682 	pBytes[0] = sal_Int8(Value >> 8);
683 	pBytes[1] = sal_Int8(Value);
684 	writeBytes( aTmp );
685 }
686 
687 
688 void ODataOutputStream::writeShort(sal_Int16 Value)
689 	throw (	IOException,
690 			RuntimeException)
691 {
692 	Sequence<sal_Int8> aTmp( 2 );
693 	sal_Int8 * pBytes = aTmp.getArray();
694 	pBytes[0] = sal_Int8(Value >> 8);
695 	pBytes[1] = sal_Int8(Value);
696 	writeBytes( aTmp );
697 }
698 
699 void ODataOutputStream::writeLong(sal_Int32 Value)
700 	throw (	IOException,
701 			RuntimeException)
702 {
703 	Sequence<sal_Int8> aTmp( 4 );
704 	sal_Int8 * pBytes = aTmp.getArray();
705 	pBytes[0] = sal_Int8(Value >> 24);
706 	pBytes[1] = sal_Int8(Value >> 16);
707 	pBytes[2] = sal_Int8(Value >> 8);
708 	pBytes[3] = sal_Int8(Value);
709 	writeBytes( aTmp );
710 }
711 
712 void ODataOutputStream::writeHyper(sal_Int64 Value)
713 	throw (	IOException,
714 			RuntimeException)
715 {
716 	Sequence<sal_Int8> aTmp( 8 );
717 	sal_Int8 * pBytes = aTmp.getArray();
718 	pBytes[0] = sal_Int8(Value >> 56);
719 	pBytes[1] = sal_Int8(Value >> 48);
720 	pBytes[2] = sal_Int8(Value >> 40);
721 	pBytes[3] = sal_Int8(Value >> 32);
722 	pBytes[4] = sal_Int8(Value >> 24);
723 	pBytes[5] = sal_Int8(Value >> 16);
724 	pBytes[6] = sal_Int8(Value >> 8);
725 	pBytes[7] = sal_Int8(Value);
726 	writeBytes( aTmp );
727 }
728 
729 
730 void ODataOutputStream::writeFloat(float Value)
731 	throw (	IOException,
732 			RuntimeException)
733 {
734 	union { float f; sal_uInt32 n; } a;
735 	a.f = Value;
736 	writeLong( a.n );
737 }
738 
739 void ODataOutputStream::writeDouble(double Value)
740 	throw (	IOException,
741 			RuntimeException)
742 {
743 	sal_uInt32 n = 1;
744 	union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
745 	a.d = Value;
746 	if( *(sal_Int8 *)&n == 1 )
747 	{
748 		// little endian
749 		writeLong( a.ad.n2 );
750 		writeLong( a.ad.n1 );
751 	}
752 	else
753 	{
754 		// big endian
755 		writeLong( a.ad.n1 );
756 		writeLong( a.ad.n2 );
757 	}
758 }
759 
760 void ODataOutputStream::writeUTF(const OUString& Value)
761 	throw (	IOException,
762 			RuntimeException)
763 {
764 	sal_Int32 nStrLen = Value.getLength();
765 	const sal_Unicode * pStr = Value.getStr();
766 	sal_Int32 nUTFLen = 0;
767 	sal_Int32 i;
768 
769 	for( i = 0 ; i < nStrLen ; i++ )
770 	{
771 	    sal_uInt16 c = pStr[i];
772 	    if( (c >= 0x0001) && (c <= 0x007F) )
773 		{
774 			nUTFLen++;
775 	    }
776 		else if( c > 0x07FF )
777 		{
778 			nUTFLen += 3;
779 	    }
780 		else
781 		{
782 			nUTFLen += 2;
783 	    }
784 	}
785 
786 
787 	// compatibility mode for older implementations, where it was not possible
788 	// to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
789 	// that are exactly 64k long can not be read by older routines when written
790 	// with these routines and the other way round !!!!!
791 	if( nUTFLen >= 0xFFFF ) {
792 		writeShort( (sal_Int16)-1 );
793 		writeLong( nUTFLen );
794 	}
795 	else {
796 		writeShort( ((sal_uInt16)nUTFLen) );
797 	}
798 	for( i = 0 ; i < nStrLen ; i++ )
799 	{
800 	    sal_uInt16 c = pStr[i];
801 	    if( (c >= 0x0001) && (c <= 0x007F) )
802 		{
803 			writeByte(sal_Int8(c));
804 	    }
805 		else if( c > 0x07FF )
806 		{
807 			writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
808 			writeByte(sal_Int8(0x80 | ((c >>  6) & 0x3F)));
809 			writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
810 			//written += 2;
811 	    }
812 		else
813 		{
814 			writeByte(sal_Int8(0xC0 | ((c >>  6) & 0x1F)));
815 			writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
816 			//written += 1;
817 	    }
818 	}
819 	//written += strlen + 2;
820 }
821 
822 // XActiveDataSource
823 void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
824 	throw (RuntimeException)
825 {
826 	if( m_output != aStream ) {
827 		m_output = aStream;
828 		m_bValidStream = m_output.is();
829 
830 		Reference < XConnectable > succ( m_output , UNO_QUERY );
831 		setSuccessor( succ );
832 	}
833 }
834 
835 Reference< XOutputStream > ODataOutputStream::getOutputStream(void)
836 	throw (RuntimeException)
837 {
838 	return m_output;
839 }
840 
841 
842 
843 
844 // XDataSink
845 void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
846 	throw (RuntimeException)
847 {
848      /// if the references match, nothing needs to be done
849      if( m_succ != r )
850 	 {
851          /// store the reference for later use
852          m_succ = r;
853 
854          if( m_succ.is() )
855 		 {
856               /// set this instance as the sink !
857               m_succ->setPredecessor( Reference < XConnectable > (
858 				  SAL_STATIC_CAST( XConnectable * , this  ) ));
859          }
860      }
861 }
862 Reference < XConnectable > ODataOutputStream::getSuccessor()	throw (RuntimeException)
863 {
864 	return m_succ;
865 }
866 
867 
868 // XDataSource
869 void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )	throw (RuntimeException)
870 {
871 	if( r != m_pred ) {
872 		m_pred = r;
873 		if( m_pred.is() ) {
874 			m_pred->setSuccessor( Reference< XConnectable > (
875 				SAL_STATIC_CAST( XConnectable * , this  ) ));
876 		}
877 	}
878 }
879 Reference < XConnectable > ODataOutputStream::getPredecessor()	throw (RuntimeException)
880 {
881 	return m_pred;
882 }
883 
884 
885 
886 // XServiceInfo
887 OUString ODataOutputStream::getImplementationName() throw ()
888 {
889     return ODataOutputStream_getImplementationName();
890 }
891 
892 // XServiceInfo
893 sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName) throw ()
894 {
895     Sequence< OUString > aSNL = getSupportedServiceNames();
896     const OUString * pArray = aSNL.getConstArray();
897 
898     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
899         if( pArray[i] == ServiceName )
900             return sal_True;
901 
902     return sal_False;
903 }
904 
905 // XServiceInfo
906 Sequence< OUString > ODataOutputStream::getSupportedServiceNames(void) throw ()
907 {
908     return ODataOutputStream_getSupportedServiceNames();
909 }
910 
911 
912 
913 
914 Reference< XInterface > SAL_CALL ODataOutputStream_CreateInstance( const Reference < XComponentContext > & ) throw(Exception)
915 {
916 	ODataOutputStream *p = new ODataOutputStream;
917 	Reference< XInterface > xService = *p;
918 	return xService;
919 }
920 
921 
922 OUString ODataOutputStream_getImplementationName()
923 {
924 	return OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.DataOutputStream" ) );
925 }
926 
927 Sequence<OUString> ODataOutputStream_getSupportedServiceNames(void)
928 {
929 	Sequence<OUString> aRet(1);
930 	aRet.getArray()[0] =  OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.DataOutputStream" ) );
931 	return aRet;
932 }
933 
934 //--------------------------------------
935 struct equalObjectContainer_Impl
936 {
937 	sal_Int32 operator()(const Reference< XInterface > & s1,
938 						 const Reference< XInterface > & s2) const
939   	{
940     	return s1 == s2;
941 	}
942 };
943 
944 //-----------------------------------------------------------------------------
945 struct hashObjectContainer_Impl
946 {
947 	size_t operator()(const Reference< XInterface > & xRef) const
948 	{
949 		return (size_t)xRef.get();
950 	}
951 };
952 
953 typedef hash_map
954 <
955 	Reference< XInterface >,
956 	sal_Int32,
957 	hashObjectContainer_Impl,
958 	equalObjectContainer_Impl
959 > ObjectContainer_Impl;
960 
961 /*---------------------------------------------
962 *
963 *
964 *
965 *
966 *--------------------------------------------*/
967 class OObjectOutputStream :
968 			public ODataOutputStream,
969 			public XObjectOutputStream,
970 			public XMarkableStream
971 {
972 public:
973 	OObjectOutputStream()
974 		: m_nMaxId(0) ,
975 		  m_bValidMarkable(sal_False)
976 		{
977 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
978 		}
979 
980 	~OObjectOutputStream();
981 
982 public:
983         Any             SAL_CALL queryInterface( const Type &type ) throw (::com::sun::star::uno::RuntimeException);
984         void    SAL_CALL acquire() throw()                                       { ODataOutputStream::acquire(); }
985         void    SAL_CALL release() throw()                                       { ODataOutputStream::release(); }
986 
987 public:
988 	// XOutputStream
989     virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
990 		throw (	NotConnectedException,
991 				BufferSizeExceededException,
992 				RuntimeException)
993 		{ ODataOutputStream::writeBytes( aData ); }
994 
995     virtual void SAL_CALL flush(void)
996 		throw (	NotConnectedException,
997 				BufferSizeExceededException,
998 				RuntimeException)
999 		{ ODataOutputStream::flush(); }
1000 
1001     virtual void SAL_CALL closeOutput(void)
1002 		throw (	NotConnectedException,
1003 				BufferSizeExceededException,
1004 				RuntimeException)
1005 		{ ODataOutputStream::closeOutput(); }
1006 
1007 public:
1008 	// XDataOutputStream
1009     virtual void SAL_CALL writeBoolean(sal_Bool Value) throw (IOException, RuntimeException)
1010     			{ ODataOutputStream::writeBoolean( Value ); }
1011     virtual void SAL_CALL writeByte(sal_Int8 Value) throw (IOException, RuntimeException)
1012     			{ ODataOutputStream::writeByte( Value ); }
1013     virtual void SAL_CALL writeChar(sal_Unicode Value) throw (IOException, RuntimeException)
1014     			{ ODataOutputStream::writeChar( Value ); }
1015     virtual void SAL_CALL writeShort(sal_Int16 Value) throw (IOException, RuntimeException)
1016     			{ ODataOutputStream::writeShort( Value ); }
1017     virtual void SAL_CALL writeLong(sal_Int32 Value) throw (IOException, RuntimeException)
1018     			{ ODataOutputStream::writeLong( Value ); }
1019     virtual void SAL_CALL writeHyper(sal_Int64 Value) throw (IOException, RuntimeException)
1020     			{ ODataOutputStream::writeHyper( Value ); }
1021     virtual void SAL_CALL writeFloat(float Value) throw (IOException, RuntimeException)
1022     			{ ODataOutputStream::writeFloat( Value ); }
1023     virtual void SAL_CALL writeDouble(double Value) throw (IOException, RuntimeException)
1024     			{ ODataOutputStream::writeDouble( Value ); }
1025     virtual void SAL_CALL writeUTF(const OUString& Value) throw (IOException, RuntimeException)
1026     			{ ODataOutputStream::writeUTF( Value );}
1027 
1028 	// XObjectOutputStream
1029         virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
1030 
1031 public: // XMarkableStream
1032     virtual sal_Int32 SAL_CALL createMark(void) 				throw (IOException, RuntimeException);
1033     virtual void SAL_CALL deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException);
1034     virtual void SAL_CALL jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException);
1035     virtual void SAL_CALL jumpToFurthest(void) 			throw (IOException, RuntimeException);
1036     virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
1037 		throw (IOException, IllegalArgumentException, RuntimeException);
1038 
1039 public: //XTypeProvider
1040 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL
1041 	        getTypes(  ) throw(::com::sun::star::uno::RuntimeException);
1042 	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
1043             getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);
1044 
1045 public: // XServiceInfo
1046     OUString                   SAL_CALL   getImplementationName() throw ();
1047     Sequence< OUString >       SAL_CALL   getSupportedServiceNames(void) throw ();
1048     sal_Bool                   SAL_CALL   supportsService(const OUString& ServiceName) throw ();
1049 
1050 private:
1051 	void connectToMarkable();
1052 private:
1053 	ObjectContainer_Impl	            m_mapObject;
1054 	sal_Int32							m_nMaxId;
1055 	Reference< XMarkableStream > 		m_rMarkable;
1056 	sal_Bool 							m_bValidMarkable;
1057 };
1058 
1059 OObjectOutputStream::~OObjectOutputStream()
1060 {
1061 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
1062 }
1063 
1064 Any OObjectOutputStream::queryInterface( const Type &aType ) throw (::com::sun::star::uno::RuntimeException)
1065 {
1066 	Any a = ::cppu::queryInterface(
1067 		aType ,
1068 		SAL_STATIC_CAST( XMarkableStream * , this ),
1069 		SAL_STATIC_CAST( XObjectOutputStream * , this ) );
1070 	if( a.hasValue() )
1071 	{
1072 		return a;
1073 	}
1074 
1075 	return ODataOutputStream::queryInterface( aType );
1076 
1077 }
1078 void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
1079 {
1080 
1081 	connectToMarkable();
1082 	sal_Bool bWriteObj = sal_False;
1083 	// create Mark to write length of info
1084 	sal_uInt32 nInfoLenMark = m_rMarkable->createMark();
1085 
1086 	// length of the info data (is later rewritten)
1087 	OObjectOutputStream::writeShort( 0 );
1088 
1089 	// write the object identifier
1090 	if( xPObj.is() )
1091 	{
1092 		Reference< XInterface > rX( xPObj , UNO_QUERY );
1093 
1094 		ObjectContainer_Impl::const_iterator aIt
1095 			= m_mapObject.find( rX );
1096 		if( aIt == m_mapObject.end() )
1097 		{
1098 			// insert new object in hash table
1099 			m_mapObject[ rX ] = ++m_nMaxId;
1100 			ODataOutputStream::writeLong( m_nMaxId );
1101 			ODataOutputStream::writeUTF( xPObj->getServiceName() );
1102 			bWriteObj = sal_True;
1103 		}
1104 		else
1105 		{
1106 			ODataOutputStream::writeLong( (*aIt).second );
1107 			OUString aName;
1108 			ODataOutputStream::writeUTF( aName );
1109 		}
1110 	}
1111 	else
1112 	{
1113 		ODataOutputStream::writeLong( 0 );
1114 		OUString aName;
1115 		ODataOutputStream::writeUTF( aName );
1116 	}
1117 
1118 	sal_uInt32 nObjLenMark = m_rMarkable->createMark();
1119 	ODataOutputStream::writeLong( 0 );
1120 
1121 	sal_Int32 nInfoLen = m_rMarkable->offsetToMark( nInfoLenMark );
1122 	m_rMarkable->jumpToMark( nInfoLenMark );
1123 	// write length of the info data
1124 	ODataOutputStream::writeShort( (sal_Int16)nInfoLen );
1125 	// jump to the end of the stream
1126 	m_rMarkable->jumpToFurthest();
1127 
1128 	if( bWriteObj )
1129 		xPObj->write( Reference< XObjectOutputStream > (
1130 			SAL_STATIC_CAST( XObjectOutputStream * , this ) ) );
1131 
1132 	sal_Int32 nObjLen = m_rMarkable->offsetToMark( nObjLenMark ) -4;
1133 	m_rMarkable->jumpToMark( nObjLenMark );
1134 	// write length of the info data
1135 	ODataOutputStream::writeLong( nObjLen );
1136 	// jump to the end of the stream
1137 	m_rMarkable->jumpToFurthest();
1138 
1139 	m_rMarkable->deleteMark( nObjLenMark );
1140 	m_rMarkable->deleteMark( nInfoLenMark );
1141 }
1142 
1143 
1144 
1145 void OObjectOutputStream::connectToMarkable(void)
1146 {
1147 	if( ! m_bValidMarkable ) {
1148 		if( ! m_bValidStream )
1149 		{
1150 			throw NotConnectedException();
1151 		}
1152 
1153 		// find the markable stream !
1154 		Reference< XInterface > rTry(m_output);
1155 		while( sal_True ) {
1156 			if( ! rTry.is() )
1157 			{
1158 				throw NotConnectedException();
1159 			}
1160 			Reference < XMarkableStream > markable( rTry , UNO_QUERY );
1161 			if( markable.is() )
1162 			{
1163 				m_rMarkable = markable;
1164 				break;
1165 			}
1166 			Reference < XActiveDataSource > source( rTry , UNO_QUERY );
1167 			rTry = source;
1168 		}
1169 		m_bValidMarkable = sal_True;
1170 	}
1171 }
1172 
1173 
1174 sal_Int32 OObjectOutputStream::createMark(void)
1175 	throw (IOException, RuntimeException)
1176 {
1177 	connectToMarkable();	// throws an exception, if a markable is not connected !
1178 
1179 	return m_rMarkable->createMark();
1180 }
1181 
1182 void OObjectOutputStream::deleteMark(sal_Int32 Mark)
1183 	throw (IOException, IllegalArgumentException, RuntimeException)
1184 {
1185 	if( ! m_bValidMarkable )
1186 	{
1187 		throw NotConnectedException();
1188 	}
1189 	m_rMarkable->deleteMark( Mark );
1190 }
1191 
1192 void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
1193 	throw (IOException, IllegalArgumentException, RuntimeException)
1194 {
1195 	if( ! m_bValidMarkable )
1196 	{
1197 		throw NotConnectedException();
1198 	}
1199 	m_rMarkable->jumpToMark( nMark );
1200 }
1201 
1202 
1203 void OObjectOutputStream::jumpToFurthest(void)
1204 	throw (IOException, RuntimeException)
1205 {
1206 	connectToMarkable();
1207 	m_rMarkable->jumpToFurthest();
1208 }
1209 
1210 sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
1211 	throw (IOException, IllegalArgumentException, RuntimeException)
1212 {
1213 	if( ! m_bValidMarkable )
1214 	{
1215 		throw NotConnectedException();
1216 	}
1217 	return m_rMarkable->offsetToMark( nMark );
1218 }
1219 
1220 
1221 
1222 
1223 Reference< XInterface > SAL_CALL OObjectOutputStream_CreateInstance( const Reference < XComponentContext > & )
1224 	throw(Exception)
1225 {
1226 	OObjectOutputStream *p = new OObjectOutputStream;
1227 	return  Reference< XInterface > ( SAL_STATIC_CAST( OWeakObject * , p ) );
1228 }
1229 
1230 OUString OObjectOutputStream_getImplementationName()
1231 {
1232 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.ObjectOutputStream" ) );
1233 }
1234 
1235 Sequence<OUString> OObjectOutputStream_getSupportedServiceNames(void)
1236 {
1237 	Sequence<OUString> aRet(1);
1238 	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.ObjectOutputStream" ) );
1239 	return aRet;
1240 }
1241 
1242 Sequence< Type > SAL_CALL OObjectOutputStream::getTypes(void) throw( RuntimeException )
1243 {
1244 	static OTypeCollection *pCollection = 0;
1245 	if( ! pCollection )
1246 	{
1247 		MutexGuard guard( Mutex::getGlobalMutex() );
1248 		if( ! pCollection )
1249 		{
1250 			static OTypeCollection collection(
1251 				getCppuType( (Reference< XMarkableStream > * ) 0 ),
1252 				getCppuType( (Reference< XObjectOutputStream > * ) 0 ),
1253 				ODataOutputStream::getTypes() );
1254 			pCollection = &collection;
1255 		}
1256 	}
1257 	return (*pCollection).getTypes();
1258 }
1259 
1260 Sequence< sal_Int8 > SAL_CALL OObjectOutputStream::getImplementationId(  ) throw( RuntimeException)
1261 {
1262 	static OImplementationId *pId = 0;
1263 	if( ! pId )
1264 	{
1265 		MutexGuard guard( Mutex::getGlobalMutex() );
1266 		if( ! pId )
1267 		{
1268 			static OImplementationId id( sal_False );
1269 			pId = &id;
1270 		}
1271 	}
1272 	return (*pId).getImplementationId();
1273 }
1274 
1275 
1276 // XServiceInfo
1277 OUString OObjectOutputStream::getImplementationName() throw ()
1278 {
1279     return ODataInputStream_getImplementationName();
1280 }
1281 
1282 // XServiceInfo
1283 sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName) throw ()
1284 {
1285     Sequence< OUString > aSNL = getSupportedServiceNames();
1286     const OUString * pArray = aSNL.getConstArray();
1287 
1288     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1289         if( pArray[i] == ServiceName )
1290             return sal_True;
1291 
1292     return sal_False;
1293 }
1294 
1295 // XServiceInfo
1296 Sequence< OUString > OObjectOutputStream::getSupportedServiceNames(void) throw ()
1297 {
1298 	return OObjectOutputStream_getSupportedServiceNames();
1299 }
1300 
1301 
1302 
1303 
1304 
1305 class OObjectInputStream :
1306 	public ODataInputStream,
1307 	public XObjectInputStream,
1308 	public XMarkableStream
1309 {
1310 public:
1311 	OObjectInputStream( const Reference < XComponentContext > &r)
1312 		: m_rSMgr( r->getServiceManager() )
1313 		, m_rCxt( r )
1314 		, m_bValidMarkable(sal_False)
1315 		{
1316 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
1317 		}
1318 	~OObjectInputStream();
1319 
1320 public:
1321         Any             SAL_CALL queryInterface( const Type &type ) throw();
1322         void    SAL_CALL acquire() throw()                                       { ODataInputStream::acquire(); }
1323         void    SAL_CALL release() throw()                                       { ODataInputStream::release(); }
1324 
1325 public: // XInputStream
1326     virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
1327 		throw (	NotConnectedException,
1328 				BufferSizeExceededException,
1329 				RuntimeException)
1330 		{ return ODataInputStream::readBytes( aData , nBytesToRead ); }
1331 
1332     virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
1333 		throw (	NotConnectedException,
1334 				BufferSizeExceededException,
1335 				RuntimeException)
1336 		{ return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }
1337 
1338     virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
1339 		throw (	NotConnectedException,
1340 				BufferSizeExceededException,
1341 				RuntimeException)
1342 		{ ODataInputStream::skipBytes( nBytesToSkip ); }
1343 
1344     virtual sal_Int32 SAL_CALL available(void)
1345 		throw (	NotConnectedException,
1346 				RuntimeException)
1347 		{ return ODataInputStream::available(); }
1348 
1349     virtual void SAL_CALL closeInput(void)
1350 		throw (	NotConnectedException,
1351 				RuntimeException)
1352 		{ ODataInputStream::closeInput(); }
1353 
1354 public: // XDataInputStream
1355     virtual sal_Int8 SAL_CALL readBoolean(void) throw (IOException, RuntimeException)
1356     			{ return ODataInputStream::readBoolean(); }
1357     virtual sal_Int8 SAL_CALL readByte(void) throw (IOException, RuntimeException)
1358     			{ return ODataInputStream::readByte(); }
1359     virtual sal_Unicode SAL_CALL readChar(void) throw (IOException, RuntimeException)
1360     			{ return ODataInputStream::readChar(); }
1361     virtual sal_Int16 SAL_CALL readShort(void) throw (IOException, RuntimeException)
1362     			{ return ODataInputStream::readShort(); }
1363     virtual sal_Int32 SAL_CALL readLong(void) throw (IOException, RuntimeException)
1364     			{ return ODataInputStream::readLong(); }
1365     virtual sal_Int64 SAL_CALL readHyper(void) throw (IOException, RuntimeException)
1366     			{ return ODataInputStream::readHyper(); }
1367     virtual float SAL_CALL readFloat(void) throw (IOException, RuntimeException)
1368     			{ return ODataInputStream::readFloat(); }
1369     virtual double SAL_CALL readDouble(void) throw (IOException, RuntimeException)
1370 		{ return ODataInputStream::readDouble(); }
1371     virtual OUString SAL_CALL readUTF(void) throw (IOException, RuntimeException)
1372     			{ return ODataInputStream::readUTF(); }
1373 
1374 public: // XObjectInputStream
1375         virtual Reference< XPersistObject > SAL_CALL readObject( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
1376 
1377 public: // XMarkableStream
1378     virtual sal_Int32 SAL_CALL createMark(void)
1379 		throw (IOException, RuntimeException);
1380 	virtual void SAL_CALL deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException);
1381 	virtual void SAL_CALL jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException);
1382 	virtual void SAL_CALL jumpToFurthest(void) 			throw (IOException, RuntimeException);
1383 	virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
1384 		throw (IOException, IllegalArgumentException, RuntimeException);
1385 
1386 public: //XTypeProvider
1387 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL
1388 	        getTypes(  ) throw(::com::sun::star::uno::RuntimeException);
1389 	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
1390             getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);
1391 
1392 public: // XServiceInfo
1393     OUString                     SAL_CALL getImplementationName() throw ();
1394 	Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
1395     sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) throw ();
1396 
1397 private:
1398 	void connectToMarkable();
1399 private:
1400 	Reference < XMultiComponentFactory > m_rSMgr;
1401 	Reference < XComponentContext >     m_rCxt;
1402 	sal_Bool 				m_bValidMarkable;
1403 	Reference < XMarkableStream > m_rMarkable;
1404 	vector < Reference<  XPersistObject > > m_aPersistVector;
1405 
1406 };
1407 
1408 OObjectInputStream::~OObjectInputStream()
1409 {
1410 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
1411 }
1412 
1413 Any OObjectInputStream::queryInterface( const Type &aType ) throw ()
1414 {
1415 	Any a = ::cppu::queryInterface(
1416 		aType ,
1417 		SAL_STATIC_CAST( XMarkableStream * , this ),
1418 		SAL_STATIC_CAST( XObjectInputStream * , this ) );
1419 	if( a.hasValue() )
1420 	{
1421 		return a;
1422 	}
1423 
1424 	return ODataInputStream::queryInterface( aType );
1425 
1426 }
1427 
1428 Reference< XPersistObject >  OObjectInputStream::readObject() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
1429 {
1430 	// check if chain contains a XMarkableStream
1431 	connectToMarkable();
1432 
1433 	Reference< XPersistObject > xLoadedObj;
1434 
1435 	// create Mark to skip newer versions
1436 	sal_uInt32 nMark = m_rMarkable->createMark();
1437 	// length of the data
1438 	sal_Int32 nLen = (sal_uInt16) ODataInputStream::readShort();
1439 	if( nLen < 0xc )
1440 	{
1441 		throw WrongFormatException();
1442 	}
1443 
1444 	// read the object identifier
1445 	sal_uInt32 nId = readLong();
1446 
1447 	// the name of the persist model
1448 	// MM ???
1449 	OUString aName = readUTF();
1450 
1451 	// Read the length of the object
1452 	sal_Int32 nObjLen = readLong();
1453 	if( ( 0 == nId && 0 != nObjLen ) )
1454 	{
1455 		throw WrongFormatException();
1456 	}
1457 
1458 	// skip data of new version
1459 	skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );
1460 
1461 	sal_Bool bLoadSuccesfull = sal_True;
1462 	if( nId )
1463 	{
1464 		if( aName.getLength() )
1465 		{
1466 			// load the object
1467 			Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
1468 			xLoadedObj = Reference< XPersistObject >( x, UNO_QUERY );
1469 			if( xLoadedObj.is() )
1470 			{
1471 				sal_uInt32 nSize = m_aPersistVector.size();
1472 				if( nSize <= nId )
1473 				{
1474 					// grow to the right size
1475 					Reference< XPersistObject > xEmpty;
1476 					m_aPersistVector.insert( m_aPersistVector.end(), (long)(nId - nSize + 1), xEmpty );
1477 				}
1478 
1479 				m_aPersistVector[nId] = xLoadedObj;
1480 				xLoadedObj->read( Reference< XObjectInputStream >(
1481 					SAL_STATIC_CAST( XObjectInputStream *, this ) ) );
1482 			}
1483 			else
1484 			{
1485 				// no service with this name could be instantiated
1486 				bLoadSuccesfull = sal_False;
1487 			}
1488 		}
1489 		else {
1490 			if( m_aPersistVector.size() < nId )
1491 			{
1492 				// id unknown, load failure !
1493 				bLoadSuccesfull = sal_False;
1494 			}
1495 			else
1496 			{
1497 				// Object has alread been read,
1498 				xLoadedObj = m_aPersistVector[nId];
1499 			}
1500 		}
1501 	}
1502 
1503 	// skip to the position behind the object
1504 	skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
1505 	m_rMarkable->deleteMark( nMark );
1506 
1507 	if( ! bLoadSuccesfull )
1508 	{
1509 		throw WrongFormatException();
1510 	}
1511 	return xLoadedObj;
1512 }
1513 
1514 
1515 void OObjectInputStream::connectToMarkable()
1516 {
1517 	if( ! m_bValidMarkable ) {
1518 		if( ! m_bValidStream )
1519 		{
1520 			throw NotConnectedException( );
1521 		}
1522 
1523 		// find the markable stream !
1524 		Reference< XInterface > rTry(m_input);
1525 		while( sal_True ) {
1526 			if( ! rTry.is() )
1527 			{
1528 				throw NotConnectedException( );
1529 			}
1530 			Reference<  XMarkableStream > markable( rTry , UNO_QUERY );
1531 			if( markable.is() )
1532 			{
1533 				m_rMarkable = markable;
1534 				break;
1535 			}
1536 			Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
1537 			rTry = sink;
1538 		}
1539 		m_bValidMarkable = sal_True;
1540 	}
1541 }
1542 
1543 sal_Int32 OObjectInputStream::createMark(void) 				throw (IOException, RuntimeException)
1544 {
1545 	connectToMarkable();	// throws an exception, if a markable is not connected !
1546 
1547 	return m_rMarkable->createMark();
1548 }
1549 
1550 void OObjectInputStream::deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException)
1551 {
1552 	if( ! m_bValidMarkable )
1553 	{
1554 		throw NotConnectedException();
1555 	}
1556 	m_rMarkable->deleteMark( Mark );
1557 }
1558 
1559 void OObjectInputStream::jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException)
1560 {
1561 	if( ! m_bValidMarkable )
1562 	{
1563 		throw NotConnectedException();
1564 	}
1565 	m_rMarkable->jumpToMark( nMark );
1566 }
1567 void OObjectInputStream::jumpToFurthest(void) 			throw (IOException, RuntimeException)
1568 {
1569 	connectToMarkable();
1570 	m_rMarkable->jumpToFurthest();
1571 }
1572 
1573 sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
1574 	throw (IOException, IllegalArgumentException, RuntimeException)
1575 {
1576 	if( ! m_bValidMarkable )
1577 	{
1578 		throw NotConnectedException();
1579 	}
1580 	return m_rMarkable->offsetToMark( nMark );
1581 }
1582 
1583 
1584 Sequence< Type > SAL_CALL OObjectInputStream::getTypes(void) throw( RuntimeException )
1585 {
1586 	static OTypeCollection *pCollection = 0;
1587 	if( ! pCollection )
1588 	{
1589 		MutexGuard guard( Mutex::getGlobalMutex() );
1590 		if( ! pCollection )
1591 		{
1592 			static OTypeCollection collection(
1593 				getCppuType( (Reference< XMarkableStream > * ) 0 ),
1594 				getCppuType( (Reference< XObjectInputStream > * ) 0 ),
1595 				ODataInputStream::getTypes() );
1596 			pCollection = &collection;
1597 		}
1598 	}
1599 	return (*pCollection).getTypes();
1600 }
1601 
1602 Sequence< sal_Int8 > SAL_CALL OObjectInputStream::getImplementationId(  ) throw( RuntimeException)
1603 {
1604 	static OImplementationId *pId = 0;
1605 	if( ! pId )
1606 	{
1607 		MutexGuard guard( Mutex::getGlobalMutex() );
1608 		if( ! pId )
1609 		{
1610 			static OImplementationId id( sal_False );
1611 			pId = &id;
1612 		}
1613 	}
1614 	return (*pId).getImplementationId();
1615 }
1616 
1617 
1618 // XServiceInfo
1619 OUString OObjectInputStream::getImplementationName() throw ()
1620 {
1621     return OObjectInputStream_getImplementationName();
1622 }
1623 
1624 // XServiceInfo
1625 sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName) throw ()
1626 {
1627     Sequence< OUString > aSNL = getSupportedServiceNames();
1628     const OUString * pArray = aSNL.getConstArray();
1629 
1630     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1631         if( pArray[i] == ServiceName )
1632             return sal_True;
1633 
1634     return sal_False;
1635 }
1636 
1637 // XServiceInfo
1638 Sequence< OUString > OObjectInputStream::getSupportedServiceNames(void) throw ()
1639 {
1640     return OObjectInputStream_getSupportedServiceNames();
1641 }
1642 
1643 
1644 
1645 
1646 Reference< XInterface > SAL_CALL OObjectInputStream_CreateInstance( const Reference < XComponentContext > & rCtx ) throw(Exception)
1647 {
1648 	OObjectInputStream *p = new OObjectInputStream( rCtx );
1649 	return Reference< XInterface> ( SAL_STATIC_CAST( OWeakObject *, p ) );
1650 }
1651 
1652 OUString OObjectInputStream_getImplementationName()
1653 {
1654 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.ObjectInputStream" ) );
1655 }
1656 
1657 Sequence<OUString> OObjectInputStream_getSupportedServiceNames(void)
1658 {
1659 	Sequence<OUString> aRet(1);
1660 	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.ObjectInputStream" ) );
1661 	return aRet;
1662 }
1663 
1664 }
1665