1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: uielementfactorymanager.cxx,v $
10 * $Revision: 1.10.12.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_________________________________________________________________________________________________________________
36 //_________________________________________________________________________________________________________________
37 #include <uifactory/uielementfactorymanager.hxx>
38 #include <uifactory/windowcontentfactorymanager.hxx>
39 #include <threadhelp/resetableguard.hxx>
42 //_________________________________________________________________________________________________________________
44 //_________________________________________________________________________________________________________________
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/container/XNameContainer.hpp>
49 #include <com/sun/star/container/XContainer.hpp>
50 #include <com/sun/star/frame/XFrame.hpp>
52 //_________________________________________________________________________________________________________________
53 // includes of other projects
54 //_________________________________________________________________________________________________________________
55 #include <rtl/ustrbuf.hxx>
56 #include <cppuhelper/weak.hxx>
57 #include <tools/urlobj.hxx>
58 #include <vcl/svapp.hxx>
59 #include <rtl/logfile.hxx>
60 //_________________________________________________________________________________________________________________
62 //_________________________________________________________________________________________________________________
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::lang
;
67 using namespace com::sun::star::beans
;
68 using namespace com::sun::star::frame
;
69 using namespace com::sun::star::container
;
70 using namespace ::com::sun::star::ui
;
71 using namespace ::com::sun::star::frame
;
73 //_________________________________________________________________________________________________________________
75 //_________________________________________________________________________________________________________________
81 // global function needed by both implementations
82 rtl::OUString
getHashKeyFromStrings( const rtl::OUString
& aType
, const rtl::OUString
& aName
, const rtl::OUString
& aModuleName
)
84 rtl::OUStringBuffer
aKey( aType
);
85 aKey
.appendAscii( "^" );
87 aKey
.appendAscii( "^" );
88 aKey
.append( aModuleName
);
89 return aKey
.makeStringAndClear();
93 //*****************************************************************************************************************
94 // Configuration access class for UIElementFactoryManager implementation
95 //*****************************************************************************************************************
98 ConfigurationAccess_FactoryManager::ConfigurationAccess_FactoryManager( Reference
< XMultiServiceFactory
>& rServiceManager
,const ::rtl::OUString
& _sRoot
) :
100 m_aPropType( RTL_CONSTASCII_USTRINGPARAM( "Type" )),
101 m_aPropName( RTL_CONSTASCII_USTRINGPARAM( "Name" )),
102 m_aPropModule( RTL_CONSTASCII_USTRINGPARAM( "Module" )),
103 m_aPropFactory( RTL_CONSTASCII_USTRINGPARAM( "FactoryImplementation" )),
105 m_xServiceManager( rServiceManager
),
106 m_bConfigAccessInitialized( sal_False
),
109 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::ConfigurationAccess_FactoryManager" );
110 m_xConfigProvider
= Reference
< XMultiServiceFactory
>( rServiceManager
->createInstance( SERVICENAME_CFGPROVIDER
),UNO_QUERY
);
113 ConfigurationAccess_FactoryManager::~ConfigurationAccess_FactoryManager()
116 ResetableGuard
aLock( m_aLock
);
118 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
119 if ( xContainer
.is() )
120 xContainer
->removeContainerListener( this );
123 rtl::OUString
ConfigurationAccess_FactoryManager::getFactorySpecifierFromTypeNameModule( const rtl::OUString
& rType
, const rtl::OUString
& rName
, const rtl::OUString
& rModule
) const
125 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactorySpecifierFromTypeNameModule" );
127 ResetableGuard
aLock( m_aLock
);
129 FactoryManagerMap::const_iterator pIter
=
130 m_aFactoryManagerMap
.find( getHashKeyFromStrings( rType
, rName
, rModule
));
131 if ( pIter
!= m_aFactoryManagerMap
.end() )
132 return pIter
->second
;
135 pIter
= m_aFactoryManagerMap
.find( getHashKeyFromStrings( rType
, rName
, rtl::OUString() ));
136 if ( pIter
!= m_aFactoryManagerMap
.end() )
137 return pIter
->second
;
140 // Support factories which uses a defined prefix before the ui name.
141 sal_Int32 nIndex
= rName
.indexOf( '_' );
144 rtl::OUString aName
= rName
.copy( 0, nIndex
+1 );
145 pIter
= m_aFactoryManagerMap
.find( getHashKeyFromStrings( rType
, aName
, rtl::OUString() ));
146 if ( pIter
!= m_aFactoryManagerMap
.end() )
147 return pIter
->second
;
150 pIter
= m_aFactoryManagerMap
.find( getHashKeyFromStrings( rType
, rtl::OUString(), rtl::OUString() ));
151 if ( pIter
!= m_aFactoryManagerMap
.end() )
152 return pIter
->second
;
156 return rtl::OUString();
159 void ConfigurationAccess_FactoryManager::addFactorySpecifierToTypeNameModule( const rtl::OUString
& rType
, const rtl::OUString
& rName
, const rtl::OUString
& rModule
, const rtl::OUString
& rServiceSpecifier
)
161 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::addFactorySpecifierToTypeNameModule" );
163 ResetableGuard
aLock( m_aLock
);
165 rtl::OUString aHashKey
= getHashKeyFromStrings( rType
, rName
, rModule
);
167 FactoryManagerMap::const_iterator pIter
= m_aFactoryManagerMap
.find( aHashKey
);
169 if ( pIter
!= m_aFactoryManagerMap
.end() )
170 throw ElementExistException();
172 m_aFactoryManagerMap
.insert( FactoryManagerMap::value_type( aHashKey
, rServiceSpecifier
));
176 void ConfigurationAccess_FactoryManager::removeFactorySpecifierFromTypeNameModule( const rtl::OUString
& rType
, const rtl::OUString
& rName
, const rtl::OUString
& rModule
)
178 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::removeFactorySpecifierFromTypeNameModule" );
180 ResetableGuard
aLock( m_aLock
);
182 rtl::OUString aHashKey
= getHashKeyFromStrings( rType
, rName
, rModule
);
184 FactoryManagerMap::const_iterator pIter
= m_aFactoryManagerMap
.find( aHashKey
);
186 if ( pIter
== m_aFactoryManagerMap
.end() )
187 throw NoSuchElementException();
189 m_aFactoryManagerMap
.erase( aHashKey
);
192 Sequence
< Sequence
< PropertyValue
> > ConfigurationAccess_FactoryManager::getFactoriesDescription() const
194 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactoriesDescription" );
196 ResetableGuard
aLock( m_aLock
);
198 Sequence
< Sequence
< PropertyValue
> > aSeqSeq
;
200 sal_Int32
nIndex( 0 );
201 FactoryManagerMap::const_iterator pIter
= m_aFactoryManagerMap
.begin();
202 while ( pIter
!= m_aFactoryManagerMap
.end() )
204 rtl::OUString aFactory
= pIter
->first
;
205 if ( aFactory
.getLength() > 0 )
207 sal_Int32 nToken
= 0;
208 Sequence
< PropertyValue
> aSeq( 1 );
210 aSeqSeq
.realloc( aSeqSeq
.getLength() + 1 );
211 aSeq
[0].Name
= m_aPropType
;
212 aSeq
[0].Value
= makeAny( aFactory
.getToken( 0, '^', nToken
));
216 aSeq
[1].Name
= m_aPropName
;
217 aSeq
[1].Value
= makeAny( aFactory
.getToken( 0, '^', nToken
));
221 aSeq
[2].Name
= m_aPropModule
;
222 aSeq
[2].Value
= makeAny( aFactory
.getToken( 0, '^', nToken
));
226 aSeqSeq
[nIndex
++] = aSeq
;
235 // container.XContainerListener
236 void SAL_CALL
ConfigurationAccess_FactoryManager::elementInserted( const ContainerEvent
& aEvent
) throw(RuntimeException
)
238 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementInserted" );
241 rtl::OUString aModule
;
242 rtl::OUString aService
;
245 ResetableGuard
aLock( m_aLock
);
247 if ( impl_getElementProps( aEvent
.Element
, aType
, aName
, aModule
, aService
))
249 // Create hash key from type, name and module as they are together a primary key to
250 // the UNO service that implements a user interface factory.
251 rtl::OUString
aHashKey( getHashKeyFromStrings( aType
, aName
, aModule
));
252 m_aFactoryManagerMap
.insert( FactoryManagerMap::value_type( aHashKey
, aService
));
256 void SAL_CALL
ConfigurationAccess_FactoryManager::elementRemoved ( const ContainerEvent
& aEvent
) throw(RuntimeException
)
258 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementRemoved " );
261 rtl::OUString aModule
;
262 rtl::OUString aService
;
265 ResetableGuard
aLock( m_aLock
);
267 if ( impl_getElementProps( aEvent
.Element
, aType
, aName
, aModule
, aService
))
269 // Create hash key from command and model as they are together a primary key to
270 // the UNO service that implements the popup menu controller.
271 rtl::OUString
aHashKey( getHashKeyFromStrings( aType
, aName
, aModule
));
272 m_aFactoryManagerMap
.erase( aHashKey
);
276 void SAL_CALL
ConfigurationAccess_FactoryManager::elementReplaced( const ContainerEvent
& aEvent
) throw(RuntimeException
)
278 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementReplaced" );
281 rtl::OUString aModule
;
282 rtl::OUString aService
;
285 ResetableGuard
aLock( m_aLock
);
287 if ( impl_getElementProps( aEvent
.Element
, aType
, aName
, aModule
, aService
))
289 // Create hash key from command and model as they are together a primary key to
290 // the UNO service that implements the popup menu controller.
291 rtl::OUString
aHashKey( getHashKeyFromStrings( aType
, aName
, aModule
));
292 m_aFactoryManagerMap
.erase( aHashKey
);
293 m_aFactoryManagerMap
.insert( FactoryManagerMap::value_type( aHashKey
, aService
));
297 // lang.XEventListener
298 void SAL_CALL
ConfigurationAccess_FactoryManager::disposing( const EventObject
& ) throw(RuntimeException
)
300 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::disposing" );
302 // remove our reference to the config access
303 ResetableGuard
aLock( m_aLock
);
304 m_xConfigAccess
.clear();
307 void ConfigurationAccess_FactoryManager::readConfigurationData()
309 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::readConfigurationData" );
311 ResetableGuard
aLock( m_aLock
);
313 if ( !m_bConfigAccessInitialized
)
315 Sequence
< Any
> aArgs( 1 );
316 PropertyValue aPropValue
;
318 aPropValue
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
319 aPropValue
.Value
<<= m_sRoot
;
320 aArgs
[0] <<= aPropValue
;
324 m_xConfigAccess
.set( m_xConfigProvider
->createInstanceWithArguments(SERVICENAME_CFGREADACCESS
,aArgs
), UNO_QUERY
);
326 catch ( WrappedTargetException
& )
330 m_bConfigAccessInitialized
= sal_True
;
333 if ( m_xConfigAccess
.is() )
335 Sequence
< rtl::OUString
> aUIElementFactories
= m_xConfigAccess
->getElementNames();
339 rtl::OUString aModule
;
340 rtl::OUString aService
;
341 rtl::OUString aHashKey
;
342 Reference
< XPropertySet
> xPropertySet
;
343 for ( sal_Int32 i
= 0; i
< aUIElementFactories
.getLength(); i
++ )
345 if ( impl_getElementProps( m_xConfigAccess
->getByName( aUIElementFactories
[i
] ), aType
, aName
, aModule
, aService
))
347 // Create hash key from type, name and module as they are together a primary key to
348 // the UNO service that implements the user interface element factory.
349 aHashKey
= getHashKeyFromStrings( aType
, aName
, aModule
);
350 m_aFactoryManagerMap
.insert( FactoryManagerMap::value_type( aHashKey
, aService
));
354 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
357 if ( xContainer
.is() )
358 xContainer
->addContainerListener( this );
362 sal_Bool
ConfigurationAccess_FactoryManager::impl_getElementProps( const Any
& aElement
, rtl::OUString
& rType
, rtl::OUString
& rName
, rtl::OUString
& rModule
, rtl::OUString
& rServiceSpecifier
) const
364 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::impl_getElementProps" );
365 Reference
< XPropertySet
> xPropertySet
;
366 aElement
>>= xPropertySet
;
368 if ( xPropertySet
.is() )
372 xPropertySet
->getPropertyValue( m_aPropType
) >>= rType
;
373 xPropertySet
->getPropertyValue( m_aPropName
) >>= rName
;
374 xPropertySet
->getPropertyValue( m_aPropModule
) >>= rModule
;
375 xPropertySet
->getPropertyValue( m_aPropFactory
) >>= rServiceSpecifier
;
377 catch ( com::sun::star::beans::UnknownPropertyException
& )
381 catch ( com::sun::star::lang::WrappedTargetException
& )
390 //*****************************************************************************************************************
391 // XInterface, XTypeProvider, XServiceInfo
392 //*****************************************************************************************************************
393 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UIElementFactoryManager
,
394 ::cppu::OWeakObject
,
395 SERVICENAME_UIELEMENTFACTORYMANAGER
,
396 IMPLEMENTATIONNAME_UIELEMENTFACTORYMANAGER
399 DEFINE_INIT_SERVICE ( UIElementFactoryManager
, {} )
401 UIElementFactoryManager::UIElementFactoryManager( const Reference
< XMultiServiceFactory
>& xServiceManager
) :
402 ThreadHelpBase( &Application::GetSolarMutex() ),
403 m_bConfigRead( sal_False
),
404 m_xServiceManager( xServiceManager
)
406 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::UIElementFactoryManager" );
407 m_pConfigAccess
= new ConfigurationAccess_FactoryManager( m_xServiceManager
,rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Factories/Registered/UIElementFactories" )) );
408 m_pConfigAccess
->acquire();
409 m_xModuleManager
= Reference
< XModuleManager
>( m_xServiceManager
->createInstance( SERVICENAME_MODULEMANAGER
), UNO_QUERY
);
412 UIElementFactoryManager::~UIElementFactoryManager()
414 ResetableGuard
aLock( m_aLock
);
416 // reduce reference count
417 m_pConfigAccess
->release();
421 Reference
< XUIElement
> SAL_CALL
UIElementFactoryManager::createUIElement(
422 const ::rtl::OUString
& ResourceURL
,
423 const Sequence
< PropertyValue
>& Args
)
424 throw ( ::com::sun::star::container::NoSuchElementException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
426 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::createUIElement" );
428 ResetableGuard
aLock( m_aLock
);
430 if ( !m_bConfigRead
)
432 m_bConfigRead
= sal_True
;
433 m_pConfigAccess
->readConfigurationData();
436 const rtl::OUString
aPropFrame( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
438 rtl::OUString aModuleId
;
439 PropertyValue aPropValue
;
440 Reference
< XFrame
> xFrame
;
442 // Retrieve the frame instance from the arguments to determine the module identifier. This must be provided
443 // to the search function. An empty module identifier is provided if the frame is missing or the module id cannot
445 for ( int i
= 0; i
< Args
.getLength(); i
++ )
447 if ( Args
[i
].Name
.equals( aPropFrame
))
448 Args
[i
].Value
>>= xFrame
;
451 Reference
< XModuleManager
> xManager( m_xModuleManager
);
454 // Determine the module identifier
457 if ( xFrame
.is() && xManager
.is() )
458 aModuleId
= xManager
->identify( Reference
< XInterface
>( xFrame
, UNO_QUERY
) );
460 Reference
< XUIElementFactory
> xUIElementFactory
= getFactory( ResourceURL
, aModuleId
);
461 if ( xUIElementFactory
.is() )
462 return xUIElementFactory
->createUIElement( ResourceURL
, Args
);
464 catch ( UnknownModuleException
& )
468 throw NoSuchElementException();
471 // XUIElementFactoryRegistration
472 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
UIElementFactoryManager::getRegisteredFactories()
473 throw ( RuntimeException
)
475 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getRegisteredFactories" );
477 ResetableGuard
aLock( m_aLock
);
479 if ( !m_bConfigRead
)
481 m_bConfigRead
= sal_True
;
482 m_pConfigAccess
->readConfigurationData();
485 return m_pConfigAccess
->getFactoriesDescription();
488 Reference
< XUIElementFactory
> SAL_CALL
UIElementFactoryManager::getFactory( const ::rtl::OUString
& aResourceURL
, const ::rtl::OUString
& aModuleId
)
489 throw ( RuntimeException
)
491 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactory" );
492 ResetableGuard
aLock( m_aLock
);
494 if ( !m_bConfigRead
)
496 m_bConfigRead
= sal_True
;
497 m_pConfigAccess
->readConfigurationData();
503 WindowContentFactoryManager::RetrieveTypeNameFromResourceURL( aResourceURL
, aType
, aName
);
505 Reference
< XMultiServiceFactory
> xSManager( m_xServiceManager
);
507 rtl::OUString aServiceSpecifier
= m_pConfigAccess
->getFactorySpecifierFromTypeNameModule( aType
, aName
, aModuleId
);
510 if ( aServiceSpecifier
.getLength() )
511 return Reference
< XUIElementFactory
>( xSManager
->createInstance( aServiceSpecifier
), UNO_QUERY
);
513 return Reference
< XUIElementFactory
>();
516 void SAL_CALL
UIElementFactoryManager::registerFactory( const ::rtl::OUString
& aType
, const ::rtl::OUString
& aName
, const ::rtl::OUString
& aModuleId
, const ::rtl::OUString
& aFactoryImplementationName
)
517 throw ( ElementExistException
, RuntimeException
)
519 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::registerFactory" );
521 ResetableGuard
aLock( m_aLock
);
523 if ( !m_bConfigRead
)
525 m_bConfigRead
= sal_True
;
526 m_pConfigAccess
->readConfigurationData();
529 m_pConfigAccess
->addFactorySpecifierToTypeNameModule( aType
, aName
, aModuleId
, aFactoryImplementationName
);
533 void SAL_CALL
UIElementFactoryManager::deregisterFactory( const ::rtl::OUString
& aType
, const ::rtl::OUString
& aName
, const ::rtl::OUString
& aModuleId
)
534 throw ( NoSuchElementException
, RuntimeException
)
536 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::deregisterFactory" );
538 ResetableGuard
aLock( m_aLock
);
540 if ( !m_bConfigRead
)
542 m_bConfigRead
= sal_True
;
543 m_pConfigAccess
->readConfigurationData();
546 m_pConfigAccess
->removeFactorySpecifierFromTypeNameModule( aType
, aName
, aModuleId
);
550 } // namespace framework