merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / api2 / providerimpl.cxx
blob03ce8a9278239ae898bf707e09ed09f3ac553535
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: providerimpl.cxx,v $
10 * $Revision: 1.69 $
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 <stdio.h>
35 #include "providerimpl.hxx"
36 #include "options.hxx"
37 #include "apifactoryimpl.hxx"
38 #include "apitreeimplobj.hxx"
39 #include "apitreeaccess.hxx"
40 #include "roottree.hxx"
41 #include "node.hxx"
42 #include "noderef.hxx"
43 #include "objectregistry.hxx"
44 #include "bootstrap.hxx"
45 #include "cachefactory.hxx"
46 #include "provider.hxx"
47 #include "treemanager.hxx"
48 #include "tracer.hxx"
49 #include <osl/interlck.h>
50 #include <com/sun/star/beans/PropertyValue.hpp>
51 #include <com/sun/star/lang/DisposedException.hpp>
52 #include <com/sun/star/lang/Locale.hpp>
53 #include <rtl/ustrbuf.hxx>
54 #include <rtl/logfile.hxx>
56 #define RTL_LOGFILE_OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
58 namespace configmgr
60 namespace css = ::com::sun::star;
61 namespace uno = css::uno;
62 namespace beans = css::beans;
64 namespace configapi
67 class ApiProviderInstances
69 rtl::Reference<ObjectRegistry> m_aObjectRegistry;
70 ReadOnlyObjectFactory m_aReaderFactory;
71 UpdateObjectFactory m_aWriterFactory;
72 ApiProvider m_aReaderProvider;
73 ApiProvider m_aWriterProvider;
74 public:
75 ApiProviderInstances(OProviderImpl& rProviderImpl)
76 : m_aObjectRegistry(new ObjectRegistry())
77 , m_aReaderFactory(m_aReaderProvider,m_aObjectRegistry)
78 , m_aWriterFactory(m_aWriterProvider,m_aObjectRegistry)
79 , m_aReaderProvider(m_aReaderFactory,rProviderImpl)
80 , m_aWriterProvider(m_aWriterFactory,rProviderImpl)
84 ~ApiProviderInstances()
87 ApiProvider& getReaderProvider() { return m_aReaderProvider; }
88 ApiProvider& getWriterProvider() { return m_aWriterProvider; }
89 Factory& getReaderFactory() { return m_aReaderFactory; }
90 Factory& getWriterFactory() { return m_aWriterFactory; }
94 //=============================================================================
96 //=============================================================================
97 //= OProviderImpl
98 //=============================================================================
99 //-----------------------------------------------------------------------------
100 OProviderImpl::OProviderImpl(OProvider* _pProvider, uno::Reference< uno::XComponentContext > const & _xContext)
101 :m_pProvider(_pProvider)
102 ,m_xTypeConverter()
103 ,m_aDefaultOptions()
104 ,m_pNewProviders(NULL)
105 ,m_aTreeManagerMutex()
106 ,m_pTreeManager(NULL)
108 OSL_ENSURE(_xContext.is(), "OProviderImpl : NULL context !");
110 uno::Reference< lang::XMultiComponentFactory > xFactory = _xContext->getServiceManager();
111 OSL_ENSURE(xFactory.is(), "OProviderImpl : missing service factory !");
113 m_xTypeConverter = m_xTypeConverter.query(
114 xFactory->createInstanceWithContext( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" )),
115 _xContext));
117 OSL_ENSURE(m_xTypeConverter.is(), "Module::Module : could not create an instance of the type converter !");
119 //-----------------------------------------------------------------------------
120 rtl::Reference< TreeManager > OProviderImpl::maybeGetTreeManager() const SAL_THROW(())
122 osl::MutexGuard aGuard(m_aTreeManagerMutex);
123 rtl::Reference< TreeManager > xResult(m_pTreeManager);
124 return xResult;
126 //-----------------------------------------------------------------------------
127 rtl::Reference< TreeManager > OProviderImpl::getTreeManager() const SAL_THROW((com::sun::star::uno::RuntimeException))
129 osl::MutexGuard aGuard(m_aTreeManagerMutex);
130 if (m_pTreeManager == NULL)
132 rtl::OUString sMsg = rtl::OUString::createFromAscii("OProviderImpl: No cache available - provider was already disposed.");
133 throw com::sun::star::lang::DisposedException(sMsg,static_cast<lang::XMultiServiceFactory*>(m_pProvider));
135 rtl::Reference< TreeManager > xResult(m_pTreeManager);
136 return xResult;
138 //-----------------------------------------------------------------------------
139 void OProviderImpl::setTreeManager(TreeManager * pTreeManager) SAL_THROW((com::sun::star::uno::RuntimeException))
141 osl::MutexGuard aGuard(m_aTreeManagerMutex);
143 OSL_PRECOND(m_pTreeManager == NULL, "OProviderImpl: TreeManager is already set");
144 OSL_PRECOND(pTreeManager != NULL, "OProviderImpl: Trying to set a NULL TreeManager");
146 if (pTreeManager == NULL)
148 rtl::OUString sMsg = rtl::OUString::createFromAscii("OProviderImpl: No cache available - cache creation failed.");
149 throw com::sun::star::uno::RuntimeException(sMsg,NULL);
152 (m_pTreeManager = pTreeManager) -> acquire();
154 //-----------------------------------------------------------------------------
155 void OProviderImpl::clearTreeManager() SAL_THROW(())
157 osl::ClearableMutexGuard aGuard(m_aTreeManagerMutex);
158 if (TreeManager * pTM = m_pTreeManager)
160 m_pTreeManager = NULL;
161 pTM->release();
164 //-----------------------------------------------------------------------------
165 bool OProviderImpl::initSession(const ContextReader& _rSettings)
167 bool bNeedProfile = false;
168 rtl::Reference< TreeManager > xNewTreeManager;
169 if (_rSettings.isUnoBackend())
171 this->implInitFromSettings(_rSettings,bNeedProfile);
173 xNewTreeManager = CacheFactory::instance().createCacheManager(_rSettings.getBaseContext());
175 else
177 throw com::sun::star::uno::RuntimeException(rtl::OUString::createFromAscii("OProviderImpl: Only UNO Backends Supported"),NULL);
180 setTreeManager( xNewTreeManager.get() );
181 OSL_ASSERT( xNewTreeManager.get() );
183 // put out of line to get rid of the order dependency (and to have a acquired configuration)
184 m_pNewProviders = new configapi::ApiProviderInstances(*this);
186 // now complete our state from the user's profile, if necessary
187 if (bNeedProfile)
190 static ::rtl::OUString ssUserProfile(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup"));
191 configuration::AbsolutePath aProfileModule = configuration::AbsolutePath::makeModulePath(ssUserProfile);
193 sharable::Node * profileTree = xNewTreeManager->requestSubtree(aProfileModule, m_aDefaultOptions);
194 if (profileTree != 0)
196 implInitFromProfile(profileTree);
198 // should we clean this up ?
199 // xNewTreeManager->releaseSubtree(aProfileModule, xTempOptions);
202 catch (uno::Exception& e)
204 // could not read profile
205 (void)e;
206 CFG_TRACE_ERROR_NI("Provider bootstrapping: Caught an exception trying to get 'Setup' data: %s", OUSTRING2ASCII(e.Message));
209 return true;
211 //-----------------------------------------------------------------------------
213 // these can be overridden. default does nothing
214 void OProviderImpl::initFromSettings(const ContextReader& , bool& )
217 //-----------------------------------------------------------------------------
218 void OProviderImpl::initFromProfile(sharable::Node *)
221 //-----------------------------------------------------------------------------
222 // these implement the base class behavior
223 void OProviderImpl::implInitFromSettings(const ContextReader& _rSettings, bool& rNeedProfile)
225 bool bIntrinsicNeedProfile = true;
227 if (_rSettings.hasLocale())
229 bIntrinsicNeedProfile = false;
230 rtl::OUString sDefaultLocale = _rSettings.getLocale();
231 m_aDefaultOptions.setIsoLocale(sDefaultLocale);
233 else if (_rSettings.isAdminService())
235 bIntrinsicNeedProfile = false;
236 m_aDefaultOptions.setAllLocales();
238 else
239 OSL_ASSERT(!m_aDefaultOptions.hasLocale());
241 if (_rSettings.hasAsyncSetting())
243 m_aDefaultOptions.enableAsync( !!_rSettings.getAsyncSetting() );
247 // call the template method
248 this->initFromSettings(_rSettings, rNeedProfile);
250 if (bIntrinsicNeedProfile)
251 rNeedProfile = true; // to get locale
253 //-----------------------------------------------------------------------------
254 void OProviderImpl::implInitFromProfile(sharable::Node * profile)
256 OSL_ASSERT(profile != 0);
258 sharable::GroupNode * profileNode = sharable::GroupNode::from(profile);
260 OSL_ASSERT(profileNode != 0);
262 // read the default locale for the user
263 if (!m_aDefaultOptions.hasLocale())
265 static rtl::OUString ssSubGroup(RTL_CONSTASCII_USTRINGPARAM("L10N"));
266 static rtl::OUString ssLocale(RTL_CONSTASCII_USTRINGPARAM("ooLocale"));
268 sharable::GroupNode * l10nNode = sharable::GroupNode::from(profileNode->getChild(ssSubGroup));
269 if (l10nNode != 0)
271 sharable::ValueNode * value = sharable::ValueNode::from(l10nNode->getChild(ssLocale));
273 if (value != 0)
275 rtl::OUString sDefaultLocale;
276 if (value->getValue() >>= sDefaultLocale)
278 m_aDefaultOptions.setIsoLocale(sDefaultLocale);
280 else
281 OSL_ENSURE(false, "Could not extract locale parameter into string");
286 // call the template method
287 this->initFromProfile(profile);
289 // last fallback, if there is no locale - even in ooLocale
290 m_aDefaultOptions.ensureLocaleSet();
293 //-----------------------------------------------------------------------------
294 void OProviderImpl::setDefaultLocale( com::sun::star::lang::Locale const & aLocale )
296 m_aDefaultOptions.setLocale( aLocale );
297 // ensure that the locale is never cleared to 'empty'
298 m_aDefaultOptions.ensureLocaleSet();
301 //-----------------------------------------------------------------------------
302 OProviderImpl::~OProviderImpl()
304 UnoApiLock aLock; // hmm...
305 clearTreeManager();
307 delete m_pNewProviders;
310 // --------------------------------- disposing ---------------------------------
311 void SAL_CALL OProviderImpl::dispose() throw()
313 try
315 rtl::Reference< TreeManager > xTM = maybeGetTreeManager();
317 if (xTM.is())
318 xTM->dispose();
320 clearTreeManager();
322 catch (uno::Exception& e)
324 (void)e;
325 CFG_TRACE_ERROR("Disposing the TreeManager or closing the session caused an exception: %s", OUSTRING2ASCII(e.Message));
326 clearTreeManager();
330 //-----------------------------------------------------------------------------
331 // access to the raw notifications
332 TreeManager * OProviderImpl::getNotifier() SAL_THROW(())
334 rtl::Reference< TreeManager > xTM = maybeGetTreeManager();
335 return xTM.get();
338 // DefaultProvider access
339 //-----------------------------------------------------------------------------
340 rtl::Reference< TreeManager > OProviderImpl::getDefaultProvider() const SAL_THROW((com::sun::star::uno::RuntimeException))
342 return getTreeManager().get();
345 //-----------------------------------------------------------------------------
346 sharable::Node * OProviderImpl::requestSubtree( configuration::AbsolutePath const& aSubtreePath,
347 RequestOptions const & _aOptions
348 ) SAL_THROW((com::sun::star::uno::Exception))
350 rtl::Reference< TreeManager > xTreeManager = getTreeManager();
352 sharable::Node * tree = 0;
355 tree = xTreeManager->requestSubtree(aSubtreePath, _aOptions);
357 catch(uno::Exception&e)
359 ::rtl::OUString sMessage = getErrorMessage(aSubtreePath, _aOptions);
360 // append the error message given by the tree provider
361 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\n\nThe backend returned the following error:\n"));
362 sMessage += e.Message;
364 throw lang::WrappedTargetException(sMessage, getProviderInstance(), uno::makeAny(e));
367 if (tree == 0)
369 ::rtl::OUString sMessage = getErrorMessage(aSubtreePath, _aOptions);
371 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\n\nNo backend error message available\n"));
373 throw uno::Exception(sMessage, getProviderInstance());
376 return tree;
379 //-----------------------------------------------------------------------------
380 void OProviderImpl::updateTree(TreeChangeList& aChanges) SAL_THROW((com::sun::star::uno::Exception))
382 getTreeManager()->updateTree(aChanges);
385 //-----------------------------------------------------------------------------
386 void OProviderImpl::releaseSubtree( configuration::AbsolutePath const& aSubtreePath, RequestOptions const& _aOptions ) SAL_THROW(())
388 rtl::Reference< TreeManager > xTM = maybeGetTreeManager();
389 if (xTM.is())
390 xTM->releaseSubtree(aSubtreePath, _aOptions);
393 //-----------------------------------------------------------------------------
394 void OProviderImpl::saveAndNotifyUpdate(TreeChangeList const& aChanges) SAL_THROW((com::sun::star::uno::Exception))
396 getTreeManager()->saveAndNotifyUpdate(aChanges);
399 //-----------------------------------------------------------------------------
400 void OProviderImpl::fetchSubtree(configuration::AbsolutePath const& aSubtreePath, RequestOptions const& _aOptions) SAL_THROW(())
402 rtl::Reference< TreeManager > xTM = maybeGetTreeManager();
403 if (xTM.is())
404 xTM->fetchSubtree(aSubtreePath, _aOptions);
407 //-----------------------------------------------------------------------------
408 sal_Bool OProviderImpl::fetchDefaultData(configuration::AbsolutePath const& aSubtreePath, RequestOptions const& _aOptions) SAL_THROW((com::sun::star::uno::Exception))
410 return getTreeManager()->fetchDefaultData(aSubtreePath, _aOptions);
412 //-----------------------------------------------------------------------------------
413 void OProviderImpl::refreshAll()SAL_THROW((com::sun::star::uno::Exception))
415 m_pTreeManager->refreshAll();
417 //-----------------------------------------------------------------------------------
418 void OProviderImpl::flushAll()SAL_THROW(())
420 m_pTreeManager->flushAll();
422 //-----------------------------------------------------------------------------------
423 void OProviderImpl::enableAsync(const sal_Bool& bEnableAsync) SAL_THROW(())
425 m_pTreeManager->enableAsync(bEnableAsync);
427 //-----------------------------------------------------------------------------
428 uno::XInterface* OProviderImpl::getProviderInstance()
430 return static_cast<com::sun::star::lang::XMultiServiceFactory*>(m_pProvider);
433 //-----------------------------------------------------------------------------------
434 rtl::OUString OProviderImpl::getErrorMessage(configuration::AbsolutePath const& _rAccessor, RequestOptions const& _aOptions)
436 rtl::OUString const sAccessor = _rAccessor.toString();
438 CFG_TRACE_ERROR("config provider: the cache manager could not provide the tree (neither from the cache nor from the session)");
439 ::rtl::OUString sMessage;
440 ::rtl::OUString sEntity(_aOptions.getEntity());
441 ::rtl::OUString sLocale(_aOptions.getLocale());
442 CFG_TRACE_INFO_NI("config provider: the entity we tried this for is \"%s\", the locale \"%s\", the path \"%s\"", OUSTRING2ASCII(sEntity), OUSTRING2ASCII(sLocale), OUSTRING2ASCII(sAccessor));
443 sMessage += sAccessor;
445 if (sEntity.getLength())
447 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" (and for entity "));
448 sMessage += sEntity;
449 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"));
452 if (sLocale.getLength())
454 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" (and for locale "));
455 sMessage += sLocale;
456 sMessage += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"));
459 sMessage += ::rtl::OUString::createFromAscii(" could not be created. Unable to retrieve the node from the configuration server.");
460 return sMessage;
463 // actual factory methods
464 //-----------------------------------------------------------------------------------
465 configapi::NodeElement* OProviderImpl::buildReadAccess(rtl::OUString const& _rAccessor, RequestOptions const& _aOptions, sal_Int32 nMinLevels) SAL_THROW((com::sun::star::uno::Exception))
467 CFG_TRACE_INFO("config provider: requesting the tree from the cache manager");
469 OSL_ASSERT(sal_Int16(nMinLevels) == nMinLevels);
471 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::OProviderImpl", "jb99855", "configmgr::OProviderImpl::buildReadAccess()");
472 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(_rAccessor) );
476 configuration::AbsolutePath aAccessorPath = configuration::AbsolutePath::parse(_rAccessor);
478 sharable::Node * tree = requestSubtree(aAccessorPath,_aOptions);
480 RTL_LOGFILE_CONTEXT_TRACE(aLog, "data loaded" );
482 unsigned int nDepth = (nMinLevels == treeop::ALL_LEVELS) ? configuration::C_TreeDepthAll : (unsigned int)(nMinLevels);
484 RTL_LOGFILE_CONTEXT_AUTHOR(aLog2, "configmgr::OProviderImpl", "jb99855", "configmgr: createReadOnlyTree()");
486 rtl::Reference< configuration::Tree > aRootTree( configuration::createReadOnlyTree(
487 aAccessorPath, tree, nDepth,
488 configuration::TemplateProvider( getTreeManager(), _aOptions )
491 return m_pNewProviders->getReaderFactory().makeAccessRoot(aRootTree, _aOptions);
493 catch (configuration::Exception& e)
495 configapi::ExceptionMapper ec(e);
496 ec.setContext(this->getProviderInstance());
497 //ec.unhandled();
498 throw lang::WrappedTargetException(ec.message(), ec.context(), uno::Any());
503 //-----------------------------------------------------------------------------------
504 configapi::NodeElement* OProviderImpl::buildUpdateAccess(rtl::OUString const& _rAccessor, RequestOptions const& _aOptions,
505 sal_Int32 nMinLevels) SAL_THROW((com::sun::star::uno::Exception))
507 CFG_TRACE_INFO("config provider: requesting the tree from the cache manager");
508 OSL_ASSERT(sal_Int16(nMinLevels) == nMinLevels);
510 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::OProviderImpl", "jb99855", "configmgr: buildUpdateAccess()");
511 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(_rAccessor) );
515 configuration::AbsolutePath aAccessorPath = configuration::AbsolutePath::parse(_rAccessor);
517 sharable::Node * tree = requestSubtree(aAccessorPath, _aOptions);
519 RTL_LOGFILE_CONTEXT_TRACE(aLog, "data loaded" );
521 unsigned int nDepth = (nMinLevels == treeop::ALL_LEVELS) ? configuration::C_TreeDepthAll : (unsigned int)(nMinLevels);
523 RTL_LOGFILE_CONTEXT_AUTHOR(aLog2, "configmgr::OProviderImpl", "jb99855", "createUpdatableTree()");
525 rtl::Reference< configuration::Tree > aRootTree( configuration::createUpdatableTree(
526 aAccessorPath, tree, nDepth,
527 configuration::TemplateProvider( getTreeManager(), _aOptions )
531 return m_pNewProviders->getWriterFactory().makeAccessRoot(aRootTree, _aOptions);
533 catch (configuration::Exception& e)
535 configapi::ExceptionMapper ec(e);
536 ec.setContext(this->getProviderInstance());
537 //ec.unhandled();
538 throw lang::WrappedTargetException(ec.message(), ec.context(), uno::Any());
542 //=============================================================================
543 //= OProvider::FactoryArguments
544 //=============================================================================
546 sal_Char const * const OProviderImpl::FactoryArguments::asciiArgumentNames[] =
548 "nodepath", // ARG_NODEPATH, // requested node path
549 "depth", // ARG_DEPTH, // depth of the tree
550 "user", // ARG_USER_DEPRECATED, // name of the user - only for admin
551 "locale", // ARG_LOCALE, // desired locale
552 "nocache", // ARG_NOCACHE_OBSOLETE, // cache disabling
553 "lazywrite", // ARG_ASYNC_DEPRECATED, // lasy write data
554 "enableasync", // ARG_ASYNC, // lasy write data
555 "entity", // ARG_ENTITY, // name of the entity to be manipulated - only for admin
556 "reload", //ARG_REFRESH // refresh component
560 OProviderImpl::FactoryArguments::Argument
561 OProviderImpl::FactoryArguments::lookupArgument(const rtl::OUString& rName)
562 SAL_THROW(())
564 rtl::OUString sCheck( rName.toAsciiLowerCase() );
566 sal_Char const * const * const pFirst = asciiArgumentNames;
567 sal_Char const * const * const pLast = pFirst + _arg_count;
569 sal_Char const * const * it = pFirst;
571 for(; it != pLast; ++it)
573 if (0 == sCheck.compareToAscii(*it))
575 break;
579 OSL_ASSERT( Argument(pLast-pFirst) == ARG_NOT_FOUND );
580 return static_cast<Argument>(it - pFirst);
583 //-----------------------------------------------------------------------------------
584 bool OProviderImpl::FactoryArguments::extractOneArgument(
585 rtl::OUString const& aName, uno::Any const& aValue,
586 rtl::OUString& /* [out] */ _rNodeAccessor,
587 sal_Int32& /* [out] */ _nLevels,
588 RequestOptions& /* [in/out] */ _rOptions )
589 SAL_THROW(())
591 switch ( lookupArgument(aName) )
593 case ARG_NODEPATH:
595 rtl::OUString sStringVal;
596 if (aValue >>= sStringVal)
597 _rNodeAccessor = sStringVal;
598 else
599 return false;
601 break;
603 case ARG_DEPTH:
605 sal_Int32 nIntVal = 0;
606 if (aValue >>= nIntVal)
607 _nLevels = nIntVal;
608 else
609 return false;
611 break;
613 case ARG_ENTITY:
614 case ARG_USER_DEPRECATED:
616 rtl::OUString sStringVal;
617 if (aValue >>= sStringVal)
618 _rOptions.setEntity(sStringVal);
619 else
620 return false;
622 break;
624 case ARG_LOCALE:
626 rtl::OUString sStringVal;
627 if (aValue >>= sStringVal)
629 _rOptions.setIsoLocale(sStringVal);
630 break;
633 lang::Locale aLocale;
634 if (aValue >>= aLocale)
636 _rOptions.setLocale(aLocale);
637 break;
640 return false;
643 case ARG_NOCACHE_OBSOLETE:
645 sal_Bool bBoolVal;
646 if (aValue >>= bBoolVal)
647 OSL_ENSURE(false,"ConfigurationProvider: Parameter \"nocache\" is obsolete and has no effect");
648 else
649 return false;
651 break;
653 case ARG_ASYNC:
654 case ARG_ASYNC_DEPRECATED:
656 sal_Bool bBoolVal = sal_False;
657 if (aValue >>= bBoolVal)
658 _rOptions.enableAsync(!!bBoolVal);
659 else
660 return false;
662 break;
663 case ARG_REFRESH:
665 sal_Bool bBoolVal = sal_False;
666 if (aValue >>= bBoolVal)
667 _rOptions.forceRefresh(!!bBoolVal);
668 else
669 return false;
671 break;
673 case ARG_NOT_FOUND:
675 rtl::OString sMessage(RTL_CONSTASCII_STRINGPARAM("Unknown argument \""));
676 sMessage += rtl::OUStringToOString(aName, RTL_TEXTENCODING_ASCII_US);
677 sMessage += rtl::OString(RTL_CONSTASCII_STRINGPARAM("\" !\n- Parameter will be ignored -\n"));
678 CFG_TRACE_WARNING( "provider: %s", sMessage.getStr() );
679 #ifdef DBG_UTIL
680 OSL_ENSURE(false, sMessage.getStr());
681 #endif
683 break;
685 default:
686 CFG_TRACE_ERROR( "Known argument is not handled" );
687 OSL_ENSURE(false, "Known argument is not handled");
688 break;
690 return true;
693 //-----------------------------------------------------------------------------------
694 static
695 void failInvalidArg(uno::Any const & aArg, sal_Int32 _nArg = -1)
696 SAL_THROW((lang::IllegalArgumentException))
698 OSL_ENSURE( sal_Int16(_nArg) == _nArg, "Argument number out of range. Raising imprecise exception.");
700 rtl::OUStringBuffer sMessage;
701 sMessage.appendAscii("Configuration Provider: An argument");
702 sMessage.appendAscii(" has the wrong type.");
703 sMessage.appendAscii("\n- Expected a NamedValue or PropertyValue");
704 sMessage.appendAscii("\n- Found type ").append( aArg.getValueType().getTypeName() );
706 throw lang::IllegalArgumentException( sMessage.makeStringAndClear(),
707 uno::Reference<uno::XInterface>(),
708 sal_Int16(_nArg+1));
711 //-----------------------------------------------------------------------------------
712 static
713 void failInvalidArgValue(rtl::OUString const & aName, uno::Any const & aValue, sal_Int32 _nArg = -1)
714 SAL_THROW((lang::IllegalArgumentException))
716 OSL_ENSURE( sal_Int16(_nArg) == _nArg, "Argument number out of range. Raising imprecise exception.");
718 rtl::OUStringBuffer sMessage;
719 sMessage.appendAscii("Configuration Provider: The argument ").append(aName);
720 sMessage.appendAscii(" has the wrong type.");
721 sMessage.appendAscii("\n- Found type ").append( aValue.getValueType().getTypeName() );
723 throw lang::IllegalArgumentException( sMessage.makeStringAndClear(),
724 uno::Reference<uno::XInterface>(),
725 sal_Int16(_nArg+1));
728 //-----------------------------------------------------------------------------------
729 static
730 bool extractLegacyArguments( const uno::Sequence<uno::Any>& _rArgs,
731 rtl::OUString& /* [out] */ _rNodeAccessor,
732 sal_Int32& /* [out] */ _nLevels )
733 SAL_THROW((lang::IllegalArgumentException))
735 OSL_ASSERT( _rArgs.getLength() != 0 );
737 // compatibility : formerly, you could specify the node path as first arg and the (optional) depth
738 // as second arg
739 if (! (_rArgs[0] >>= _rNodeAccessor) )
740 return false;
742 switch (_rArgs.getLength() )
744 case 1:
745 // valid single argument
746 return true;
748 case 2:
749 // valid second argument
750 if (_rArgs[1] >>= _nLevels)
751 return true;
753 break;
755 default:
756 if (_rArgs[1] >>= _nLevels)
758 // valid second argument, but too many arguments altogether
759 throw lang::IllegalArgumentException(
760 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
761 "Configuration Provider: Too many arguments. "
762 "Additional arguments are not supported when passing the node path as string (deprecated convention).")),
763 uno::Reference<uno::XInterface>(),
764 sal_Int16(3)
768 break;
771 // here we have an invalid second argument
773 if (_rArgs[1].getValueTypeClass() != uno::TypeClass_STRUCT)
775 // completely invalid second argument
776 failInvalidArgValue(rtl::OUString::createFromAscii("<depth>"),_rArgs[1],1);
779 // Assume PropertyValue or NamedValue,
780 // which should be handled consistently by caller
781 return false;
784 //-----------------------------------------------------------------------------------
785 void OProviderImpl::FactoryArguments::extractArgs( const uno::Sequence<uno::Any>& _rArgs,
786 rtl::OUString& /* [out] */ _rNodeAccessor,
787 sal_Int32& /* [out] */ _nLevels,
788 RequestOptions & /* [in/out] */ _aOptions )
789 SAL_THROW((lang::IllegalArgumentException))
791 UnoApiLock aLock;
793 _nLevels = treeop::ALL_LEVELS; // setting a fallback
795 // the args have to be a sequence of property or named values
796 beans::NamedValue aNV;
797 beans::PropertyValue aPV;
798 for (sal_Int32 i=0; i<_rArgs.getLength(); ++i)
800 if (_rArgs[i] >>= aPV)
802 if ( !extractOneArgument(aPV.Name,aPV.Value,_rNodeAccessor,_nLevels,_aOptions) )
803 failInvalidArgValue(aPV.Name,aPV.Value,i);
805 else if (_rArgs[i] >>= aNV)
807 if ( !extractOneArgument(aNV.Name,aNV.Value,_rNodeAccessor,_nLevels,_aOptions) )
808 failInvalidArgValue(aNV.Name,aNV.Value,i);
810 else
812 if (i == 0)// try compatibility format
813 if ( extractLegacyArguments(_rArgs,_rNodeAccessor,_nLevels))
814 break;
816 failInvalidArg(_rArgs[i],i);
817 OSL_ASSERT(false);
821 if (_rNodeAccessor.getLength() == 0)
823 rtl::OUString sMessage(RTL_CONSTASCII_USTRINGPARAM("Configuration Provider: Missing argument: no nodepath was provided"));
824 throw lang::IllegalArgumentException(sMessage,uno::Reference<uno::XInterface>(),0);
828 //--------------------------------------------------------------------------
829 uno::Reference<uno::XInterface> OProviderImpl::createReadAccess( uno::Sequence<uno::Any> const& aArgs)
830 SAL_THROW((com::sun::star::uno::Exception))
832 CFG_TRACE_INFO("config provider: going to create a read access instance");
834 // extract the args
835 rtl::OUString sPath;
836 sal_Int32 nLevels;
838 RequestOptions aOptions = getDefaultOptions();
840 OProviderImpl::FactoryArguments::extractArgs(aArgs, sPath, nLevels, aOptions);
842 CFG_TRACE_INFO_NI("config provider: node accessor extracted from the args is %s", OUSTRING2ASCII(sPath));
843 CFG_TRACE_INFO_NI("config provider: level depth extracted from the args is %i", nLevels);
845 // create the access object
846 uno::Reference< uno::XInterface > xReturn;
848 configapi::NodeElement* pElement = buildReadAccess(sPath, aOptions, nLevels);
849 if (pElement != 0)
851 xReturn = pElement->getUnoInstance();
852 if (xReturn.is())
853 // acquired once by buildReadAccess
854 xReturn->release();
857 return xReturn;
860 //-----------------------------------------------------------------------------------
861 uno::Reference<uno::XInterface> OProviderImpl::createUpdateAccess( uno::Sequence<uno::Any> const& aArgs)
862 SAL_THROW((com::sun::star::uno::Exception))
864 CFG_TRACE_INFO("config provider: going to create an update access instance");
866 // extract the args
867 rtl::OUString sPath;
868 sal_Int32 nLevels;
870 RequestOptions aOptions = getDefaultOptions();
872 OProviderImpl::FactoryArguments::extractArgs(aArgs, sPath, nLevels, aOptions);
874 CFG_TRACE_INFO_NI("config provider: node accessor extracted from the args is %s", OUSTRING2ASCII(sPath));
875 CFG_TRACE_INFO_NI("config provider: level depth extracted from the args is %i", nLevels);
877 // create the access object
878 uno::Reference< uno::XInterface > xReturn;
880 configapi::NodeElement* pElement = buildUpdateAccess(sPath, aOptions, nLevels);
881 if (pElement != 0)
883 xReturn = pElement->getUnoInstance();
884 if (xReturn.is())
885 // acquired once by buildReadAccess
886 xReturn->release();
889 return xReturn;
891 //-----------------------------------------------------------------------------------
894 } // namespace configmgr