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_unotools.hxx" 30 #include <unotools/configvaluecontainer.hxx> 31 #include <unotools/confignode.hxx> 32 #include <tools/debug.hxx> 33 #include <comphelper/stl_types.hxx> 34 #include <uno/data.h> 35 #include <algorithm> 36 37 #ifdef DBG_UTIL 38 #include <rtl/strbuf.hxx> 39 #endif 40 41 //......................................................................... 42 namespace utl 43 { 44 //......................................................................... 45 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::lang; 48 49 //===================================================================== 50 //= NodeValueAccessor 51 //===================================================================== 52 enum LocationType 53 { 54 ltSimplyObjectInstance, 55 ltAnyInstance, 56 57 ltUnbound 58 }; 59 60 struct NodeValueAccessor 61 { 62 private: 63 ::rtl::OUString sRelativePath; // the relative path of the node 64 LocationType eLocationType; // the type of location where the value is stored 65 void* pLocation; // the pointer to the location 66 Type aDataType; // the type object pointed to by pLocation 67 68 public: 69 NodeValueAccessor( const ::rtl::OUString& _rNodePath ); 70 71 void bind( void* _pLocation, const Type& _rType ); 72 void bind( Any* _pLocation ); 73 74 bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); } 75 const ::rtl::OUString& getPath( ) const { return sRelativePath; } 76 LocationType getLocType( ) const { return eLocationType; } 77 void* getLocation( ) const { return pLocation; } 78 const Type& getDataType( ) const { return aDataType; } 79 80 bool operator == ( const NodeValueAccessor& rhs ) const; 81 bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); } 82 }; 83 84 //--------------------------------------------------------------------- 85 //--- 20.08.01 17:21:13 ----------------------------------------------- 86 87 NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath ) 88 :sRelativePath( _rNodePath ) 89 ,eLocationType( ltUnbound ) 90 ,pLocation( NULL ) 91 { 92 } 93 94 //--------------------------------------------------------------------- 95 //--- 20.08.01 17:06:36 ----------------------------------------------- 96 97 bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const 98 { 99 return ( sRelativePath == rhs.sRelativePath ) 100 && ( eLocationType == rhs.eLocationType ) 101 && ( pLocation == rhs.pLocation ); 102 } 103 104 //--------------------------------------------------------------------- 105 //--- 20.08.01 17:47:43 ----------------------------------------------- 106 107 void NodeValueAccessor::bind( void* _pLocation, const Type& _rType ) 108 { 109 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" ); 110 111 eLocationType = ltSimplyObjectInstance; 112 pLocation = _pLocation; 113 aDataType = _rType; 114 } 115 116 //--------------------------------------------------------------------- 117 //--- 20.08.01 17:48:47 ----------------------------------------------- 118 119 void NodeValueAccessor::bind( Any* _pLocation ) 120 { 121 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" ); 122 123 eLocationType = ltAnyInstance; 124 pLocation = _pLocation; 125 aDataType = ::getCppuType( _pLocation ); 126 } 127 128 //--------------------------------------------------------------------- 129 //--- 20.08.01 17:42:17 ----------------------------------------------- 130 131 #ifndef UNX 132 static 133 #endif 134 void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex ) 135 { 136 ::osl::MutexGuard aGuard( _rMutex ); 137 138 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" ); 139 switch ( _rAccessor.getLocType() ) 140 { 141 case ltSimplyObjectInstance: 142 { 143 if ( _rData.hasValue() ) 144 { 145 #ifdef DBG_UTIL 146 sal_Bool bSuccess = 147 #endif 148 // assign the value 149 uno_type_assignData( 150 _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(), 151 const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(), 152 (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release 153 ); 154 #ifdef DBG_UTIL 155 rtl::OStringBuffer aBuf( 256 ); 156 aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: "); 157 aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) ); 158 aBuf.append( " !" ); 159 DBG_ASSERT( bSuccess, aBuf.getStr() ); 160 #endif 161 } 162 else { 163 DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" ); 164 } 165 } 166 break; 167 case ltAnyInstance: 168 // a simple assignment of an Any ... 169 *static_cast< Any* >( _rAccessor.getLocation() ) = _rData; 170 break; 171 default: 172 break; 173 } 174 } 175 176 //--------------------------------------------------------------------- 177 //--- 21.08.01 12:06:43 ----------------------------------------------- 178 179 #ifndef UNX 180 static 181 #endif 182 void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex ) 183 { 184 ::osl::MutexGuard aGuard( _rMutex ); 185 186 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" ); 187 switch ( _rAccessor.getLocType() ) 188 { 189 case ltSimplyObjectInstance: 190 // a simple setValue .... 191 _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() ); 192 break; 193 194 case ltAnyInstance: 195 // a simple assignment of an Any ... 196 _rData = *static_cast< Any* >( _rAccessor.getLocation() ); 197 break; 198 default: 199 break; 200 } 201 } 202 203 //===================================================================== 204 //= functors on NodeValueAccessor instances 205 //===================================================================== 206 207 //--------------------------------------------------------------------- 208 //--- 21.08.01 12:01:16 ----------------------------------------------- 209 210 /// base class for functors syncronizing between exchange locations and config sub nodes 211 struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void > 212 { 213 protected: 214 const OConfigurationNode& m_rRootNode; 215 ::osl::Mutex& m_rMutex; 216 217 public: 218 SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) 219 :m_rRootNode( _rRootNode ) 220 ,m_rMutex( _rMutex ) 221 { 222 } 223 }; 224 225 //--------------------------------------------------------------------- 226 //--- 21.08.01 11:25:56 ----------------------------------------------- 227 228 struct UpdateFromConfig : public SubNodeAccess 229 { 230 public: 231 UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { } 232 233 void operator() ( NodeValueAccessor& _rAccessor ) 234 { 235 ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex ); 236 } 237 }; 238 239 //--------------------------------------------------------------------- 240 //--- 21.08.01 11:25:56 ----------------------------------------------- 241 242 struct UpdateToConfig : public SubNodeAccess 243 { 244 public: 245 UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { } 246 247 void operator() ( NodeValueAccessor& _rAccessor ) 248 { 249 Any aNewValue; 250 lcl_copyData( aNewValue, _rAccessor, m_rMutex ); 251 m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue ); 252 } 253 }; 254 255 //--------------------------------------------------------------------- 256 //--- 20.08.01 16:58:24 ----------------------------------------------- 257 258 DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors ); 259 260 //===================================================================== 261 //= OConfigurationValueContainerImpl 262 //===================================================================== 263 struct OConfigurationValueContainerImpl 264 { 265 Reference< XMultiServiceFactory > xORB; // the service factory 266 ::osl::Mutex& rMutex; // the mutex for accessing the data containers 267 OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing 268 269 NodeValueAccessors aAccessors; // the accessors to the node values 270 271 OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex ) 272 :xORB( _rxORB ) 273 ,rMutex( _rMutex ) 274 { 275 } 276 }; 277 278 //===================================================================== 279 //= OConfigurationValueContainer 280 //===================================================================== 281 282 //--------------------------------------------------------------------- 283 //--- 20.08.01 15:53:35 ----------------------------------------------- 284 285 OConfigurationValueContainer::OConfigurationValueContainer( 286 const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety, 287 const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) 288 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) ) 289 { 290 implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels ); 291 } 292 293 //--------------------------------------------------------------------- 294 //--- 20.08.01 15:55:20 ----------------------------------------------- 295 296 OConfigurationValueContainer::OConfigurationValueContainer( 297 const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety, 298 const ::rtl::OUString& _rConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) 299 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) ) 300 { 301 implConstruct( _rConfigLocation, _nAccessFlags, _nLevels ); 302 } 303 304 //--------------------------------------------------------------------- 305 //--- 20.08.01 16:01:29 ----------------------------------------------- 306 307 OConfigurationValueContainer::~OConfigurationValueContainer() 308 { 309 delete m_pImpl; 310 } 311 312 //--------------------------------------------------------------------- 313 //--- 20.08.01 15:59:13 ----------------------------------------------- 314 315 const Reference< XMultiServiceFactory >& OConfigurationValueContainer::getServiceFactory( ) const 316 { 317 return m_pImpl->xORB; 318 } 319 320 //--------------------------------------------------------------------- 321 //--- 20.08.01 16:02:07 ----------------------------------------------- 322 323 void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation, 324 const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) 325 { 326 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" ); 327 328 // ................................. 329 // create the configuration node we're about to work with 330 m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory( 331 m_pImpl->xORB, 332 _rConfigLocation, 333 _nLevels, 334 ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_UPDATABLE : OConfigurationTreeRoot::CM_READONLY, 335 ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True 336 ); 337 #ifdef DBG_UTIL 338 rtl::OStringBuffer aBuf(256); 339 aBuf.append("Could not access the configuration node located at "); 340 aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) ); 341 aBuf.append( " !" ); 342 DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() ); 343 #endif 344 } 345 346 //--------------------------------------------------------------------- 347 //--- 20.08.01 16:39:05 ----------------------------------------------- 348 349 void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath, 350 void* _pContainer, const Type& _rValueType ) 351 { 352 // checks .... 353 DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" ); 354 DBG_ASSERT( ( TypeClass_CHAR == _rValueType.getTypeClass( ) ) 355 || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) ) 356 || ( TypeClass_BYTE == _rValueType.getTypeClass( ) ) 357 || ( TypeClass_SHORT == _rValueType.getTypeClass( ) ) 358 || ( TypeClass_LONG == _rValueType.getTypeClass( ) ) 359 || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) ) 360 || ( TypeClass_STRING == _rValueType.getTypeClass( ) ) 361 || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) ), 362 "OConfigurationValueContainer::registerExchangeLocation: invalid type!" ); 363 364 // build an accessor for this container 365 NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) ); 366 aNewAccessor.bind( _pContainer, _rValueType ); 367 368 // insert it into our structure 369 implRegisterExchangeLocation( aNewAccessor ); 370 } 371 372 //--------------------------------------------------------------------- 373 //--- 21.08.01 14:44:45 ----------------------------------------------- 374 375 void OConfigurationValueContainer::registerNullValueExchangeLocation( const sal_Char* _pRelativePath, Any* _pContainer ) 376 { 377 // build an accessor for this container 378 NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) ); 379 aNewAccessor.bind( _pContainer ); 380 381 // insert it into our structure 382 implRegisterExchangeLocation( aNewAccessor ); 383 } 384 385 //--------------------------------------------------------------------- 386 //--- 21.08.01 10:23:34 ----------------------------------------------- 387 388 void OConfigurationValueContainer::read( ) 389 { 390 for_each( 391 m_pImpl->aAccessors.begin(), 392 m_pImpl->aAccessors.end(), 393 UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex ) 394 ); 395 } 396 397 //--------------------------------------------------------------------- 398 //--- 21.08.01 12:04:48 ----------------------------------------------- 399 400 void OConfigurationValueContainer::write( sal_Bool _bCommit ) 401 { 402 // collect the current values in the exchange locations 403 for_each( 404 m_pImpl->aAccessors.begin(), 405 m_pImpl->aAccessors.end(), 406 UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex ) 407 ); 408 409 // commit the changes done (if requested) 410 if ( _bCommit ) 411 commit( sal_False ); 412 } 413 414 //--------------------------------------------------------------------- 415 //--- 21.08.01 12:09:45 ----------------------------------------------- 416 417 void OConfigurationValueContainer::commit( sal_Bool _bWrite ) 418 { 419 // write the current values in the exchange locations (if requested) 420 if ( _bWrite ) 421 write( sal_False ); 422 423 // commit the changes done 424 m_pImpl->aConfigRoot.commit( ); 425 } 426 427 //--------------------------------------------------------------------- 428 //--- 20.08.01 17:29:27 ----------------------------------------------- 429 430 void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor ) 431 { 432 // some checks 433 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ), 434 "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" ); 435 436 #ifdef DBG_UTIL 437 // another check (should be the first container for this node) 438 ConstNodeValueAccessorsIterator aExistent = ::std::find( 439 m_pImpl->aAccessors.begin(), 440 m_pImpl->aAccessors.end(), 441 _rAccessor 442 ); 443 DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" ); 444 #endif 445 446 // remember the accessor 447 m_pImpl->aAccessors.push_back( _rAccessor ); 448 449 // and initially fill the value 450 lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex ); 451 } 452 453 //......................................................................... 454 } // namespace utl 455 //......................................................................... 456 457