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