diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /ucbhelper/source/provider/contenthelper.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ucbhelper/source/provider/contenthelper.cxx')
-rw-r--r-- | ucbhelper/source/provider/contenthelper.cxx | 862 |
1 files changed, 862 insertions, 0 deletions
diff --git a/ucbhelper/source/provider/contenthelper.cxx b/ucbhelper/source/provider/contenthelper.cxx new file mode 100644 index 000000000..75d0a8479 --- /dev/null +++ b/ucbhelper/source/provider/contenthelper.cxx @@ -0,0 +1,862 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/ucb/ContentAction.hpp> +#include <com/sun/star/ucb/IllegalIdentifierException.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/beans/IllegalTypeException.hpp> +#include <com/sun/star/beans/NotRemoveableException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyExistException.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <ucbhelper/contenthelper.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include "contentinfo.hxx" +#include <ucbhelper/providerhelper.hxx> +#include <ucbhelper/macros.hxx> + +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <rtl/ref.hxx> + +#include <unordered_map> + +using namespace com::sun::star; + +namespace ucbhelper_impl +{ + +namespace { + +class PropertyEventSequence +{ + uno::Sequence< beans::PropertyChangeEvent > m_aSeq; + sal_uInt32 m_nPos; + +public: + explicit PropertyEventSequence( sal_uInt32 nSize ) + : m_aSeq( nSize ), m_nPos( 0 ) {}; + + void append( const beans::PropertyChangeEvent& rEvt ) + { m_aSeq.getArray()[ m_nPos ] = rEvt; ++m_nPos; } + + const uno::Sequence< beans::PropertyChangeEvent >& getEvents() + { m_aSeq.realloc( m_nPos ); return m_aSeq; } +}; + +} + +typedef void* XPropertiesChangeListenerPtr; // -> Compiler problems! + +namespace { + +struct equalPtr +{ + bool operator()( const XPropertiesChangeListenerPtr& rp1, + const XPropertiesChangeListenerPtr& rp2 ) const + { + return ( rp1 == rp2 ); + } +}; + +struct hashPtr +{ + size_t operator()( const XPropertiesChangeListenerPtr& rp ) const + { + return reinterpret_cast<size_t>(rp); + } +}; + +} + +typedef std::unordered_map +< + XPropertiesChangeListenerPtr, + PropertyEventSequence, + hashPtr, + equalPtr +> +PropertiesEventListenerMap; + +typedef cppu::OMultiTypeInterfaceContainerHelperVar<OUString> + PropertyChangeListeners; + +struct ContentImplHelper_Impl +{ + rtl::Reference< ::ucbhelper::PropertySetInfo > m_xPropSetInfo; + rtl::Reference< ::ucbhelper::CommandProcessorInfo > m_xCommandsInfo; + std::unique_ptr<cppu::OInterfaceContainerHelper> m_pDisposeEventListeners; + std::unique_ptr<comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>> + m_pContentEventListeners; + std::unique_ptr<comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>> + m_pPropSetChangeListeners; + std::unique_ptr<cppu::OInterfaceContainerHelper> m_pCommandChangeListeners; + std::unique_ptr<PropertyChangeListeners> m_pPropertyChangeListeners; +}; + +} // namespace ucbhelper_impl + +using namespace ucbhelper_impl; + +namespace ucbhelper { + +ContentImplHelper::ContentImplHelper( + const uno::Reference< uno::XComponentContext >& rxContext, + const rtl::Reference< ContentProviderImplHelper >& rxProvider, + const uno::Reference< + css::ucb::XContentIdentifier >& Identifier ) +: m_pImpl( new ContentImplHelper_Impl ), + m_xContext( rxContext ), + m_xIdentifier( Identifier ), + m_xProvider( rxProvider ), + m_nCommandId( 0 ) +{ +} + +// virtual +ContentImplHelper::~ContentImplHelper() +{ +} + +void SAL_CALL ContentImplHelper::release() + noexcept +{ + // #144882# - Call to OWeakObject::release may destroy m_xProvider. + // Prevent this. + rtl::Reference< ContentProviderImplHelper > xKeepProviderAlive( + m_xProvider ); + + osl::MutexGuard aGuard( m_xProvider->m_aMutex ); + OWeakObject::release(); +} + +uno::Any SAL_CALL ContentImplHelper::queryInterface( const uno::Type & rType ) +{ + css::uno::Any aRet = cppu::queryInterface( rType, + static_cast< lang::XTypeProvider * >(this), + static_cast< lang::XServiceInfo * >(this), + static_cast< lang::XComponent * >(this), + static_cast< css::ucb::XContent * >(this), + static_cast< css::ucb::XCommandProcessor * >(this), + static_cast< beans::XPropertiesChangeNotifier * >(this), + static_cast< css::ucb::XCommandInfoChangeNotifier * >(this), + static_cast< beans::XPropertyContainer * >(this), + static_cast< beans::XPropertySetInfoChangeNotifier * >(this), + static_cast< container::XChild * >(this)); + return aRet.hasValue() ? aRet : cppu::OWeakObject::queryInterface( rType ); +} + +XTYPEPROVIDER_IMPL_10( ContentImplHelper, + lang::XTypeProvider, + lang::XServiceInfo, + lang::XComponent, + css::ucb::XContent, + css::ucb::XCommandProcessor, + beans::XPropertiesChangeNotifier, + css::ucb::XCommandInfoChangeNotifier, + beans::XPropertyContainer, + beans::XPropertySetInfoChangeNotifier, + container::XChild ); + +// virtual +sal_Bool SAL_CALL ContentImplHelper::supportsService( + const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +// virtual +void SAL_CALL ContentImplHelper::dispose() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pImpl->m_pDisposeEventListeners && + m_pImpl->m_pDisposeEventListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pContentEventListeners && + m_pImpl->m_pContentEventListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< css::ucb::XContent * >( this ); + m_pImpl->m_pContentEventListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source + = static_cast< beans::XPropertySetInfoChangeNotifier * >( this ); + m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pCommandChangeListeners && + m_pImpl->m_pCommandChangeListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< css::ucb::XCommandInfoChangeNotifier * >( this ); + m_pImpl->m_pCommandChangeListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pPropertyChangeListeners ) + { + lang::EventObject aEvt; + aEvt.Source + = static_cast< beans::XPropertiesChangeNotifier * >( this ); + m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt ); + } +} + +// virtual +void SAL_CALL ContentImplHelper::addEventListener( + const uno::Reference< lang::XEventListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pDisposeEventListeners ) + m_pImpl->m_pDisposeEventListeners.reset( + new cppu::OInterfaceContainerHelper( m_aMutex )); + + m_pImpl->m_pDisposeEventListeners->addInterface( Listener ); +} + +// virtual +void SAL_CALL ContentImplHelper::removeEventListener( + const uno::Reference< lang::XEventListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pImpl->m_pDisposeEventListeners ) + m_pImpl->m_pDisposeEventListeners->removeInterface( Listener ); +} + +// virtual +uno::Reference< css::ucb::XContentIdentifier > SAL_CALL +ContentImplHelper::getIdentifier() +{ + return m_xIdentifier; +} + +// virtual +void SAL_CALL ContentImplHelper::addContentEventListener( + const uno::Reference< css::ucb::XContentEventListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pContentEventListeners ) + m_pImpl->m_pContentEventListeners.reset( + new comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>( m_aMutex )); + + m_pImpl->m_pContentEventListeners->addInterface( Listener ); +} + +// virtual +void SAL_CALL ContentImplHelper::removeContentEventListener( + const uno::Reference< css::ucb::XContentEventListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pImpl->m_pContentEventListeners ) + m_pImpl->m_pContentEventListeners->removeInterface( Listener ); +} + +// virtual +sal_Int32 SAL_CALL ContentImplHelper::createCommandIdentifier() +{ + osl::MutexGuard aGuard( m_aMutex ); + + // Just increase counter on every call to generate an identifier. + return ++m_nCommandId; +} + +// virtual +void SAL_CALL ContentImplHelper::addPropertiesChangeListener( + const uno::Sequence< OUString >& PropertyNames, + const uno::Reference< beans::XPropertiesChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + m_pImpl->m_pPropertyChangeListeners.reset( + new PropertyChangeListeners( m_aMutex )); + + if ( !PropertyNames.hasElements() ) + { + // Note: An empty sequence means a listener for "all" properties. + m_pImpl->m_pPropertyChangeListeners->addInterface( + OUString(), Listener ); + } + else + { + for ( const OUString& rName : PropertyNames ) + { + if ( !rName.isEmpty() ) + m_pImpl->m_pPropertyChangeListeners->addInterface( + rName, Listener ); + } + } +} + +// virtual +void SAL_CALL ContentImplHelper::removePropertiesChangeListener( + const uno::Sequence< OUString >& PropertyNames, + const uno::Reference< beans::XPropertiesChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + return; + + if ( !PropertyNames.hasElements() ) + { + // Note: An empty sequence means a listener for "all" properties. + m_pImpl->m_pPropertyChangeListeners->removeInterface( + OUString(), Listener ); + } + else + { + for ( const OUString& rName : PropertyNames ) + { + if ( !rName.isEmpty() ) + m_pImpl->m_pPropertyChangeListeners->removeInterface( + rName, Listener ); + } + } +} + +// virtual +void SAL_CALL ContentImplHelper::addCommandInfoChangeListener( + const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pCommandChangeListeners ) + m_pImpl->m_pCommandChangeListeners.reset( + new cppu::OInterfaceContainerHelper( m_aMutex )); + + m_pImpl->m_pCommandChangeListeners->addInterface( Listener ); +} + +// virtual +void SAL_CALL ContentImplHelper::removeCommandInfoChangeListener( + const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pImpl->m_pCommandChangeListeners ) + m_pImpl->m_pCommandChangeListeners->removeInterface( Listener ); +} + +// virtual +void SAL_CALL ContentImplHelper::addProperty( + const OUString& Name, + sal_Int16 Attributes, + const uno::Any& DefaultValue ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + // Make sure a property with the requested name does not already + // exist in dynamic and static(!) properties. + + // @@@ Need real command environment here, but where to get it from? + // XPropertyContainer interface should be replaced by + // XCommandProcessor commands! + uno::Reference< css::ucb::XCommandEnvironment > xEnv; + + if ( getPropertySetInfo( xEnv )->hasPropertyByName( Name ) ) + { + // Property does already exist. + throw beans::PropertyExistException(); + } + + // Add a new dynamic property. + // Open/create persistent property set. + uno::Reference< css::ucb::XPersistentPropertySet > xSet( + getAdditionalPropertySet( true ) ); + + OSL_ENSURE( xSet.is(), + "ContentImplHelper::addProperty - No property set!" ); + + if ( !xSet.is() ) + return; + + uno::Reference< beans::XPropertyContainer > xContainer( + xSet, uno::UNO_QUERY ); + + OSL_ENSURE( + xContainer.is(), + "ContentImplHelper::addProperty - No property container!" ); + + if ( !xContainer.is() ) + return; + + // Property is always removable. + Attributes |= beans::PropertyAttribute::REMOVABLE; + + try + { + xContainer->addProperty( Name, Attributes, DefaultValue ); + } + catch ( beans::PropertyExistException const & ) + { + OSL_FAIL( "ContentImplHelper::addProperty - Exists!" ); + throw; + } + catch ( beans::IllegalTypeException const & ) + { + OSL_FAIL( "ContentImplHelper::addProperty - Wrong Type!" ); + throw; + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_FAIL( "ContentImplHelper::addProperty - Illegal Arg!" ); + throw; + } + + // Success! + + if ( m_pImpl->m_xPropSetInfo.is() ) + { + // Info cached in propertyset info is invalid now! + m_pImpl->m_xPropSetInfo->reset(); + } + + // Notify propertyset info change listeners. + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + beans::PropertySetInfoChangeEvent evt( + static_cast< cppu::OWeakObject * >( this ), + Name, + -1, // No handle available + beans::PropertySetInfoChange::PROPERTY_INSERTED ); + notifyPropertySetInfoChange( evt ); + } +} + +// virtual +void SAL_CALL ContentImplHelper::removeProperty( const OUString& Name ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + try + { + // @@@ Need real command environment here, but where to get it from? + // XPropertyContainer interface should be replaced by + // XCommandProcessor commands! + uno::Reference< css::ucb::XCommandEnvironment > xEnv; + + beans::Property aProp + = getPropertySetInfo( xEnv )->getPropertyByName( Name ); + + if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVABLE ) ) + { + // Not removable! + throw beans::NotRemoveableException(); + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" ); + throw; + } + + // Try to remove property from dynamic property set. + // Open persistent property set, if exists. + uno::Reference< css::ucb::XPersistentPropertySet > xSet( + getAdditionalPropertySet( false ) ); + if ( !xSet.is() ) + return; + + uno::Reference< beans::XPropertyContainer > xContainer( + xSet, uno::UNO_QUERY ); + + OSL_ENSURE( + xContainer.is(), + "ContentImplHelper::removeProperty - No property container!" ); + + if ( !xContainer.is() ) + return; + + try + { + xContainer->removeProperty( Name ); + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" ); + throw; + } + catch ( beans::NotRemoveableException const & ) + { + OSL_FAIL( + "ContentImplHelper::removeProperty - Unremovable!" ); + throw; + } + + xContainer = nullptr; + + // Success! + + if ( !xSet->getPropertySetInfo()->getProperties().hasElements() ) + { + // Remove empty propertyset from registry. + uno::Reference< css::ucb::XPropertySetRegistry > + xReg = xSet->getRegistry(); + if ( xReg.is() ) + { + OUString aKey( xSet->getKey() ); + xSet = nullptr; + xReg->removePropertySet( aKey ); + } + } + + if ( m_pImpl->m_xPropSetInfo.is() ) + { + // Info cached in propertyset info is invalid now! + m_pImpl->m_xPropSetInfo->reset(); + } + + // Notify propertyset info change listeners. + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + beans::PropertySetInfoChangeEvent evt( + static_cast< cppu::OWeakObject * >( this ), + Name, + -1, // No handle available + beans::PropertySetInfoChange::PROPERTY_REMOVED ); + notifyPropertySetInfoChange( evt ); + } +} + +// virtual +void SAL_CALL ContentImplHelper::addPropertySetInfoChangeListener( + const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_pPropSetChangeListeners ) + m_pImpl->m_pPropSetChangeListeners.reset( + new comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>( m_aMutex )); + + m_pImpl->m_pPropSetChangeListeners->addInterface( Listener ); +} + +// virtual +void SAL_CALL ContentImplHelper::removePropertySetInfoChangeListener( + const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pImpl->m_pPropSetChangeListeners ) + m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener ); +} + +// virtual +uno::Reference< uno::XInterface > SAL_CALL ContentImplHelper::getParent() +{ + uno::Reference< uno::XInterface > xParent; + OUString aURL = getParentURL(); + + if ( !aURL.isEmpty() ) + { + uno::Reference< css::ucb::XContentIdentifier > xId( + new ContentIdentifier( aURL ) ); + try + { + xParent.set( m_xProvider->queryContent( xId ) ); + } + catch ( css::ucb::IllegalIdentifierException const & ) + { + } + } + + return xParent; +} + +// virtual +void SAL_CALL ContentImplHelper::setParent( + const uno::Reference< uno::XInterface >& ) +{ + throw lang::NoSupportException(); +} + +uno::Reference< css::ucb::XPersistentPropertySet > +ContentImplHelper::getAdditionalPropertySet( bool bCreate ) +{ + // Get propertyset from provider. + return m_xProvider->getAdditionalPropertySet( + m_xIdentifier->getContentIdentifier(), bCreate ); +} + +bool ContentImplHelper::renameAdditionalPropertySet( + const OUString& rOldKey, + const OUString& rNewKey ) +{ + return m_xProvider->renameAdditionalPropertySet( + rOldKey, rNewKey, true/*bRecursive*/ ); +} + +bool ContentImplHelper::copyAdditionalPropertySet( + const OUString& rSourceKey, + const OUString& rTargetKey ) +{ + return m_xProvider->copyAdditionalPropertySet( + rSourceKey, rTargetKey, true/*bRecursive*/ ); +} + +bool ContentImplHelper::removeAdditionalPropertySet() +{ + return m_xProvider->removeAdditionalPropertySet( + m_xIdentifier->getContentIdentifier(), true/*bRecursive*/ ); +} + +void ContentImplHelper::notifyPropertiesChange( + const uno::Sequence< beans::PropertyChangeEvent >& evt ) const +{ + if ( !m_pImpl->m_pPropertyChangeListeners ) + return; + + sal_Int32 nCount = evt.getLength(); + if ( !nCount ) + return; + + // First, notify listeners interested in changes of every property. + cppu::OInterfaceContainerHelper* pAllPropsContainer + = m_pImpl->m_pPropertyChangeListeners->getContainer( + OUString() ); + if ( pAllPropsContainer ) + { + cppu::OInterfaceIteratorHelper aIter( *pAllPropsContainer ); + while ( aIter.hasMoreElements() ) + { + // Propagate event. + static_cast< beans::XPropertiesChangeListener* >( + aIter.next())->propertiesChange( evt ); + } + } + + PropertiesEventListenerMap aListeners; + + for ( const beans::PropertyChangeEvent& rEvent : evt ) + { + const OUString& rName = rEvent.PropertyName; + + cppu::OInterfaceContainerHelper* pPropsContainer + = m_pImpl->m_pPropertyChangeListeners->getContainer( rName ); + if ( pPropsContainer ) + { + cppu::OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + PropertyEventSequence* p = nullptr; + + beans::XPropertiesChangeListener* pListener = + static_cast< beans::XPropertiesChangeListener * >( + aIter.next() ); + PropertiesEventListenerMap::iterator it = + aListeners.find( pListener ); + if ( it == aListeners.end() ) + { + // Not in map - create and insert new entry. + p = &aListeners.emplace( pListener, PropertyEventSequence(nCount)).first->second; + } + else + p = &it->second; + + if ( p ) + p->append( rEvent ); + } + } + } + + // Notify listeners. + PropertiesEventListenerMap::iterator it = aListeners.begin(); + while ( !aListeners.empty() ) + { + beans::XPropertiesChangeListener* pListener = + static_cast< beans::XPropertiesChangeListener * >( (*it).first ); + PropertyEventSequence pSeq = std::move(it->second); + + // Remove current element. + aListeners.erase( it ); + + // Propagate event. + pListener->propertiesChange( pSeq.getEvents() ); + + it = aListeners.begin(); + } +} + +void ContentImplHelper::notifyPropertySetInfoChange( + const beans::PropertySetInfoChangeEvent& evt ) const +{ + if ( !m_pImpl->m_pPropSetChangeListeners ) + return; + + // Notify event listeners. + m_pImpl->m_pPropSetChangeListeners->notifyEach( &beans::XPropertySetInfoChangeListener::propertySetInfoChange, evt ); +} + +void ContentImplHelper::notifyContentEvent( + const css::ucb::ContentEvent& evt ) const +{ + if ( !m_pImpl->m_pContentEventListeners ) + return; + + // Notify event listeners. + m_pImpl->m_pContentEventListeners->notifyEach( &css::ucb::XContentEventListener::contentEvent, evt); +} + +void ContentImplHelper::inserted() +{ + // Content is not yet registered at provider. + m_xProvider->registerNewContent( this ); + + // If the parent content is currently not instantiated, there can be + // no listeners interested in changes ;-) + + rtl::Reference< ContentImplHelper > xParent + = m_xProvider->queryExistingContent( getParentURL() ); + + if ( xParent.is() ) + { + css::ucb::ContentEvent aEvt( + static_cast< cppu::OWeakObject * >( xParent.get() ), // Source + css::ucb::ContentAction::INSERTED, // Action + this, // Content + xParent->getIdentifier() ); // Id + xParent->notifyContentEvent( aEvt ); + } +} + +void ContentImplHelper::deleted() +{ + uno::Reference< css::ucb::XContent > xThis = this; + + rtl::Reference< ContentImplHelper > xParent + = m_xProvider->queryExistingContent( getParentURL() ); + + if ( xParent.is() ) + { + // Let parent notify "REMOVED" event. + css::ucb::ContentEvent aEvt( + static_cast< cppu::OWeakObject * >( xParent.get() ), + css::ucb::ContentAction::REMOVED, + this, + xParent->getIdentifier() ); + xParent->notifyContentEvent( aEvt ); + } + + // Notify "DELETED" event. + css::ucb::ContentEvent aEvt1( + static_cast< cppu::OWeakObject * >( this ), + css::ucb::ContentAction::DELETED, + this, + getIdentifier() ); + notifyContentEvent( aEvt1 ); + + m_xProvider->removeContent( this ); +} + +bool ContentImplHelper::exchange( + const uno::Reference< css::ucb::XContentIdentifier >& rNewId ) +{ + uno::Reference< css::ucb::XContent > xThis = this; + + osl::ClearableMutexGuard aGuard( m_aMutex ); + + rtl::Reference< ContentImplHelper > xContent + = m_xProvider->queryExistingContent( rNewId ); + if ( xContent.is() ) + { + // @@@ + // Big trouble. Another object with the new identity exists. + // How shall I mutate to / merge with the other object? + return false; + } + + uno::Reference< css::ucb::XContentIdentifier > xOldId + = getIdentifier(); + + // Re-insert at provider. + m_xProvider->removeContent( this ); + m_xIdentifier = rNewId; + m_xProvider->registerNewContent( this ); + + aGuard.clear(); + + // Notify "EXCHANGED" event. + css::ucb::ContentEvent aEvt( + static_cast< cppu::OWeakObject * >( this ), + css::ucb::ContentAction::EXCHANGED, + this, + xOldId ); + notifyContentEvent( aEvt ); + return true; +} + +uno::Reference< css::ucb::XCommandInfo > +ContentImplHelper::getCommandInfo( + const uno::Reference< css::ucb::XCommandEnvironment > & xEnv, + bool bCache ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_xCommandsInfo.is() ) + m_pImpl->m_xCommandsInfo + = new CommandProcessorInfo( xEnv, this ); + else if ( !bCache ) + m_pImpl->m_xCommandsInfo->reset(); + + return m_pImpl->m_xCommandsInfo; +} + +uno::Reference< beans::XPropertySetInfo > +ContentImplHelper::getPropertySetInfo( + const uno::Reference< css::ucb::XCommandEnvironment > & xEnv, + bool bCache ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pImpl->m_xPropSetInfo.is() ) + m_pImpl->m_xPropSetInfo + = new PropertySetInfo( xEnv, this ); + else if ( !bCache ) + m_pImpl->m_xPropSetInfo->reset(); + + return m_pImpl->m_xPropSetInfo; +} + +} // namespace ucbhelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |