blob: 63c429913a9b4c25c60e1e3d8235560c502f771f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"
//_________________________________________________________________________________________________________________
// my own includes
//_________________________________________________________________________________________________________________
#include <uifactory/uielementfactorymanager.hxx>
#include <uifactory/windowcontentfactorymanager.hxx>
#include <threadhelp/resetableguard.hxx>
#include "services.h"
//_________________________________________________________________________________________________________________
// interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/container/XContainer.hpp>
#include <com/sun/star/frame/XFrame.hpp>
//_________________________________________________________________________________________________________________
// includes of other projects
//_________________________________________________________________________________________________________________
#include <rtl/ustrbuf.hxx>
#include <cppuhelper/weak.hxx>
#include <tools/urlobj.hxx>
#include <vcl/svapp.hxx>
#include <rtl/logfile.hxx>
//_________________________________________________________________________________________________________________
// Defines
//_________________________________________________________________________________________________________________
//
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::frame;
using namespace com::sun::star::container;
using namespace ::com::sun::star::ui;
using namespace ::com::sun::star::frame;
//_________________________________________________________________________________________________________________
// Namespace
//_________________________________________________________________________________________________________________
//
namespace framework
{
// global function needed by both implementations
rtl::OUString getHashKeyFromStrings( const rtl::OUString& aType, const rtl::OUString& aName, const rtl::OUString& aModuleName )
{
rtl::OUStringBuffer aKey( aType );
aKey.appendAscii( "^" );
aKey.append( aName );
aKey.appendAscii( "^" );
aKey.append( aModuleName );
return aKey.makeStringAndClear();
}
//*****************************************************************************************************************
// Configuration access class for UIElementFactoryManager implementation
//*****************************************************************************************************************
ConfigurationAccess_FactoryManager::ConfigurationAccess_FactoryManager( Reference< XMultiServiceFactory >& rServiceManager,const ::rtl::OUString& _sRoot ) :
ThreadHelpBase(),
m_aPropType( RTL_CONSTASCII_USTRINGPARAM( "Type" )),
m_aPropName( RTL_CONSTASCII_USTRINGPARAM( "Name" )),
m_aPropModule( RTL_CONSTASCII_USTRINGPARAM( "Module" )),
m_aPropFactory( RTL_CONSTASCII_USTRINGPARAM( "FactoryImplementation" )),
m_sRoot(_sRoot),
m_xServiceManager( rServiceManager ),
m_bConfigAccessInitialized( sal_False ),
m_bConfigDirty(true)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::ConfigurationAccess_FactoryManager" );
m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance( SERVICENAME_CFGPROVIDER),UNO_QUERY );
}
ConfigurationAccess_FactoryManager::~ConfigurationAccess_FactoryManager()
{
// SAFE
ResetableGuard aLock( m_aLock );
Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
if ( xContainer.is() )
xContainer->removeContainerListener( this );
}
rtl::OUString ConfigurationAccess_FactoryManager::getFactorySpecifierFromTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule ) const
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactorySpecifierFromTypeNameModule" );
// SAFE
ResetableGuard aLock( m_aLock );
FactoryManagerMap::const_iterator pIter =
m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rModule ));
if ( pIter != m_aFactoryManagerMap.end() )
return pIter->second;
else
{
pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rtl::OUString() ));
if ( pIter != m_aFactoryManagerMap.end() )
return pIter->second;
else
{
// Support factories which uses a defined prefix before the ui name.
sal_Int32 nIndex = rName.indexOf( '_' );
if ( nIndex > 0 )
{
rtl::OUString aName = rName.copy( 0, nIndex+1 );
pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, aName, rtl::OUString() ));
if ( pIter != m_aFactoryManagerMap.end() )
return pIter->second;
}
pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rtl::OUString(), rtl::OUString() ));
if ( pIter != m_aFactoryManagerMap.end() )
return pIter->second;
}
}
return rtl::OUString();
}
void ConfigurationAccess_FactoryManager::addFactorySpecifierToTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule, const rtl::OUString& rServiceSpecifier )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::addFactorySpecifierToTypeNameModule" );
// SAFE
ResetableGuard aLock( m_aLock );
rtl::OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule );
FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey );
if ( pIter != m_aFactoryManagerMap.end() )
throw ElementExistException();
else
m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, rServiceSpecifier ));
}
void ConfigurationAccess_FactoryManager::removeFactorySpecifierFromTypeNameModule( const rtl::OUString& rType, const rtl::OUString& rName, const rtl::OUString& rModule )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::removeFactorySpecifierFromTypeNameModule" );
// SAFE
ResetableGuard aLock( m_aLock );
rtl::OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule );
FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey );
if ( pIter == m_aFactoryManagerMap.end() )
throw NoSuchElementException();
else
m_aFactoryManagerMap.erase( aHashKey );
}
Sequence< Sequence< PropertyValue > > ConfigurationAccess_FactoryManager::getFactoriesDescription() const
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactoriesDescription" );
// SAFE
ResetableGuard aLock( m_aLock );
Sequence< Sequence< PropertyValue > > aSeqSeq;
sal_Int32 nIndex( 0 );
FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.begin();
while ( pIter != m_aFactoryManagerMap.end() )
{
rtl::OUString aFactory = pIter->first;
if ( aFactory.getLength() > 0 )
{
sal_Int32 nToken = 0;
Sequence< PropertyValue > aSeq( 1 );
aSeqSeq.realloc( aSeqSeq.getLength() + 1 );
aSeq[0].Name = m_aPropType;
aSeq[0].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
if ( nToken > 0 )
{
aSeq.realloc( 2 );
aSeq[1].Name = m_aPropName;
aSeq[1].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
if ( nToken > 0 )
{
aSeq.realloc( 3 );
aSeq[2].Name = m_aPropModule;
aSeq[2].Value = makeAny( aFactory.getToken( 0, '^', nToken ));
}
}
aSeqSeq[nIndex++] = aSeq;
}
++pIter;
}
return aSeqSeq;
}
// container.XContainerListener
void SAL_CALL ConfigurationAccess_FactoryManager::elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementInserted" );
rtl::OUString aType;
rtl::OUString aName;
rtl::OUString aModule;
rtl::OUString aService;
// SAFE
ResetableGuard aLock( m_aLock );
if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
{
// Create hash key from type, name and module as they are together a primary key to
// the UNO service that implements a user interface factory.
rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
}
}
void SAL_CALL ConfigurationAccess_FactoryManager::elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementRemoved " );
rtl::OUString aType;
rtl::OUString aName;
rtl::OUString aModule;
rtl::OUString aService;
// SAFE
ResetableGuard aLock( m_aLock );
if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
{
// Create hash key from command and model as they are together a primary key to
// the UNO service that implements the popup menu controller.
rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
m_aFactoryManagerMap.erase( aHashKey );
}
}
void SAL_CALL ConfigurationAccess_FactoryManager::elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::elementReplaced" );
rtl::OUString aType;
rtl::OUString aName;
rtl::OUString aModule;
rtl::OUString aService;
// SAFE
ResetableGuard aLock( m_aLock );
if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService ))
{
// Create hash key from command and model as they are together a primary key to
// the UNO service that implements the popup menu controller.
rtl::OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule ));
m_aFactoryManagerMap.erase( aHashKey );
m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
}
}
// lang.XEventListener
void SAL_CALL ConfigurationAccess_FactoryManager::disposing( const EventObject& ) throw(RuntimeException)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::disposing" );
// SAFE
// remove our reference to the config access
ResetableGuard aLock( m_aLock );
m_xConfigAccess.clear();
}
void ConfigurationAccess_FactoryManager::readConfigurationData()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::readConfigurationData" );
// SAFE
ResetableGuard aLock( m_aLock );
if ( !m_bConfigAccessInitialized )
{
Sequence< Any > aArgs( 1 );
PropertyValue aPropValue;
aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
aPropValue.Value <<= m_sRoot;
aArgs[0] <<= aPropValue;
try
{
m_xConfigAccess.set( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ), UNO_QUERY );
}
catch ( WrappedTargetException& )
{
}
m_bConfigAccessInitialized = sal_True;
}
if ( m_xConfigAccess.is() )
{
Sequence< rtl::OUString > aUIElementFactories = m_xConfigAccess->getElementNames();
rtl::OUString aType;
rtl::OUString aName;
rtl::OUString aModule;
rtl::OUString aService;
rtl::OUString aHashKey;
Reference< XPropertySet > xPropertySet;
for ( sal_Int32 i = 0; i < aUIElementFactories.getLength(); i++ )
{
if ( impl_getElementProps( m_xConfigAccess->getByName( aUIElementFactories[i] ), aType, aName, aModule, aService ))
{
// Create hash key from type, name and module as they are together a primary key to
// the UNO service that implements the user interface element factory.
aHashKey = getHashKeyFromStrings( aType, aName, aModule );
m_aFactoryManagerMap.insert( FactoryManagerMap::value_type( aHashKey, aService ));
}
}
Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
aLock.unlock();
// UNSAFE
if ( xContainer.is() )
xContainer->addContainerListener( this );
}
}
sal_Bool ConfigurationAccess_FactoryManager::impl_getElementProps( const Any& aElement, rtl::OUString& rType, rtl::OUString& rName, rtl::OUString& rModule, rtl::OUString& rServiceSpecifier ) const
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::impl_getElementProps" );
Reference< XPropertySet > xPropertySet;
aElement >>= xPropertySet;
if ( xPropertySet.is() )
{
try
{
xPropertySet->getPropertyValue( m_aPropType ) >>= rType;
xPropertySet->getPropertyValue( m_aPropName ) >>= rName;
xPropertySet->getPropertyValue( m_aPropModule ) >>= rModule;
xPropertySet->getPropertyValue( m_aPropFactory ) >>= rServiceSpecifier;
}
catch ( com::sun::star::beans::UnknownPropertyException& )
{
return sal_False;
}
catch ( com::sun::star::lang::WrappedTargetException& )
{
return sal_False;
}
}
return sal_True;
}
//*****************************************************************************************************************
// XInterface, XTypeProvider, XServiceInfo
//*****************************************************************************************************************
DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UIElementFactoryManager ,
::cppu::OWeakObject ,
SERVICENAME_UIELEMENTFACTORYMANAGER ,
IMPLEMENTATIONNAME_UIELEMENTFACTORYMANAGER
)
DEFINE_INIT_SERVICE ( UIElementFactoryManager, {} )
UIElementFactoryManager::UIElementFactoryManager( const Reference< XMultiServiceFactory >& xServiceManager ) :
ThreadHelpBase( &Application::GetSolarMutex() ),
m_bConfigRead( sal_False ),
m_xServiceManager( xServiceManager )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::UIElementFactoryManager" );
m_pConfigAccess = new ConfigurationAccess_FactoryManager( m_xServiceManager,rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Factories/Registered/UIElementFactories" )) );
m_pConfigAccess->acquire();
m_xModuleManager = Reference< XModuleManager >( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY );
}
UIElementFactoryManager::~UIElementFactoryManager()
{
ResetableGuard aLock( m_aLock );
// reduce reference count
m_pConfigAccess->release();
}
// XUIElementFactory
Reference< XUIElement > SAL_CALL UIElementFactoryManager::createUIElement(
const ::rtl::OUString& ResourceURL,
const Sequence< PropertyValue >& Args )
throw ( ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::createUIElement" );
// SAFE
ResetableGuard aLock( m_aLock );
if ( !m_bConfigRead )
{
m_bConfigRead = sal_True;
m_pConfigAccess->readConfigurationData();
}
const rtl::OUString aPropFrame( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
rtl::OUString aModuleId;
PropertyValue aPropValue;
Reference< XFrame > xFrame;
// Retrieve the frame instance from the arguments to determine the module identifier. This must be provided
// to the search function. An empty module identifier is provided if the frame is missing or the module id cannot
// retrieve from it.
for ( int i = 0; i < Args.getLength(); i++ )
{
if ( Args[i].Name.equals( aPropFrame ))
Args[i].Value >>= xFrame;
}
Reference< XModuleManager > xManager( m_xModuleManager );
aLock.unlock();
// Determine the module identifier
try
{
if ( xFrame.is() && xManager.is() )
aModuleId = xManager->identify( Reference< XInterface >( xFrame, UNO_QUERY ) );
Reference< XUIElementFactory > xUIElementFactory = getFactory( ResourceURL, aModuleId );
if ( xUIElementFactory.is() )
return xUIElementFactory->createUIElement( ResourceURL, Args );
}
catch ( UnknownModuleException& )
{
}
throw NoSuchElementException();
}
// XUIElementFactoryRegistration
Sequence< Sequence< PropertyValue > > SAL_CALL UIElementFactoryManager::getRegisteredFactories()
throw ( RuntimeException )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getRegisteredFactories" );
// SAFE
ResetableGuard aLock( m_aLock );
if ( !m_bConfigRead )
{
m_bConfigRead = sal_True;
m_pConfigAccess->readConfigurationData();
}
return m_pConfigAccess->getFactoriesDescription();
}
Reference< XUIElementFactory > SAL_CALL UIElementFactoryManager::getFactory( const ::rtl::OUString& aResourceURL, const ::rtl::OUString& aModuleId )
throw ( RuntimeException )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::getFactory" );
ResetableGuard aLock( m_aLock );
if ( !m_bConfigRead )
{
m_bConfigRead = sal_True;
m_pConfigAccess->readConfigurationData();
}
rtl::OUString aType;
rtl::OUString aName;
WindowContentFactoryManager::RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName );
Reference< XMultiServiceFactory > xSManager( m_xServiceManager );
rtl::OUString aServiceSpecifier = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId );
aLock.unlock();
if ( aServiceSpecifier.getLength() )
return Reference< XUIElementFactory >( xSManager->createInstance( aServiceSpecifier ), UNO_QUERY );
else
return Reference< XUIElementFactory >();
}
void SAL_CALL UIElementFactoryManager::registerFactory( const ::rtl::OUString& aType, const ::rtl::OUString& aName, const ::rtl::OUString& aModuleId, const ::rtl::OUString& aFactoryImplementationName )
throw ( ElementExistException, RuntimeException )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::registerFactory" );
// SAFE
ResetableGuard aLock( m_aLock );
if ( !m_bConfigRead )
{
m_bConfigRead = sal_True;
m_pConfigAccess->readConfigurationData();
}
m_pConfigAccess->addFactorySpecifierToTypeNameModule( aType, aName, aModuleId, aFactoryImplementationName );
// SAFE
}
void SAL_CALL UIElementFactoryManager::deregisterFactory( const ::rtl::OUString& aType, const ::rtl::OUString& aName, const ::rtl::OUString& aModuleId )
throw ( NoSuchElementException, RuntimeException )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UIElementFactoryManager::deregisterFactory" );
// SAFE
ResetableGuard aLock( m_aLock );
if ( !m_bConfigRead )
{
m_bConfigRead = sal_True;
m_pConfigAccess->readConfigurationData();
}
m_pConfigAccess->removeFactorySpecifierFromTypeNameModule( aType, aName, aModuleId );
// SAFE
}
} // namespace framework