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_framework.hxx" 30 31 #include "services/modulemanager.hxx" 32 #include "services/frame.hxx" 33 34 //_______________________________________________ 35 // own includes 36 #include <threadhelp/readguard.hxx> 37 #include <threadhelp/writeguard.hxx> 38 #include <services.h> 39 40 //_______________________________________________ 41 // interface includes 42 #include <com/sun/star/frame/XFrame.hpp> 43 #include <com/sun/star/frame/XController.hpp> 44 #include <com/sun/star/frame/XModel.hpp> 45 #include <com/sun/star/frame/XModule.hpp> 46 #include <comphelper/configurationhelper.hxx> 47 #include <comphelper/sequenceashashmap.hxx> 48 #include <comphelper/sequenceasvector.hxx> 49 #include <comphelper/enumhelper.hxx> 50 51 //_______________________________________________ 52 // other includes 53 #include <rtl/logfile.hxx> 54 55 namespace framework 56 { 57 58 static const ::rtl::OUString CFGPATH_FACTORIES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories"); 59 static const ::rtl::OUString MODULEPROP_IDENTIFIER = ::rtl::OUString::createFromAscii("ooSetupFactoryModuleIdentifier" ); 60 61 /*----------------------------------------------- 62 04.12.2003 09:32 63 -----------------------------------------------*/ 64 DEFINE_XINTERFACE_7(ModuleManager , 65 OWeakObject , 66 DIRECT_INTERFACE(css::lang::XTypeProvider ), 67 DIRECT_INTERFACE(css::lang::XServiceInfo ), 68 DIRECT_INTERFACE(css::container::XNameReplace ), 69 DIRECT_INTERFACE(css::container::XNameAccess ), 70 DIRECT_INTERFACE(css::container::XElementAccess ), 71 DIRECT_INTERFACE(css::container::XContainerQuery), 72 DIRECT_INTERFACE(css::frame::XModuleManager )) 73 74 /*----------------------------------------------- 75 04.12.2003 09:32 76 -----------------------------------------------*/ 77 DEFINE_XTYPEPROVIDER_7(ModuleManager , 78 css::lang::XTypeProvider , 79 css::lang::XServiceInfo , 80 css::container::XNameReplace , 81 css::container::XNameAccess , 82 css::container::XElementAccess , 83 css::container::XContainerQuery, 84 css::frame::XModuleManager ) 85 86 /*----------------------------------------------- 87 04.12.2003 09:35 88 -----------------------------------------------*/ 89 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(ModuleManager , 90 ::cppu::OWeakObject , 91 SERVICENAME_MODULEMANAGER , 92 IMPLEMENTATIONNAME_MODULEMANAGER) 93 94 /*----------------------------------------------- 95 04.12.2003 09:35 96 -----------------------------------------------*/ 97 DEFINE_INIT_SERVICE( 98 ModuleManager, 99 { 100 /*Attention 101 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() 102 to create a new instance of this class by our own supported service factory. 103 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! 104 */ 105 } 106 ) 107 108 /*----------------------------------------------- 109 04.12.2003 09:30 110 -----------------------------------------------*/ 111 ModuleManager::ModuleManager(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 112 : ThreadHelpBase( ) 113 , m_xSMGR (xSMGR) 114 { 115 } 116 117 /*----------------------------------------------- 118 10.12.2003 11:59 119 -----------------------------------------------*/ 120 ModuleManager::~ModuleManager() 121 { 122 if (m_xCFG.is()) 123 m_xCFG.clear(); 124 } 125 126 /*----------------------------------------------- 127 10.12.2003 11:02 128 -----------------------------------------------*/ 129 ::rtl::OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule) 130 throw(css::lang::IllegalArgumentException, 131 css::frame::UnknownModuleException, 132 css::uno::RuntimeException ) 133 { 134 // valid parameter? 135 css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY); 136 css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY); 137 css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY); 138 css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY); 139 140 if ( 141 (!xFrame.is() ) && 142 (!xWindow.is() ) && 143 (!xController.is()) && 144 (!xModel.is() ) 145 ) 146 { 147 throw css::lang::IllegalArgumentException( 148 ::rtl::OUString::createFromAscii("Given module is not a frame nor a window, controller or model."), 149 static_cast< ::cppu::OWeakObject* >(this), 150 1); 151 } 152 153 if (xFrame.is()) 154 { 155 xController = xFrame->getController(); 156 xWindow = xFrame->getComponentWindow(); 157 } 158 if (xController.is()) 159 xModel = xController->getModel(); 160 161 // modules are implemented by the deepest component in hierarchy ... 162 // Means: model -> controller -> window 163 // No fallbacks to higher components are allowed ! 164 // Note : A frame provides access to module components only ... but it's not a module by himself. 165 166 ::rtl::OUString sModule; 167 if (xModel.is()) 168 sModule = implts_identify(xModel); 169 else 170 if (xController.is()) 171 sModule = implts_identify(xController); 172 else 173 if (xWindow.is()) 174 sModule = implts_identify(xWindow); 175 176 if (sModule.getLength() < 1) 177 throw css::frame::UnknownModuleException( 178 ::rtl::OUString::createFromAscii("Cant find suitable module for the given component."), 179 static_cast< ::cppu::OWeakObject* >(this)); 180 181 return sModule; 182 } 183 184 /*----------------------------------------------- 185 08.03.2007 09:55 186 -----------------------------------------------*/ 187 void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName , 188 const css::uno::Any& aValue) 189 throw (css::lang::IllegalArgumentException , 190 css::container::NoSuchElementException, 191 css::lang::WrappedTargetException , 192 css::uno::RuntimeException ) 193 { 194 ::comphelper::SequenceAsHashMap lProps(aValue); 195 if (lProps.empty() ) 196 { 197 throw css::lang::IllegalArgumentException( 198 ::rtl::OUString::createFromAscii("No properties given to replace part of module."), 199 static_cast< css::container::XNameAccess* >(this), 200 2); 201 } 202 203 // SAFE -> ---------------------------------- 204 ReadGuard aReadLock(m_aLock); 205 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 206 aReadLock.unlock(); 207 // <- SAFE ---------------------------------- 208 209 // get access to the element 210 // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further 211 // it cache it as a member of this module manager instance. If we change some props there ... but dont 212 // flush changes (because an error occured) we will read them later. If we use a different config access 213 // we can close it without a flush ... and our read data wont be affected .-) 214 css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig( 215 xSMGR, 216 CFGPATH_FACTORIES, 217 ::comphelper::ConfigurationHelper::E_STANDARD); 218 css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW); 219 css::uno::Reference< css::container::XNameReplace > xModule ; 220 221 xModules->getByName(sName) >>= xModule; 222 if (!xModule.is()) 223 { 224 throw css::uno::RuntimeException( 225 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."), 226 static_cast< css::container::XNameAccess* >(this)); 227 } 228 229 ::comphelper::SequenceAsHashMap::const_iterator pProp; 230 for ( pProp = lProps.begin(); 231 pProp != lProps.end() ; 232 ++pProp ) 233 { 234 const ::rtl::OUString& sPropName = pProp->first; 235 const css::uno::Any& aPropValue = pProp->second; 236 237 // let "NoSuchElementException" out ! We support the same API ... 238 // and without a flush() at the end all changed data before will be ignored ! 239 xModule->replaceByName(sPropName, aPropValue); 240 } 241 242 ::comphelper::ConfigurationHelper::flush(xCfg); 243 } 244 245 /*----------------------------------------------- 246 10.12.2003 12:05 247 -----------------------------------------------*/ 248 css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName) 249 throw(css::container::NoSuchElementException, 250 css::lang::WrappedTargetException , 251 css::uno::RuntimeException ) 252 { 253 // get access to the element 254 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 255 css::uno::Reference< css::container::XNameAccess > xModule; 256 xCFG->getByName(sName) >>= xModule; 257 if (!xModule.is()) 258 { 259 throw css::uno::RuntimeException( 260 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."), 261 static_cast< css::container::XNameAccess* >(this)); 262 } 263 264 // convert it to seq< PropertyValue > 265 const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames(); 266 ::comphelper::SequenceAsHashMap lProps ; 267 sal_Int32 c = lPropNames.getLength(); 268 sal_Int32 i = 0; 269 270 lProps[MODULEPROP_IDENTIFIER] <<= sName; 271 for (i=0; i<c; ++i) 272 { 273 const ::rtl::OUString& sPropName = lPropNames[i]; 274 lProps[sPropName] = xModule->getByName(sPropName); 275 } 276 277 return css::uno::makeAny(lProps.getAsConstPropertyValueList()); 278 } 279 280 /*----------------------------------------------- 281 10.12.2003 11:58 282 -----------------------------------------------*/ 283 css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames() 284 throw(css::uno::RuntimeException) 285 { 286 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 287 return xCFG->getElementNames(); 288 } 289 290 /*----------------------------------------------- 291 10.12.2003 11:57 292 -----------------------------------------------*/ 293 sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName) 294 throw(css::uno::RuntimeException) 295 { 296 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 297 return xCFG->hasByName(sName); 298 } 299 300 /*----------------------------------------------- 301 10.12.2003 11:35 302 -----------------------------------------------*/ 303 css::uno::Type SAL_CALL ModuleManager::getElementType() 304 throw(css::uno::RuntimeException) 305 { 306 return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0); 307 } 308 309 /*----------------------------------------------- 310 10.12.2003 11:56 311 -----------------------------------------------*/ 312 sal_Bool SAL_CALL ModuleManager::hasElements() 313 throw(css::uno::RuntimeException) 314 { 315 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 316 return xCFG->hasElements(); 317 } 318 319 /*----------------------------------------------- 320 07.03.2007 12:55 321 -----------------------------------------------*/ 322 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&) 323 throw(css::uno::RuntimeException) 324 { 325 return css::uno::Reference< css::container::XEnumeration >(); 326 } 327 328 /*----------------------------------------------- 329 07.03.2007 12:55 330 -----------------------------------------------*/ 331 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) 332 throw(css::uno::RuntimeException) 333 { 334 ::comphelper::SequenceAsHashMap lSearchProps (lProperties); 335 css::uno::Sequence< ::rtl::OUString > lModules = getElementNames(); 336 sal_Int32 c = lModules.getLength(); 337 sal_Int32 i = 0; 338 ::comphelper::SequenceAsVector< css::uno::Any > lResult ; 339 340 for (i=0; i<c; ++i) 341 { 342 try 343 { 344 const ::rtl::OUString& sModule = lModules[i]; 345 ::comphelper::SequenceAsHashMap lModuleProps = getByName(sModule); 346 347 if (lModuleProps.match(lSearchProps)) 348 lResult.push_back(css::uno::makeAny(lModuleProps.getAsConstPropertyValueList())); 349 } 350 catch(const css::uno::Exception&) 351 {} 352 } 353 354 ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lResult.getAsConstList()); 355 css::uno::Reference< css::container::XEnumeration > xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW); 356 return xEnum; 357 } 358 359 /*----------------------------------------------- 360 14.12.2003 09:45 361 -----------------------------------------------*/ 362 css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig() 363 throw(css::uno::RuntimeException) 364 { 365 // SAFE -> ---------------------------------- 366 ReadGuard aReadLock(m_aLock); 367 if (m_xCFG.is()) 368 return m_xCFG; 369 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 370 aReadLock.unlock(); 371 // <- SAFE ---------------------------------- 372 373 css::uno::Reference< css::uno::XInterface > xCfg; 374 try 375 { 376 xCfg = ::comphelper::ConfigurationHelper::openConfig( 377 xSMGR, 378 CFGPATH_FACTORIES, 379 ::comphelper::ConfigurationHelper::E_READONLY); 380 } 381 catch(const css::uno::RuntimeException& exRun) 382 { throw exRun; } 383 catch(const css::uno::Exception&) 384 { xCfg.clear(); } 385 386 // SAFE -> ---------------------------------- 387 WriteGuard aWriteLock(m_aLock); 388 m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW); 389 return m_xCFG; 390 // <- SAFE ---------------------------------- 391 } 392 393 /*----------------------------------------------- 394 30.01.2004 07:54 395 -----------------------------------------------*/ 396 ::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent) 397 { 398 // Search for an optional (!) interface XModule first. 399 // Its used to overrule an existing service name. Used e.g. by our database form designer 400 // which uses a writer module internaly. 401 css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY); 402 if (xModule.is()) 403 return xModule->getIdentifier(); 404 405 // detect modules in a generic way ... 406 // comparing service names with configured entries ... 407 css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY); 408 if (!xInfo.is()) 409 return ::rtl::OUString(); 410 411 const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames(); 412 const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray(); 413 sal_Int32 c = lKnownModules.getLength(); 414 sal_Int32 i = 0; 415 416 for (i=0; i<c; ++i) 417 { 418 if (xInfo->supportsService(pKnownModules[i])) 419 return pKnownModules[i]; 420 } 421 422 return ::rtl::OUString(); 423 } 424 425 } // namespace framework 426