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