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