office-gobmx/configmgr/source/backend/backendaccess.cxx

836 lines
33 KiB
C++
Raw Normal View History

2002-05-27 11:11:41 -05:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2002-05-27 11:11:41 -05:00
*
* Copyright 2008 by Sun Microsystems, Inc.
2002-05-27 11:11:41 -05:00
*
* OpenOffice.org - a multi-platform office productivity suite
2002-05-27 11:11:41 -05:00
*
* $RCSfile: backendaccess.cxx,v $
* $Revision: 1.27 $
2002-05-27 11:11:41 -05:00
*
* This file is part of OpenOffice.org.
2002-05-27 11:11:41 -05:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2002-05-27 11:11:41 -05:00
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2002-05-27 11:11:41 -05:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2002-05-27 11:11:41 -05:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"
2002-05-27 11:11:41 -05:00
#include "backendaccess.hxx"
#include "logger.hxx"
#include "matchlocale.hxx"
2002-05-27 11:11:41 -05:00
#include "layermerge.hxx"
#include "schemabuilder.hxx"
2002-06-13 10:45:34 -05:00
#ifndef CONFIGMGR_BACKEND_UPDATEDISPATCHER_HXX
#include "updatedispatch.hxx"
#endif // CONFIGMGR_BACKEND_UPDATEDISPATCHER_HXX
#include "backendnotifier.hxx"
#include "emptylayer.hxx"
#include "filehelper.hxx"
#include "simpleinteractionrequest.hxx"
#include "configinteractionhandler.hxx"
#include <com/sun/star/configuration/backend/XVersionedSchemaSupplier.hpp>
#include <com/sun/star/configuration/backend/XCompositeLayer.hpp>
#include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
#include <com/sun/star/configuration/backend/XBackendEntities.hpp>
#include <com/sun/star/configuration/backend/MergeRecoveryRequest.hpp>
#include <com/sun/star/configuration/backend/MalformedDataException.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/lang/NullPointerException.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include "com/sun/star/task/XInteractionHandler.hpp"
#include <rtl/ustrbuf.hxx>
#include <rtl/ref.hxx>
#include <rtl/logfile.hxx>
#include <cppuhelper/exc_hlp.hxx>
2002-05-27 11:11:41 -05:00
#ifndef INCLUDED_VECTOR
#include <vector>
#define INCLUDED_VECTOR
#endif //INCLUDED_VECTOR
#ifndef INCLUDED_ALGORITHM
#include <algorithm>
#define INCLUDED_ALGORITHM
#endif //INCLUDED_ALGORITHM
#define OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
#define RTL_LOGFILE_OU2A(rtlOUString) OU2A(rtlOUString)
#define OUSTR(txt) OUString( RTL_CONSTASCII_USTRINGPARAM(txt) )
2002-05-27 11:11:41 -05:00
namespace configmgr { namespace backend {
2002-05-27 11:11:41 -05:00
//------------------------------------------------------------------------------
namespace task = com::sun::star::task;
typedef uno::Reference< backenduno::XUpdatableLayer > LayerDataRemover;
2002-05-27 11:11:41 -05:00
inline
uno::Reference<lang::XMultiServiceFactory> BackendAccess::getServiceFactory() const
{
return uno::Reference<lang::XMultiServiceFactory>(mContext->getServiceManager(),uno::UNO_QUERY_THROW);
}
//------------------------------------------------------------------------------
2002-06-13 10:45:34 -05:00
BackendAccess::BackendAccess(
const uno::Reference<backenduno::XBackend>& xBackend,
const uno::Reference<uno::XComponentContext>& xContext)
: mContext(xContext)
, mBackend(xBackend)
, mBinaryCache(xContext)
{
OSL_ENSURE(mContext.is(), "BackendAccess: Context is missing");
if (!mContext.is())
throw lang::NullPointerException(OUString::createFromAscii("BackendAccess: NULL Context passed"), NULL);
if (!xBackend.is())
throw lang::NullPointerException(OUSTR("Configuration: Trying to create backend access without backend"),NULL);
if (!uno::Reference<backenduno::XSchemaSupplier>::query(xBackend).is())
throw lang::NullPointerException(OUSTR("Configuration: No backend for schemas available"),NULL);
mNotifier = new BackendChangeNotifier(xBackend);
//Stored as uno::reference to facilitate sharing with MultiStratumBackend
mXNotifier = mNotifier;
//Create Binary Cache
uno::Reference<backenduno::XBackendEntities> xBackendEntities = uno::Reference<backenduno::XBackendEntities>( mBackend, uno::UNO_QUERY) ;
OSL_ENSURE(xBackendEntities.is(),"Backend does not provide entity information");
if ( xBackendEntities.is() ) mBinaryCache.setOwnerEntity(xBackendEntities->getOwnerEntity());
2002-05-27 11:11:41 -05:00
}
//------------------------------------------------------------------------------
BackendAccess::~BackendAccess() {}
2002-05-27 11:11:41 -05:00
//------------------------------------------------------------------------------
namespace
{
using localehelper::Locale;
using localehelper::LocaleSequence;
//------------------------------------------------------------------------------
static inline
bool findLocale(LocaleSequence const & seq, Locale const & loc)
{
LocaleSequence::const_iterator first = seq.begin();
LocaleSequence::const_iterator last = seq.end();
for ( ; first != last; ++first)
if (localehelper::equalLocale(*first, loc))
return true;
return false;
}
//------------------------------------------------------------------------------
static inline
void addLocale( Locale const & aLocale, LocaleSequence & inoutLocales)
{
if (!findLocale(inoutLocales,aLocale))
inoutLocales.push_back(aLocale);
}
//------------------------------------------------------------------------------
static OUString toString(uno::Sequence< OUString > const & seq, sal_Unicode separator = ',')
{
rtl::OUStringBuffer buf;
if (sal_Int32 const nCount = seq.getLength())
{
buf.append(seq[0]);
for (sal_Int32 ix=1; ix < nCount; ++ix)
buf.append(separator).append(seq[ix]);
}
else
buf.appendAscii("<none>");
return buf.makeStringAndClear();
}
//------------------------------------------------------------------------------
static
uno::Sequence< OUString > intersect(uno::Sequence< OUString > const & seq1, uno::Sequence< OUString > const & seq2)
{
sal_Int32 const len1 = seq1.getLength();
uno::Sequence< OUString > aResult(len1);
2002-05-27 11:11:41 -05:00
OUString const * const beg2 = seq2.getConstArray();
OUString const * const end2 = beg2 + seq2.getLength();
2002-07-03 07:38:50 -05:00
sal_Int32 ix = 0;
for (sal_Int32 i1 = 0; i1 < len1; ++i1)
{
if (std::find(beg2,end2,seq1[i1]) != end2)
aResult[ix++] = seq1[i1];
}
aResult.realloc(ix);
return aResult;
}
//------------------------------------------------------------------------------
} // anonymous namespace
//------------------------------------------------------------------------------
// helper used by the binary cache
uno::Sequence< rtl::OUString >
getAvailableLocales(const uno::Reference<backenduno::XLayer> * pLayers, sal_Int32 nNumLayers)
{
uno::Sequence< rtl::OUString > aResult;
2002-07-03 07:38:50 -05:00
for (sal_Int32 i = 0 ; i < nNumLayers ; ++ i)
{
uno::Reference<backenduno::XCompositeLayer> compositeLayer(
pLayers [i], uno::UNO_QUERY) ;
if (compositeLayer.is())
{
uno::Sequence<rtl::OUString> aLocales = compositeLayer->listSubLayerIds();
if (aResult.getLength() == 0)
{
aResult = aLocales;
2002-07-03 07:38:50 -05:00
}
else
{
OSL_TRACE("Warning: multiple composite layers found. Detection of available locales is inaccurate.");
// be defensive: only locales present in all composite layers are 'available'
aResult= intersect(aResult,aLocales);
2002-07-03 07:38:50 -05:00
}
}
}
return aResult;
2002-07-03 07:38:50 -05:00
}
//------------------------------------------------------------------------------
static OUString getLayerURL(const uno::Reference<backenduno::XLayer> & aLayer);
2002-07-03 07:38:50 -05:00
void BackendAccess::merge(
2002-06-07 10:53:05 -05:00
MergedComponentData& aData,
const uno::Reference<backenduno::XLayer> * pLayers,
sal_Int32 aNumLayers,
localehelper::Locale const & aRequestedLocale,
localehelper::LocaleSequence & inoutMergedLocales,
ITemplateDataProvider *aTemplateProvider,
sal_Int32 * pLayersMerged)
CFG_UNO_THROW_ALL()
2002-05-27 11:11:41 -05:00
{
LayerMergeHandler * pMerger = new LayerMergeHandler(mContext, aData, aTemplateProvider );
uno::Reference<backenduno::XLayerHandler> xLayerMerger(pMerger);
Logger logger(mContext);
RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::merge()");
RTL_LOGFILE_CONTEXT_TRACE1(aLog, "merging %d layers", int(aNumLayers) );
OUString const & aLanguage = aRequestedLocale.Language;
bool const needAllLanguages = localehelper::isAnyLanguage(aLanguage);
if (aLanguage.getLength() && !needAllLanguages)
{
if (!localehelper::isDefaultLanguage(aLanguage))
addLocale(aRequestedLocale,inoutMergedLocales);
}
bool const needLocalizedData = needAllLanguages || !inoutMergedLocales.empty();
if (logger.isLogging(LogLevel::FINEST))
{
if (!needLocalizedData)
logger.finest("Starting merge with NO locales", "merge()","configmgr::Backend");
else if (needAllLanguages)
logger.finest("Starting merge for ALL locales", "merge()","configmgr::Backend");
else
logger.finest(OUSTR("Starting merge for locale(s): ") +
toString(localehelper::makeIsoSequence(inoutMergedLocales)),
"merge()","configmgr::Backend");
}
if (pLayersMerged) *pLayersMerged = 0;
for (sal_Int32 i = 0 ; i < aNumLayers ; ++ i)
{
if (logger.isLogging(LogLevel::FINEST))
logger.finest(OUSTR("+ Merging layer: ") + getLayerURL(pLayers[i]),
"merge()","configmgr::Backend");
pMerger->prepareLayer() ;
pLayers [i]->readData(xLayerMerger) ;
if (needLocalizedData)
{
uno::Reference<backenduno::XCompositeLayer> compositeLayer(
pLayers [i], uno::UNO_QUERY) ;
if (compositeLayer.is())
{
uno::Sequence<rtl::OUString> aSubLayerIds = compositeLayer->listSubLayerIds();
logger.finest(OUSTR("++ Found locales: ") + toString(aSubLayerIds),
"merge()","configmgr::Backend");
for (sal_Int32 j = 0; j < aSubLayerIds.getLength(); ++j)
{
OUString const & aLocaleIso = aSubLayerIds[j];
Locale aLocale = localehelper::makeLocale(aLocaleIso);
// requesting de-CH, we accept de-CH and de, but not de-DE
const localehelper::MatchQuality kMatchAccept = localehelper::MATCH_LANGUAGE_PLAIN;
if (needAllLanguages || localehelper::isMatch(aLocale,inoutMergedLocales,kMatchAccept))
{
if(pMerger->prepareSublayer(aLocaleIso))
{
logger.finest(OUSTR("++ Merging sublayer for locale: ") + aLocaleIso,
"merge()","configmgr::Backend");
compositeLayer->readSubLayerData(xLayerMerger,aLocaleIso) ;
addLocale(aLocale,inoutMergedLocales);
}
// else dropLocale(aLocale,inoutMergedLocales); ?
}
}
2002-07-03 07:38:50 -05:00
}
}
if (pLayersMerged) ++*pLayersMerged;
2002-05-27 11:11:41 -05:00
}
}
//------------------------------------------------------------------------------
bool BackendAccess::readDefaultData( MergedComponentData & aComponentData,
OUString const & aComponent,
RequestOptions const & aOptions,
bool bIncludeTemplates,
const uno::Reference<backenduno::XLayer> * pLayers,
sal_Int32 nNumLayers,
ITemplateDataProvider *aTemplateProvider,
sal_Int32 * pLayersMerged)
CFG_UNO_THROW_ALL()
{
RTL_LOGFILE_CONTEXT_AUTHOR(aLog1, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::readDefaultData()");
Logger logger(mContext);
const Logger::Level detail = LogLevel::FINER;
bool const bLogDetail = logger.isLogging(detail);
OUString const aSchemaVersion = this->getSchemaVersion(aComponent);
if (logger.isLogging(LogLevel::FINE))
{
rtl::OUStringBuffer aMsg;
aMsg.appendAscii("Reading data for component \"").append(aComponent).appendAscii("\"");
aMsg.appendAscii(" [version=").append(aSchemaVersion).appendAscii("]");
logger.fine( aMsg.makeStringAndClear(), "readDefaultData()","configmgr::Backend");
}
localehelper::Locale const aRequestedLocale = localehelper::makeLocale(aOptions.getLocale());
localehelper::LocaleSequence aKnownLocales;
if (bLogDetail) logger.log(detail, "... attempt to read from binary cache", "readDefaultData()","configmgr::Backend");
bool bCacheHit = mBinaryCache.readComponentData(aComponentData, getServiceFactory(),
aComponent, aSchemaVersion,
aOptions.getEntity(),
aRequestedLocale, aKnownLocales,
pLayers, nNumLayers, bIncludeTemplates);
if (!bCacheHit)
{
RTL_LOGFILE_CONTEXT_AUTHOR(aLog2, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::readDefaultData() - not in cache");
if (bLogDetail) logger.log(detail, "... cache miss - need full merge", "readDefaultData()","configmgr::Backend");
if (bLogDetail) logger.log(detail, "... reading schema", "readDefaultData()","configmgr::Backend");
{
SchemaBuilder *schemaBuilder = new SchemaBuilder( mContext, aComponent, aComponentData, aTemplateProvider );
uno::Reference<backenduno::XSchemaHandler> schemaHandler = schemaBuilder ;
uno::Reference<backenduno::XSchema> schema = this->getSchema(aComponent);
schema->readSchema(schemaHandler) ;
}
if (bLogDetail) logger.log(detail, "... merging layers", "readDefaultData()","configmgr::Backend");
this->merge(aComponentData, pLayers, nNumLayers, aRequestedLocale, aKnownLocales, aTemplateProvider, pLayersMerged );
promoteToDefault(aComponentData);
if (mBinaryCache.isCacheEnabled(aOptions.getEntity()))
{
if (bLogDetail) logger.log(detail, "... creating binary cache", "readDefaultData()","configmgr::Backend");
bool bWriteSuccess = mBinaryCache.writeComponentData( aComponentData, getServiceFactory(),
aComponent, aSchemaVersion,
aOptions.getEntity(), aKnownLocales,
pLayers, nNumLayers );
if (!bWriteSuccess)
{
logger.info("Binary cache write failed - disabling binary cache","readDefaultData()","configmgr::Backend");
mBinaryCache.disableCache();
}
}
else if (bLogDetail)
logger.log(detail, "... cache hit", "readDefaultData()","configmgr::Backend");
}
else if (pLayersMerged)
*pLayersMerged = nNumLayers;
return aComponentData.hasSchema();
}
//------------------------------------------------------------------------------
static OUString getLayerURL(const uno::Reference<backenduno::XLayer> & aLayer)
{
try
{
namespace beans = com::sun::star::beans;
uno::Reference< beans::XPropertySet > xLayerProps( aLayer, uno::UNO_QUERY );
if (xLayerProps.is())
{
uno::Any aPropVal = xLayerProps->getPropertyValue( OUSTR("URL") );
OUString aResult;
if (aPropVal >>= aResult)
return aResult;
}
OSL_TRACE("Warning - Cannot get location of layer data\n");
}
catch (uno::Exception & e)
{
OSL_TRACE("Warning - Configuration: Retrieving layer URL failed: [%s]\n", OU2A(e.Message));
}
// TODO: use better fallback, e.g. ServiceName
const char * const aFallback = aLayer.is() ? "<Unknown Layer Type>" : "<NULL Layer>";
return OUString::createFromAscii(aFallback);
}
//------------------------------------------------------------------------------
static inline
OUString getLayerIdentifier(const uno::Reference<backenduno::XLayer> & aLayer)
{
return getLayerURL(aLayer);
}
//------------------------------------------------------------------------------
static void removeLayerData(uno::Reference< backenduno::XLayer > const & xLayer)
{
OSL_ASSERT(xLayer.is());
LayerDataRemover xLayerRemover(xLayer,uno::UNO_QUERY);
if (xLayerRemover.is())
try
{
xLayerRemover->replaceWith(createEmptyLayer());
}
catch (uno::Exception & e)
{
OSL_TRACE("Warning - Configuration: Could not clear Layer data. Error: [%s]\n", OU2A(e.Message));
}
else
{
if (! FileHelper::tryToRemoveFile(getLayerURL(xLayer),true))
OSL_TRACE("Warning - Configuration: Could not remove broken user Layer data: [-Not Updatable-]\n");
}
}
//------------------------------------------------------------------------------
static void discardLayer(uno::Sequence<uno::Reference<backenduno::XLayer> >& layers, sal_Int32 nLayer)
{
OSL_ASSERT(0 <= nLayer && nLayer < layers.getLength());
sal_Int32 nNewSize = layers.getLength() - 1;
for (sal_Int32 i = nLayer; i<nNewSize; ++i)
layers[i] = layers[i+1];
layers.realloc(nNewSize);
}
//------------------------------------------------------------------------------
namespace {
class RecursiveHandler:
public cppu::WeakImplHelper1< task::XInteractionHandler >
{
public:
explicit RecursiveHandler(
uno::Reference< task::XInteractionHandler > const & outer):
m_outer(outer) {}
virtual void SAL_CALL handle(
uno::Reference< task::XInteractionRequest > const & request)
throw (uno::RuntimeException)
{
backenduno::MergeRecoveryRequest req;
if (request->getRequest() >>= req) {
uno::Sequence< uno::Reference< task::XInteractionContinuation > >
cs(request->getContinuations());
for (sal_Int32 i = 0; i < cs.getLength(); ++i) {
uno::Reference< task::XInteractionDisapprove > dis(
cs[i], uno::UNO_QUERY);
if (dis.is()) {
dis->select();
break;
}
}
} else if (m_outer.is()) {
m_outer->handle(request);
}
}
private:
RecursiveHandler(RecursiveHandler &); // not defined
void operator =(RecursiveHandler &); // not defined
virtual ~RecursiveHandler() {}
uno::Reference< task::XInteractionHandler > m_outer;
};
}
bool BackendAccess::approveRecovery(const uno::Any & aMergeException,
const uno::Reference<backenduno::XLayer> & aBrokenLayer,
bool bUserLayerData)
CFG_UNO_THROW_ALL()
{
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< task::XInteractionHandler > h(handler.get());
if (h.is()) {
handler.setRecursive(new RecursiveHandler(h));
rtl::Reference< SimpleInteractionRequest > req(
new SimpleInteractionRequest(
uno::makeAny(
backenduno::MergeRecoveryRequest(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"Recover from configuration merge"
" failure")),
aBrokenLayer, aMergeException,
getLayerIdentifier(aBrokenLayer),
(bUserLayerData
&& (LayerDataRemover::query(aBrokenLayer).is()
|| FileHelper::fileExists(
getLayerURL(aBrokenLayer)))))),
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: approve, if user data
return bUserLayerData;
}
//------------------------------------------------------------------------------
ComponentResult BackendAccess::getNodeData(const ComponentRequest& aRequest,
ITemplateDataProvider *_aTemplateProvider,
INodeDataListener *aListener)
2002-05-27 11:11:41 -05:00
CFG_UNO_THROW_ALL()
{
rtl::OUString const component = aRequest.getComponentName().toString() ;
ITemplateDataProvider * const aTemplateProvider = _aTemplateProvider ? _aTemplateProvider : this;
2002-05-27 11:11:41 -05:00
RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getNodeData()");
RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(component) );
uno::Sequence<uno::Reference<backenduno::XLayer> > layers =
this->getLayers(component, aRequest.getOptions()) ;
sal_Int32 const k_NumUserLayers = 1;
sal_Int32 nNumDefaultLayers = layers.getLength() - k_NumUserLayers;
sal_Int32 nCurrentLayer( -1 );
bool bDefaultRecoveryApproved = false;
Logger logger(mContext);
do try // loop to allow recovery from merge failures
{
MergedComponentData aComponentData;
nCurrentLayer = -1;
if (!this->readDefaultData(aComponentData, component, aRequest.getOptions(), true,
layers.getConstArray(),nNumDefaultLayers,
aTemplateProvider, &nCurrentLayer))
{
rtl::OUStringBuffer sMessage;
sMessage.appendAscii("Configuration: No data for request. Component \"");
sMessage.append(component);
sMessage.appendAscii("\" contains no data. ");
throw com::sun::star::container::NoSuchElementException(sMessage.makeStringAndClear(),mBackend);
}
OSL_ASSERT(nCurrentLayer == nNumDefaultLayers);
sal_Int32 const nNumUserLayers = layers.getLength() - nNumDefaultLayers;
if (nNumUserLayers > 0)
{
//Merge User layer (with all locales)
logger.finer("... merging user layer", "getNodeData()","configmgr::Backend");
localehelper::LocaleSequence aLocales;
merge(aComponentData,
layers.getConstArray()+nNumDefaultLayers, nNumUserLayers,
localehelper::getAnyLocale(), aLocales, aTemplateProvider );
// mark this one as done
++nCurrentLayer;
}
logger.finer("Reading component data finished successfully", "getNodeData()","configmgr::Backend");
ComponentInstance retCode(aComponentData.extractSchemaTree(),
aComponentData.extractTemplatesTree(),
aRequest.getComponentName()) ;
//Register listener with notifier
if(aListener)
{
mNotifier->addListener(aListener, aRequest);
}
return ComponentResult(retCode) ;
}
catch (com::sun::star::container::NoSuchElementException &) { throw; }
catch (com::sun::star::uno::RuntimeException &) { throw; }
catch (uno::Exception & )
{
// can only recover if layer merging broke
if (nCurrentLayer < 0 || layers.getLength() <= nCurrentLayer)
throw;
uno::Reference< backenduno::XLayer > xBrokenLayer = layers[nCurrentLayer];
bool bUserLayerBroken = (nCurrentLayer == nNumDefaultLayers);
if (!bDefaultRecoveryApproved || bUserLayerBroken)
{
logger.info("Parsing data layer failed. Requesting approval for automated recovery", "getNodeData()","configmgr::Backend");
uno::Any theError = cppu::getCaughtException();
if (!approveRecovery(theError,xBrokenLayer,bUserLayerBroken))
cppu::throwException( theError );
}
// now do the recovery
discardLayer(layers,nCurrentLayer);
if (bUserLayerBroken)
{
logger.info("Recovering from broken user data layer - discarding the data", "getNodeData()","configmgr::Backend");
removeLayerData(xBrokenLayer);
}
else
{
logger.info("Recovering from broken default layer - skipping", "getNodeData()","configmgr::Backend");
bDefaultRecoveryApproved = true;
--nNumDefaultLayers;
}
}
while (true);
2002-05-27 11:11:41 -05:00
}
//------------------------------------------------------------------------------
void BackendAccess::updateNodeData(const UpdateRequest& aUpdate)
CFG_UNO_THROW_ALL()
{
2002-06-07 10:53:05 -05:00
rtl::OUString entity = aUpdate.getOptions().getEntity() ;
rtl::OUString component =
aUpdate.getUpdateRoot().getModuleName().toString() ;
uno::Reference<backenduno::XUpdateHandler> handler ;
RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::updateNodeData()");
RTL_LOGFILE_CONTEXT_TRACE1(aLog, "updating component: %s", RTL_LOGFILE_OU2A(component) );
2002-06-07 10:53:05 -05:00
if (entity.getLength() == 0) {
handler = mBackend->getOwnUpdateHandler(component) ;
}
else { handler = mBackend->getUpdateHandler(component, entity) ; }
2002-06-13 10:45:34 -05:00
UpdateDispatcher dispatcher(handler, aUpdate.getOptions().getLocale()) ;
dispatcher.dispatchUpdate(aUpdate.getUpdateRoot().location(),
*aUpdate.getUpdateData()) ;
2002-05-27 11:11:41 -05:00
}
//------------------------------------------------------------------------------
NodeResult BackendAccess::getDefaultData(const NodeRequest& aRequest)
CFG_UNO_THROW_ALL()
{
rtl::OUString const component = aRequest.getPath().getModuleName().toString() ;
2002-05-27 11:11:41 -05:00
RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getDefaultData()");
RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(aRequest.getPath().toString()) );
uno::Sequence<uno::Reference<backenduno::XLayer> > const layers =
this->getLayers(component, aRequest.getOptions()) ;
sal_Int32 const nNumUserLayers = 1;
sal_Int32 const nNumDefaultLayers = layers.getLength() - nNumUserLayers;
MergedComponentData aComponentData;
if (!this->readDefaultData(aComponentData, component, aRequest.getOptions(), false,
layers.getConstArray(),nNumDefaultLayers,
this))
{
rtl::OUStringBuffer sMessage;
sMessage.appendAscii("Configuration: No data for request. Component \"");
sMessage.append(component);
sMessage.appendAscii("\" contains no default data. ");
OUString const sMsg = sMessage.makeStringAndClear();
Logger(mContext).finer(sMsg,"getDefaultData()","configmgr::BackendAccess");
throw com::sun::star::container::NoSuchElementException(sMsg,mBackend);
}
std::auto_ptr<ISubtree> aResultTree = aComponentData.extractSchemaTree();
AbsolutePath aPath = aRequest.getPath();
if( aPath.begin() != aPath.end())
{
for(AbsolutePath::Iterator it=aPath.begin()+1,endIt=aPath.end();it!=endIt; ++it)
{
std::auto_ptr<INode> aChild=aResultTree->removeChild(it->getName().toString());
if(aChild.get()== NULL)
{
rtl::OUStringBuffer sMessage;
sMessage.appendAscii("Configuration: No data for request. Element \"");
sMessage.append(aPath.toString());
sMessage.appendAscii("\" does not exist in the default data. ");
OUString const sMsg = sMessage.makeStringAndClear();
Logger(mContext).finest(sMsg,"getDefaultData()","configmgr::BackendAccess");
throw com::sun::star::container::NoSuchElementException(sMsg,mBackend);
}
ISubtree *pChildAsSubtree = aChild->asISubtree();
if(pChildAsSubtree == NULL)
{
OUString sMsg = OUString::createFromAscii("BackendAccess::getDefaultData - Node Expected, Found Property: ").concat(it->getName().toString());
Logger(mContext).finer(sMsg,"getDefaultData()","configmgr::BackendAccess");
throw MalformedDataException(sMsg, mBackend, uno::Any());
}
aResultTree.reset(pChildAsSubtree);
aChild.release();
}
}
NodeInstance retCode(aResultTree, aRequest.getPath()) ;
return NodeResult(retCode) ;
2002-05-27 11:11:41 -05:00
}
//------------------------------------------------------------------------------
TemplateResult BackendAccess::getTemplateData(const TemplateRequest& aRequest)
CFG_UNO_THROW_ALL()
{
rtl::OUString component = aRequest.getComponentName().toString();
RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getTemplateData()");
RTL_LOGFILE_CONTEXT_TRACE2(aLog, "requested template: %s/%s",
RTL_LOGFILE_OU2A(aRequest.getComponentName().toString()) ,
aRequest.isComponentRequest() ? "*" : RTL_LOGFILE_OU2A(aRequest.getComponentName().toString()) );
MergedComponentData aComponentData;
{
SchemaBuilder *schemaBuilder = new SchemaBuilder( mContext, component, aComponentData ) ;
uno::Reference<backenduno::XSchemaHandler> handler = schemaBuilder ;
uno::Reference<backenduno::XSchema> schema = this->getSchema(component);
schema->readTemplates(handler) ;
}
2002-05-27 11:11:41 -05:00
TemplateInstance::Data aResultData;
if (aRequest.isComponentRequest())
{
aResultData.reset( aComponentData.extractTemplatesTree().release() );
}
else
{
backenduno::TemplateIdentifier templateId ;
templateId.Name = aRequest.getTemplateName().toString() ;
templateId.Component = aRequest.getComponentName().toString() ;
aResultData = aComponentData.extractTemplateNode(templateId.Name);
}
2002-05-27 11:11:41 -05:00
TemplateInstance retCode(aResultData,aRequest.getTemplateName(), aRequest.getComponentName()) ;
2002-05-27 11:11:41 -05:00
return TemplateResult(retCode) ;
}
//------------------------------------------------------------------------------
uno::Reference< backenduno::XSchema > BackendAccess::getSchema(const OUString& aComponent)
{
uno::Reference< backenduno::XSchemaSupplier > xSchemaBackend(mBackend, uno::UNO_QUERY_THROW);
OSL_ASSERT(xSchemaBackend.is());
2002-05-27 11:11:41 -05:00
uno::Reference< backenduno::XSchema > xSchema = xSchemaBackend->getComponentSchema(aComponent) ;
if (!xSchema.is())
{
rtl::OUStringBuffer sMessage;
sMessage.appendAscii("Configuration: No data for request. Component \"");
sMessage.append(aComponent);
sMessage.appendAscii("\" is unknown. [No schema available]");
OUString const sMsg = sMessage.makeStringAndClear();
Logger(mContext).warning(sMsg,"getSchema()","configmgr::BackendAccess");
throw com::sun::star::container::NoSuchElementException(sMsg,xSchemaBackend);
}
return xSchema;
}
//------------------------------------------------------------------------------
OUString BackendAccess::getSchemaVersion(const OUString& aComponent)
{
uno::Reference< backenduno::XVersionedSchemaSupplier > xSchemaBackend(mBackend, uno::UNO_QUERY);
if (xSchemaBackend.is())
return xSchemaBackend->getSchemaVersion(aComponent);
else
return OUString();
}
//------------------------------------------------------------------------------
uno::Sequence< uno::Reference<backenduno::XLayer> > BackendAccess::getLayers(const OUString& aComponent,const RequestOptions& aOptions)
{
rtl::OUString aEntity = aOptions.getEntity() ;
if (aEntity.getLength() == 0)
{
2002-05-27 11:11:41 -05:00
// Use own entity instead
return mBackend->listOwnLayers(aComponent) ;
2002-05-27 11:11:41 -05:00
}
else
{
return mBackend->listLayers(aComponent, aEntity) ;
2002-05-27 11:11:41 -05:00
}
}
//------------------------------------------------------------------------------
void BackendAccess::removeRequestListener(INodeDataListener *aListener,
const ComponentRequest& aRequest)
CFG_NOTHROW()
{
2002-05-27 11:11:41 -05:00
OSL_PRECOND(aListener, "ERROR: trying to remove a NULL listener");
mNotifier->removeListener(aListener, aRequest);
}
//------------------------------------------------------------------------------
2002-05-27 11:11:41 -05:00
} } // configmgr.backend