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_framework.hxx" 26 27 //_________________________________________________________________________________________________________________ 28 // my own includes 29 //_________________________________________________________________________________________________________________ 30 #include <uifactory/uielementfactorymanager.hxx> 31 #include <uifactory/windowcontentfactorymanager.hxx> 32 #include <threadhelp/resetableguard.hxx> 33 #include "services.h" 34 35 //_________________________________________________________________________________________________________________ 36 // interface includes 37 //_________________________________________________________________________________________________________________ 38 #include <com/sun/star/beans/PropertyValue.hpp> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include <com/sun/star/container/XNameAccess.hpp> 41 #include <com/sun/star/container/XNameContainer.hpp> 42 #include <com/sun/star/container/XContainer.hpp> 43 #include <com/sun/star/frame/XFrame.hpp> 44 45 //_________________________________________________________________________________________________________________ 46 // includes of other projects 47 //_________________________________________________________________________________________________________________ 48 #include <rtl/ustrbuf.hxx> 49 #include <cppuhelper/weak.hxx> 50 #include <tools/urlobj.hxx> 51 #include <vcl/svapp.hxx> 52 #include <rtl/logfile.hxx> 53 //_________________________________________________________________________________________________________________ 54 // Defines 55 //_________________________________________________________________________________________________________________ 56 // 57 58 using namespace com::sun::star::uno; 59 using namespace com::sun::star::lang; 60 using namespace com::sun::star::beans; 61 using namespace com::sun::star::frame; 62 using namespace com::sun::star::container; 63 using namespace ::com::sun::star::ui; 64 using namespace ::com::sun::star::frame; 65 66 //_________________________________________________________________________________________________________________ 67 // Namespace 68 //_________________________________________________________________________________________________________________ 69 // 70 71 namespace framework 72 { 73 74 // global function needed by both implementations 75 rtl::OUString getHashKeyFromStrings( const rtl::OUString& aType, const rtl::OUString& aName, const rtl::OUString& aModuleName ) 76 { 77 rtl::OUStringBuffer aKey( aType ); 78 aKey.appendAscii( "^" ); 79 aKey.append( aName ); 80 aKey.appendAscii( "^" ); 81 aKey.append( aModuleName ); 82 return aKey.makeStringAndClear(); 83 } 84 85 86 //***************************************************************************************************************** 87 // Configuration access class for UIElementFactoryManager implementation 88 //***************************************************************************************************************** 89 90 91 ConfigurationAccess_FactoryManager::ConfigurationAccess_FactoryManager( Reference< XMultiServiceFactory >& rServiceManager,const ::rtl::OUString& _sRoot ) : 92 ThreadHelpBase(), 93 m_aPropType( RTL_CONSTASCII_USTRINGPARAM( "Type" )), 94 m_aPropName( RTL_CONSTASCII_USTRINGPARAM( "Name" )), 95 m_aPropModule( RTL_CONSTASCII_USTRINGPARAM( "Module" )), 96 m_aPropFactory( RTL_CONSTASCII_USTRINGPARAM( "FactoryImplementation" )), 97 m_sRoot(_sRoot), 98 m_xServiceManager( rServiceManager ), 99 m_bConfigAccessInitialized( sal_False ), 100 m_bConfigDirty(true) 101 { 102 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::ConfigurationAccess_FactoryManager" ); 103 m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance( SERVICENAME_CFGPROVIDER),UNO_QUERY ); 104 } 105 106 ConfigurationAccess_FactoryManager::~ConfigurationAccess_FactoryManager() 107 { 108 // SAFE 109 ResetableGuard aLock( m_aLock ); 110 111 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); 112 if ( xContainer.is() ) 113 xContainer->removeContainerListener( this ); 114 } 115 116 rtl::OUString ConfigurationAccess_FactoryManager::getFactorySpecifierFromTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule ) const 117 { 118 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactorySpecifierFromTypeNameModule" ); 119 // SAFE 120 ResetableGuard aLock( m_aLock ); 121 122 FactoryManagerMap::const_iterator pIter = 123 m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rModule )); 124 if ( pIter != m_aFactoryManagerMap.end() ) 125 return pIter->second; 126 else 127 { 128 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rtl::OUString() )); 129 if ( pIter != m_aFactoryManagerMap.end() ) 130 return pIter->second; 131 else 132 { 133 // Support factories which uses a defined prefix before the ui name. 134 sal_Int32 nIndex = rName.indexOf( '_' ); 135 if ( nIndex > 0 ) 136 { 137 rtl::OUString aName = rName.copy( 0, nIndex+1 ); 138 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, aName, rtl::OUString() )); 139 if ( pIter != m_aFactoryManagerMap.end() ) 140 return pIter->second; 141 } 142 143 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rtl::OUString(), rtl::OUString() )); 144 if ( pIter != m_aFactoryManagerMap.end() ) 145 return pIter->second; 146 } 147 } 148 149 return rtl::OUString(); 150 } 151 152 void ConfigurationAccess_FactoryManager::addFactorySpecifierToTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule, const rtl::OUString& rServiceSpecifier ) 153 { 154 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::addFactorySpecifierToTypeNameModule" ); 155 // SAFE 156 ResetableGuard aLock( m_aLock ); 157 158 rtl::OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule ); 159 160 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey ); 161 162 if ( pIter != m_aFactoryManagerMap.end() ) 163 throw ElementExistException(); 164 else 165 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, rServiceSpecifier )); 166 } 167 168 169 void ConfigurationAccess_FactoryManager::removeFactorySpecifierFromTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule ) 170 { 171 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::removeFactorySpecifierFromTypeNameModule" ); 172 // SAFE 173 ResetableGuard aLock( m_aLock ); 174 175 rtl::OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule ); 176 177 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey ); 178 179 if ( pIter == m_aFactoryManagerMap.end() ) 180 throw NoSuchElementException(); 181 else 182 m_aFactoryManagerMap.erase( aHashKey ); 183 } 184 185 Sequence< Sequence< PropertyValue > > ConfigurationAccess_FactoryManager::getFactoriesDescription() const 186 { 187 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactoriesDescription" ); 188 // SAFE 189 ResetableGuard aLock( m_aLock ); 190 191 Sequence< Sequence< PropertyValue > > aSeqSeq; 192 193 sal_Int32 nIndex( 0 ); 194 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.begin(); 195 while ( pIter != m_aFactoryManagerMap.end() ) 196 { 197 rtl::OUString aFactory = pIter->first; 198 if ( aFactory.getLength() > 0 ) 199 { 200 sal_Int32 nToken = 0; 201 Sequence< PropertyValue > aSeq( 1 ); 202 203 aSeqSeq.realloc( aSeqSeq.getLength() + 1 ); 204 aSeq[0].Name = m_aPropType; 205 aSeq[0].Value = makeAny( aFactory.getToken( 0, '^', nToken )); 206 if ( nToken > 0 ) 207 { 208 aSeq.realloc( 2 ); 209 aSeq[1].Name = m_aPropName; 210 aSeq[1].Value = makeAny( aFactory.getToken( 0, '^', nToken )); 211 if ( nToken > 0 ) 212 { 213 aSeq.realloc( 3 ); 214 aSeq[2].Name = m_aPropModule; 215 aSeq[2].Value = makeAny( aFactory.getToken( 0, '^', nToken )); 216 } 217 } 218 219 aSeqSeq[nIndex++] = aSeq; 220 } 221 222 ++pIter; 223 } 224 225 return aSeqSeq; 226 } 227 228 // container.XContainerListener 229 void SAL_CALL ConfigurationAccess_FactoryManager::elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException) 230 { 231 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementInserted" ); 232 rtl::OUString aType; 233 rtl::OUString aName; 234 rtl::OUString aModule; 235 rtl::OUString aService; 236 237 // SAFE 238 ResetableGuard aLock( m_aLock ); 239 240 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) 241 { 242 // Create hash key from type, name and module as they are together a primary key to 243 // the UNO service that implements a user interface factory. 244 rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); 245 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService )); 246 } 247 } 248 249 void SAL_CALL ConfigurationAccess_FactoryManager::elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException) 250 { 251 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementRemoved " ); 252 rtl::OUString aType; 253 rtl::OUString aName; 254 rtl::OUString aModule; 255 rtl::OUString aService; 256 257 // SAFE 258 ResetableGuard aLock( m_aLock ); 259 260 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) 261 { 262 // Create hash key from command and model as they are together a primary key to 263 // the UNO service that implements the popup menu controller. 264 rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); 265 m_aFactoryManagerMap.erase( aHashKey ); 266 } 267 } 268 269 void SAL_CALL ConfigurationAccess_FactoryManager::elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException) 270 { 271 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementReplaced" ); 272 rtl::OUString aType; 273 rtl::OUString aName; 274 rtl::OUString aModule; 275 rtl::OUString aService; 276 277 // SAFE 278 ResetableGuard aLock( m_aLock ); 279 280 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) 281 { 282 // Create hash key from command and model as they are together a primary key to 283 // the UNO service that implements the popup menu controller. 284 rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); 285 m_aFactoryManagerMap.erase( aHashKey ); 286 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService )); 287 } 288 } 289 290 // lang.XEventListener 291 void SAL_CALL ConfigurationAccess_FactoryManager::disposing( const EventObject& ) throw(RuntimeException) 292 { 293 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::disposing" ); 294 // SAFE 295 // remove our reference to the config access 296 ResetableGuard aLock( m_aLock ); 297 m_xConfigAccess.clear(); 298 } 299 300 void ConfigurationAccess_FactoryManager::readConfigurationData() 301 { 302 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::readConfigurationData" ); 303 // SAFE 304 ResetableGuard aLock( m_aLock ); 305 306 if ( !m_bConfigAccessInitialized ) 307 { 308 Sequence< Any > aArgs( 1 ); 309 PropertyValue aPropValue; 310 311 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); 312 aPropValue.Value <<= m_sRoot; 313 aArgs[0] <<= aPropValue; 314 315 try 316 { 317 m_xConfigAccess.set( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ), UNO_QUERY ); 318 } 319 catch ( WrappedTargetException& ) 320 { 321 } 322 323 m_bConfigAccessInitialized = sal_True; 324 } 325 326 if ( m_xConfigAccess.is() ) 327 { 328 Sequence< rtl::OUString > aUIElementFactories = m_xConfigAccess->getElementNames(); 329 330 rtl::OUString aType; 331 rtl::OUString aName; 332 rtl::OUString aModule; 333 rtl::OUString aService; 334 rtl::OUString aHashKey; 335 Reference< XPropertySet > xPropertySet; 336 for ( sal_Int32 i = 0; i < aUIElementFactories.getLength(); i++ ) 337 { 338 if ( impl_getElementProps( m_xConfigAccess->getByName( aUIElementFactories[i] ), aType, aName, aModule, aService )) 339 { 340 // Create hash key from type, name and module as they are together a primary key to 341 // the UNO service that implements the user interface element factory. 342 aHashKey = getHashKeyFromStrings( aType, aName, aModule ); 343 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService )); 344 } 345 } 346 347 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); 348 aLock.unlock(); 349 // UNSAFE 350 if ( xContainer.is() ) 351 xContainer->addContainerListener( this ); 352 } 353 } 354 355 sal_Bool ConfigurationAccess_FactoryManager::impl_getElementProps( const Any& aElement, rtl::OUString& rType, rtl::OUString& rName, rtl::OUString& rModule, rtl::OUString& rServiceSpecifier ) const 356 { 357 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::impl_getElementProps" ); 358 Reference< XPropertySet > xPropertySet; 359 aElement >>= xPropertySet; 360 361 if ( xPropertySet.is() ) 362 { 363 try 364 { 365 xPropertySet->getPropertyValue( m_aPropType ) >>= rType; 366 xPropertySet->getPropertyValue( m_aPropName ) >>= rName; 367 xPropertySet->getPropertyValue( m_aPropModule ) >>= rModule; 368 xPropertySet->getPropertyValue( m_aPropFactory ) >>= rServiceSpecifier; 369 } 370 catch ( com::sun::star::beans::UnknownPropertyException& ) 371 { 372 return sal_False; 373 } 374 catch ( com::sun::star::lang::WrappedTargetException& ) 375 { 376 return sal_False; 377 } 378 } 379 380 return sal_True; 381 } 382 383 //***************************************************************************************************************** 384 // XInterface, XTypeProvider, XServiceInfo 385 //***************************************************************************************************************** 386 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UIElementFactoryManager , 387 ::cppu::OWeakObject , 388 SERVICENAME_UIELEMENTFACTORYMANAGER , 389 IMPLEMENTATIONNAME_UIELEMENTFACTORYMANAGER 390 ) 391 392 DEFINE_INIT_SERVICE ( UIElementFactoryManager, {} ) 393 394 UIElementFactoryManager::UIElementFactoryManager( const Reference< XMultiServiceFactory >& xServiceManager ) : 395 ThreadHelpBase( &Application::GetSolarMutex() ), 396 m_bConfigRead( sal_False ), 397 m_xServiceManager( xServiceManager ) 398 { 399 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::UIElementFactoryManager" ); 400 m_pConfigAccess = new ConfigurationAccess_FactoryManager( m_xServiceManager,rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Factories/Registered/UIElementFactories" )) ); 401 m_pConfigAccess->acquire(); 402 m_xModuleManager = Reference< XModuleManager >( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY ); 403 } 404 405 UIElementFactoryManager::~UIElementFactoryManager() 406 { 407 ResetableGuard aLock( m_aLock ); 408 409 // reduce reference count 410 m_pConfigAccess->release(); 411 } 412 413 // XUIElementFactory 414 Reference< XUIElement > SAL_CALL UIElementFactoryManager::createUIElement( 415 const ::rtl::OUString& ResourceURL, 416 const Sequence< PropertyValue >& Args ) 417 throw ( ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) 418 { 419 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::createUIElement" ); 420 // SAFE 421 ResetableGuard aLock( m_aLock ); 422 423 if ( !m_bConfigRead ) 424 { 425 m_bConfigRead = sal_True; 426 m_pConfigAccess->readConfigurationData(); 427 } 428 429 const rtl::OUString aPropFrame( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); 430 431 rtl::OUString aModuleId; 432 PropertyValue aPropValue; 433 Reference< XFrame > xFrame; 434 435 // Retrieve the frame instance from the arguments to determine the module identifier. This must be provided 436 // to the search function. An empty module identifier is provided if the frame is missing or the module id cannot 437 // retrieve from it. 438 for ( int i = 0; i < Args.getLength(); i++ ) 439 { 440 if ( Args[i].Name.equals( aPropFrame )) 441 Args[i].Value >>= xFrame; 442 } 443 444 Reference< XModuleManager > xManager( m_xModuleManager ); 445 aLock.unlock(); 446 447 // Determine the module identifier 448 try 449 { 450 if ( xFrame.is() && xManager.is() ) 451 aModuleId = xManager->identify( Reference< XInterface >( xFrame, UNO_QUERY ) ); 452 453 Reference< XUIElementFactory > xUIElementFactory = getFactory( ResourceURL, aModuleId ); 454 if ( xUIElementFactory.is() ) 455 return xUIElementFactory->createUIElement( ResourceURL, Args ); 456 } 457 catch ( UnknownModuleException& ) 458 { 459 } 460 461 throw NoSuchElementException(); 462 } 463 464 // XUIElementFactoryRegistration 465 Sequence< Sequence< PropertyValue > > SAL_CALL UIElementFactoryManager::getRegisteredFactories() 466 throw ( RuntimeException ) 467 { 468 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getRegisteredFactories" ); 469 // SAFE 470 ResetableGuard aLock( m_aLock ); 471 472 if ( !m_bConfigRead ) 473 { 474 m_bConfigRead = sal_True; 475 m_pConfigAccess->readConfigurationData(); 476 } 477 478 return m_pConfigAccess->getFactoriesDescription(); 479 } 480 481 Reference< XUIElementFactory > SAL_CALL UIElementFactoryManager::getFactory( const ::rtl::OUString& aResourceURL, const ::rtl::OUString& aModuleId ) 482 throw ( RuntimeException ) 483 { 484 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactory" ); 485 ResetableGuard aLock( m_aLock ); 486 487 if ( !m_bConfigRead ) 488 { 489 m_bConfigRead = sal_True; 490 m_pConfigAccess->readConfigurationData(); 491 } 492 493 rtl::OUString aType; 494 rtl::OUString aName; 495 496 WindowContentFactoryManager::RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName ); 497 498 Reference< XMultiServiceFactory > xSManager( m_xServiceManager ); 499 500 rtl::OUString aServiceSpecifier = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId ); 501 502 aLock.unlock(); 503 if ( aServiceSpecifier.getLength() ) 504 return Reference< XUIElementFactory >( xSManager->createInstance( aServiceSpecifier ), UNO_QUERY ); 505 else 506 return Reference< XUIElementFactory >(); 507 } 508 509 void SAL_CALL UIElementFactoryManager::registerFactory( const ::rtl::OUString& aType, const ::rtl::OUString& aName, const ::rtl::OUString& aModuleId, const ::rtl::OUString& aFactoryImplementationName ) 510 throw ( ElementExistException, RuntimeException ) 511 { 512 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::registerFactory" ); 513 // SAFE 514 ResetableGuard aLock( m_aLock ); 515 516 if ( !m_bConfigRead ) 517 { 518 m_bConfigRead = sal_True; 519 m_pConfigAccess->readConfigurationData(); 520 } 521 522 m_pConfigAccess->addFactorySpecifierToTypeNameModule( aType, aName, aModuleId, aFactoryImplementationName ); 523 // SAFE 524 } 525 526 void SAL_CALL UIElementFactoryManager::deregisterFactory( const ::rtl::OUString& aType, const ::rtl::OUString& aName, const ::rtl::OUString& aModuleId ) 527 throw ( NoSuchElementException, RuntimeException ) 528 { 529 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::deregisterFactory" ); 530 // SAFE 531 ResetableGuard aLock( m_aLock ); 532 533 if ( !m_bConfigRead ) 534 { 535 m_bConfigRead = sal_True; 536 m_pConfigAccess->readConfigurationData(); 537 } 538 539 m_pConfigAccess->removeFactorySpecifierFromTypeNameModule( aType, aName, aModuleId ); 540 // SAFE 541 } 542 543 } // namespace framework 544