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