/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "services/modulemanager.hxx" #include "services/frame.hxx" //_______________________________________________ // own includes #include #include #include //_______________________________________________ // interface includes #include #include #include #include #include #include #include #include //_______________________________________________ // other includes #include namespace framework { static const ::rtl::OUString CFGPATH_FACTORIES (RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Setup/Office/Factories")); static const ::rtl::OUString MODULEPROP_IDENTIFIER(RTL_CONSTASCII_USTRINGPARAM("ooSetupFactoryModuleIdentifier")); /*----------------------------------------------- 04.12.2003 09:32 -----------------------------------------------*/ DEFINE_XINTERFACE_7(ModuleManager , OWeakObject , DIRECT_INTERFACE(css::lang::XTypeProvider ), DIRECT_INTERFACE(css::lang::XServiceInfo ), DIRECT_INTERFACE(css::container::XNameReplace ), DIRECT_INTERFACE(css::container::XNameAccess ), DIRECT_INTERFACE(css::container::XElementAccess ), DIRECT_INTERFACE(css::container::XContainerQuery), DIRECT_INTERFACE(css::frame::XModuleManager )) /*----------------------------------------------- 04.12.2003 09:32 -----------------------------------------------*/ DEFINE_XTYPEPROVIDER_7(ModuleManager , css::lang::XTypeProvider , css::lang::XServiceInfo , css::container::XNameReplace , css::container::XNameAccess , css::container::XElementAccess , css::container::XContainerQuery, css::frame::XModuleManager ) /*----------------------------------------------- 04.12.2003 09:35 -----------------------------------------------*/ DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(ModuleManager , ::cppu::OWeakObject , SERVICENAME_MODULEMANAGER , IMPLEMENTATIONNAME_MODULEMANAGER) /*----------------------------------------------- 04.12.2003 09:35 -----------------------------------------------*/ DEFINE_INIT_SERVICE( ModuleManager, { /*Attention I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() to create a new instance of this class by our own supported service factory. see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! */ } ) /*----------------------------------------------- 04.12.2003 09:30 -----------------------------------------------*/ ModuleManager::ModuleManager(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) : ThreadHelpBase( ) , m_xSMGR (xSMGR) { } /*----------------------------------------------- 10.12.2003 11:59 -----------------------------------------------*/ ModuleManager::~ModuleManager() { if (m_xCFG.is()) m_xCFG.clear(); } /*----------------------------------------------- 10.12.2003 11:02 -----------------------------------------------*/ ::rtl::OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule) throw(css::lang::IllegalArgumentException, css::frame::UnknownModuleException, css::uno::RuntimeException ) { // valid parameter? css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY); css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY); css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY); css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY); if ( (!xFrame.is() ) && (!xWindow.is() ) && (!xController.is()) && (!xModel.is() ) ) { throw css::lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Given module is not a frame nor a window, controller or model.")), static_cast< ::cppu::OWeakObject* >(this), 1); } if (xFrame.is()) { xController = xFrame->getController(); xWindow = xFrame->getComponentWindow(); } if (xController.is()) xModel = xController->getModel(); // modules are implemented by the deepest component in hierarchy ... // Means: model -> controller -> window // No fallbacks to higher components are allowed ! // Note : A frame provides access to module components only ... but it's not a module by himself. ::rtl::OUString sModule; if (xModel.is()) sModule = implts_identify(xModel); else if (xController.is()) sModule = implts_identify(xController); else if (xWindow.is()) sModule = implts_identify(xWindow); if (sModule.isEmpty()) throw css::frame::UnknownModuleException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cant find suitable module for the given component.")), static_cast< ::cppu::OWeakObject* >(this)); return sModule; } /*----------------------------------------------- 08.03.2007 09:55 -----------------------------------------------*/ void SAL_CALL ModuleManager::replaceByName(const ::rtl::OUString& sName , const css::uno::Any& aValue) throw (css::lang::IllegalArgumentException , css::container::NoSuchElementException, css::lang::WrappedTargetException , css::uno::RuntimeException ) { ::comphelper::SequenceAsHashMap lProps(aValue); if (lProps.empty() ) { throw css::lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No properties given to replace part of module.")), static_cast< css::container::XNameAccess* >(this), 2); } // SAFE -> ---------------------------------- ReadGuard aReadLock(m_aLock); css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; aReadLock.unlock(); // <- SAFE ---------------------------------- // get access to the element // Note: Dont use impl_getConfig() method here. Because it creates a readonly access only, further // it cache it as a member of this module manager instance. If we change some props there ... but dont // flush changes (because an error occurred) we will read them later. If we use a different config access // we can close it without a flush ... and our read data wont be affected .-) css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig( xSMGR, CFGPATH_FACTORIES, ::comphelper::ConfigurationHelper::E_STANDARD); css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW); css::uno::Reference< css::container::XNameReplace > xModule ; xModules->getByName(sName) >>= xModule; if (!xModule.is()) { throw css::uno::RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Was not able to get write access to the requested module entry inside configuration.")), static_cast< css::container::XNameAccess* >(this)); } ::comphelper::SequenceAsHashMap::const_iterator pProp; for ( pProp = lProps.begin(); pProp != lProps.end() ; ++pProp ) { const ::rtl::OUString& sPropName = pProp->first; const css::uno::Any& aPropValue = pProp->second; // let "NoSuchElementException" out ! We support the same API ... // and without a flush() at the end all changed data before will be ignored ! xModule->replaceByName(sPropName, aPropValue); } ::comphelper::ConfigurationHelper::flush(xCfg); } /*----------------------------------------------- 10.12.2003 12:05 -----------------------------------------------*/ css::uno::Any SAL_CALL ModuleManager::getByName(const ::rtl::OUString& sName) throw(css::container::NoSuchElementException, css::lang::WrappedTargetException , css::uno::RuntimeException ) { // get access to the element css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); css::uno::Reference< css::container::XNameAccess > xModule; xCFG->getByName(sName) >>= xModule; if (!xModule.is()) { throw css::uno::RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Was not able to get write access to the requested module entry inside configuration.")), static_cast< css::container::XNameAccess* >(this)); } // convert it to seq< PropertyValue > const css::uno::Sequence< ::rtl::OUString > lPropNames = xModule->getElementNames(); ::comphelper::SequenceAsHashMap lProps ; sal_Int32 c = lPropNames.getLength(); sal_Int32 i = 0; lProps[MODULEPROP_IDENTIFIER] <<= sName; for (i=0; igetByName(sPropName); } return css::uno::makeAny(lProps.getAsConstPropertyValueList()); } /*----------------------------------------------- 10.12.2003 11:58 -----------------------------------------------*/ css::uno::Sequence< ::rtl::OUString > SAL_CALL ModuleManager::getElementNames() throw(css::uno::RuntimeException) { css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); return xCFG->getElementNames(); } /*----------------------------------------------- 10.12.2003 11:57 -----------------------------------------------*/ sal_Bool SAL_CALL ModuleManager::hasByName(const ::rtl::OUString& sName) throw(css::uno::RuntimeException) { css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); return xCFG->hasByName(sName); } /*----------------------------------------------- 10.12.2003 11:35 -----------------------------------------------*/ css::uno::Type SAL_CALL ModuleManager::getElementType() throw(css::uno::RuntimeException) { return ::getCppuType((const css::uno::Sequence< css::beans::PropertyValue >*)0); } /*----------------------------------------------- 10.12.2003 11:56 -----------------------------------------------*/ sal_Bool SAL_CALL ModuleManager::hasElements() throw(css::uno::RuntimeException) { css::uno::Reference< css::container::XNameAccess > xCFG = implts_getConfig(); return xCFG->hasElements(); } /*----------------------------------------------- 07.03.2007 12:55 -----------------------------------------------*/ css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const ::rtl::OUString&) throw(css::uno::RuntimeException) { return css::uno::Reference< css::container::XEnumeration >(); } /*----------------------------------------------- 07.03.2007 12:55 -----------------------------------------------*/ css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) throw(css::uno::RuntimeException) { ::comphelper::SequenceAsHashMap lSearchProps (lProperties); css::uno::Sequence< ::rtl::OUString > lModules = getElementNames(); sal_Int32 c = lModules.getLength(); sal_Int32 i = 0; ::comphelper::SequenceAsVector< css::uno::Any > lResult ; for (i=0; i xEnum(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY_THROW); return xEnum; } /*----------------------------------------------- 14.12.2003 09:45 -----------------------------------------------*/ css::uno::Reference< css::container::XNameAccess > ModuleManager::implts_getConfig() throw(css::uno::RuntimeException) { // SAFE -> ---------------------------------- ReadGuard aReadLock(m_aLock); if (m_xCFG.is()) return m_xCFG; css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; aReadLock.unlock(); // <- SAFE ---------------------------------- css::uno::Reference< css::uno::XInterface > xCfg; try { xCfg = ::comphelper::ConfigurationHelper::openConfig( xSMGR, CFGPATH_FACTORIES, ::comphelper::ConfigurationHelper::E_READONLY); } catch(const css::uno::RuntimeException& exRun) { throw exRun; } catch(const css::uno::Exception&) { xCfg.clear(); } // SAFE -> ---------------------------------- WriteGuard aWriteLock(m_aLock); m_xCFG = css::uno::Reference< css::container::XNameAccess >(xCfg, css::uno::UNO_QUERY_THROW); return m_xCFG; // <- SAFE ---------------------------------- } /*----------------------------------------------- 30.01.2004 07:54 -----------------------------------------------*/ ::rtl::OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent) { // Search for an optional (!) interface XModule first. // Its used to overrule an existing service name. Used e.g. by our database form designer // which uses a writer module internaly. css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY); if (xModule.is()) return xModule->getIdentifier(); // detect modules in a generic way ... // comparing service names with configured entries ... css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY); if (!xInfo.is()) return ::rtl::OUString(); const css::uno::Sequence< ::rtl::OUString > lKnownModules = getElementNames(); const ::rtl::OUString* pKnownModules = lKnownModules.getConstArray(); sal_Int32 c = lKnownModules.getLength(); sal_Int32 i = 0; for (i=0; isupportsService(pKnownModules[i])) return pKnownModules[i]; } return ::rtl::OUString(); } } // namespace framework /* vim:set shiftwidth=4 softtabstop=4 expandtab: */