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