1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 #include <com/sun/star/lang/XServiceInfo.hpp> 31 #include <com/sun/star/lang/XTypeProvider.hpp> 32 #include <cppuhelper/weakagg.hxx> 33 #include <cppuhelper/interfacecontainer.hxx> 34 #include <comphelper/propertysethelper.hxx> 35 #include <osl/mutex.hxx> 36 #include <comphelper/genericpropertyset.hxx> 37 #include <comphelper/propertysetinfo.hxx> 38 #include <comphelper/stl_types.hxx> 39 #include <vos/mutex.hxx> 40 #include <rtl/uuid.h> 41 #include <boost/mem_fn.hpp> 42 #include <boost/bind.hpp> 43 #include <boost/utility.hpp> 44 45 /////////////////////////////////////////////////////////////////////// 46 47 using namespace ::rtl; 48 using namespace ::osl; 49 using namespace ::cppu; 50 using namespace ::comphelper; 51 using namespace ::com::sun::star; 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::beans; 54 using namespace ::com::sun::star::lang; 55 56 DECLARE_STL_USTRINGACCESS_MAP( Any, GenericAnyMapImpl ); 57 58 namespace comphelper 59 { 60 struct IMPL_GenericPropertySet_MutexContainer 61 { 62 Mutex maMutex ; 63 } ; 64 65 class GenericPropertySet : public OWeakAggObject, 66 public XServiceInfo, 67 public XTypeProvider, 68 public PropertySetHelper, 69 private IMPL_GenericPropertySet_MutexContainer 70 { 71 private: 72 GenericAnyMapImpl maAnyMap; 73 ::cppu::OMultiTypeInterfaceContainerHelperVar< ::rtl::OUString,UStringHash,UStringEqual> m_aListener; 74 75 protected: 76 virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException ); 77 virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue ) throw( UnknownPropertyException, WrappedTargetException ); 78 79 public: 80 GenericPropertySet( PropertySetInfo* pInfo ) throw(); 81 virtual ~GenericPropertySet() throw(); 82 83 // XInterface 84 virtual Any SAL_CALL queryAggregation( const Type & rType ) throw( RuntimeException); 85 virtual Any SAL_CALL queryInterface( const Type & rType ) throw( RuntimeException); 86 virtual void SAL_CALL acquire() throw(); 87 virtual void SAL_CALL release() throw(); 88 89 // XTypeProvider 90 virtual Sequence< Type > SAL_CALL getTypes( ) throw( RuntimeException); 91 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw( RuntimeException); 92 93 // XServiceInfo 94 virtual rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException ); 95 virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( RuntimeException ); 96 virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException ); 97 98 // XPropertySet 99 virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); 100 virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); 101 }; 102 103 } 104 105 /////////////////////////////////////////////////////////////////////// 106 107 GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw() 108 : PropertySetHelper( pInfo ) 109 ,m_aListener(maMutex) 110 { 111 } 112 113 GenericPropertySet::~GenericPropertySet() throw() 114 { 115 } 116 void SAL_CALL GenericPropertySet::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 117 { 118 Reference < XPropertySetInfo > xInfo = getPropertySetInfo( ); 119 if ( xInfo.is() ) 120 { 121 if ( !aPropertyName.getLength() ) 122 { 123 Sequence< Property> aSeq = xInfo->getProperties(); 124 const Property* pIter = aSeq.getConstArray(); 125 const Property* pEnd = pIter + aSeq.getLength(); 126 for( ; pIter != pEnd ; ++pIter) 127 { 128 m_aListener.addInterface(pIter->Name,xListener); 129 } 130 } 131 else if ( xInfo->hasPropertyByName(aPropertyName) ) 132 m_aListener.addInterface(aPropertyName,xListener); 133 else 134 throw UnknownPropertyException( aPropertyName, *this ); 135 } 136 } 137 138 void SAL_CALL GenericPropertySet::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 139 { 140 ResettableMutexGuard aGuard( maMutex ); 141 Reference < XPropertySetInfo > xInfo = getPropertySetInfo( ); 142 aGuard.clear(); 143 if ( xInfo.is() ) 144 { 145 if ( !aPropertyName.getLength() ) 146 { 147 Sequence< Property> aSeq = xInfo->getProperties(); 148 const Property* pIter = aSeq.getConstArray(); 149 const Property* pEnd = pIter + aSeq.getLength(); 150 for( ; pIter != pEnd ; ++pIter) 151 { 152 m_aListener.removeInterface(pIter->Name,xListener); 153 } 154 } 155 else if ( xInfo->hasPropertyByName(aPropertyName) ) 156 m_aListener.removeInterface(aPropertyName,xListener); 157 else 158 throw UnknownPropertyException( aPropertyName, *this ); 159 } 160 } 161 162 void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) 163 throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException ) 164 { 165 ResettableMutexGuard aGuard( maMutex ); 166 167 while( *ppEntries ) 168 { 169 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US ); 170 OInterfaceContainerHelper * pHelper = m_aListener.getContainer(aPropertyName); 171 172 maAnyMap[ aPropertyName ] = *pValues; 173 174 if ( pHelper ) 175 { 176 PropertyChangeEvent aEvt; 177 aEvt.PropertyName = aPropertyName; 178 aEvt.NewValue = *pValues; 179 aGuard.clear(); 180 pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt ); 181 aGuard.reset(); 182 } 183 184 ppEntries++; 185 pValues++; 186 } 187 } 188 189 void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue ) 190 throw( UnknownPropertyException, WrappedTargetException ) 191 { 192 MutexGuard aGuard( maMutex ); 193 194 while( *ppEntries ) 195 { 196 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US ); 197 *pValue = maAnyMap[ aPropertyName ]; 198 199 ppEntries++; 200 pValue++; 201 } 202 } 203 204 // XInterface 205 206 Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType ) 207 throw( RuntimeException ) 208 { 209 return OWeakAggObject::queryInterface( rType ); 210 } 211 212 Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType ) 213 throw(RuntimeException) 214 { 215 Any aAny; 216 217 if( rType == ::getCppuType((const Reference< XServiceInfo >*)0) ) 218 aAny <<= Reference< XServiceInfo >(this); 219 else if( rType == ::getCppuType((const Reference< XTypeProvider >*)0) ) 220 aAny <<= Reference< XTypeProvider >(this); 221 else if( rType == ::getCppuType((const Reference< XPropertySet >*)0) ) 222 aAny <<= Reference< XPropertySet >(this); 223 else if( rType == ::getCppuType((const Reference< XMultiPropertySet >*)0) ) 224 aAny <<= Reference< XMultiPropertySet >(this); 225 else 226 aAny <<= OWeakAggObject::queryAggregation( rType ); 227 228 return aAny; 229 } 230 231 void SAL_CALL GenericPropertySet::acquire() throw() 232 { 233 OWeakAggObject::acquire(); 234 } 235 236 void SAL_CALL GenericPropertySet::release() throw() 237 { 238 OWeakAggObject::release(); 239 } 240 241 uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes() 242 throw (uno::RuntimeException) 243 { 244 uno::Sequence< uno::Type > aTypes( 5 ); 245 uno::Type* pTypes = aTypes.getArray(); 246 247 *pTypes++ = ::getCppuType((const uno::Reference< XAggregation>*)0); 248 *pTypes++ = ::getCppuType((const uno::Reference< XServiceInfo>*)0); 249 *pTypes++ = ::getCppuType((const uno::Reference< XTypeProvider>*)0); 250 *pTypes++ = ::getCppuType((const uno::Reference< XPropertySet>*)0); 251 *pTypes++ = ::getCppuType((const uno::Reference< XMultiPropertySet>*)0); 252 253 return aTypes; 254 } 255 256 uno::Sequence< sal_Int8 > SAL_CALL GenericPropertySet::getImplementationId() 257 throw (uno::RuntimeException) 258 { 259 MutexGuard aGuard( maMutex ); 260 261 static uno::Sequence< sal_Int8 > aId; 262 if( aId.getLength() == 0 ) 263 { 264 aId.realloc( 16 ); 265 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); 266 } 267 return aId; 268 } 269 270 // XServiceInfo 271 272 sal_Bool SAL_CALL GenericPropertySet::supportsService( const OUString& ServiceName ) throw(RuntimeException) 273 { 274 Sequence< OUString > aSNL( getSupportedServiceNames() ); 275 const OUString * pArray = aSNL.getConstArray(); 276 277 for( sal_Int32 i = 0; i < aSNL.getLength(); ++i ) 278 if( pArray[i] == ServiceName ) 279 return sal_True; 280 281 return sal_False; 282 } 283 284 OUString SAL_CALL GenericPropertySet::getImplementationName() throw( RuntimeException ) 285 { 286 return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.comphelper.GenericPropertySet") ); 287 } 288 289 Sequence< OUString > SAL_CALL GenericPropertySet::getSupportedServiceNames( ) 290 throw( RuntimeException ) 291 { 292 Sequence< OUString > aSNS( 1 ); 293 aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.XPropertySet" )); 294 return aSNS; 295 } 296 297 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > comphelper::GenericPropertySet_CreateInstance( comphelper::PropertySetInfo* pInfo ) 298 { 299 return (XPropertySet*)new GenericPropertySet( pInfo ); 300 } 301 302