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: provider.cxx,v $
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_configmgr.hxx"
34 #include "apiserviceinfo.hxx"
35 #include "confapifactory.hxx"
36 #include "configpath.hxx"
37 #include "datalock.hxx"
38 #include "provider.hxx"
39 #include "providerimpl.hxx"
41 #include "bootstrap.hxx"
42 #include "wrapexception.hxx"
43 #include <osl/mutex.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #ifndef __SGI_STL_ALGORITHM
48 #include <comphelper/sequence.hxx>
49 #include <cppuhelper/typeprovider.hxx>
50 #include <com/sun/star/beans/PropertyValue.hpp>
51 #include <cppuhelper/typeprovider.hxx>
52 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
53 #include <com/sun/star/lang/XEventListener.hpp>
57 namespace css
= ::com::sun::star
;
58 namespace uno
= css::uno
;
59 namespace lang
= css::lang
;
60 namespace beans
= css::beans
;
64 //------------------------------------------------------------------------
65 sal_Char
const * const aConfigProviderServices
[] =
67 "com.sun.star.configuration.ConfigurationProvider",
70 sal_Char
const * const aAdminProviderServices
[] =
72 "com.sun.star.configuration.AdministrationProvider",
75 //------------------------------------------------------------------------
77 ServiceImplementationInfo
const aConfigProviderInfo
=
79 "com.sun.star.comp.configuration.ConfigurationProvider",
80 aConfigProviderServices
,
83 ServiceImplementationInfo
const aAdminProviderInfo
=
85 "com.sun.star.comp.configuration.AdministrationProvider",
86 aAdminProviderServices
,
87 aConfigProviderServices
89 //------------------------------------------------------------------------
91 sal_Char
const * const
92 aDefaultProviderServiceAndImplName
= A_DefaultProviderServiceAndImplName
;
94 //------------------------------------------------------------------------
96 sal_Char
const * const aDefaultProviderServices
[] =
98 aDefaultProviderServiceAndImplName
,
101 //------------------------------------------------------------------------
103 ServiceRegistrationInfo
const aDefaultProviderInfo
=
105 aDefaultProviderServiceAndImplName
,
106 aDefaultProviderServices
108 SingletonRegistrationInfo
const aDefaultProviderSingletonInfo
=
110 A_DefaultProviderSingletonName
,
111 aDefaultProviderServiceAndImplName
,
112 aDefaultProviderServiceAndImplName
,
115 //------------------------------------------------------------------------
116 typedef uno::Reference
< uno::XInterface
> (OProviderImpl::*CreatorFunc
)(const uno::Sequence
< uno::Any
>& aArguments
);
117 struct ServiceCreationInfo
119 ServiceRegistrationInfo
const* info
;
123 static sal_Int32
getCreateServiceDataCount()
128 static const ServiceCreationInfo
* getCreateServiceData()
130 static ServiceCreationInfo
const createServiceData
[] =
132 { &configapi::aCreateReadAccessSI
, &OProviderImpl::createReadAccess
},
133 { &configapi::aCreateUpdateAccessSI
, &OProviderImpl::createUpdateAccess
},
135 OSL_ENSURE(sizeof(createServiceData
)/sizeof(createServiceData
[0]) == getCreateServiceDataCount(),
136 "getCreateServiceData : inconsistent data !");
137 return createServiceData
;
139 //------------------------------------------------------------------------
142 static ServiceCreationInfo
const* findCreationInfo( const rtl::OUString
& aServiceSpecifier
)
144 for (int i
= 0; i
<getCreateServiceDataCount(); ++i
)
146 ServiceCreationInfo
const& rCreationInfo
= getCreateServiceData()[i
];
148 ServiceRegistrationInfo
const* pInfo
= rCreationInfo
.info
;
152 if (sal_Char
const * pImplName
= pInfo
->implementationName
)
154 if (0 == aServiceSpecifier
.compareToAscii(pImplName
))
155 return &rCreationInfo
;
158 if (sal_Char
const * const* pNames
= pInfo
->registeredServiceNames
)
162 if (0 == aServiceSpecifier
.compareToAscii(*pNames
))
163 return &rCreationInfo
;
173 //#define ID_PREFETCH 1
174 static const int ID_PREFETCH
=1;
175 static const int ID_ENABLEASYNC
=2;
178 rtl::OUString
getPrefetchPropName() { return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PrefetchNodes") ); }
180 rtl::OUString
getEnableAsyncPropName() { return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("EnableAsync") ); }
181 //=============================================================================
183 //=============================================================================
184 // service info export
185 const ServiceRegistrationInfo
* getConfigurationProviderServiceInfo()
187 return getRegistrationInfo(&aConfigProviderInfo
);
190 const ServiceRegistrationInfo
* getAdminProviderServiceInfo()
192 return getRegistrationInfo(&aAdminProviderInfo
);
195 const ServiceRegistrationInfo
* getDefaultProviderServiceInfo()
197 return &aDefaultProviderInfo
;
200 const SingletonRegistrationInfo
* getDefaultProviderSingletonInfo()
202 return &aDefaultProviderSingletonInfo
;
205 //-----------------------------------------------------------------------------
206 uno::Reference
<uno::XInterface
> SAL_CALL
207 getDefaultConfigProviderSingleton( uno::Reference
< uno::XComponentContext
> const& xContext
)
209 OSL_ENSURE( xContext
.is(), "ERROR: NULL context has no singletons" );
211 UnoContextTunnel aTunnel
;
212 aTunnel
.passthru( xContext
);
214 uno::Reference
<uno::XInterface
> xResult
;
219 rtl::OUString aSingletonName
= SINGLETON(A_DefaultProviderSingletonName
);
220 uno::Any aResult
= xContext
->getValueByName(aSingletonName
);
223 catch (uno::Exception
& )
225 // to do: really use the tunneled failure when that is set properly
226 if ( aTunnel
.recoverFailure(true).hasValue() )
228 // have a failure, but can't recover it
229 // -> try to regenerate
230 instantiateDefaultProvider(xContext
);
232 OSL_ENSURE(false, "Cannot recreate configuration backend instantiation failure - using generic error");
234 // cannot recover any failure
240 // ------------------------------------------------------------------------
241 // ----------------------------------------------------------------------------
242 #define TUNNEL_ALL_EXCEPTIONS() \
243 WRAP_CONFIGBACKEND_CREATION_EXCEPTIONS1( UnoContextTunnel::tunnelFailure, true)
245 // ----------------------------------------------------------------------------
246 // ------------------------------------------------------------------------
248 uno::Reference
< uno::XInterface
> SAL_CALL
instantiateDefaultProvider( uno::Reference
< uno::XComponentContext
> const & xTargetContext
)
250 uno::Reference
< uno::XComponentContext
> xContext
= UnoContextTunnel::recoverContext(xTargetContext
);
252 ServiceImplementationInfo
const * pProviderInfo
=
253 ContextReader::testAdminService(xContext
,true) ? &aAdminProviderInfo
: &aConfigProviderInfo
;
255 OProvider
* pNewProvider
= new OProvider(xContext
,pProviderInfo
);
256 uno::Reference
< lang::XMultiServiceFactory
> aRet( pNewProvider
);
260 pNewProvider
->connect();
262 TUNNEL_ALL_EXCEPTIONS()
264 return uno::Reference
< uno::XInterface
>( aRet
, uno::UNO_QUERY
);
267 // -----------------------------------------------------------------------------
268 class OProviderDisposingListener
: public cppu::WeakImplHelper1
<lang::XEventListener
>
270 OProvider
* m_pProvider
;
273 OProviderDisposingListener(OProvider
* pProvider
)
274 :m_pProvider(pProvider
){}
276 virtual void SAL_CALL
disposing(com::sun::star::lang::EventObject
const& rEvt
) throw()
278 CFG_TRACE_INFO("Service Manager or context disposed, disposing the provider");
279 if (OProvider
* pProvider
= m_pProvider
)
282 pProvider
->disposing(rEvt
);
287 //=============================================================================
289 //=============================================================================
290 //-----------------------------------------------------------------------------
291 OProvider::OProvider(uno::Reference
< uno::XComponentContext
> const & xContext
, ServiceImplementationInfo
const* pInfo
)
292 :ServiceComponentImpl(pInfo
)
293 ,OPropertyContainer(ServiceComponentImpl::rBHelper
)
294 ,m_xContext(xContext
)
296 ,m_bEnableAsync(false)
298 OSL_ENSURE(m_xContext
.is(), "Creating a provider without a context");
300 registerProperty(getPrefetchPropName(), ID_PREFETCH
, 0,&m_aPrefetchNodes
, ::getCppuType(&m_aPrefetchNodes
));
301 registerProperty(getEnableAsyncPropName(), ID_ENABLEASYNC
, 0, &m_bEnableAsync
, ::getBooleanCppuType());
304 //-----------------------------------------------------------------------------
305 OProvider::~OProvider()
308 discardContext(releaseContext());
311 //-----------------------------------------------------------------------------
312 void OProvider::connect() throw (uno::Exception
)
314 OSL_ENSURE( m_pImpl
== NULL
, "Error: Configuration Provider already is connected");
316 std::auto_ptr
<OProviderImpl
> pNewImpl( new OProviderImpl(this, m_xContext
) );
318 implConnect(*pNewImpl
,ContextReader(m_xContext
));
320 m_pImpl
= pNewImpl
.release();
323 sal_Bool isEnabled
= m_pImpl
->getDefaultOptions().isAsyncEnabled();
324 this->setPropertyValue( getEnableAsyncPropName(), uno::makeAny(isEnabled
) );
328 //-----------------------------------------------------------------------------
329 void OProvider::attachToContext()
332 ::osl::MutexGuard
aGuard(ServiceComponentImpl::rBHelper
.rMutex
);
333 OSL_ASSERT(!m_xDisposeListener
.is());
336 uno::Reference
< lang::XComponent
> xContextComp(m_xContext
, uno::UNO_QUERY
);
337 uno::Reference
< lang::XComponent
> xServiceMgrComp(m_xContext
->getServiceManager(), uno::UNO_QUERY
);
339 m_xDisposeListener
= new OProviderDisposingListener(this);
341 if (xContextComp
.is()) xContextComp
->addEventListener(m_xDisposeListener
);
342 if (xServiceMgrComp
.is()) xServiceMgrComp
->addEventListener(m_xDisposeListener
);
344 OSL_ENSURE(xServiceMgrComp
.is() || xContextComp
.is(),
345 "Provider cannot detect shutdown -> no XComponent found");
349 //-----------------------------------------------------------------------------
350 uno::Reference
< lang::XComponent
> OProvider::releaseContext()
353 ::osl::MutexGuard
aGuard(ServiceComponentImpl::rBHelper
.rMutex
);
355 uno::Reference
< lang::XComponent
> xContextComp(m_xContext
, uno::UNO_QUERY
);
356 if (m_xDisposeListener
.is() && m_xContext
.is())
358 uno::Reference
< lang::XComponent
> xServiceMgrComp(m_xContext
->getServiceManager(), uno::UNO_QUERY
);
360 if (xContextComp
.is())
362 try { xContextComp
->removeEventListener(m_xDisposeListener
); }
363 catch (uno::Exception
& ) {}
366 if (xServiceMgrComp
.is())
368 try { xServiceMgrComp
->removeEventListener(m_xDisposeListener
); }
369 catch (uno::Exception
& ) {}
372 m_xDisposeListener
= NULL
;
377 //-----------------------------------------------------------------------------
379 void OProvider::discardContext(uno::Reference
< lang::XComponent
> const & xContext
)
384 uno::Reference
< uno::XComponentContext
> xCC(xContext
,uno::UNO_QUERY
);
385 OSL_ASSERT(xCC
.is());
387 if (BootstrapContext::isWrapper(xCC
))
389 try { xContext
->dispose(); }
390 catch (uno::Exception
& ) {}
394 //-----------------------------------------------------------------------------
396 //-----------------------------------------------------------------------------
397 uno::Sequence
< uno::Type
> SAL_CALL
OProvider::getTypes( ) throw(uno::RuntimeException
)
399 cppu::OTypeCollection
aCollection(::getCppuType( (const uno::Reference
< beans::XPropertySet
> *)0 ),
400 ::getCppuType( (const uno::Reference
< beans::XFastPropertySet
> *)0 ),
401 ::getCppuType( (const uno::Reference
< beans::XMultiPropertySet
> *)0 ),
402 ::comphelper::concatSequences(ServiceComponentImpl::getTypes(), cppu::ImplHelper4
< lang::XMultiServiceFactory
, lang::XLocalizable
, util::XRefreshable
, util::XFlushable
>::getTypes()));
403 return aCollection
.getTypes();
407 //-----------------------------------------------------------------------------
408 uno::Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
OProvider::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException
)
410 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
413 //-----------------------------------------------------------------------------
414 uno::Reference
< uno::XInterface
> SAL_CALL
OProvider::createInstance( const rtl::OUString
& aServiceSpecifier
)
415 throw(uno::Exception
, uno::RuntimeException
)
418 // same as creating with empty sequence of arguments
419 return this->createInstanceWithArguments( aServiceSpecifier
, uno::Sequence
< uno::Any
>() );
422 //-----------------------------------------------------------------------------
423 uno::Reference
< uno::XInterface
> SAL_CALL
424 OProvider::createInstanceWithArguments( const rtl::OUString
& aServiceSpecifier
, const uno::Sequence
< uno::Any
>& aArguments
)
425 throw(uno::Exception
, uno::RuntimeException
)
429 OSL_ENSURE(m_pImpl
, "OProvider: no implementation available");
431 if (ServiceCreationInfo
const* pInfo
= findCreationInfo(aServiceSpecifier
))
433 // it's a known service name - try to create without args
434 if (CreatorFunc create
= pInfo
->create
)
436 return (m_pImpl
->*create
)(aArguments
);
440 rtl::OUStringBuffer sMsg
;
441 sMsg
.appendAscii("ConfigurationProvider: Cannot create view - ");
442 sMsg
.append( aServiceSpecifier
) .appendAscii(" is not a valid configuration access service. ");
444 throw lang::ServiceNotRegisteredException(sMsg
.makeStringAndClear(),*this);
447 //-----------------------------------------------------------------------------
448 uno::Sequence
< rtl::OUString
> SAL_CALL
OProvider::getAvailableServiceNames( )
449 throw(uno::RuntimeException
)
453 sal_Int32 nCount
= 0;
455 for (int i
= 0; i
< getCreateServiceDataCount(); ++i
)
456 nCount
+= countServices(getCreateServiceData()[i
].info
);
459 uno::Sequence
< rtl::OUString
> aNames(nCount
);
463 for (int i
= 0; i
<getCreateServiceDataCount(); ++i
)
465 ServiceRegistrationInfo
const* pInfo
= getCreateServiceData()[i
].info
;
466 sal_Char
const * const* pNames
= pInfo
? pInfo
->registeredServiceNames
: 0;
472 aNames
[n
] = rtl::OUString::createFromAscii(*pNames
);
484 //-----------------------------------------------------------------------------
485 void SAL_CALL
OProvider::setLocale( const lang::Locale
& eLocale
)
486 throw (uno::RuntimeException
)
490 OSL_ENSURE(m_pImpl
, "OProvider: no implementation available");
492 m_pImpl
->setDefaultLocale( eLocale
);
495 //-----------------------------------------------------------------------------
496 lang::Locale SAL_CALL
OProvider::getLocale()
497 throw (uno::RuntimeException
)
501 OSL_ENSURE(m_pImpl
, "OProvider: no implementation available");
503 return m_pImpl
->getDefaultOptions().getUnoLocale();
507 //-----------------------------------------------------------------------------
508 void SAL_CALL
OProvider::refresh()
509 throw (uno::RuntimeException
)
513 OSL_ENSURE(m_pImpl
, "OProvider: no implementation available");
517 m_pImpl
->refreshAll();
519 catch (uno::RuntimeException
& ) { throw; }
520 catch (uno::Exception
& e
)
522 // FIXME: use getCaughtException()
523 throw lang::WrappedTargetRuntimeException(e
.Message
, *this, uno::makeAny(e
));
525 //Broadcast the changes
526 uno::Reference
< css::util::XRefreshListener
> const * const pRefresh
= 0;
527 cppu::OInterfaceContainerHelper
* aInterfaceContainer
=
528 getBroadcastHelper().getContainer (::getCppuType(pRefresh
));
530 if(aInterfaceContainer
)
532 lang::EventObject
aEventObject(*this);
534 cppu::OInterfaceIteratorHelper
aIterator(*aInterfaceContainer
);
535 while(aIterator
.hasMoreElements())
537 uno::Reference
< uno::XInterface
> xIface
= aIterator
.next();
538 uno::Reference
< util::XRefreshListener
> xRefresh (xIface
, uno::UNO_QUERY
);
541 xRefresh
->refreshed(aEventObject
);
546 //-----------------------------------------------------------------------------
547 void SAL_CALL
OProvider::addRefreshListener(
548 const uno::Reference
< util::XRefreshListener
>& aListener
)
549 throw (uno::RuntimeException
)
552 getBroadcastHelper().addListener(::getCppuType(&aListener
), aListener
);
554 //-----------------------------------------------------------------------------
555 void SAL_CALL
OProvider::removeRefreshListener(
556 const uno::Reference
< util::XRefreshListener
>& aListener
)
557 throw (uno::RuntimeException
)
560 getBroadcastHelper().removeListener(::getCppuType(&aListener
), aListener
);
563 //-----------------------------------------------------------------------------
564 void SAL_CALL
OProvider::flush( )
565 throw (uno::RuntimeException
)
568 OSL_ENSURE(m_pImpl
, "OProvider: no implementation available");
571 //Broadcast the changes
572 uno::Reference
< css::util::XFlushListener
> const * const pFlush
= 0;
573 cppu::OInterfaceContainerHelper
* aInterfaceContainer
=
574 getBroadcastHelper().getContainer(::getCppuType(pFlush
));
576 if(aInterfaceContainer
)
578 lang::EventObject
aEventObject(*this);
580 cppu::OInterfaceIteratorHelper
aIterator(*aInterfaceContainer
);
581 while(aIterator
.hasMoreElements())
583 uno::Reference
< uno::XInterface
> xIface
= aIterator
.next();
584 uno::Reference
< util::XFlushListener
> xFlush (xIface
, uno::UNO_QUERY
);
587 xFlush
->flushed(aEventObject
);
592 //-----------------------------------------------------------------------------
593 void SAL_CALL
OProvider::addFlushListener(
594 const uno::Reference
< util::XFlushListener
>& aListener
)
595 throw (uno::RuntimeException
)
598 getBroadcastHelper().addListener(::getCppuType(&aListener
), aListener
);
600 //-----------------------------------------------------------------------------
601 void SAL_CALL
OProvider::removeFlushListener(
602 const uno::Reference
< util::XFlushListener
>& aListener
)
603 throw (uno::RuntimeException
)
606 getBroadcastHelper().removeListener(::getCppuType(&aListener
), aListener
);
610 //-----------------------------------------------------------------------------
611 uno::Any SAL_CALL
OProvider::queryInterface(uno::Type
const& rType
) throw(uno::RuntimeException
)
614 uno::Any
aRet( ServiceComponentImpl::queryInterface(rType
) );
615 if ( !aRet
.hasValue() )
616 aRet
= cppu::ImplHelper4
< lang::XMultiServiceFactory
, lang::XLocalizable
, util::XRefreshable
, util::XFlushable
>::queryInterface(rType
);
617 if ( !aRet
.hasValue() )
618 aRet
= queryPropertyInterface(rType
);
622 //-----------------------------------------------------------------------------
623 void OProvider::implConnect(OProviderImpl
& _rFreshProviderImpl
, const ContextReader
& _rSettings
) throw(uno::Exception
)
626 if (!_rFreshProviderImpl
.initSession(_rSettings
))
627 throw uno::Exception(::rtl::OUString::createFromAscii("Could not connect to the configuration. Please check your settings."), static_cast< ::cppu::OWeakObject
* >(this) );
630 //-----------------------------------------------------------------------------
631 void SAL_CALL
OProvider::disposing(com::sun::star::lang::EventObject
const& /*rEvt*/) throw()
638 //-----------------------------------------------------------------------------
639 void SAL_CALL
OProvider::disposing()
646 uno::Reference
< lang::XComponent
> xComp
= releaseContext();
648 ServiceComponentImpl::disposing();
649 OPropertyContainer::disposing();
651 discardContext( xComp
);
654 // OPropertyArrayUsageHelper
655 // -------------------------------------------------------------------------
656 ::cppu::IPropertyArrayHelper
* OProvider::createArrayHelper( ) const
659 uno::Sequence
< beans::Property
> aProps
;
660 describeProperties(aProps
);
661 return new ::cppu::OPropertyArrayHelper(aProps
);
663 // -------------------------------------------------------------------------
664 ::cppu::IPropertyArrayHelper
& OProvider::getInfoHelper()
667 return *getArrayHelper();
670 void SAL_CALL
OProvider::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const ::com::sun::star::uno::Any
& rValue
)
671 throw (::com::sun::star::uno::Exception
)
675 OPropertyContainer::setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
681 uno::Sequence
< rtl::OUString
> aNodeList
;
682 rValue
>>= aNodeList
;
684 RequestOptions
const aOptions
= m_pImpl
->getDefaultOptions();
686 for (sal_Int32 i
= 0; i
< aNodeList
.getLength(); i
++)
688 configuration::AbsolutePath aModulePath
= configuration::AbsolutePath::makeModulePath(aNodeList
[i
]);
689 m_pImpl
->fetchSubtree(aModulePath
, aOptions
);
695 //Forward to TreeManager
697 if (rValue
>>= bAsync
)
699 m_pImpl
->enableAsync(bAsync
);
704 OSL_ENSURE(false, "Unexpected type of new property value");
709 OSL_ENSURE(false, "OProvider::setFastPropertyValue_NoBroadcast -unknown property");
714 } // namespace configmgr