| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_ucbhelper.hxx" |
| |
| /************************************************************************** |
| TODO |
| ************************************************************************** |
| |
| *************************************************************************/ |
| |
| #include <hash_map> |
| #include <com/sun/star/beans/XPropertyAccess.hpp> |
| #include <com/sun/star/container/XNameAccess.hpp> |
| #include <com/sun/star/container/XNamed.hpp> |
| #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> |
| #include <com/sun/star/ucb/XPropertySetRegistry.hpp> |
| |
| #include "osl/diagnose.h" |
| #include "osl/mutex.hxx" |
| #include "cppuhelper/weakref.hxx" |
| #include <ucbhelper/contentidentifier.hxx> |
| #include <ucbhelper/providerhelper.hxx> |
| #include <ucbhelper/contenthelper.hxx> |
| |
| using namespace com::sun::star; |
| |
| namespace ucbhelper_impl |
| { |
| |
| //========================================================================= |
| // |
| // Contents. |
| // |
| //========================================================================= |
| |
| struct equalString |
| { |
| bool operator()( |
| const rtl::OUString& rKey11, const rtl::OUString& rKey22 ) const |
| { |
| return !!( rKey11 == rKey22 ); |
| } |
| }; |
| |
| struct hashString |
| { |
| size_t operator()( const rtl::OUString & rName ) const |
| { |
| return rName.hashCode(); |
| } |
| }; |
| |
| typedef std::hash_map |
| < |
| rtl::OUString, |
| uno::WeakReference< ucb::XContent >, |
| hashString, |
| equalString |
| > |
| Contents; |
| |
| //========================================================================= |
| // |
| // struct ContentProviderImplHelper_Impl. |
| // |
| //========================================================================= |
| |
| struct ContentProviderImplHelper_Impl |
| { |
| uno::Reference< com::sun::star::ucb::XPropertySetRegistry > |
| m_xPropertySetRegistry; |
| Contents |
| m_aContents; |
| }; |
| |
| } // namespace ucbhelper_impl |
| |
| //========================================================================= |
| //========================================================================= |
| // |
| // ContentProviderImplHelper Implementation. |
| // |
| //========================================================================= |
| //========================================================================= |
| |
| namespace ucbhelper { |
| |
| ContentProviderImplHelper::ContentProviderImplHelper( |
| const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) |
| : m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ), |
| m_xSMgr( rXSMgr ) |
| { |
| } |
| |
| //========================================================================= |
| // virtual |
| ContentProviderImplHelper::~ContentProviderImplHelper() |
| { |
| delete m_pImpl; |
| } |
| |
| //========================================================================= |
| // |
| // XInterface methods. |
| // |
| //========================================================================= |
| |
| XINTERFACE_IMPL_3( ContentProviderImplHelper, |
| lang::XTypeProvider, |
| lang::XServiceInfo, |
| com::sun::star::ucb::XContentProvider ); |
| |
| //========================================================================= |
| // |
| // XTypeProvider methods. |
| // |
| //========================================================================= |
| |
| XTYPEPROVIDER_IMPL_3( ContentProviderImplHelper, |
| lang::XTypeProvider, |
| lang::XServiceInfo, |
| com::sun::star::ucb::XContentProvider ); |
| |
| //========================================================================= |
| // |
| // XServiceInfo methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| sal_Bool SAL_CALL ContentProviderImplHelper::supportsService( |
| const rtl::OUString& ServiceName ) |
| throw( uno::RuntimeException ) |
| { |
| uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); |
| const rtl::OUString* pArray = aSNL.getConstArray(); |
| for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) |
| { |
| if ( pArray[ i ] == ServiceName ) |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| //========================================================================= |
| // |
| // XContentProvider methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds( |
| const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id1, |
| const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id2 ) |
| throw( uno::RuntimeException ) |
| { |
| // Simply do a string compare. |
| |
| rtl::OUString aURL1( Id1->getContentIdentifier() ); |
| rtl::OUString aURL2( Id2->getContentIdentifier() ); |
| |
| return aURL1.compareTo( aURL2 );; |
| } |
| |
| //========================================================================= |
| // |
| // Non-interface methods |
| // |
| //========================================================================= |
| |
| void ContentProviderImplHelper::cleanupRegisteredContents() |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| ucbhelper_impl::Contents::iterator it |
| = m_pImpl->m_aContents.begin(); |
| while( it != m_pImpl->m_aContents.end() ) |
| { |
| uno::Reference< ucb::XContent > xContent( (*it).second ); |
| if ( !xContent.is() ) |
| { |
| ucbhelper_impl::Contents::iterator tmp = it; |
| ++it; |
| m_pImpl->m_aContents.erase( tmp ); |
| } |
| else |
| { |
| ++it; |
| } |
| } |
| } |
| |
| //========================================================================= |
| |
| void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| cleanupRegisteredContents(); |
| |
| const rtl::OUString aURL( |
| pContent->getIdentifier()->getContentIdentifier() ); |
| |
| ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL ); |
| |
| if ( it != m_pImpl->m_aContents.end() ) |
| m_pImpl->m_aContents.erase( it ); |
| } |
| |
| //========================================================================= |
| rtl::Reference< ContentImplHelper > |
| ContentProviderImplHelper::queryExistingContent( |
| const uno::Reference< com::sun::star::ucb::XContentIdentifier >& |
| Identifier ) |
| { |
| return queryExistingContent( Identifier->getContentIdentifier() ); |
| } |
| |
| //========================================================================= |
| rtl::Reference< ContentImplHelper > |
| ContentProviderImplHelper::queryExistingContent( const rtl::OUString& rURL ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| cleanupRegisteredContents(); |
| |
| // Check, if a content with given id already exists... |
| |
| ucbhelper_impl::Contents::const_iterator it |
| = m_pImpl->m_aContents.find( rURL ); |
| if ( it != m_pImpl->m_aContents.end() ) |
| { |
| uno::Reference< ucb::XContent > xContent( (*it).second ); |
| if ( xContent.is() ) |
| { |
| return rtl::Reference< ContentImplHelper >( |
| static_cast< ContentImplHelper * >( xContent.get() ) ); |
| } |
| } |
| return rtl::Reference< ContentImplHelper >(); |
| } |
| |
| //========================================================================= |
| void ContentProviderImplHelper::queryExistingContents( |
| ContentRefList& rContents ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| cleanupRegisteredContents(); |
| |
| ucbhelper_impl::Contents::const_iterator it |
| = m_pImpl->m_aContents.begin(); |
| ucbhelper_impl::Contents::const_iterator end |
| = m_pImpl->m_aContents.end(); |
| |
| while ( it != end ) |
| { |
| uno::Reference< ucb::XContent > xContent( (*it).second ); |
| if ( xContent.is() ) |
| { |
| rContents.push_back( |
| rtl::Reference< ContentImplHelper >( |
| static_cast< ContentImplHelper * >( xContent.get() ) ) ); |
| } |
| ++it; |
| } |
| } |
| |
| //========================================================================= |
| void ContentProviderImplHelper::registerNewContent( |
| const uno::Reference< ucb::XContent > & xContent ) |
| { |
| if ( xContent.is() ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| cleanupRegisteredContents(); |
| |
| const rtl::OUString aURL( |
| xContent->getIdentifier()->getContentIdentifier() ); |
| ucbhelper_impl::Contents::const_iterator it |
| = m_pImpl->m_aContents.find( aURL ); |
| if ( it == m_pImpl->m_aContents.end() ) |
| m_pImpl->m_aContents[ aURL ] = xContent; |
| } |
| } |
| |
| //========================================================================= |
| uno::Reference< com::sun::star::ucb::XPropertySetRegistry > |
| ContentProviderImplHelper::getAdditionalPropertySetRegistry() |
| { |
| // Get propertyset registry. |
| |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| if ( !m_pImpl->m_xPropertySetRegistry.is() ) |
| { |
| uno::Reference< com::sun::star::ucb::XPropertySetRegistryFactory > |
| xRegFac( |
| m_xSMgr->createInstance( |
| rtl::OUString::createFromAscii( |
| "com.sun.star.ucb.Store" ) ), |
| uno::UNO_QUERY ); |
| |
| OSL_ENSURE( xRegFac.is(), |
| "ContentProviderImplHelper::getAdditionalPropertySet - " |
| "No UCB-Store service!" ); |
| |
| if ( xRegFac.is() ) |
| { |
| // Open/create a registry. |
| m_pImpl->m_xPropertySetRegistry |
| = xRegFac->createPropertySetRegistry( rtl::OUString() ); |
| |
| OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(), |
| "ContentProviderImplHelper::getAdditionalPropertySet - " |
| "Error opening registry!" ); |
| } |
| } |
| |
| return m_pImpl->m_xPropertySetRegistry; |
| } |
| |
| |
| //========================================================================= |
| uno::Reference< com::sun::star::ucb::XPersistentPropertySet > |
| ContentProviderImplHelper::getAdditionalPropertySet( |
| const rtl::OUString& rKey, sal_Bool bCreate ) |
| { |
| // Get propertyset registry. |
| getAdditionalPropertySetRegistry(); |
| |
| if ( m_pImpl->m_xPropertySetRegistry.is() ) |
| { |
| // Open/create persistent property set. |
| return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >( |
| m_pImpl->m_xPropertySetRegistry->openPropertySet( |
| rKey, bCreate ) ); |
| } |
| |
| return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >(); |
| } |
| |
| //========================================================================= |
| sal_Bool ContentProviderImplHelper::renameAdditionalPropertySet( |
| const rtl::OUString& rOldKey, |
| const rtl::OUString& rNewKey, |
| sal_Bool bRecursive ) |
| { |
| if ( rOldKey == rNewKey ) |
| return sal_True; |
| |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| if ( bRecursive ) |
| { |
| // Get propertyset registry. |
| getAdditionalPropertySetRegistry(); |
| |
| if ( m_pImpl->m_xPropertySetRegistry.is() ) |
| { |
| uno::Reference< container::XNameAccess > xNameAccess( |
| m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); |
| if ( xNameAccess.is() ) |
| { |
| uno::Sequence< rtl::OUString > aKeys |
| = xNameAccess->getElementNames(); |
| sal_Int32 nCount = aKeys.getLength(); |
| if ( nCount > 0 ) |
| { |
| rtl::OUString aOldKeyWithSlash = rOldKey; |
| rtl::OUString aOldKeyWithoutSlash; |
| if ( aOldKeyWithSlash.lastIndexOf( |
| sal_Unicode('/') |
| != aOldKeyWithSlash.getLength() - 1 ) ) |
| { |
| aOldKeyWithSlash += rtl::OUString( sal_Unicode('/') ); |
| aOldKeyWithoutSlash = rOldKey; |
| } |
| else if ( rOldKey.getLength() ) |
| aOldKeyWithoutSlash |
| = rOldKey.copy( 0, rOldKey.getLength() - 1 ); |
| |
| const rtl::OUString* pKeys = aKeys.getConstArray(); |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const rtl::OUString& rKey = pKeys[ n ]; |
| if ( rKey.compareTo( |
| aOldKeyWithSlash, |
| aOldKeyWithSlash.getLength() ) == 0 |
| || rKey.equals( aOldKeyWithoutSlash ) ) |
| { |
| rtl::OUString aNewKey |
| = rKey.replaceAt( |
| 0, rOldKey.getLength(), rNewKey ); |
| if ( !renameAdditionalPropertySet( |
| rKey, aNewKey, sal_False ) ) |
| return sal_False; |
| } |
| } |
| } |
| } |
| else |
| return sal_False; |
| } |
| else |
| return sal_False; |
| } |
| else |
| { |
| // Get old property set, if exists. |
| uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xOldSet |
| = getAdditionalPropertySet( rOldKey, sal_False ); |
| if ( xOldSet.is() ) |
| { |
| // Rename property set. |
| uno::Reference< container::XNamed > xNamed( |
| xOldSet, uno::UNO_QUERY ); |
| if ( xNamed.is() ) |
| { |
| // ??? throws no exceptions and has no return value ??? |
| xNamed->setName( rNewKey ); |
| } |
| else |
| return sal_False; |
| } |
| } |
| return sal_True; |
| } |
| |
| //========================================================================= |
| sal_Bool ContentProviderImplHelper::copyAdditionalPropertySet( |
| const rtl::OUString& rSourceKey, |
| const rtl::OUString& rTargetKey, |
| sal_Bool bRecursive ) |
| { |
| if ( rSourceKey == rTargetKey ) |
| return sal_True; |
| |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| if ( bRecursive ) |
| { |
| // Get propertyset registry. |
| getAdditionalPropertySetRegistry(); |
| |
| if ( m_pImpl->m_xPropertySetRegistry.is() ) |
| { |
| uno::Reference< container::XNameAccess > xNameAccess( |
| m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); |
| if ( xNameAccess.is() ) |
| { |
| uno::Sequence< rtl::OUString > aKeys |
| = xNameAccess->getElementNames(); |
| sal_Int32 nCount = aKeys.getLength(); |
| if ( nCount > 0 ) |
| { |
| rtl::OUString aSrcKeyWithSlash = rSourceKey; |
| rtl::OUString aSrcKeyWithoutSlash; |
| if ( aSrcKeyWithSlash.lastIndexOf( |
| sal_Unicode('/') |
| != aSrcKeyWithSlash.getLength() - 1 ) ) |
| { |
| aSrcKeyWithSlash += rtl::OUString( sal_Unicode('/') ); |
| aSrcKeyWithoutSlash = rSourceKey; |
| } |
| else if ( rSourceKey.getLength() ) |
| aSrcKeyWithoutSlash = rSourceKey.copy( |
| 0, rSourceKey.getLength() - 1 ); |
| |
| const rtl::OUString* pKeys = aKeys.getConstArray(); |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const rtl::OUString& rKey = pKeys[ n ]; |
| if ( rKey.compareTo( |
| aSrcKeyWithSlash, |
| aSrcKeyWithSlash.getLength() ) == 0 |
| || rKey.equals( aSrcKeyWithoutSlash ) ) |
| { |
| rtl::OUString aNewKey |
| = rKey.replaceAt( |
| 0, rSourceKey.getLength(), rTargetKey ); |
| if ( !copyAdditionalPropertySet( |
| rKey, aNewKey, sal_False ) ) |
| return sal_False; |
| } |
| } |
| } |
| } |
| else |
| return sal_False; |
| } |
| else |
| return sal_False; |
| } |
| else |
| { |
| // Get old property set, if exists. |
| uno::Reference< com::sun::star::ucb::XPersistentPropertySet > |
| xOldPropSet = getAdditionalPropertySet( rSourceKey, sal_False ); |
| if ( !xOldPropSet.is() ) |
| return sal_False; |
| |
| uno::Reference< beans::XPropertySetInfo > xPropSetInfo |
| = xOldPropSet->getPropertySetInfo(); |
| if ( !xPropSetInfo.is() ) |
| return sal_False; |
| |
| uno::Reference< beans::XPropertyAccess > xOldPropAccess( |
| xOldPropSet, uno::UNO_QUERY ); |
| if ( !xOldPropAccess.is() ) |
| return sal_False; |
| |
| // Obtain all values from old set. |
| uno::Sequence< beans::PropertyValue > aValues |
| = xOldPropAccess->getPropertyValues(); |
| sal_Int32 nCount = aValues.getLength(); |
| |
| uno::Sequence< beans::Property > aProps |
| = xPropSetInfo->getProperties(); |
| |
| if ( nCount ) |
| { |
| // Fail, if property set with new key already exists. |
| uno::Reference< com::sun::star::ucb::XPersistentPropertySet > |
| xNewPropSet |
| = getAdditionalPropertySet( rTargetKey, sal_False ); |
| if ( xNewPropSet.is() ) |
| return sal_False; |
| |
| // Create new, empty set. |
| xNewPropSet = getAdditionalPropertySet( rTargetKey, sal_True ); |
| if ( !xNewPropSet.is() ) |
| return sal_False; |
| |
| uno::Reference< beans::XPropertyContainer > xNewPropContainer( |
| xNewPropSet, uno::UNO_QUERY ); |
| if ( !xNewPropContainer.is() ) |
| return sal_False; |
| |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const beans::PropertyValue& rValue = aValues[ n ]; |
| |
| sal_Int16 nAttribs = 0; |
| for ( sal_Int32 m = 0; m < aProps.getLength(); ++m ) |
| { |
| if ( aProps[ m ].Name == rValue.Name ) |
| { |
| nAttribs = aProps[ m ].Attributes; |
| break; |
| } |
| } |
| |
| try |
| { |
| xNewPropContainer->addProperty( |
| rValue.Name, nAttribs, rValue.Value ); |
| } |
| catch ( beans::PropertyExistException & ) |
| { |
| } |
| catch ( beans::IllegalTypeException & ) |
| { |
| } |
| catch ( lang::IllegalArgumentException & ) |
| { |
| } |
| } |
| } |
| } |
| return sal_True; |
| } |
| |
| //========================================================================= |
| sal_Bool ContentProviderImplHelper::removeAdditionalPropertySet( |
| const rtl::OUString& rKey, sal_Bool bRecursive ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| if ( bRecursive ) |
| { |
| // Get propertyset registry. |
| getAdditionalPropertySetRegistry(); |
| |
| if ( m_pImpl->m_xPropertySetRegistry.is() ) |
| { |
| uno::Reference< container::XNameAccess > xNameAccess( |
| m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); |
| if ( xNameAccess.is() ) |
| { |
| uno::Sequence< rtl::OUString > aKeys |
| = xNameAccess->getElementNames(); |
| sal_Int32 nCount = aKeys.getLength(); |
| if ( nCount > 0 ) |
| { |
| rtl::OUString aKeyWithSlash = rKey; |
| rtl::OUString aKeyWithoutSlash; |
| if ( aKeyWithSlash.lastIndexOf( |
| sal_Unicode('/') |
| != aKeyWithSlash.getLength() - 1 ) ) |
| { |
| aKeyWithSlash += rtl::OUString( (sal_Unicode)'/' ); |
| aKeyWithoutSlash = rKey; |
| } |
| else if ( rKey.getLength() ) |
| aKeyWithoutSlash |
| = rKey.copy( 0, rKey.getLength() - 1 ); |
| |
| const rtl::OUString* pKeys = aKeys.getConstArray(); |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const rtl::OUString& rCurrKey = pKeys[ n ]; |
| if ( rCurrKey.compareTo( |
| aKeyWithSlash, |
| aKeyWithSlash.getLength() ) == 0 |
| || rCurrKey.equals( aKeyWithoutSlash ) ) |
| { |
| if ( !removeAdditionalPropertySet( |
| rCurrKey, sal_False ) ) |
| return sal_False; |
| } |
| } |
| } |
| } |
| else |
| return sal_False; |
| } |
| else |
| return sal_False; |
| } |
| else |
| { |
| // Get propertyset registry. |
| getAdditionalPropertySetRegistry(); |
| |
| if ( m_pImpl->m_xPropertySetRegistry.is() ) |
| m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey ); |
| else |
| return sal_False; |
| } |
| return sal_True; |
| } |
| |
| } // namespace ucbhelper |