xref: /trunk/main/io/source/stm/odata.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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