1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
23 **************************************************************************
25 - remove root storage access workaround
27 *************************************************************************/
29 #include <comphelper/diagnose_ex.hxx>
30 #include <com/sun/star/io/IOException.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <com/sun/star/reflection/ProxyFactory.hpp>
35 #include "tdoc_docmgr.hxx"
36 #include "tdoc_uri.hxx"
38 #include "tdoc_stgelems.hxx"
40 using namespace com::sun::star
;
41 using namespace tdoc_ucp
;
44 // ParentStorageHolder Implementation.
47 ParentStorageHolder::ParentStorageHolder(
48 uno::Reference
< embed::XStorage
> xParentStorage
,
49 const OUString
& rUri
)
50 : m_xParentStorage(std::move( xParentStorage
)),
51 m_bParentIsRootStorage( false )
54 if ( aUri
.isDocument() )
55 m_bParentIsRootStorage
= true;
59 // Storage Implementation.
62 Storage::Storage( const uno::Reference
< uno::XComponentContext
> & rxContext
,
63 rtl::Reference
< StorageElementFactory
> xFactory
,
64 const OUString
& rUri
,
65 const uno::Reference
< embed::XStorage
> & xParentStorage
,
66 const uno::Reference
< embed::XStorage
> & xStorageToWrap
)
67 : ParentStorageHolder( xParentStorage
, Uri( rUri
).getParentUri() ),
68 m_xFactory(std::move( xFactory
)),
69 m_xWrappedStorage( xStorageToWrap
),
70 m_xWrappedTransObj( xStorageToWrap
, uno::UNO_QUERY
), // optional interface
71 m_xWrappedComponent( xStorageToWrap
),
72 m_xWrappedTypeProv( xStorageToWrap
, uno::UNO_QUERY
),
73 m_bIsDocumentStorage( Uri( rUri
).isDocument() )
75 OSL_ENSURE( m_xWrappedStorage
.is(),
76 "Storage::Storage: No storage to wrap!" );
78 OSL_ENSURE( m_xWrappedComponent
.is(),
79 "Storage::Storage: No component to wrap!" );
81 OSL_ENSURE( m_xWrappedTypeProv
.is(),
82 "Storage::Storage: No Type Provider!" );
84 // Use proxy factory service to create aggregatable proxy.
87 uno::Reference
< reflection::XProxyFactory
> xProxyFac
=
88 reflection::ProxyFactory::create( rxContext
);
89 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedStorage
);
91 catch ( uno::Exception
const & )
93 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
96 OSL_ENSURE( m_xAggProxy
.is(),
97 "Storage::Storage: Wrapped storage cannot be aggregated!" );
99 if ( !m_xAggProxy
.is() )
102 osl_atomic_increment( &m_refCount
);
104 // Solaris compiler problem:
105 // Extra block to enforce destruction of temporary object created
106 // in next statement _before_ osl_atomic_decrement is
107 // called. Otherwise 'this' will destroy itself even before ctor
108 // is completed (See impl. of XInterface::release())!
110 m_xAggProxy
->setDelegator(
113 osl_atomic_decrement( &m_refCount
);
120 if ( m_xAggProxy
.is() )
121 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
123 // Never dispose a document storage. Not owner!
124 if ( m_bIsDocumentStorage
)
127 if ( !m_xWrappedComponent
.is() )
133 m_xWrappedComponent
->dispose();
135 catch ( lang::DisposedException
const & )
141 TOOLS_WARN_EXCEPTION( "ucb", "Storage::~Storage - Caught exception!" );
150 uno::Any SAL_CALL
Storage::queryInterface( const uno::Type
& aType
)
152 // First, try to use interfaces implemented by myself and base class(es)
153 uno::Any aRet
= StorageUNOBase::queryInterface( aType
);
155 if ( aRet
.hasValue() )
158 // Try to use requested interface from aggregated storage
159 return m_xAggProxy
->queryAggregation( aType
);
164 void SAL_CALL
Storage::acquire()
167 osl_atomic_increment( &m_refCount
);
172 void SAL_CALL
Storage::release()
175 //#i120738, Storage::release overrides OWeakObject::release(),
176 //need call OWeakObject::release() to release OWeakObject::m_pWeakConnectionPoint
178 if ( m_refCount
== 1 )
179 m_xFactory
->releaseElement( this );
182 OWeakObject::release();
186 // lang::XTypeProvider
190 uno::Sequence
< uno::Type
> SAL_CALL
Storage::getTypes()
192 return m_xWrappedTypeProv
->getTypes();
197 uno::Sequence
< sal_Int8
> SAL_CALL
Storage::getImplementationId()
199 return css::uno::Sequence
<sal_Int8
>();
203 // lang::XComponent (base of embed::XStorage)
207 void SAL_CALL
Storage::dispose()
209 m_xWrappedStorage
->dispose();
210 m_xWrappedStorage
.clear();
215 void SAL_CALL
Storage::addEventListener(
216 const uno::Reference
< lang::XEventListener
>& xListener
)
218 m_xWrappedStorage
->addEventListener( xListener
);
222 void SAL_CALL
Storage::removeEventListener(
223 const uno::Reference
< lang::XEventListener
>& aListener
)
225 m_xWrappedStorage
->removeEventListener( aListener
);
229 // container::XElementAccess (base of container::XNameAccess)
233 uno::Type SAL_CALL
Storage::getElementType()
235 return m_xWrappedStorage
->getElementType();
240 sal_Bool SAL_CALL
Storage::hasElements()
242 return m_xWrappedStorage
->hasElements();
246 // container::XNameAccess (base of embed::XStorage)
250 uno::Any SAL_CALL
Storage::getByName( const OUString
& aName
)
252 return m_xWrappedStorage
->getByName( aName
);
257 uno::Sequence
< OUString
> SAL_CALL
Storage::getElementNames()
259 return m_xWrappedStorage
->getElementNames();
264 sal_Bool SAL_CALL
Storage::hasByName( const OUString
& aName
)
266 return m_xWrappedStorage
->hasByName( aName
);
274 void SAL_CALL
Storage::copyToStorage(
275 const uno::Reference
< embed::XStorage
>& xDest
)
277 m_xWrappedStorage
->copyToStorage( xDest
);
282 uno::Reference
< io::XStream
> SAL_CALL
Storage::openStreamElement(
283 const OUString
& aStreamName
, sal_Int32 nOpenMode
)
285 return m_xWrappedStorage
->openStreamElement( aStreamName
, nOpenMode
);
290 uno::Reference
< io::XStream
> SAL_CALL
Storage::openEncryptedStreamElement(
291 const OUString
& aStreamName
,
293 const OUString
& aPassword
)
295 return m_xWrappedStorage
->openEncryptedStreamElement(
296 aStreamName
, nOpenMode
, aPassword
);
301 uno::Reference
< embed::XStorage
> SAL_CALL
Storage::openStorageElement(
302 const OUString
& aStorName
, sal_Int32 nOpenMode
)
304 return m_xWrappedStorage
->openStorageElement( aStorName
, nOpenMode
);
309 uno::Reference
< io::XStream
> SAL_CALL
Storage::cloneStreamElement(
310 const OUString
& aStreamName
)
312 return m_xWrappedStorage
->cloneStreamElement( aStreamName
);
317 uno::Reference
< io::XStream
> SAL_CALL
Storage::cloneEncryptedStreamElement(
318 const OUString
& aStreamName
,
319 const OUString
& aPassword
)
321 return m_xWrappedStorage
->cloneEncryptedStreamElement( aStreamName
,
327 void SAL_CALL
Storage::copyLastCommitTo(
328 const uno::Reference
< embed::XStorage
>& xTargetStorage
)
330 m_xWrappedStorage
->copyLastCommitTo( xTargetStorage
);
335 void SAL_CALL
Storage::copyStorageElementLastCommitTo(
336 const OUString
& aStorName
,
337 const uno::Reference
< embed::XStorage
>& xTargetStorage
)
339 m_xWrappedStorage
->copyStorageElementLastCommitTo( aStorName
, xTargetStorage
);
344 sal_Bool SAL_CALL
Storage::isStreamElement(
345 const OUString
& aElementName
)
347 return m_xWrappedStorage
->isStreamElement( aElementName
);
352 sal_Bool SAL_CALL
Storage::isStorageElement(
353 const OUString
& aElementName
)
355 return m_xWrappedStorage
->isStorageElement( aElementName
);
360 void SAL_CALL
Storage::removeElement( const OUString
& aElementName
)
362 m_xWrappedStorage
->removeElement( aElementName
);
367 void SAL_CALL
Storage::renameElement( const OUString
& aEleName
,
368 const OUString
& aNewName
)
370 m_xWrappedStorage
->renameElement( aEleName
, aNewName
);
375 void SAL_CALL
Storage::copyElementTo(
376 const OUString
& aElementName
,
377 const uno::Reference
< embed::XStorage
>& xDest
,
378 const OUString
& aNewName
)
380 m_xWrappedStorage
->copyElementTo( aElementName
, xDest
, aNewName
);
385 void SAL_CALL
Storage::moveElementTo(
386 const OUString
& aElementName
,
387 const uno::Reference
< embed::XStorage
>& xDest
,
388 const OUString
& rNewName
)
390 m_xWrappedStorage
->moveElementTo( aElementName
, xDest
, rNewName
);
394 // embed::XTransactedObject
398 void SAL_CALL
Storage::commit()
400 // Never commit a root storage (-> has no parent)!
401 // Would lead in writing the whole document to disk.
403 uno::Reference
< embed::XStorage
> xParentStorage
= getParentStorage();
404 if ( !xParentStorage
.is() )
407 OSL_ENSURE( m_xWrappedTransObj
.is(), "No XTransactedObject interface!" );
409 if ( !m_xWrappedTransObj
.is() )
412 m_xWrappedTransObj
->commit();
414 if ( !isParentARootStorage() )
416 uno::Reference
< embed::XTransactedObject
> xParentTA(
417 xParentStorage
, uno::UNO_QUERY
);
418 OSL_ENSURE( xParentTA
.is(), "No XTransactedObject interface!" );
420 if ( xParentTA
.is() )
427 void SAL_CALL
Storage::revert()
429 uno::Reference
< embed::XStorage
> xParentStorage
= getParentStorage();
430 if ( !xParentStorage
.is() )
433 OSL_ENSURE( m_xWrappedTransObj
.is(), "No XTransactedObject interface!" );
435 if ( !m_xWrappedTransObj
.is() )
438 m_xWrappedTransObj
->revert();
440 if ( !isParentARootStorage() )
442 uno::Reference
< embed::XTransactedObject
> xParentTA(
443 xParentStorage
, uno::UNO_QUERY
);
444 OSL_ENSURE( xParentTA
.is(), "No XTransactedObject interface!" );
446 if ( xParentTA
.is() )
452 // OutputStream Implementation.
455 OutputStream::OutputStream(
456 const uno::Reference
< uno::XComponentContext
> & rxContext
,
457 const OUString
& rUri
,
458 const uno::Reference
< embed::XStorage
> & xParentStorage
,
459 const uno::Reference
< io::XOutputStream
> & xStreamToWrap
)
460 : ParentStorageHolder( xParentStorage
, Uri( rUri
).getParentUri() ),
461 m_xWrappedStream( xStreamToWrap
),
462 m_xWrappedComponent( xStreamToWrap
, uno::UNO_QUERY
),
463 m_xWrappedTypeProv( xStreamToWrap
, uno::UNO_QUERY
)
465 OSL_ENSURE( m_xWrappedStream
.is(),
466 "OutputStream::OutputStream: No stream to wrap!" );
468 OSL_ENSURE( m_xWrappedComponent
.is(),
469 "OutputStream::OutputStream: No component to wrap!" );
471 OSL_ENSURE( m_xWrappedTypeProv
.is(),
472 "OutputStream::OutputStream: No Type Provider!" );
474 // Use proxy factory service to create aggregatable proxy.
477 uno::Reference
< reflection::XProxyFactory
> xProxyFac
=
478 reflection::ProxyFactory::create( rxContext
);
479 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedStream
);
481 catch ( uno::Exception
const & )
483 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
486 OSL_ENSURE( m_xAggProxy
.is(),
487 "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" );
489 if ( !m_xAggProxy
.is() )
492 osl_atomic_increment( &m_refCount
);
494 // Solaris compiler problem:
495 // Extra block to enforce destruction of temporary object created
496 // in next statement _before_ osl_atomic_decrement is
497 // called. Otherwise 'this' will destroy itself even before ctor
498 // is completed (See impl. of XInterface::release())!
500 m_xAggProxy
->setDelegator(
503 osl_atomic_decrement( &m_refCount
);
508 OutputStream::~OutputStream()
510 if ( m_xAggProxy
.is() )
511 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
519 uno::Any SAL_CALL
OutputStream::queryInterface( const uno::Type
& aType
)
521 uno::Any aRet
= OutputStreamUNOBase::queryInterface( aType
);
523 if ( aRet
.hasValue() )
526 if ( m_xAggProxy
.is() )
527 return m_xAggProxy
->queryAggregation( aType
);
533 // lang::XTypeProvider
537 uno::Sequence
< uno::Type
> SAL_CALL
OutputStream::getTypes()
539 return m_xWrappedTypeProv
->getTypes();
544 uno::Sequence
< sal_Int8
> SAL_CALL
OutputStream::getImplementationId()
546 return css::uno::Sequence
<sal_Int8
>();
555 OutputStream::writeBytes( const uno::Sequence
< sal_Int8
>& aData
)
557 m_xWrappedStream
->writeBytes( aData
);
563 OutputStream::flush()
565 m_xWrappedStream
->flush();
571 OutputStream::closeOutput( )
573 m_xWrappedStream
->closeOutput();
575 // Release parent storage.
576 // Now, that the stream is closed/disposed it is not needed any longer.
577 clearParentStorage();
586 OutputStream::dispose()
588 m_xWrappedComponent
->dispose();
590 // Release parent storage.
591 // Now, that the stream is closed/disposed it is not needed any longer.
592 clearParentStorage();
598 OutputStream::addEventListener(
599 const uno::Reference
< lang::XEventListener
>& xListener
)
601 m_xWrappedComponent
->addEventListener( xListener
);
607 OutputStream::removeEventListener(
608 const uno::Reference
< lang::XEventListener
>& aListener
)
610 m_xWrappedComponent
->removeEventListener( aListener
);
614 // Stream Implementation.
618 const uno::Reference
< uno::XComponentContext
> & rxContext
,
619 rtl::Reference
<OfficeDocumentsManager
> const & docsMgr
,
620 const OUString
& rUri
,
621 const uno::Reference
< embed::XStorage
> & xParentStorage
,
622 const uno::Reference
< io::XStream
> & xStreamToWrap
)
623 : ParentStorageHolder( xParentStorage
, Uri( rUri
).getParentUri() ),
626 m_xWrappedStream( xStreamToWrap
),
627 m_xWrappedOutputStream( xStreamToWrap
->getOutputStream() ), // might be empty
628 m_xWrappedTruncate( m_xWrappedOutputStream
, uno::UNO_QUERY
), // might be empty
629 m_xWrappedInputStream( xStreamToWrap
->getInputStream() ),
630 m_xWrappedComponent( xStreamToWrap
, uno::UNO_QUERY
),
631 m_xWrappedTypeProv( xStreamToWrap
, uno::UNO_QUERY
)
633 OSL_ENSURE( m_xWrappedStream
.is(),
634 "OutputStream::OutputStream: No stream to wrap!" );
636 OSL_ENSURE( m_xWrappedComponent
.is(),
637 "OutputStream::OutputStream: No component to wrap!" );
639 OSL_ENSURE( m_xWrappedTypeProv
.is(),
640 "OutputStream::OutputStream: No Type Provider!" );
642 // Use proxy factory service to create aggregatable proxy.
645 uno::Reference
< reflection::XProxyFactory
> xProxyFac
=
646 reflection::ProxyFactory::create( rxContext
);
647 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedStream
);
649 catch ( uno::Exception
const & )
651 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
654 OSL_ENSURE( m_xAggProxy
.is(),
655 "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" );
657 if ( !m_xAggProxy
.is() )
660 osl_atomic_increment( &m_refCount
);
662 // Solaris compiler problem:
663 // Extra block to enforce destruction of temporary object created
664 // in next statement _before_ osl_atomic_decrement is
665 // called. Otherwise 'this' will destroy itself even before ctor
666 // is completed (See impl. of XInterface::release())!
668 m_xAggProxy
->setDelegator(
671 osl_atomic_decrement( &m_refCount
);
678 if ( m_xAggProxy
.is() )
679 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
687 uno::Any SAL_CALL
Stream::queryInterface( const uno::Type
& aType
)
689 uno::Any aRet
= StreamUNOBase::queryInterface( aType
);
691 if ( aRet
.hasValue() )
694 if ( m_xAggProxy
.is() )
695 return m_xAggProxy
->queryAggregation( aType
);
701 // lang::XTypeProvider
705 uno::Sequence
< uno::Type
> SAL_CALL
Stream::getTypes()
707 return m_xWrappedTypeProv
->getTypes();
712 uno::Sequence
< sal_Int8
> SAL_CALL
Stream::getImplementationId()
714 return css::uno::Sequence
<sal_Int8
>();
722 uno::Reference
< io::XInputStream
> SAL_CALL
Stream::getInputStream()
724 return uno::Reference
< io::XInputStream
>( this );
729 uno::Reference
< io::XOutputStream
> SAL_CALL
Stream::getOutputStream()
731 return uno::Reference
< io::XOutputStream
>( this );
735 // io::XOutputStream.
739 void SAL_CALL
Stream::writeBytes( const uno::Sequence
< sal_Int8
>& aData
)
741 if ( m_xWrappedOutputStream
.is() )
743 m_xWrappedOutputStream
->writeBytes( aData
);
750 void SAL_CALL
Stream::flush()
752 if ( m_xWrappedOutputStream
.is() )
754 m_xWrappedOutputStream
->flush();
761 void SAL_CALL
Stream::closeOutput()
763 if ( m_xWrappedOutputStream
.is() )
765 m_xWrappedOutputStream
->closeOutput();
769 // Release parent storage.
770 // Now, that the stream is closed/disposed it is not needed any longer.
771 clearParentStorage();
779 void SAL_CALL
Stream::truncate()
781 if ( m_xWrappedTruncate
.is() )
783 m_xWrappedTruncate
->truncate();
793 sal_Int32 SAL_CALL
Stream::readBytes( uno::Sequence
< sal_Int8
>& aData
,
794 sal_Int32 nBytesToRead
)
796 return m_xWrappedInputStream
->readBytes( aData
, nBytesToRead
);
801 sal_Int32 SAL_CALL
Stream::readSomeBytes( uno::Sequence
< sal_Int8
>& aData
,
802 sal_Int32 nMaxBytesToRead
)
804 return m_xWrappedInputStream
->readSomeBytes( aData
, nMaxBytesToRead
);
809 void SAL_CALL
Stream::skipBytes( sal_Int32 nBytesToSkip
)
811 m_xWrappedInputStream
->skipBytes( nBytesToSkip
);
816 sal_Int32 SAL_CALL
Stream::available()
818 return m_xWrappedInputStream
->available();
823 void SAL_CALL
Stream::closeInput()
825 m_xWrappedInputStream
->closeInput();
833 void SAL_CALL
Stream::dispose()
835 m_xWrappedComponent
->dispose();
837 // Release parent storage.
838 // Now, that the stream is closed/disposed it is not needed any longer.
839 clearParentStorage();
844 void SAL_CALL
Stream::addEventListener(
845 const uno::Reference
< lang::XEventListener
>& xListener
)
847 m_xWrappedComponent
->addEventListener( xListener
);
852 void SAL_CALL
Stream::removeEventListener(
853 const uno::Reference
< lang::XEventListener
>& aListener
)
855 m_xWrappedComponent
->removeEventListener( aListener
);
862 void Stream::commitChanges()
864 uno::Reference
< embed::XTransactedObject
>
865 xParentTA( getParentStorage(), uno::UNO_QUERY
);
866 OSL_ENSURE( xParentTA
.is(), "No XTransactedObject interface!" );
868 if ( xParentTA
.is() )
874 catch ( lang::WrappedTargetException
const & )
876 throw io::IOException(); // @@@
879 m_docsMgr
->updateStreamDateModified(m_uri
);
882 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */