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