fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / uifactory / uielementfactorymanager.cxx
blob9e47837dbd455d289d771edef505fc413853a42e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <uifactory/configurationaccessfactorymanager.hxx>
23 #include <helper/mischelper.hxx>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/configuration/theDefaultProvider.hpp>
28 #include <com/sun/star/container/XContainer.hpp>
29 #include <com/sun/star/container/XContainerListener.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
32 #include <com/sun/star/frame/ModuleManager.hpp>
33 #include <com/sun/star/frame/XFrame.hpp>
34 #include <com/sun/star/frame/XModuleManager2.hpp>
35 #include <com/sun/star/ui/XUIElementFactoryManager.hpp>
37 #include <rtl/ustrbuf.hxx>
38 #include <cppuhelper/basemutex.hxx>
39 #include <cppuhelper/compbase2.hxx>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <vcl/svapp.hxx>
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::lang;
45 using namespace com::sun::star::beans;
46 using namespace com::sun::star::frame;
47 using namespace com::sun::star::configuration;
48 using namespace com::sun::star::container;
49 using namespace ::com::sun::star::ui;
50 using namespace ::com::sun::star::frame;
51 using namespace framework;
53 namespace framework
56 // global function needed by both implementations
57 static OUString getHashKeyFromStrings( const OUString& aType, const OUString& aName, const OUString& aModuleName )
59 OUStringBuffer aKey( aType );
60 aKey.appendAscii( "^" );
61 aKey.append( aName );
62 aKey.appendAscii( "^" );
63 aKey.append( aModuleName );
64 return aKey.makeStringAndClear();
67 ConfigurationAccess_FactoryManager::ConfigurationAccess_FactoryManager( const Reference< XComponentContext >& rxContext, const OUString& _sRoot ) :
68 m_aPropType( "Type" ),
69 m_aPropName( "Name" ),
70 m_aPropModule( "Module" ),
71 m_aPropFactory( "FactoryImplementation" ),
72 m_sRoot(_sRoot),
73 m_bConfigAccessInitialized( false )
75 m_xConfigProvider = theDefaultProvider::get( rxContext );
78 ConfigurationAccess_FactoryManager::~ConfigurationAccess_FactoryManager()
80 // SAFE
81 osl::MutexGuard g(m_aMutex);
83 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
84 if ( xContainer.is() )
85 xContainer->removeContainerListener(m_xConfigListener);
88 OUString ConfigurationAccess_FactoryManager::getFactorySpecifierFromTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule ) const
90 // SAFE
91 osl::MutexGuard g(m_aMutex);
93 FactoryManagerMap::const_iterator pIter =
94 m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rModule ));
95 if ( pIter != m_aFactoryManagerMap.end() )
96 return pIter->second;
97 else
99 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, OUString() ));
100 if ( pIter != m_aFactoryManagerMap.end() )
101 return pIter->second;
102 else
104 // Support factories which uses a defined prefix before the ui name.
105 sal_Int32 nIndex = rName.indexOf( '_' );
106 if ( nIndex > 0 )
108 OUString aName = rName.copy( 0, nIndex+1 );
109 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, aName, OUString() ));
110 if ( pIter != m_aFactoryManagerMap.end() )
111 return pIter->second;
114 pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, OUString(), OUString() ));
115 if ( pIter != m_aFactoryManagerMap.end() )
116 return pIter->second;
120 return OUString();
123 void ConfigurationAccess_FactoryManager::addFactorySpecifierToTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule, const OUString& rServiceSpecifier )
125 // SAFE
126 osl::MutexGuard g(m_aMutex);
128 OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule );
130 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey );
132 if ( pIter != m_aFactoryManagerMap.end() )
133 throw ElementExistException();
134 else
135 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, rServiceSpecifier ));
138 void ConfigurationAccess_FactoryManager::removeFactorySpecifierFromTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule )
140 // SAFE
141 osl::MutexGuard g(m_aMutex);
143 OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule );
145 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey );
147 if ( pIter == m_aFactoryManagerMap.end() )
148 throw NoSuchElementException();
149 else
150 m_aFactoryManagerMap.erase( aHashKey );
153 Sequence< Sequence< PropertyValue > > ConfigurationAccess_FactoryManager::getFactoriesDescription() const
155 // SAFE
156 osl::MutexGuard g(m_aMutex);
158 Sequence< Sequence< PropertyValue > > aSeqSeq;
160 sal_Int32 nIndex( 0 );
161 FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.begin();
162 while ( pIter != m_aFactoryManagerMap.end() )
164 OUString aFactory = pIter->first;
165 if ( !aFactory.isEmpty() )
167 sal_Int32 nToken = 0;
168 Sequence< PropertyValue > aSeq( 1 );
170 aSeqSeq.realloc( aSeqSeq.getLength() + 1 );
171 aSeq[0].Name = m_aPropType;
172 aSeq[0].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
173 if ( nToken > 0 )
175 aSeq.realloc( 2 );
176 aSeq[1].Name = m_aPropName;
177 aSeq[1].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
178 if ( nToken > 0 )
180 aSeq.realloc( 3 );
181 aSeq[2].Name = m_aPropModule;
182 aSeq[2].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
186 aSeqSeq[nIndex++] = aSeq;
189 ++pIter;
192 return aSeqSeq;
195 // container.XContainerListener
196 void SAL_CALL ConfigurationAccess_FactoryManager::elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException, std::exception)
198 OUString aType;
199 OUString aName;
200 OUString aModule;
201 OUString aService;
203 // SAFE
204 osl::MutexGuard g(m_aMutex);
206 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
208 // Create hash key from type, name and module as they are together a primary key to
209 // the UNO service that implements a user interface factory.
210 OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
211 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
215 void SAL_CALL ConfigurationAccess_FactoryManager::elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException, std::exception)
217 OUString aType;
218 OUString aName;
219 OUString aModule;
220 OUString aService;
222 // SAFE
223 osl::MutexGuard g(m_aMutex);
225 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
227 // Create hash key from command and model as they are together a primary key to
228 // the UNO service that implements the popup menu controller.
229 OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
230 m_aFactoryManagerMap.erase( aHashKey );
234 void SAL_CALL ConfigurationAccess_FactoryManager::elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException, std::exception)
236 OUString aType;
237 OUString aName;
238 OUString aModule;
239 OUString aService;
241 // SAFE
242 osl::MutexGuard g(m_aMutex);
244 if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
246 // Create hash key from command and model as they are together a primary key to
247 // the UNO service that implements the popup menu controller.
248 OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
249 m_aFactoryManagerMap.erase( aHashKey );
250 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
254 // lang.XEventListener
255 void SAL_CALL ConfigurationAccess_FactoryManager::disposing( const EventObject& ) throw(RuntimeException, std::exception)
257 // SAFE
258 // remove our reference to the config access
259 osl::MutexGuard g(m_aMutex);
260 m_xConfigAccess.clear();
263 void ConfigurationAccess_FactoryManager::readConfigurationData()
265 // SAFE
266 osl::MutexGuard g(m_aMutex);
268 if ( !m_bConfigAccessInitialized )
270 Sequence< Any > aArgs( 1 );
271 PropertyValue aPropValue;
273 aPropValue.Name = "nodepath";
274 aPropValue.Value <<= m_sRoot;
275 aArgs[0] <<= aPropValue;
279 m_xConfigAccess.set( m_xConfigProvider->createInstanceWithArguments(
280 "com.sun.star.configuration.ConfigurationAccess", aArgs ), UNO_QUERY );
282 catch ( const WrappedTargetException& )
286 m_bConfigAccessInitialized = true;
289 if ( m_xConfigAccess.is() )
291 Sequence< OUString > aUIElementFactories = m_xConfigAccess->getElementNames();
293 OUString aType;
294 OUString aName;
295 OUString aModule;
296 OUString aService;
297 OUString aHashKey;
298 Reference< XPropertySet > xPropertySet;
299 for ( sal_Int32 i = 0; i < aUIElementFactories.getLength(); i++ )
301 if ( impl_getElementProps( m_xConfigAccess->getByName( aUIElementFactories[i] ), aType, aName, aModule, aService ))
303 // Create hash key from type, name and module as they are together a primary key to
304 // the UNO service that implements the user interface element factory.
305 aHashKey = getHashKeyFromStrings( aType, aName, aModule );
306 m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
310 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
311 if ( xContainer.is() )
313 m_xConfigListener = new WeakContainerListener(this);
314 xContainer->addContainerListener(m_xConfigListener);
319 bool ConfigurationAccess_FactoryManager::impl_getElementProps( const Any& aElement, OUString& rType, OUString& rName, OUString& rModule, OUString& rServiceSpecifier ) const
321 Reference< XPropertySet > xPropertySet;
322 aElement >>= xPropertySet;
324 if ( xPropertySet.is() )
328 xPropertySet->getPropertyValue( m_aPropType ) >>= rType;
329 xPropertySet->getPropertyValue( m_aPropName ) >>= rName;
330 xPropertySet->getPropertyValue( m_aPropModule ) >>= rModule;
331 xPropertySet->getPropertyValue( m_aPropFactory ) >>= rServiceSpecifier;
333 catch ( const com::sun::star::beans::UnknownPropertyException& )
335 return false;
337 catch ( const com::sun::star::lang::WrappedTargetException& )
339 return false;
343 return true;
346 } // framework
348 namespace {
350 typedef ::cppu::WeakComponentImplHelper2<
351 css::lang::XServiceInfo,
352 css::ui::XUIElementFactoryManager> UIElementFactoryManager_BASE;
354 class UIElementFactoryManager : private cppu::BaseMutex,
355 public UIElementFactoryManager_BASE
357 virtual void SAL_CALL disposing() SAL_OVERRIDE;
358 public:
359 UIElementFactoryManager( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
360 virtual ~UIElementFactoryManager();
362 virtual OUString SAL_CALL getImplementationName()
363 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
365 return OUString("com.sun.star.comp.framework.UIElementFactoryManager");
368 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
369 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
371 return cppu::supportsService(this, ServiceName);
374 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
375 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
377 css::uno::Sequence< OUString > aSeq(1);
378 aSeq[0] = "com.sun.star.ui.UIElementFactoryManager";
379 return aSeq;
382 // XUIElementFactory
383 virtual css::uno::Reference< css::ui::XUIElement > SAL_CALL createUIElement( const OUString& ResourceURL, const css::uno::Sequence< css::beans::PropertyValue >& Args ) throw (css::container::NoSuchElementException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
385 // XUIElementFactoryRegistration
386 virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getRegisteredFactories( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
387 virtual css::uno::Reference< css::ui::XUIElementFactory > SAL_CALL getFactory( const OUString& ResourceURL, const OUString& ModuleIdentifier ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
388 virtual void SAL_CALL registerFactory( const OUString& aType, const OUString& aName, const OUString& aModuleIdentifier, const OUString& aFactoryImplementationName ) throw (css::container::ElementExistException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
389 virtual void SAL_CALL deregisterFactory( const OUString& aType, const OUString& aName, const OUString& aModuleIdentifier ) throw (css::container::NoSuchElementException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
391 private:
392 bool m_bConfigRead;
393 css::uno::Reference< css::uno::XComponentContext > m_xContext;
394 ConfigurationAccess_FactoryManager* m_pConfigAccess;
397 UIElementFactoryManager::UIElementFactoryManager( const Reference< XComponentContext >& rxContext ) :
398 UIElementFactoryManager_BASE(m_aMutex),
399 m_bConfigRead( false ),
400 m_xContext(rxContext)
402 m_pConfigAccess = new ConfigurationAccess_FactoryManager(rxContext,
403 "/org.openoffice.Office.UI.Factories/Registered/UIElementFactories");
404 m_pConfigAccess->acquire();
407 UIElementFactoryManager::~UIElementFactoryManager()
409 disposing();
412 void SAL_CALL UIElementFactoryManager::disposing()
414 osl::MutexGuard g(rBHelper.rMutex);
415 if (m_pConfigAccess)
417 // reduce reference count
418 m_pConfigAccess->release();
419 m_pConfigAccess = 0;
423 // XUIElementFactory
424 Reference< XUIElement > SAL_CALL UIElementFactoryManager::createUIElement(
425 const OUString& ResourceURL,
426 const Sequence< PropertyValue >& Args )
427 throw ( ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception )
429 Reference< XFrame > xFrame;
430 { // SAFE
431 osl::MutexGuard g(rBHelper.rMutex);
433 if ( !m_bConfigRead )
435 m_bConfigRead = true;
436 m_pConfigAccess->readConfigurationData();
439 // Retrieve the frame instance from the arguments to determine the module identifier. This must be provided
440 // to the search function. An empty module identifier is provided if the frame is missing or the module id cannot
441 // retrieve from it.
442 for ( int i = 0; i < Args.getLength(); i++ )
444 if ( Args[i].Name == "Frame")
445 Args[i].Value >>= xFrame;
447 } // SAFE
449 Reference< XModuleManager2 > xManager = ModuleManager::create( m_xContext );
451 // Determine the module identifier
454 OUString aModuleId;
455 if ( xFrame.is() && xManager.is() )
456 aModuleId = xManager->identify( Reference<XInterface>( xFrame, UNO_QUERY ) );
458 Reference< XUIElementFactory > xUIElementFactory = getFactory( ResourceURL, aModuleId );
459 if ( xUIElementFactory.is() )
460 return xUIElementFactory->createUIElement( ResourceURL, Args );
462 catch ( const UnknownModuleException& )
466 throw NoSuchElementException();
469 // XUIElementFactoryRegistration
470 Sequence< Sequence< PropertyValue > > SAL_CALL UIElementFactoryManager::getRegisteredFactories()
471 throw ( RuntimeException, std::exception )
473 // SAFE
474 osl::MutexGuard g(rBHelper.rMutex);
476 if ( !m_bConfigRead )
478 m_bConfigRead = true;
479 m_pConfigAccess->readConfigurationData();
482 return m_pConfigAccess->getFactoriesDescription();
485 Reference< XUIElementFactory > SAL_CALL UIElementFactoryManager::getFactory( const OUString& aResourceURL, const OUString& aModuleId )
486 throw ( RuntimeException, std::exception )
488 OUString aServiceSpecifier;
489 { // SAFE
490 osl::MutexGuard g(rBHelper.rMutex);
492 if ( !m_bConfigRead )
494 m_bConfigRead = true;
495 m_pConfigAccess->readConfigurationData();
498 OUString aType;
499 OUString aName;
501 RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName );
503 aServiceSpecifier = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId );
504 } // SAFE
506 if ( !aServiceSpecifier.isEmpty() ) try
508 return Reference< XUIElementFactory >(m_xContext->getServiceManager()->
509 createInstanceWithContext(aServiceSpecifier, m_xContext), UNO_QUERY);
511 catch ( const css::loader::CannotActivateFactoryException& )
513 SAL_WARN("fwk.uielement", aServiceSpecifier <<
514 " not available. This should happen only on mobile platforms.");
516 return Reference< XUIElementFactory >();
519 void SAL_CALL UIElementFactoryManager::registerFactory( const OUString& aType, const OUString& aName, const OUString& aModuleId, const OUString& aFactoryImplementationName )
520 throw ( ElementExistException, RuntimeException, std::exception )
522 // SAFE
523 osl::MutexGuard g(rBHelper.rMutex);
525 if ( !m_bConfigRead )
527 m_bConfigRead = true;
528 m_pConfigAccess->readConfigurationData();
531 m_pConfigAccess->addFactorySpecifierToTypeNameModule( aType, aName, aModuleId, aFactoryImplementationName );
532 // SAFE
535 void SAL_CALL UIElementFactoryManager::deregisterFactory( const OUString& aType, const OUString& aName, const OUString& aModuleId )
536 throw ( NoSuchElementException, RuntimeException, std::exception )
538 // SAFE
539 osl::MutexGuard g(rBHelper.rMutex);
541 if ( !m_bConfigRead )
543 m_bConfigRead = true;
544 m_pConfigAccess->readConfigurationData();
547 m_pConfigAccess->removeFactorySpecifierFromTypeNameModule( aType, aName, aModuleId );
548 // SAFE
551 struct Instance {
552 explicit Instance(
553 css::uno::Reference<css::uno::XComponentContext> const & context):
554 instance(static_cast<cppu::OWeakObject *>(
555 new UIElementFactoryManager(context)))
559 css::uno::Reference<css::uno::XInterface> instance;
562 struct Singleton:
563 public rtl::StaticWithArg<
564 Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
569 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
570 com_sun_star_comp_framework_UIElementFactoryManager_get_implementation(
571 css::uno::XComponentContext *context,
572 css::uno::Sequence<css::uno::Any> const &)
574 return cppu::acquire(static_cast<cppu::OWeakObject *>(
575 Singleton::get(context).instance.get()));
578 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */