ac957f0d93
2006/09/01 17:20:31 kaib 1.10.18.1: #i68856# Added header markers and pch files
973 lines
33 KiB
C++
973 lines
33 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: multistratumbackend.cxx,v $
|
|
*
|
|
* $Revision: 1.11 $
|
|
*
|
|
* last change: $Author: obo $ $Date: 2006-09-16 15:06:31 $
|
|
*
|
|
* The Contents of this file are made available subject to
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
|
*
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_configmgr.hxx"
|
|
|
|
#include "multistratumbackend.hxx"
|
|
|
|
#ifndef CONFIGMGR_API_FACTORY_HXX_
|
|
#include "confapifactory.hxx"
|
|
#endif // CONFIGMGR_API_FACTORY_HXX_
|
|
|
|
#ifndef CONFIGMGR_SERVICEINFOHELPER_HXX_
|
|
#include "serviceinfohelper.hxx"
|
|
#endif // CONFIGMGR_SERVICEINFOHELPER_HXX_
|
|
|
|
#ifndef CONFIGMGR_BACKEND_BACKENDSTRATALISTENER_HXX
|
|
#include "backendstratalistener.hxx"
|
|
#endif
|
|
|
|
#ifndef _CONFIGMGR_BOOTSTRAP_HXX
|
|
#include "bootstrap.hxx"
|
|
#endif
|
|
|
|
#ifndef CONFIGMGR_SIMPLEINTERACTIONREQUEST_HXX
|
|
#include "simpleinteractionrequest.hxx"
|
|
#endif
|
|
|
|
#ifndef CONFIGMGR_CONFIGINTERACTIONHANDLER_HXX
|
|
#include "configinteractionhandler.hxx"
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XMULTILAYERSTRATUM_HPP_
|
|
#include <com/sun/star/configuration/backend/XMultiLayerStratum.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XSINGLELAYERSTRATUM_HPP_
|
|
#include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_STRATUMCREATIONEXCEPTION_HPP_
|
|
#include <com/sun/star/configuration/backend/StratumCreationException.hpp>
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP_
|
|
#include <com/sun/star/task/XInteractionHandler.hpp>
|
|
#endif // _COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP_
|
|
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
|
|
#include <com/sun/star/lang/DisposedException.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_LANG_WRAPPEDTARGETRUNTIMEEXCEPTION_HPP_
|
|
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
|
|
#endif
|
|
|
|
#ifndef _RTL_USTRBUF_HXX_
|
|
#include <rtl/ustrbuf.hxx>
|
|
#endif // _RTL_USTRBUF_HXX_
|
|
|
|
#include <cppuhelper/exc_hlp.hxx>
|
|
|
|
#include <stdio.h>
|
|
|
|
//==============================================================================
|
|
#define OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
|
|
//==============================================================================
|
|
|
|
namespace {
|
|
|
|
namespace css = com::sun::star;
|
|
|
|
}
|
|
|
|
namespace configmgr { namespace backend {
|
|
|
|
//==============================================================================
|
|
static const rtl::OUString kSchemaServiceParam(
|
|
RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_ "SchemaSupplier"));
|
|
|
|
static const rtl::OUString kStrataServiceParam(
|
|
RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_ "Strata"));
|
|
|
|
static const rtl::OUString kEntity(
|
|
RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_PREFIX_"EntityLayer")) ;
|
|
|
|
static const rtl::OUString kAdminModeFlag(
|
|
RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_ADMINFLAG)) ;
|
|
|
|
static const rtl::OUString kThisOwnerEntity(
|
|
RTL_CONSTASCII_USTRINGPARAM("<ThisOwnerEntity>")) ;
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool checkOptionalArg(rtl::OUString& aArg)
|
|
{
|
|
if (aArg.getLength() && aArg[0] == sal_Unicode('?'))
|
|
{
|
|
aArg = aArg.copy(1);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
typedef std::pair<rtl::OUString, rtl::OUString> ServiceInfo;
|
|
typedef std::vector<ServiceInfo> ServiceInfoList;
|
|
void parseStrataInfo(const rtl::OUString aServiceList,
|
|
ServiceInfoList& aServiceInfoList,
|
|
const uno::Reference<uno::XInterface>& pContext)
|
|
{
|
|
sal_Int32 nNextToken =0;
|
|
sal_Int32 nLength = aServiceList.getLength();
|
|
|
|
do
|
|
{
|
|
OUString aServiceName =aServiceList.getToken(0, ':',nNextToken);
|
|
if((nNextToken ==-1)||(aServiceName.getLength()==0))
|
|
{
|
|
throw backenduno::BackendSetupException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"Malformed Strata Service specified")),
|
|
pContext, uno::Any()) ;
|
|
}
|
|
OUString aServiceData = aServiceList.getToken(0, ';',nNextToken);
|
|
|
|
ServiceInfo aServiceInfo(aServiceName,aServiceData);
|
|
aServiceInfoList.push_back(aServiceInfo);
|
|
}
|
|
while (nNextToken >= 0 && nNextToken < nLength ) ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
MultiStratumBackend::MultiStratumBackend(
|
|
const uno::Reference<uno::XComponentContext>& xContext)
|
|
: BackendBase(mMutex), mFactory(xContext->getServiceManager(),uno::UNO_QUERY_THROW)
|
|
,mListenerList()
|
|
{
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
MultiStratumBackend::~MultiStratumBackend()
|
|
{
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
bool MultiStratumBackend::checkOkState()
|
|
{
|
|
if (!mSchemaSupplier.is())
|
|
{
|
|
if(rBHelper.bDisposed)
|
|
{
|
|
throw lang::DisposedException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: Backends already disposed")),*this);
|
|
}
|
|
else
|
|
{
|
|
throw uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: Object was never Initialised")),*this);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
void SAL_CALL MultiStratumBackend::initialize(
|
|
const uno::Sequence<uno::Any>& aParameters)
|
|
throw (uno::RuntimeException, uno::Exception,
|
|
css::configuration::InvalidBootstrapFileException,
|
|
backenduno::BackendSetupException) {
|
|
|
|
if (aParameters.getLength() == 0) {
|
|
throw lang::IllegalArgumentException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"No parameters provided to MultiStratumBackend")),
|
|
*this, 0) ;
|
|
}
|
|
|
|
uno::Reference<uno::XComponentContext> context ;
|
|
|
|
for (sal_Int32 i = 0 ; i < aParameters.getLength() ; ++ i) {
|
|
if (aParameters [i] >>= context) { break ; }
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
//Initialize Backends
|
|
initializeSchemaSupplier (context);
|
|
initializeBackendStrata(context);
|
|
|
|
sal_Bool bAdminMode = false;
|
|
context->getValueByName(kAdminModeFlag) >>= bAdminMode;
|
|
|
|
if (bAdminMode)
|
|
{
|
|
// find given entity
|
|
OUString sDefaultEntity;
|
|
if ( (context->getValueByName(kEntity) >>= sDefaultEntity) && sDefaultEntity.getLength() )
|
|
{
|
|
for (sal_uInt32 i = 0; i < mBackendStrata.size(); i++)
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( mBackendStrata[i], uno::UNO_QUERY );
|
|
if (xEntities.is()&& xEntities->supportsEntity(sDefaultEntity))
|
|
{
|
|
mBackendStrata.resize(i+1);
|
|
mOwnerEntity = sDefaultEntity;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mBackendStrata.resize(1);
|
|
}
|
|
}
|
|
|
|
if(mOwnerEntity.getLength()==0)
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities(
|
|
mBackendStrata[mBackendStrata.size()-1], uno::UNO_QUERY );
|
|
if (xEntities.is())
|
|
{
|
|
mOwnerEntity = xEntities->getOwnerEntity();
|
|
}
|
|
else
|
|
{
|
|
mOwnerEntity = kThisOwnerEntity;
|
|
}
|
|
}
|
|
mStrataListener = new BackendStrataListener(*this);
|
|
|
|
}
|
|
catch(uno::Exception& )
|
|
{
|
|
mSchemaSupplier.clear();
|
|
mBackendStrata.clear() ;
|
|
|
|
throw;
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
typedef uno::Reference<backenduno::XSchemaSupplier> SchemaSupplier;
|
|
void MultiStratumBackend::initializeSchemaSupplier(const uno::Reference<uno::XComponentContext>& aContext)
|
|
{
|
|
|
|
OUString aServiceName;
|
|
|
|
aContext->getValueByName(kSchemaServiceParam) >>= aServiceName;
|
|
uno::Sequence< uno::Any > aInitArgs( 1 );
|
|
aInitArgs[0] <<= aContext;
|
|
mSchemaSupplier = SchemaSupplier::query(mFactory->createInstanceWithArguments(aServiceName,aInitArgs)) ;
|
|
if (!mSchemaSupplier.is())
|
|
{
|
|
throw backenduno::BackendSetupException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: Could not create Schema Supplier service")),
|
|
*this, uno::Any()) ;
|
|
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
static
|
|
bool approveRecovery(const backenduno::StratumCreationException & aError)
|
|
{
|
|
using namespace apihelper;
|
|
typedef SimpleInteractionRequest::Continuation Choice;
|
|
Choice const k_supported_choices = CONTINUATION_APPROVE ; //| CONTINUATION_DISAPPROVE;
|
|
|
|
Choice chosen = CONTINUATION_UNKNOWN;
|
|
|
|
ConfigurationInteractionHandler handler;
|
|
try {
|
|
uno::Reference< css::task::XInteractionHandler > h(handler.get());
|
|
if (h.is()) {
|
|
rtl::Reference< SimpleInteractionRequest > req(
|
|
new SimpleInteractionRequest(
|
|
uno::makeAny(aError), k_supported_choices));
|
|
h->handle(req.get());
|
|
chosen = req->getResponse();
|
|
}
|
|
} catch (uno::Exception & e) {
|
|
OSL_TRACE("Warning - Configuration: Interaction handler failed: [%s]\n", OU2A(e.Message));
|
|
}
|
|
|
|
switch (chosen)
|
|
{
|
|
case CONTINUATION_APPROVE: return true;
|
|
case CONTINUATION_DISAPPROVE: return false;
|
|
case CONTINUATION_UNKNOWN: break;
|
|
|
|
default: OSL_ENSURE(false,"Unsolicited continuation chosen"); break;
|
|
}
|
|
// no choice available - default: disapprove
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void MultiStratumBackend::initializeBackendStrata(const uno::Reference<uno::XComponentContext>& aContext)
|
|
{
|
|
|
|
OUString sStrata;
|
|
//Get Strata
|
|
aContext->getValueByName(kStrataServiceParam) >>= sStrata;
|
|
if(sStrata.getLength()==0)
|
|
{
|
|
throw backenduno::BackendSetupException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: No Strata Services Specified")),
|
|
*this, uno::Any()) ;
|
|
|
|
}
|
|
|
|
//need to parse the Strata to extract service names and data location
|
|
ServiceInfoList aServiceInfoList;
|
|
parseStrataInfo(sStrata,aServiceInfoList,*this);
|
|
|
|
for (ServiceInfoList::const_iterator it = aServiceInfoList.begin(); it != aServiceInfoList.end(); ++it)
|
|
{
|
|
uno::Sequence< uno::Any > aInitArgs( 1 );
|
|
OUString sServiceName = it->first;
|
|
const OUString& sServiceData = it->second;
|
|
aInitArgs[0] <<= sServiceData;
|
|
uno::Reference <uno::XInterface> xBackend;
|
|
bool bOptional = checkOptionalArg(sServiceName);
|
|
try
|
|
{
|
|
xBackend= mFactory->createInstanceWithArguments(sServiceName,aInitArgs);
|
|
}
|
|
catch (uno::Exception& exception)
|
|
{
|
|
if(!bOptional)
|
|
{
|
|
static const sal_Char sErrContext[] = "MultiStratumBackend: Could not create Backend Stratum Service: ";
|
|
OUString const sContext(RTL_CONSTASCII_USTRINGPARAM(sErrContext));
|
|
OUString const sMessage = sContext.concat(exception.Message);
|
|
|
|
backenduno::StratumCreationException error(sMessage,*this,
|
|
::cppu::getCaughtException(),
|
|
sServiceName,sServiceData);
|
|
if (!approveRecovery(error))
|
|
throw error;
|
|
}
|
|
|
|
}
|
|
if (xBackend.is())
|
|
{
|
|
mBackendStrata.push_back(xBackend) ;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------------------------
|
|
// XBackendEntities
|
|
rtl::OUString SAL_CALL
|
|
MultiStratumBackend::getOwnerEntity( )
|
|
throw (uno::RuntimeException)
|
|
{
|
|
|
|
if (checkOkState())
|
|
{
|
|
return mOwnerEntity;
|
|
}
|
|
return OUString();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
rtl::OUString SAL_CALL
|
|
MultiStratumBackend::getAdminEntity()
|
|
throw (uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if (checkOkState())
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( mBackendStrata[0], uno::UNO_QUERY );
|
|
if(xEntities.is())
|
|
{
|
|
return xEntities->getAdminEntity();
|
|
}
|
|
else
|
|
{
|
|
return OUString();
|
|
}
|
|
}
|
|
return OUString();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL
|
|
MultiStratumBackend::supportsEntity( const rtl::OUString& aEntity )
|
|
throw (backenduno::BackendAccessException, uno::RuntimeException)
|
|
{
|
|
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if (checkOkState())
|
|
{
|
|
for (BackendStrata::const_iterator it = mBackendStrata.begin(); it != mBackendStrata.end(); ++it)
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( *it, uno::UNO_QUERY );
|
|
if (xEntities.is())
|
|
{
|
|
if( xEntities->supportsEntity(aEntity))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL
|
|
MultiStratumBackend::isEqualEntity( const rtl::OUString& aEntity, const rtl::OUString& aOtherEntity )
|
|
throw (backenduno::BackendAccessException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if (aEntity.getLength() == 0)
|
|
{
|
|
rtl::OUString const sMsg(RTL_CONSTASCII_USTRINGPARAM(
|
|
"LocalSingleBackend - Invalid empty entity."));
|
|
|
|
throw lang::IllegalArgumentException(sMsg, *this, 1);
|
|
}
|
|
if (aOtherEntity.getLength() == 0)
|
|
{
|
|
rtl::OUString const sMsg(RTL_CONSTASCII_USTRINGPARAM(
|
|
"LocalSingleBackend - Invalid empty entity."));
|
|
|
|
throw lang::IllegalArgumentException(sMsg, *this, 2);
|
|
}
|
|
|
|
|
|
if (aEntity.equals(aOtherEntity))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (checkOkState())
|
|
{
|
|
for (BackendStrata::const_iterator it = mBackendStrata.begin(); it != mBackendStrata.end(); ++it)
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( *it, uno::UNO_QUERY );
|
|
if (xEntities.is())
|
|
{
|
|
if( xEntities->supportsEntity(aEntity))
|
|
return xEntities->isEqualEntity(aEntity,aOtherEntity);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
rtl::OUString SAL_CALL
|
|
MultiStratumBackend::getSchemaVersion(const rtl::OUString& aComponent)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
|
|
if (checkOkState())
|
|
{
|
|
uno::Reference<backenduno::XVersionedSchemaSupplier> xVersionSupplier(mSchemaSupplier,uno::UNO_QUERY);
|
|
if (xVersionSupplier.is())
|
|
return xVersionSupplier->getSchemaVersion(aComponent) ;
|
|
}
|
|
return rtl::OUString();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
uno::Reference<backenduno::XSchema> SAL_CALL
|
|
MultiStratumBackend::getComponentSchema(const rtl::OUString& aComponent)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
|
|
if (checkOkState())
|
|
{
|
|
return mSchemaSupplier->getComponentSchema(aComponent) ;
|
|
}
|
|
return NULL;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
uno::Sequence<uno::Reference<backenduno::XLayer> > SAL_CALL
|
|
MultiStratumBackend::listOwnLayers(const rtl::OUString& aComponent)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
if (checkOkState())
|
|
{
|
|
return listLayers(aComponent, mOwnerEntity ) ;
|
|
}
|
|
return uno::Sequence<uno::Reference<backenduno::XLayer> >() ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
uno::Reference<backenduno::XUpdateHandler> SAL_CALL
|
|
MultiStratumBackend::getOwnUpdateHandler(const rtl::OUString& aComponent)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::NoSupportException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
if (checkOkState())
|
|
{
|
|
return getUpdateHandler(aComponent, mOwnerEntity) ;
|
|
}
|
|
return NULL;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
uno::Sequence<uno::Reference<backenduno::XLayer> > SAL_CALL
|
|
MultiStratumBackend::listLayers(const rtl::OUString& aComponent,
|
|
const rtl::OUString& aEntity)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if (checkOkState())
|
|
{
|
|
sal_Int32 nNumSupportedLayers = mBackendStrata.size();
|
|
if(aEntity != mOwnerEntity)
|
|
{
|
|
nNumSupportedLayers = findSupportingStratum(aEntity);
|
|
}
|
|
return searchSupportingStrata(nNumSupportedLayers,aEntity,aComponent);
|
|
}
|
|
return uno::Sequence<uno::Reference<backenduno::XLayer> >();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 MultiStratumBackend::findSupportingStratum(const rtl::OUString& aEntity)
|
|
{
|
|
sal_Int32 nNumLayers = mBackendStrata.size();
|
|
for (BackendStrata::reverse_iterator it = mBackendStrata.rbegin(); it != mBackendStrata.rend(); ++it)
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( *it, uno::UNO_QUERY );
|
|
if (xEntities.is())
|
|
{
|
|
if( xEntities->supportsEntity(aEntity))
|
|
{
|
|
return nNumLayers;
|
|
}
|
|
}
|
|
nNumLayers--;
|
|
}
|
|
rtl::OUStringBuffer sMsg;
|
|
sMsg.appendAscii("\n MultiStratumBackend: No Backend supports Entity: \"");
|
|
sMsg.append(aEntity);
|
|
throw lang::IllegalArgumentException(sMsg.makeStringAndClear(),
|
|
*this, 0) ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
typedef std::vector<uno::Reference<backenduno::XLayer> > BackendLayers;
|
|
uno::Sequence<uno::Reference<backenduno::XLayer> >
|
|
MultiStratumBackend::searchSupportingStrata(sal_Int32 nNumLayers,
|
|
rtl::OUString aEntity,
|
|
const rtl::OUString& aComponent)
|
|
{
|
|
uno::Sequence<uno::Reference<backenduno::XLayer> > aLayers;
|
|
BackendLayers aBackendLayers;
|
|
for (sal_Int32 i = 0 ; i < nNumLayers ; ++ i)
|
|
{
|
|
uno::Sequence<uno::Reference<backenduno::XLayer> > aMultiLayers;
|
|
uno::Reference< backenduno::XBackendEntities > xEntities(mBackendStrata[i], uno::UNO_QUERY );
|
|
|
|
uno::Reference<backenduno::XBackend> xBackend(mBackendStrata[i], uno::UNO_QUERY) ;
|
|
if (xBackend.is())
|
|
{
|
|
if (xEntities.is())
|
|
{
|
|
if( !xEntities->supportsEntity(aEntity))
|
|
{
|
|
aEntity = xEntities->getOwnerEntity();
|
|
}
|
|
aMultiLayers = xBackend->listLayers(aComponent, aEntity) ;
|
|
}
|
|
else
|
|
{
|
|
aMultiLayers = xBackend->listOwnLayers(aComponent);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uno::Reference<backenduno::XMultiLayerStratum> xMultiLayerStratum(
|
|
mBackendStrata[i], uno::UNO_QUERY) ;
|
|
|
|
if (xMultiLayerStratum.is())
|
|
{
|
|
if (xEntities.is())
|
|
{
|
|
if( !xEntities->supportsEntity(aEntity))
|
|
{
|
|
aEntity = xEntities->getOwnerEntity();
|
|
}
|
|
aMultiLayers = xMultiLayerStratum->getLayers(
|
|
xMultiLayerStratum->listLayerIds(aComponent, aEntity),
|
|
rtl::OUString()) ;
|
|
|
|
}
|
|
else
|
|
{
|
|
throw backenduno::BackendSetupException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: XMultiLayerStratum must support XBackendEntities")),
|
|
*this, uno::Any()) ;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
uno::Reference<backenduno::XSingleLayerStratum> xSingleLayerStratum(
|
|
mBackendStrata[i], uno::UNO_REF_QUERY_THROW) ;
|
|
if (xSingleLayerStratum.is())
|
|
{
|
|
uno::Reference<backenduno::XLayer> xLayer = xSingleLayerStratum->getLayer( aComponent, OUString());
|
|
//Could be an empty layer
|
|
if (xLayer.is())
|
|
{
|
|
aBackendLayers.push_back(xLayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// There might be non-existent layers in the list if there's no
|
|
// actual data associated to a given layer id. Hence we have to
|
|
// compress the list.
|
|
for (sal_Int32 j = 0 ; j < aMultiLayers.getLength() ; ++j)
|
|
{
|
|
if (aMultiLayers [j].is())
|
|
{
|
|
aBackendLayers.push_back( aMultiLayers[j]);
|
|
}
|
|
}
|
|
}
|
|
aLayers.realloc(aBackendLayers.size());
|
|
for (sal_uInt32 k =0; k < aBackendLayers.size();k++)
|
|
{
|
|
aLayers[k] = aBackendLayers[k];
|
|
}
|
|
return aLayers;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
uno::Reference<backenduno::XUpdateHandler> SAL_CALL
|
|
MultiStratumBackend::getUpdateHandler(const rtl::OUString& aComponent,
|
|
const rtl::OUString& aEntity)
|
|
throw (backenduno::BackendAccessException,
|
|
lang::NoSupportException,
|
|
lang::IllegalArgumentException,
|
|
uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
|
|
if (checkOkState())
|
|
{
|
|
|
|
sal_Int32 nNumSupportedLayers = mBackendStrata.size();
|
|
OUString aUsedEntity;
|
|
|
|
if(aEntity != mOwnerEntity)
|
|
{
|
|
nNumSupportedLayers = findSupportingStratum(aEntity);
|
|
aUsedEntity = aEntity;
|
|
}
|
|
else
|
|
{
|
|
uno::Reference< backenduno::XBackendEntities > xEntities( mBackendStrata[mBackendStrata.size()-1], uno::UNO_QUERY );
|
|
if (xEntities.is())
|
|
{
|
|
aUsedEntity = xEntities->getOwnerEntity();
|
|
}
|
|
}
|
|
sal_Int32 nStrataIndex = nNumSupportedLayers -1;
|
|
|
|
uno::Reference<backenduno::XBackend> xBackend(
|
|
mBackendStrata[nStrataIndex], uno::UNO_QUERY) ;
|
|
uno::Reference< uno::XInterface > xHandler;
|
|
if(xBackend.is())
|
|
{
|
|
if (aUsedEntity.getLength()==0)
|
|
{
|
|
xHandler = xBackend->getOwnUpdateHandler(aComponent) ;
|
|
return uno::Reference<backenduno::XUpdateHandler>(xHandler,uno::UNO_REF_QUERY_THROW);
|
|
}
|
|
else
|
|
{
|
|
xHandler = xBackend->getUpdateHandler(aComponent, aUsedEntity) ;
|
|
return uno::Reference<backenduno::XUpdateHandler>(xHandler,uno::UNO_REF_QUERY_THROW);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
uno::Sequence<uno::Any> arguments(1) ;
|
|
|
|
uno::Reference< backenduno::XMultiLayerStratum > xMultiLayerStratum
|
|
(mBackendStrata[nStrataIndex], uno::UNO_QUERY );
|
|
if(xMultiLayerStratum.is())
|
|
{
|
|
arguments [0] <<= xMultiLayerStratum->getUpdatableLayer(
|
|
xMultiLayerStratum->getUpdateLayerId(aComponent,aUsedEntity));
|
|
}
|
|
else
|
|
{
|
|
uno::Reference< backenduno::XSingleLayerStratum > xSingleLayerStratum(
|
|
mBackendStrata[nStrataIndex], uno::UNO_REF_QUERY_THROW );
|
|
|
|
arguments [0] <<= xSingleLayerStratum->getUpdatableLayer(aComponent);
|
|
|
|
}
|
|
|
|
if(!xHandler.is())
|
|
{
|
|
try
|
|
{
|
|
const rtl::OUString kUpdateMerger(RTL_CONSTASCII_USTRINGPARAM(
|
|
"com.sun.star.configuration.backend.LayerUpdateMerger")) ;
|
|
|
|
|
|
if(!mFactory.is())
|
|
{
|
|
throw lang::DisposedException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
"MultiStratumBackend: Service Factory already dispoed")),*this);
|
|
}
|
|
|
|
xHandler = mFactory->createInstanceWithArguments(kUpdateMerger, arguments);
|
|
}
|
|
catch (uno::RuntimeException & )
|
|
{throw;}
|
|
catch (uno::Exception & e)
|
|
{
|
|
const rtl::OUString sMessage(RTL_CONSTASCII_USTRINGPARAM(
|
|
"Configuration MultiStratumBackend: Cannot create UpdateMerger - error message: ")) ;
|
|
throw uno::RuntimeException(sMessage.concat(e.Message),*this);
|
|
}
|
|
}
|
|
return uno::Reference<backenduno::XUpdateHandler>(xHandler, uno::UNO_REF_QUERY_THROW) ;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
// ---------------------------------------------------------------------------
|
|
// ComponentHelper
|
|
void SAL_CALL MultiStratumBackend::disposing()
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if (mFactory.is())
|
|
{
|
|
mFactory.clear();
|
|
}
|
|
if (mSchemaSupplier.is())
|
|
{
|
|
uno::Reference< lang::XComponent> xComp( mSchemaSupplier, uno::UNO_QUERY);
|
|
if (xComp.is())
|
|
{
|
|
xComp->dispose();
|
|
}
|
|
if (mSchemaSupplier.is())
|
|
{
|
|
mSchemaSupplier.clear();
|
|
}
|
|
}
|
|
if (!mBackendStrata.empty())
|
|
{
|
|
for (BackendStrata::const_iterator it = mBackendStrata.begin(); it != mBackendStrata.end(); ++it)
|
|
{
|
|
uno::Reference< lang::XComponent> xComp( *it, uno::UNO_QUERY );
|
|
if (xComp.is())
|
|
{
|
|
try
|
|
{
|
|
xComp->dispose();
|
|
}
|
|
catch(uno::Exception &){}
|
|
}
|
|
}
|
|
mBackendStrata.clear();
|
|
|
|
}
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
static const sal_Char * const kBackendService = "com.sun.star.configuration.backend.Backend" ;
|
|
|
|
static const sal_Char * const kImplementation =
|
|
"com.sun.star.comp.configuration.backend.MultiStratumBackend" ;
|
|
|
|
static const AsciiServiceName kServiceNames [] =
|
|
{
|
|
kBackendService,
|
|
0
|
|
} ;
|
|
static const ServiceImplementationInfo kServiceInfo =
|
|
{
|
|
kImplementation,
|
|
kServiceNames,
|
|
0
|
|
} ;
|
|
|
|
const ServiceRegistrationInfo *getMultiStratumBackendServiceInfo()
|
|
{
|
|
return getRegistrationInfo(&kServiceInfo) ;
|
|
}
|
|
|
|
uno::Reference<uno::XInterface> SAL_CALL
|
|
instantiateMultiStratumBackend(const CreationContext& xContext)
|
|
{
|
|
return *new MultiStratumBackend(xContext) ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
static const rtl::OUString kImplementationName(
|
|
RTL_CONSTASCII_USTRINGPARAM(kImplementation)) ;
|
|
//------------------------------------------------------------------------------
|
|
|
|
rtl::OUString SAL_CALL
|
|
MultiStratumBackend::getImplementationName(void)
|
|
throw (uno::RuntimeException)
|
|
{
|
|
return ServiceInfoHelper(&kServiceInfo).getImplementationName() ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL
|
|
MultiStratumBackend::supportsService(const rtl::OUString& aServiceName)
|
|
throw (uno::RuntimeException)
|
|
{
|
|
return ServiceInfoHelper(&kServiceInfo).supportsService(aServiceName) ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
uno::Sequence<rtl::OUString> SAL_CALL
|
|
MultiStratumBackend::getSupportedServiceNames(void)
|
|
throw (uno::RuntimeException)
|
|
{
|
|
return ServiceInfoHelper(&kServiceInfo).getSupportedServiceNames() ;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL MultiStratumBackend::addChangesListener( const uno::Reference<backenduno::XBackendChangesListener>& xListener,
|
|
const rtl::OUString& aComponent)
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if(checkOkState())
|
|
{
|
|
|
|
mListenerList.insert( ListenerList::value_type(aComponent, xListener));
|
|
//Now register with lower layers
|
|
for (sal_uInt32 i = 0 ; i < mBackendStrata.size() ; ++ i)
|
|
{
|
|
uno::Reference<backenduno::XBackendChangesNotifier> xBackend(mBackendStrata[i], uno::UNO_QUERY) ;
|
|
if (xBackend.is())
|
|
{
|
|
xBackend->addChangesListener(mStrataListener, aComponent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL MultiStratumBackend::removeChangesListener( const uno::Reference<backenduno::XBackendChangesListener>& /*xListner*/,
|
|
const rtl::OUString& aComponent)
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
osl::MutexGuard aGuard(mMutex);
|
|
if(checkOkState())
|
|
{
|
|
sal_Int32 nCount = mListenerList.count(aComponent);
|
|
if (nCount == 0)
|
|
{
|
|
OSL_TRACE("MultiStratumBackend: removeListener: no listener registered for component %s"
|
|
, aComponent.getStr());
|
|
}
|
|
else
|
|
{
|
|
ListenerList::iterator aIter;
|
|
aIter = mListenerList.find(aComponent);
|
|
mListenerList.erase(aIter);
|
|
if (nCount == 1)
|
|
{
|
|
//Deregister Listener from strata backend if they support notification
|
|
for (sal_uInt32 i = 0 ; i < mBackendStrata.size(); ++ i)
|
|
{
|
|
uno::Reference<backenduno::XBackendChangesNotifier> xBackend(mBackendStrata[i], uno::UNO_QUERY) ;
|
|
if (xBackend.is())
|
|
{
|
|
xBackend->removeChangesListener(mStrataListener, aComponent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void MultiStratumBackend::componentDataChanged(const backenduno::ComponentChangeEvent& aEvent)
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
try
|
|
{
|
|
notifyListeners( aEvent);
|
|
|
|
}
|
|
catch (uno::RuntimeException& ) { throw; }
|
|
catch (uno::Exception& e)
|
|
{
|
|
throw lang::WrappedTargetRuntimeException(e.Message, *this, uno::makeAny(e));
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void MultiStratumBackend::disposing( lang::EventObject const & /*rSource*/ )
|
|
throw (::com::sun::star::uno::RuntimeException)
|
|
{}
|
|
//------------------------------------------------------------------------------
|
|
void MultiStratumBackend::notifyListeners(const backenduno::ComponentChangeEvent& aEvent)const
|
|
{
|
|
//fire off notification to all registered listeners for specific Component
|
|
ListenerList::const_iterator aIter;
|
|
OUString aComponentName = aEvent.Component;
|
|
if (mListenerList.empty())
|
|
{
|
|
OSL_TRACE("MultiStratumBackend: notifyListeners: no listeners registered for component %s",
|
|
aComponentName.getStr());
|
|
}
|
|
else
|
|
{
|
|
aIter = mListenerList.begin();
|
|
do{
|
|
if (aIter->first == aComponentName)
|
|
{
|
|
aIter->second->componentDataChanged(aEvent);
|
|
}
|
|
aIter++;
|
|
}while (aIter != mListenerList.end());
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
} } // configmgr.backend
|
|
|