1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucb.hxx"
30 
31 /**************************************************************************
32 								TODO
33  **************************************************************************
34 
35  - remove root storage access workaround
36 
37  *************************************************************************/
38 
39 #include "com/sun/star/lang/DisposedException.hpp"
40 #include "com/sun/star/reflection/XProxyFactory.hpp"
41 
42 #include "tdoc_uri.hxx"
43 
44 #include "tdoc_stgelems.hxx"
45 
46 using namespace com::sun::star;
47 using namespace tdoc_ucp;
48 
49 //=========================================================================
50 //=========================================================================
51 //
52 // ParentStorageHolder Implementation.
53 //
54 //=========================================================================
55 //=========================================================================
56 
57 ParentStorageHolder::ParentStorageHolder(
58             const uno::Reference< embed::XStorage > & xParentStorage,
59             const rtl::OUString & rUri )
60 : m_xParentStorage( xParentStorage ),
61   m_bParentIsRootStorage( false )
62 {
63     Uri aUri( rUri );
64     if ( aUri.isDocument() )
65         m_bParentIsRootStorage = true;
66 }
67 
68 //=========================================================================
69 //=========================================================================
70 //
71 // Storage Implementation.
72 //
73 //=========================================================================
74 //=========================================================================
75 
76 Storage::Storage( const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
77                   const rtl::Reference< StorageElementFactory > & xFactory,
78                   const rtl::OUString & rUri,
79                   const uno::Reference< embed::XStorage > & xParentStorage,
80                   const uno::Reference< embed::XStorage > & xStorageToWrap )
81 : ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
82   m_xFactory( xFactory ),
83   m_xWrappedStorage( xStorageToWrap ),
84   m_xWrappedTransObj( xStorageToWrap, uno::UNO_QUERY ), // optional interface
85   m_xWrappedComponent( xStorageToWrap, uno::UNO_QUERY ),
86   m_xWrappedTypeProv( xStorageToWrap, uno::UNO_QUERY ),
87   m_bIsDocumentStorage( Uri( rUri ).isDocument() )
88 {
89     OSL_ENSURE( m_xWrappedStorage.is(),
90                 "Storage::Storage: No storage to wrap!" );
91 
92     OSL_ENSURE( m_xWrappedComponent.is(),
93                 "Storage::Storage: No component to wrap!" );
94 
95     OSL_ENSURE( m_xWrappedTypeProv.is(),
96                 "Storage::Storage: No Type Provider!" );
97 
98     // Use proxy factory service to create aggregatable proxy.
99     try
100     {
101         uno::Reference< reflection::XProxyFactory > xProxyFac(
102             xSMgr->createInstance(
103                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
104                     "com.sun.star.reflection.ProxyFactory" ) ) ),
105             uno::UNO_QUERY );
106         if ( xProxyFac.is() )
107         {
108             m_xAggProxy = xProxyFac->createProxy( m_xWrappedStorage );
109         }
110     }
111     catch ( uno::Exception const & )
112     {
113         OSL_ENSURE( false, "Storage::Storage: Caught exception!" );
114     }
115 
116     OSL_ENSURE( m_xAggProxy.is(),
117                 "Storage::Storage: Wrapped storage cannot be aggregated!" );
118 
119     if ( m_xAggProxy.is() )
120     {
121         osl_incrementInterlockedCount( &m_refCount );
122 		{
123 			// Solaris compiler problem:
124 			// Extra block to enforce destruction of temporary object created
125             // in next statement _before_ osl_decrementInterlockedCount is
126             // called.  Otherwise 'this' will destroy itself even before ctor
127             // is completed (See impl. of XInterface::release())!
128 
129         	m_xAggProxy->setDelegator(
130 				static_cast< cppu::OWeakObject * >( this ) );
131 		}
132         osl_decrementInterlockedCount( &m_refCount );
133     }
134 }
135 
136 //=========================================================================
137 // virtual
138 Storage::~Storage()
139 {
140     if ( m_xAggProxy.is() )
141         m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
142 
143     // Never dispose a document storage. Not owner!
144     if ( !isDocumentStorage() )
145     {
146         if ( m_xWrappedComponent.is() )
147         {
148             // "Auto-dispose"...
149             try
150             {
151                 m_xWrappedComponent->dispose();
152             }
153             catch ( lang::DisposedException const & )
154             {
155                 // might happen.
156             }
157             catch ( ... )
158             {
159                 OSL_ENSURE( false, "Storage::~Storage - Caught exception!" );
160             }
161         }
162     }
163 }
164 
165 //=========================================================================
166 //
167 // uno::XInterface
168 //
169 //=========================================================================
170 
171 // virtual
172 uno::Any SAL_CALL Storage::queryInterface( const uno::Type& aType )
173     throw ( uno::RuntimeException )
174 {
175     // First, try to use interfaces implemented by myself and base class(es)
176     uno::Any aRet = StorageUNOBase::queryInterface( aType );
177 
178     if ( aRet.hasValue() )
179         return aRet;
180 
181     // Try to use requested interface from aggregated storage
182     return m_xAggProxy->queryAggregation( aType );
183 }
184 
185 //=========================================================================
186 // virtual
187 void SAL_CALL Storage::acquire()
188     throw ()
189 {
190     osl_incrementInterlockedCount( &m_refCount );
191 }
192 
193 //=========================================================================
194 // virtual
195 void SAL_CALL Storage::release()
196     throw ()
197 {
198     if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
199     {
200         m_xFactory->releaseElement( this );
201         delete this;
202     }
203 }
204 
205 //=========================================================================
206 //
207 // lang::XTypeProvider
208 //
209 //=========================================================================
210 
211 // virtual
212 uno::Sequence< uno::Type > SAL_CALL Storage::getTypes()
213     throw ( uno::RuntimeException )
214 {
215     return m_xWrappedTypeProv->getTypes();
216 }
217 
218 //=========================================================================
219 // virtual
220 uno::Sequence< sal_Int8 > SAL_CALL Storage::getImplementationId()
221     throw ( uno::RuntimeException )
222 {
223     return m_xWrappedTypeProv->getImplementationId();
224 }
225 
226 //=========================================================================
227 //
228 // lang::XComponent (base of embed::XStorage)
229 //
230 //=========================================================================
231 // virtual
232 void SAL_CALL Storage::dispose()
233     throw ( uno::RuntimeException )
234 {
235     m_xWrappedStorage->dispose();
236 }
237 
238 //=========================================================================
239 // virtual
240 void SAL_CALL Storage::addEventListener(
241         const uno::Reference< lang::XEventListener >& xListener )
242     throw ( uno::RuntimeException )
243 {
244     m_xWrappedStorage->addEventListener( xListener );
245 }
246 //=========================================================================
247 // virtual
248 void SAL_CALL Storage::removeEventListener(
249         const uno::Reference< lang::XEventListener >& aListener )
250     throw (uno::RuntimeException)
251 {
252     m_xWrappedStorage->removeEventListener( aListener );
253 }
254 
255 //=========================================================================
256 //
257 // container::XElementAccess (base of container::XNameAccess)
258 //
259 //=========================================================================
260 
261 // virtual
262 uno::Type SAL_CALL Storage::getElementType()
263     throw ( uno::RuntimeException )
264 {
265     return m_xWrappedStorage->getElementType();
266 }
267 
268 //=========================================================================
269 // virtual
270 ::sal_Bool SAL_CALL Storage::hasElements()
271     throw ( uno::RuntimeException )
272 {
273     return m_xWrappedStorage->hasElements();
274 }
275 
276 //=========================================================================
277 //
278 // container::XNameAccess (base of embed::XStorage)
279 //
280 //=========================================================================
281 
282 // virtual
283 uno::Any SAL_CALL Storage::getByName( const ::rtl::OUString& aName )
284     throw ( container::NoSuchElementException,
285             lang::WrappedTargetException,
286             uno::RuntimeException )
287 {
288     return m_xWrappedStorage->getByName( aName );
289 }
290 
291 //=========================================================================
292 // virtual
293 uno::Sequence< ::rtl::OUString > SAL_CALL Storage::getElementNames()
294     throw ( uno::RuntimeException )
295 {
296     return m_xWrappedStorage->getElementNames();
297 }
298 
299 //=========================================================================
300 // virtual
301 ::sal_Bool SAL_CALL Storage::hasByName( const ::rtl::OUString& aName )
302     throw ( uno::RuntimeException )
303 {
304     return m_xWrappedStorage->hasByName( aName );
305 }
306 
307 //=========================================================================
308 //
309 // embed::XStorage
310 //
311 //=========================================================================
312 
313 // virtual
314 void SAL_CALL Storage::copyToStorage(
315         const uno::Reference< embed::XStorage >& xDest )
316     throw ( embed::InvalidStorageException,
317             lang::IllegalArgumentException,
318             io::IOException,
319             embed::StorageWrappedTargetException,
320             uno::RuntimeException )
321 {
322     m_xWrappedStorage->copyToStorage( xDest );
323 }
324 
325 //=========================================================================
326 // virtual
327 uno::Reference< io::XStream > SAL_CALL Storage::openStreamElement(
328         const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode )
329     throw ( embed::InvalidStorageException,
330             lang::IllegalArgumentException,
331             packages::WrongPasswordException,
332             io::IOException,
333             embed::StorageWrappedTargetException,
334             uno::RuntimeException )
335 {
336     return m_xWrappedStorage->openStreamElement( aStreamName, nOpenMode );
337 }
338 
339 //=========================================================================
340 // virtual
341 uno::Reference< io::XStream > SAL_CALL Storage::openEncryptedStreamElement(
342         const ::rtl::OUString& aStreamName,
343         sal_Int32 nOpenMode,
344         const ::rtl::OUString& aPassword )
345     throw ( embed::InvalidStorageException,
346             lang::IllegalArgumentException,
347             packages::NoEncryptionException,
348             packages::WrongPasswordException,
349             io::IOException,
350             embed::StorageWrappedTargetException,
351             uno::RuntimeException )
352 {
353     return m_xWrappedStorage->openEncryptedStreamElement(
354         aStreamName, nOpenMode, aPassword );
355 }
356 
357 //=========================================================================
358 // virtual
359 uno::Reference< embed::XStorage > SAL_CALL Storage::openStorageElement(
360         const ::rtl::OUString& aStorName, sal_Int32 nOpenMode )
361     throw ( embed::InvalidStorageException,
362             lang::IllegalArgumentException,
363             io::IOException,
364             embed::StorageWrappedTargetException,
365             uno::RuntimeException )
366 {
367     return m_xWrappedStorage->openStorageElement( aStorName, nOpenMode );
368 }
369 
370 //=========================================================================
371 // virtual
372 uno::Reference< io::XStream > SAL_CALL Storage::cloneStreamElement(
373         const ::rtl::OUString& aStreamName )
374     throw ( embed::InvalidStorageException,
375             lang::IllegalArgumentException,
376             packages::WrongPasswordException,
377             io::IOException,
378             embed::StorageWrappedTargetException,
379             uno::RuntimeException )
380 {
381     return m_xWrappedStorage->cloneStreamElement( aStreamName );
382 }
383 
384 //=========================================================================
385 // virtual
386 uno::Reference< io::XStream > SAL_CALL Storage::cloneEncryptedStreamElement(
387         const ::rtl::OUString& aStreamName,
388         const ::rtl::OUString& aPassword )
389     throw ( embed::InvalidStorageException,
390             lang::IllegalArgumentException,
391             packages::NoEncryptionException,
392             packages::WrongPasswordException,
393             io::IOException,
394             embed::StorageWrappedTargetException,
395             uno::RuntimeException )
396 {
397     return m_xWrappedStorage->cloneEncryptedStreamElement( aStreamName,
398                                                            aPassword );
399 }
400 
401 //=========================================================================
402 // virtual
403 void SAL_CALL Storage::copyLastCommitTo(
404         const uno::Reference< embed::XStorage >& xTargetStorage )
405     throw ( embed::InvalidStorageException,
406             lang::IllegalArgumentException,
407             io::IOException,
408             embed::StorageWrappedTargetException,
409             uno::RuntimeException)
410 {
411     m_xWrappedStorage->copyLastCommitTo( xTargetStorage );
412 }
413 
414 //=========================================================================
415 // virtual
416 void SAL_CALL Storage::copyStorageElementLastCommitTo(
417         const ::rtl::OUString& aStorName,
418         const uno::Reference< embed::XStorage >& xTargetStorage )
419     throw ( embed::InvalidStorageException,
420             lang::IllegalArgumentException,
421             io::IOException,
422             embed::StorageWrappedTargetException,
423             uno::RuntimeException)
424 {
425     m_xWrappedStorage->copyStorageElementLastCommitTo( aStorName, xTargetStorage );
426 }
427 
428 //=========================================================================
429 // virtual
430 sal_Bool SAL_CALL Storage::isStreamElement(
431         const ::rtl::OUString& aElementName )
432     throw ( container::NoSuchElementException,
433             lang::IllegalArgumentException,
434             embed::InvalidStorageException,
435             uno::RuntimeException )
436 {
437     return m_xWrappedStorage->isStreamElement( aElementName );
438 }
439 
440 //=========================================================================
441 // virtual
442 sal_Bool SAL_CALL Storage::isStorageElement(
443         const ::rtl::OUString& aElementName )
444     throw ( container::NoSuchElementException,
445             lang::IllegalArgumentException,
446             embed::InvalidStorageException,
447             uno::RuntimeException )
448 {
449     return m_xWrappedStorage->isStorageElement( aElementName );
450 }
451 
452 //=========================================================================
453 // virtual
454 void SAL_CALL Storage::removeElement( const ::rtl::OUString& aElementName )
455     throw ( embed::InvalidStorageException,
456             lang::IllegalArgumentException,
457             container::NoSuchElementException,
458             io::IOException,
459             embed::StorageWrappedTargetException,
460             uno::RuntimeException )
461 {
462     m_xWrappedStorage->removeElement( aElementName );
463 }
464 
465 //=========================================================================
466 // virtual
467 void SAL_CALL Storage::renameElement( const ::rtl::OUString& aEleName,
468                                       const ::rtl::OUString& aNewName )
469     throw ( embed::InvalidStorageException,
470             lang::IllegalArgumentException,
471             container::NoSuchElementException,
472             container::ElementExistException,
473             io::IOException,
474             embed::StorageWrappedTargetException,
475             uno::RuntimeException )
476 {
477     m_xWrappedStorage->renameElement( aEleName, aNewName );
478 }
479 
480 //=========================================================================
481 // virtual
482 void SAL_CALL Storage::copyElementTo(
483         const ::rtl::OUString& aElementName,
484         const uno::Reference< embed::XStorage >& xDest,
485         const ::rtl::OUString& aNewName )
486     throw ( embed::InvalidStorageException,
487             lang::IllegalArgumentException,
488             container::NoSuchElementException,
489             container::ElementExistException,
490             io::IOException,
491             embed::StorageWrappedTargetException,
492             uno::RuntimeException )
493 {
494     m_xWrappedStorage->copyElementTo( aElementName, xDest, aNewName );
495 }
496 
497 //=========================================================================
498 // virtual
499 void SAL_CALL Storage::moveElementTo(
500         const ::rtl::OUString& aElementName,
501         const uno::Reference< embed::XStorage >& xDest,
502         const ::rtl::OUString& rNewName )
503     throw ( embed::InvalidStorageException,
504             lang::IllegalArgumentException,
505             container::NoSuchElementException,
506             container::ElementExistException,
507             io::IOException,
508             embed::StorageWrappedTargetException,
509             uno::RuntimeException )
510 {
511     m_xWrappedStorage->moveElementTo( aElementName, xDest, rNewName );
512 }
513 
514 //=========================================================================
515 //
516 // embed::XTransactedObject
517 //
518 //=========================================================================
519 
520 // virtual
521 void SAL_CALL Storage::commit()
522     throw ( io::IOException,
523             lang::WrappedTargetException,
524             uno::RuntimeException )
525 {
526     // Never commit a root storage (-> has no parent)!
527     // Would lead in writing the whole document to disk.
528 
529     uno::Reference< embed::XStorage > xParentStorage = getParentStorage();
530     if ( xParentStorage.is() )
531     {
532         OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" );
533 
534         if ( m_xWrappedTransObj.is() )
535         {
536             m_xWrappedTransObj->commit();
537 
538             if ( !isParentARootStorage() )
539             {
540                 uno::Reference< embed::XTransactedObject > xParentTA(
541                     xParentStorage, uno::UNO_QUERY );
542                 OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" );
543 
544                 if ( xParentTA.is() )
545                     xParentTA->commit();
546             }
547         }
548     }
549 }
550 
551 //=========================================================================
552 // virtual
553 void SAL_CALL Storage::revert()
554     throw ( io::IOException,
555             lang::WrappedTargetException,
556             uno::RuntimeException )
557 {
558     uno::Reference< embed::XStorage > xParentStorage = getParentStorage();
559     if ( xParentStorage.is() )
560     {
561         OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" );
562 
563         if ( m_xWrappedTransObj.is() )
564         {
565             m_xWrappedTransObj->revert();
566 
567             if ( !isParentARootStorage() )
568             {
569                 uno::Reference< embed::XTransactedObject > xParentTA(
570                     xParentStorage, uno::UNO_QUERY );
571                 OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" );
572 
573                 if ( xParentTA.is() )
574                     xParentTA->revert();
575             }
576         }
577     }
578 }
579 
580 //=========================================================================
581 //=========================================================================
582 //
583 // OutputStream Implementation.
584 //
585 //=========================================================================
586 //=========================================================================
587 
588 OutputStream::OutputStream(
589             const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
590             const rtl::OUString & rUri,
591             const uno::Reference< embed::XStorage >  & xParentStorage,
592             const uno::Reference< io::XOutputStream > & xStreamToWrap )
593 : ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
594   m_xWrappedStream( xStreamToWrap ),
595   m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ),
596   m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY )
597 {
598     OSL_ENSURE( m_xWrappedStream.is(),
599                 "OutputStream::OutputStream: No stream to wrap!" );
600 
601     OSL_ENSURE( m_xWrappedComponent.is(),
602                 "OutputStream::OutputStream: No component to wrap!" );
603 
604     OSL_ENSURE( m_xWrappedTypeProv.is(),
605                 "OutputStream::OutputStream: No Type Provider!" );
606 
607     // Use proxy factory service to create aggregatable proxy.
608     try
609     {
610         uno::Reference< reflection::XProxyFactory > xProxyFac(
611             xSMgr->createInstance(
612                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
613                     "com.sun.star.reflection.ProxyFactory" ) ) ),
614             uno::UNO_QUERY );
615         if ( xProxyFac.is() )
616         {
617             m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream );
618         }
619     }
620     catch ( uno::Exception const & )
621     {
622         OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" );
623     }
624 
625     OSL_ENSURE( m_xAggProxy.is(),
626             "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" );
627 
628     if ( m_xAggProxy.is() )
629     {
630         osl_incrementInterlockedCount( &m_refCount );
631 		{
632 			// Solaris compiler problem:
633 			// Extra block to enforce destruction of temporary object created
634             // in next statement _before_ osl_decrementInterlockedCount is
635             // called.  Otherwise 'this' will destroy itself even before ctor
636             // is completed (See impl. of XInterface::release())!
637 
638 	        m_xAggProxy->setDelegator(
639 				static_cast< cppu::OWeakObject * >( this ) );
640 		}
641         osl_decrementInterlockedCount( &m_refCount );
642     }
643 }
644 
645 //=========================================================================
646 // virtual
647 OutputStream::~OutputStream()
648 {
649     if ( m_xAggProxy.is() )
650         m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
651 }
652 
653 //=========================================================================
654 //
655 // uno::XInterface
656 //
657 //=========================================================================
658 
659 // virtual
660 uno::Any SAL_CALL OutputStream::queryInterface( const uno::Type& aType )
661     throw ( uno::RuntimeException )
662 {
663     uno::Any aRet = OutputStreamUNOBase::queryInterface( aType );
664 
665     if ( aRet.hasValue() )
666         return aRet;
667 
668     if ( m_xAggProxy.is() )
669         return m_xAggProxy->queryAggregation( aType );
670     else
671         return uno::Any();
672 }
673 
674 //=========================================================================
675 //
676 // lang::XTypeProvider
677 //
678 //=========================================================================
679 
680 // virtual
681 uno::Sequence< uno::Type > SAL_CALL OutputStream::getTypes()
682     throw ( uno::RuntimeException )
683 {
684     return m_xWrappedTypeProv->getTypes();
685 }
686 
687 //=========================================================================
688 // virtual
689 uno::Sequence< sal_Int8 > SAL_CALL OutputStream::getImplementationId()
690     throw ( uno::RuntimeException )
691 {
692     return m_xWrappedTypeProv->getImplementationId();
693 }
694 
695 //=========================================================================
696 //
697 // io::XOutputStream
698 //
699 //=========================================================================
700 
701 // virtual
702 void SAL_CALL
703 OutputStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
704     throw ( io::NotConnectedException,
705             io::BufferSizeExceededException,
706             io::IOException,
707             uno::RuntimeException )
708 {
709     m_xWrappedStream->writeBytes( aData );
710 }
711 
712 //=========================================================================
713 // virtual
714 void SAL_CALL
715 OutputStream::flush()
716     throw ( io::NotConnectedException,
717             io::BufferSizeExceededException,
718             io::IOException,
719             uno::RuntimeException )
720 {
721     m_xWrappedStream->flush();
722 }
723 
724 //=========================================================================
725 // virtual
726 void SAL_CALL
727 OutputStream::closeOutput(  )
728     throw ( io::NotConnectedException,
729             io::BufferSizeExceededException,
730             io::IOException,
731             uno::RuntimeException )
732 {
733     m_xWrappedStream->closeOutput();
734 
735     // Release parent storage.
736     // Now, that the stream is closed/disposed it is not needed any longer.
737     setParentStorage( uno::Reference< embed::XStorage >() );
738 }
739 
740 //=========================================================================
741 //
742 // lang::XComponent
743 //
744 //=========================================================================
745 
746 // virtual
747 void SAL_CALL
748 OutputStream::dispose()
749     throw ( uno::RuntimeException )
750 {
751     m_xWrappedComponent->dispose();
752 
753     // Release parent storage.
754     // Now, that the stream is closed/disposed it is not needed any longer.
755     setParentStorage( uno::Reference< embed::XStorage >() );
756 }
757 
758 //=========================================================================
759 // virtual
760 void SAL_CALL
761 OutputStream::addEventListener(
762         const uno::Reference< lang::XEventListener >& xListener )
763     throw ( uno::RuntimeException )
764 {
765     m_xWrappedComponent->addEventListener( xListener );
766 }
767 
768 //=========================================================================
769 // virtual
770 void SAL_CALL
771 OutputStream::removeEventListener(
772         const uno::Reference< lang::XEventListener >& aListener )
773     throw ( uno::RuntimeException )
774 {
775     m_xWrappedComponent->removeEventListener( aListener );
776 }
777 
778 //=========================================================================
779 //=========================================================================
780 //
781 // Stream Implementation.
782 //
783 //=========================================================================
784 //=========================================================================
785 
786 Stream::Stream(
787             const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
788             const rtl::OUString & rUri,
789             const uno::Reference< embed::XStorage >  & xParentStorage,
790             const uno::Reference< io::XStream > & xStreamToWrap )
791 : ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
792   m_xWrappedStream( xStreamToWrap ),
793   m_xWrappedOutputStream( xStreamToWrap->getOutputStream() ), // might be empty
794   m_xWrappedTruncate( m_xWrappedOutputStream, uno::UNO_QUERY ), // might be empty
795   m_xWrappedInputStream( xStreamToWrap->getInputStream(), uno::UNO_QUERY ),
796   m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ),
797   m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY )
798 {
799     OSL_ENSURE( m_xWrappedStream.is(),
800                 "OutputStream::OutputStream: No stream to wrap!" );
801 
802     OSL_ENSURE( m_xWrappedComponent.is(),
803                 "OutputStream::OutputStream: No component to wrap!" );
804 
805     OSL_ENSURE( m_xWrappedTypeProv.is(),
806                 "OutputStream::OutputStream: No Type Provider!" );
807 
808     // Use proxy factory service to create aggregatable proxy.
809     try
810     {
811         uno::Reference< reflection::XProxyFactory > xProxyFac(
812             xSMgr->createInstance(
813                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
814                     "com.sun.star.reflection.ProxyFactory" ) ) ),
815             uno::UNO_QUERY );
816         if ( xProxyFac.is() )
817         {
818             m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream );
819         }
820     }
821     catch ( uno::Exception const & )
822     {
823         OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" );
824     }
825 
826     OSL_ENSURE( m_xAggProxy.is(),
827             "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" );
828 
829     if ( m_xAggProxy.is() )
830     {
831         osl_incrementInterlockedCount( &m_refCount );
832 		{
833 			// Solaris compiler problem:
834 			// Extra block to enforce destruction of temporary object created
835             // in next statement _before_ osl_decrementInterlockedCount is
836             // called.  Otherwise 'this' will destroy itself even before ctor
837             // is completed (See impl. of XInterface::release())!
838 
839         	m_xAggProxy->setDelegator(
840 				static_cast< cppu::OWeakObject * >( this ) );
841 		}
842         osl_decrementInterlockedCount( &m_refCount );
843     }
844 }
845 
846 //=========================================================================
847 // virtual
848 Stream::~Stream()
849 {
850     if ( m_xAggProxy.is() )
851         m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
852 }
853 
854 //=========================================================================
855 //
856 // uno::XInterface
857 //
858 //=========================================================================
859 
860 // virtual
861 uno::Any SAL_CALL Stream::queryInterface( const uno::Type& aType )
862     throw ( uno::RuntimeException )
863 {
864     uno::Any aRet = StreamUNOBase::queryInterface( aType );
865 
866     if ( aRet.hasValue() )
867         return aRet;
868 
869     if ( m_xAggProxy.is() )
870         return m_xAggProxy->queryAggregation( aType );
871     else
872         return uno::Any();
873 }
874 
875 //=========================================================================
876 //
877 // lang::XTypeProvider
878 //
879 //=========================================================================
880 
881 // virtual
882 uno::Sequence< uno::Type > SAL_CALL Stream::getTypes()
883     throw ( uno::RuntimeException )
884 {
885     return m_xWrappedTypeProv->getTypes();
886 }
887 
888 //=========================================================================
889 // virtual
890 uno::Sequence< sal_Int8 > SAL_CALL Stream::getImplementationId()
891     throw ( uno::RuntimeException )
892 {
893     return m_xWrappedTypeProv->getImplementationId();
894 }
895 
896 //=========================================================================
897 //
898 // io::XStream.
899 //
900 //=========================================================================
901 
902 // virtual
903 uno::Reference< io::XInputStream > SAL_CALL Stream::getInputStream()
904     throw( uno::RuntimeException )
905 {
906     return uno::Reference< io::XInputStream >( this );
907 }
908 
909 //=========================================================================
910 // virtual
911 uno::Reference< io::XOutputStream > SAL_CALL Stream::getOutputStream()
912     throw( uno::RuntimeException )
913 {
914     return uno::Reference< io::XOutputStream >( this );
915 }
916 
917 //=========================================================================
918 //
919 // io::XOutputStream.
920 //
921 //=========================================================================
922 
923 // virtual
924 void SAL_CALL Stream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
925     throw( io::NotConnectedException,
926            io::BufferSizeExceededException,
927            io::IOException,
928            uno::RuntimeException )
929 {
930     if ( m_xWrappedOutputStream.is() )
931     {
932         m_xWrappedOutputStream->writeBytes( aData );
933         commitChanges();
934     }
935 }
936 
937 //=========================================================================
938 // virtual
939 void SAL_CALL Stream::flush()
940     throw( io::NotConnectedException,
941            io::BufferSizeExceededException,
942            io::IOException,
943            uno::RuntimeException )
944 {
945     if ( m_xWrappedOutputStream.is() )
946     {
947         m_xWrappedOutputStream->flush();
948         commitChanges();
949     }
950 }
951 
952 //=========================================================================
953 // virtual
954 void SAL_CALL Stream::closeOutput()
955     throw( io::NotConnectedException,
956            io::IOException,
957            uno::RuntimeException )
958 {
959     if ( m_xWrappedOutputStream.is() )
960     {
961         m_xWrappedOutputStream->closeOutput();
962         commitChanges();
963     }
964 
965     // Release parent storage.
966     // Now, that the stream is closed/disposed it is not needed any longer.
967     setParentStorage( uno::Reference< embed::XStorage >() );
968 }
969 
970 //=========================================================================
971 //
972 // io::XTruncate.
973 //
974 //=========================================================================
975 
976 // virtual
977 void SAL_CALL Stream::truncate()
978     throw( io::IOException,
979            uno::RuntimeException )
980 {
981     if ( m_xWrappedTruncate.is() )
982     {
983         m_xWrappedTruncate->truncate();
984         commitChanges();
985     }
986 }
987 
988 //=========================================================================
989 //
990 // io::XInputStream.
991 //
992 //=========================================================================
993 
994 // virtual
995 sal_Int32 SAL_CALL Stream::readBytes( uno::Sequence< sal_Int8 >& aData,
996                                       sal_Int32 nBytesToRead )
997     throw( io::NotConnectedException,
998            io::BufferSizeExceededException,
999            io::IOException,
1000            uno::RuntimeException )
1001 {
1002     return m_xWrappedInputStream->readBytes( aData, nBytesToRead );
1003 }
1004 
1005 //=========================================================================
1006 // virtual
1007 sal_Int32 SAL_CALL Stream::readSomeBytes( uno::Sequence< sal_Int8 >& aData,
1008                                           sal_Int32 nMaxBytesToRead )
1009     throw( io::NotConnectedException,
1010            io::BufferSizeExceededException,
1011            io::IOException,
1012            uno::RuntimeException )
1013 {
1014     return m_xWrappedInputStream->readSomeBytes( aData, nMaxBytesToRead );
1015 }
1016 
1017 //=========================================================================
1018 // virtual
1019 void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip )
1020     throw( io::NotConnectedException,
1021            io::BufferSizeExceededException,
1022            io::IOException,
1023            uno::RuntimeException )
1024 {
1025     m_xWrappedInputStream->skipBytes( nBytesToSkip );
1026 }
1027 
1028 //=========================================================================
1029 // virtual
1030 sal_Int32 SAL_CALL Stream::available()
1031     throw( io::NotConnectedException,
1032            io::IOException,
1033            uno::RuntimeException )
1034 {
1035     return m_xWrappedInputStream->available();
1036 }
1037 
1038 //=========================================================================
1039 // virtual
1040 void SAL_CALL Stream::closeInput()
1041     throw( io::NotConnectedException,
1042            io::IOException,
1043            uno::RuntimeException )
1044 {
1045     m_xWrappedInputStream->closeInput();
1046 }
1047 
1048 //=========================================================================
1049 //
1050 // lang::XComponent
1051 //
1052 //=========================================================================
1053 
1054 // virtual
1055 void SAL_CALL Stream::dispose()
1056     throw ( uno::RuntimeException )
1057 {
1058     m_xWrappedComponent->dispose();
1059 
1060     // Release parent storage.
1061     // Now, that the stream is closed/disposed it is not needed any longer.
1062     setParentStorage( uno::Reference< embed::XStorage >() );
1063 }
1064 
1065 //=========================================================================
1066 // virtual
1067 void SAL_CALL Stream::addEventListener(
1068         const uno::Reference< lang::XEventListener >& xListener )
1069     throw ( uno::RuntimeException )
1070 {
1071     m_xWrappedComponent->addEventListener( xListener );
1072 }
1073 
1074 //=========================================================================
1075 // virtual
1076 void SAL_CALL Stream::removeEventListener(
1077         const uno::Reference< lang::XEventListener >& aListener )
1078     throw ( uno::RuntimeException )
1079 {
1080     m_xWrappedComponent->removeEventListener( aListener );
1081 }
1082 
1083 //=========================================================================
1084 //
1085 // Non-UNO
1086 //
1087 //=========================================================================
1088 
1089 void Stream::commitChanges()
1090     throw( io::IOException )
1091 {
1092     uno::Reference< embed::XTransactedObject >
1093         xParentTA( getParentStorage(), uno::UNO_QUERY );
1094     OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" );
1095 
1096     if ( xParentTA.is() )
1097     {
1098         try
1099         {
1100             xParentTA->commit();
1101         }
1102         catch ( lang::WrappedTargetException const & )
1103         {
1104             throw io::IOException(); // @@@
1105         }
1106     }
1107 }
1108 
1109