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 { 127 // valid parameter? 128 css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY); 129 css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY); 130 css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY); 131 css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY); 132 133 if ( 134 (!xFrame.is() ) && 135 (!xWindow.is() ) && 136 (!xController.is()) && 137 (!xModel.is() ) 138 ) 139 { 140 throw css::lang::IllegalArgumentException( 141 ::rtl::OUString::createFromAscii("Given module is not a frame nor a window, controller or model."), 142 static_cast< ::cppu::OWeakObject* >(this), 143 1); 144 } 145 146 if (xFrame.is()) 147 { 148 xController = xFrame->getController(); 149 xWindow = xFrame->getComponentWindow(); 150 } 151 if (xController.is()) 152 xModel = xController->getModel(); 153 154 // modules are implemented by the deepest component in hierarchy ... 155 // Means: model -> controller -> window 156 // No fallbacks to higher components are allowed ! 157 // Note : A frame provides access to module components only ... but it's not a module by himself. 158 159 ::rtl::OUString sModule; 160 if (xModel.is()) 161 sModule = implts_identify(xModel); 162 else 163 if (xController.is()) 164 sModule = implts_identify(xController); 165 else 166 if (xWindow.is()) 167 sModule = implts_identify(xWindow); 168 169 if (sModule.getLength() < 1) 170 throw css::frame::UnknownModuleException( 171 ::rtl::OUString::createFromAscii("Can't find suitable module for the given component."), 172 static_cast< ::cppu::OWeakObject* >(this)); 173 174 return sModule; 175 } 176 177 /*----------------------------------------------- 178 08.03.2007 09:55 179 -----------------------------------------------*/ 180 void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName , 181 const css::uno::Any& aValue) 182 { 183 ::comphelper::SequenceAsHashMap lProps(aValue); 184 if (lProps.empty() ) 185 { 186 throw css::lang::IllegalArgumentException( 187 ::rtl::OUString::createFromAscii("No properties given to replace part of module."), 188 static_cast< css::container::XNameAccess* >(this), 189 2); 190 } 191 192 // SAFE -> ---------------------------------- 193 ReadGuard aReadLock(m_aLock); 194 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 195 aReadLock.unlock(); 196 // <- SAFE ---------------------------------- 197 198 // get access to the element 199 // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further 200 // it cache it as a member of this module manager instance. If we change some props there ... but dont 201 // flush changes (because an error occurred) we will read them later. If we use a different config access 202 // we can close it without a flush ... and our read data won't be affected .-) 203 css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig( 204 xSMGR, 205 CFGPATH_FACTORIES, 206 ::comphelper::ConfigurationHelper::E_STANDARD); 207 css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW); 208 css::uno::Reference< css::container::XNameReplace > xModule ; 209 210 xModules->getByName(sName) >>= xModule; 211 if (!xModule.is()) 212 { 213 throw css::uno::RuntimeException( 214 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."), 215 static_cast< css::container::XNameAccess* >(this)); 216 } 217 218 ::comphelper::SequenceAsHashMap::const_iterator pProp; 219 for ( pProp = lProps.begin(); 220 pProp != lProps.end() ; 221 ++pProp ) 222 { 223 const ::rtl::OUString& sPropName = pProp->first; 224 const css::uno::Any& aPropValue = pProp->second; 225 226 // let "NoSuchElementException" out ! We support the same API ... 227 // and without a flush() at the end all changed data before will be ignored ! 228 xModule->replaceByName(sPropName, aPropValue); 229 } 230 231 ::comphelper::ConfigurationHelper::flush(xCfg); 232 } 233 234 /*----------------------------------------------- 235 10.12.2003 12:05 236 -----------------------------------------------*/ 237 css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName) 238 { 239 // get access to the element 240 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 241 css::uno::Reference< css::container::XNameAccess > xModule; 242 xCFG->getByName(sName) >>= xModule; 243 if (!xModule.is()) 244 { 245 throw css::uno::RuntimeException( 246 ::rtl::OUString::createFromAscii("Was not able to get write access to the requested module entry inside configuration."), 247 static_cast< css::container::XNameAccess* >(this)); 248 } 249 250 // convert it to seq< PropertyValue > 251 const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames(); 252 ::comphelper::SequenceAsHashMap lProps ; 253 sal_Int32 c = lPropNames.getLength(); 254 sal_Int32 i = 0; 255 256 lProps[MODULEPROP_IDENTIFIER] <<= sName; 257 for (i=0; i<c; ++i) 258 { 259 const ::rtl::OUString& sPropName = lPropNames[i]; 260 lProps[sPropName] = xModule->getByName(sPropName); 261 } 262 263 return css::uno::makeAny(lProps.getAsConstPropertyValueList()); 264 } 265 266 /*----------------------------------------------- 267 10.12.2003 11:58 268 -----------------------------------------------*/ 269 css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames() 270 { 271 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 272 return xCFG->getElementNames(); 273 } 274 275 /*----------------------------------------------- 276 10.12.2003 11:57 277 -----------------------------------------------*/ 278 sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName) 279 { 280 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 281 return xCFG->hasByName(sName); 282 } 283 284 /*----------------------------------------------- 285 10.12.2003 11:35 286 -----------------------------------------------*/ 287 css::uno::Type SAL_CALL ModuleManager::getElementType() 288 { 289 return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0); 290 } 291 292 /*----------------------------------------------- 293 10.12.2003 11:56 294 -----------------------------------------------*/ 295 sal_Bool SAL_CALL ModuleManager::hasElements() 296 { 297 css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); 298 return xCFG->hasElements(); 299 } 300 301 /*----------------------------------------------- 302 07.03.2007 12:55 303 -----------------------------------------------*/ 304 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&) 305 { 306 return css::uno::Reference< css::container::XEnumeration >(); 307 } 308 309 /*----------------------------------------------- 310 07.03.2007 12:55 311 -----------------------------------------------*/ 312 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) 313 { 314 ::comphelper::SequenceAsHashMap lSearchProps (lProperties); 315 css::uno::Sequence< ::rtl::OUString > lModules = getElementNames(); 316 sal_Int32 c = lModules.getLength(); 317 sal_Int32 i = 0; 318 ::comphelper::SequenceAsVector< css::uno::Any > lResult ; 319 320 for (i=0; i<c; ++i) 321 { 322 try 323 { 324 const ::rtl::OUString& sModule = lModules[i]; 325 ::comphelper::SequenceAsHashMap lModuleProps = getByName(sModule); 326 327 if (lModuleProps.match(lSearchProps)) 328 lResult.push_back(css::uno::makeAny(lModuleProps.getAsConstPropertyValueList())); 329 } 330 catch(const css::uno::Exception&) 331 {} 332 } 333 334 ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lResult.getAsConstList()); 335 css::uno::Reference< css::container::XEnumeration > xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW); 336 return xEnum; 337 } 338 339 /*----------------------------------------------- 340 14.12.2003 09:45 341 -----------------------------------------------*/ 342 css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig() 343 { 344 // SAFE -> ---------------------------------- 345 ReadGuard aReadLock(m_aLock); 346 if (m_xCFG.is()) 347 return m_xCFG; 348 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 349 aReadLock.unlock(); 350 // <- SAFE ---------------------------------- 351 352 css::uno::Reference< css::uno::XInterface > xCfg; 353 try 354 { 355 xCfg = ::comphelper::ConfigurationHelper::openConfig( 356 xSMGR, 357 CFGPATH_FACTORIES, 358 ::comphelper::ConfigurationHelper::E_READONLY); 359 } 360 catch(const css::uno::RuntimeException& exRun) 361 { throw exRun; } 362 catch(const css::uno::Exception&) 363 { xCfg.clear(); } 364 365 // SAFE -> ---------------------------------- 366 WriteGuard aWriteLock(m_aLock); 367 m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW); 368 return m_xCFG; 369 // <- SAFE ---------------------------------- 370 } 371 372 /*----------------------------------------------- 373 30.01.2004 07:54 374 -----------------------------------------------*/ 375 ::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent) 376 { 377 // Search for an optional (!) interface XModule first. 378 // It's used to overrule an existing service name. Used e.g. by our database form designer 379 // which uses a writer module internally. 380 css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY); 381 if (xModule.is()) 382 return xModule->getIdentifier(); 383 384 // detect modules in a generic way ... 385 // comparing service names with configured entries ... 386 css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY); 387 if (!xInfo.is()) 388 return ::rtl::OUString(); 389 390 const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames(); 391 const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray(); 392 sal_Int32 c = lKnownModules.getLength(); 393 sal_Int32 i = 0; 394 395 for (i=0; i<c; ++i) 396 { 397 if (xInfo->supportsService(pKnownModules[i])) 398 return pKnownModules[i]; 399 } 400 401 return ::rtl::OUString(); 402 } 403 404 } // namespace framework 405