merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / backend / backendaccess.cxx
blobc84a4d7e5e469eb423fbef0e42f1fcc9b33455fe
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: backendaccess.cxx,v $
10 * $Revision: 1.27 $
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"
33 #include "backendaccess.hxx"
34 #include "logger.hxx"
35 #include "matchlocale.hxx"
36 #include "layermerge.hxx"
37 #include "schemabuilder.hxx"
39 #ifndef CONFIGMGR_BACKEND_UPDATEDISPATCHER_HXX
40 #include "updatedispatch.hxx"
41 #endif // CONFIGMGR_BACKEND_UPDATEDISPATCHER_HXX
42 #include "backendnotifier.hxx"
43 #include "emptylayer.hxx"
44 #include "filehelper.hxx"
45 #include "simpleinteractionrequest.hxx"
46 #include "configinteractionhandler.hxx"
47 #include <com/sun/star/configuration/backend/XVersionedSchemaSupplier.hpp>
48 #include <com/sun/star/configuration/backend/XCompositeLayer.hpp>
49 #include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
50 #include <com/sun/star/configuration/backend/XBackendEntities.hpp>
51 #include <com/sun/star/configuration/backend/MergeRecoveryRequest.hpp>
52 #include <com/sun/star/configuration/backend/MalformedDataException.hpp>
53 #include <com/sun/star/container/NoSuchElementException.hpp>
54 #include <com/sun/star/lang/NullPointerException.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include "com/sun/star/task/XInteractionHandler.hpp"
57 #include <rtl/ustrbuf.hxx>
58 #include <rtl/ref.hxx>
59 #include <rtl/logfile.hxx>
61 #include <cppuhelper/exc_hlp.hxx>
63 #ifndef INCLUDED_VECTOR
64 #include <vector>
65 #define INCLUDED_VECTOR
66 #endif //INCLUDED_VECTOR
68 #ifndef INCLUDED_ALGORITHM
69 #include <algorithm>
70 #define INCLUDED_ALGORITHM
71 #endif //INCLUDED_ALGORITHM
73 #define OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
74 #define RTL_LOGFILE_OU2A(rtlOUString) OU2A(rtlOUString)
76 #define OUSTR(txt) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(txt) )
78 namespace configmgr { namespace backend {
79 //------------------------------------------------------------------------------
80 namespace task = com::sun::star::task;
82 inline
83 uno::Reference<lang::XMultiServiceFactory> BackendAccess::getServiceFactory() const
85 return uno::Reference<lang::XMultiServiceFactory>(mContext->getServiceManager(),uno::UNO_QUERY_THROW);
87 //------------------------------------------------------------------------------
89 BackendAccess::BackendAccess(
90 const uno::Reference<backenduno::XBackend>& xBackend,
91 const uno::Reference<uno::XComponentContext>& xContext)
92 : mContext(xContext)
93 , mBackend(xBackend)
94 , mBinaryCache(xContext)
96 OSL_ENSURE(mContext.is(), "BackendAccess: Context is missing");
97 if (!mContext.is())
98 throw lang::NullPointerException(rtl::OUString::createFromAscii("BackendAccess: NULL Context passed"), NULL);
99 if (!xBackend.is())
100 throw lang::NullPointerException(OUSTR("Configuration: Trying to create backend access without backend"),NULL);
101 if (!uno::Reference<backenduno::XSchemaSupplier>::query(xBackend).is())
102 throw lang::NullPointerException(OUSTR("Configuration: No backend for schemas available"),NULL);
105 mNotifier = new BackendChangeNotifier(xBackend);
106 //Stored as uno::reference to facilitate sharing with MultiStratumBackend
107 mXNotifier = mNotifier;
109 //Create Binary Cache
110 uno::Reference<backenduno::XBackendEntities> xBackendEntities = uno::Reference<backenduno::XBackendEntities>( mBackend, uno::UNO_QUERY) ;
111 OSL_ENSURE(xBackendEntities.is(),"Backend does not provide entity information");
113 if ( xBackendEntities.is() ) mBinaryCache.setOwnerEntity(xBackendEntities->getOwnerEntity());
115 //------------------------------------------------------------------------------
117 BackendAccess::~BackendAccess() {}
118 //------------------------------------------------------------------------------
119 namespace
121 //------------------------------------------------------------------------------
123 static inline
124 bool findLocale(std::vector< com::sun::star::lang::Locale > const & seq, com::sun::star::lang::Locale const & loc)
126 std::vector< com::sun::star::lang::Locale >::const_iterator first = seq.begin();
127 std::vector< com::sun::star::lang::Locale >::const_iterator last = seq.end();
128 for ( ; first != last; ++first)
129 if (localehelper::equalLocale(*first, loc))
130 return true;
131 return false;
133 //------------------------------------------------------------------------------
135 static inline
136 void addLocale( com::sun::star::lang::Locale const & aLocale, std::vector< com::sun::star::lang::Locale > & inoutLocales)
138 if (!findLocale(inoutLocales,aLocale))
139 inoutLocales.push_back(aLocale);
141 //------------------------------------------------------------------------------
143 static rtl::OUString toString(uno::Sequence< rtl::OUString > const & seq, sal_Unicode separator = ',')
145 rtl::OUStringBuffer buf;
147 if (sal_Int32 const nCount = seq.getLength())
149 buf.append(seq[0]);
150 for (sal_Int32 ix=1; ix < nCount; ++ix)
151 buf.append(separator).append(seq[ix]);
153 else
154 buf.appendAscii("<none>");
156 return buf.makeStringAndClear();
158 //------------------------------------------------------------------------------
160 static
161 uno::Sequence< rtl::OUString > intersect(uno::Sequence< rtl::OUString > const & seq1, uno::Sequence< rtl::OUString > const & seq2)
163 sal_Int32 const len1 = seq1.getLength();
164 uno::Sequence< rtl::OUString > aResult(len1);
166 rtl::OUString const * const beg2 = seq2.getConstArray();
167 rtl::OUString const * const end2 = beg2 + seq2.getLength();
169 sal_Int32 ix = 0;
170 for (sal_Int32 i1 = 0; i1 < len1; ++i1)
172 if (std::find(beg2,end2,seq1[i1]) != end2)
173 aResult[ix++] = seq1[i1];
175 aResult.realloc(ix);
176 return aResult;
178 //------------------------------------------------------------------------------
179 } // anonymous namespace
180 //------------------------------------------------------------------------------
182 // helper used by the binary cache
183 uno::Sequence< rtl::OUString >
184 getAvailableLocales(const uno::Reference<backenduno::XLayer> * pLayers, sal_Int32 nNumLayers)
186 uno::Sequence< rtl::OUString > aResult;
188 for (sal_Int32 i = 0 ; i < nNumLayers ; ++ i)
190 uno::Reference<backenduno::XCompositeLayer> compositeLayer(
191 pLayers [i], uno::UNO_QUERY) ;
193 if (compositeLayer.is())
195 uno::Sequence<rtl::OUString> aLocales = compositeLayer->listSubLayerIds();
197 if (aResult.getLength() == 0)
199 aResult = aLocales;
201 else
203 OSL_TRACE("Warning: multiple composite layers found. Detection of available locales is inaccurate.");
204 // be defensive: only locales present in all composite layers are 'available'
205 aResult= intersect(aResult,aLocales);
209 return aResult;
211 //------------------------------------------------------------------------------
212 static rtl::OUString getLayerURL(const uno::Reference<backenduno::XLayer> & aLayer);
214 void BackendAccess::merge(
215 MergedComponentData& aData,
216 const uno::Reference<backenduno::XLayer> * pLayers,
217 sal_Int32 aNumLayers,
218 com::sun::star::lang::Locale const & aRequestedLocale,
219 std::vector< com::sun::star::lang::Locale > & inoutMergedLocales,
220 ITemplateDataProvider *aTemplateProvider,
221 sal_Int32 * pLayersMerged)
222 SAL_THROW((com::sun::star::uno::Exception))
224 LayerMergeHandler * pMerger = new LayerMergeHandler(mContext, aData, aTemplateProvider );
225 uno::Reference<backenduno::XLayerHandler> xLayerMerger(pMerger);
227 Logger logger(mContext);
229 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::merge()");
230 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "merging %d layers", int(aNumLayers) );
232 rtl::OUString const & aLanguage = aRequestedLocale.Language;
233 bool const needAllLanguages = localehelper::isAnyLanguage(aLanguage);
235 if (aLanguage.getLength() && !needAllLanguages)
237 if (!localehelper::isDefaultLanguage(aLanguage))
238 addLocale(aRequestedLocale,inoutMergedLocales);
240 bool const needLocalizedData = needAllLanguages || !inoutMergedLocales.empty();
242 if (logger.isLogging(LogLevel::FINEST))
244 if (!needLocalizedData)
245 logger.finest("Starting merge with NO locales", "merge()","configmgr::Backend");
247 else if (needAllLanguages)
248 logger.finest("Starting merge for ALL locales", "merge()","configmgr::Backend");
250 else
251 logger.finest(OUSTR("Starting merge for locale(s): ") +
252 toString(localehelper::makeIsoSequence(inoutMergedLocales)),
253 "merge()","configmgr::Backend");
256 if (pLayersMerged) *pLayersMerged = 0;
258 for (sal_Int32 i = 0 ; i < aNumLayers ; ++ i)
260 if (logger.isLogging(LogLevel::FINEST))
261 logger.finest(OUSTR("+ Merging layer: ") + getLayerURL(pLayers[i]),
262 "merge()","configmgr::Backend");
264 pMerger->prepareLayer() ;
265 pLayers [i]->readData(xLayerMerger) ;
267 if (needLocalizedData)
269 uno::Reference<backenduno::XCompositeLayer> compositeLayer(
270 pLayers [i], uno::UNO_QUERY) ;
272 if (compositeLayer.is())
274 uno::Sequence<rtl::OUString> aSubLayerIds = compositeLayer->listSubLayerIds();
275 logger.finest(OUSTR("++ Found locales: ") + toString(aSubLayerIds),
276 "merge()","configmgr::Backend");
278 for (sal_Int32 j = 0; j < aSubLayerIds.getLength(); ++j)
280 rtl::OUString const & aLocaleIso = aSubLayerIds[j];
281 com::sun::star::lang::Locale aLocale = localehelper::makeLocale(aLocaleIso);
283 // requesting de-CH, we accept de-CH and de, but not de-DE
284 const localehelper::MatchQuality kMatchAccept = localehelper::MATCH_LANGUAGE_PLAIN;
286 if (needAllLanguages || localehelper::isMatch(aLocale,inoutMergedLocales,kMatchAccept))
288 if(pMerger->prepareSublayer(aLocaleIso))
290 logger.finest(OUSTR("++ Merging sublayer for locale: ") + aLocaleIso,
291 "merge()","configmgr::Backend");
292 compositeLayer->readSubLayerData(xLayerMerger,aLocaleIso) ;
293 addLocale(aLocale,inoutMergedLocales);
295 // else dropLocale(aLocale,inoutMergedLocales); ?
300 if (pLayersMerged) ++*pLayersMerged;
303 //------------------------------------------------------------------------------
305 bool BackendAccess::readDefaultData( MergedComponentData & aComponentData,
306 rtl::OUString const & aComponent,
307 RequestOptions const & aOptions,
308 bool bIncludeTemplates,
309 const uno::Reference<backenduno::XLayer> * pLayers,
310 sal_Int32 nNumLayers,
311 ITemplateDataProvider *aTemplateProvider,
312 sal_Int32 * pLayersMerged)
313 SAL_THROW((com::sun::star::uno::Exception))
315 RTL_LOGFILE_CONTEXT_AUTHOR(aLog1, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::readDefaultData()");
317 Logger logger(mContext);
318 const sal_Int32 detail = LogLevel::FINER;
319 bool const bLogDetail = logger.isLogging(detail);
321 rtl::OUString const aSchemaVersion = this->getSchemaVersion(aComponent);
323 if (logger.isLogging(LogLevel::FINE))
325 rtl::OUStringBuffer aMsg;
326 aMsg.appendAscii("Reading data for component \"").append(aComponent).appendAscii("\"");
327 aMsg.appendAscii(" [version=").append(aSchemaVersion).appendAscii("]");
329 logger.fine( aMsg.makeStringAndClear(), "readDefaultData()","configmgr::Backend");
332 com::sun::star::lang::Locale const aRequestedLocale = localehelper::makeLocale(aOptions.getLocale());
333 std::vector< com::sun::star::lang::Locale > aKnownLocales;
335 if (bLogDetail) logger.log(detail, "... attempt to read from binary cache", "readDefaultData()","configmgr::Backend");
336 bool bCacheHit = mBinaryCache.readComponentData(aComponentData, getServiceFactory(),
337 aComponent, aSchemaVersion,
338 aOptions.getEntity(),
339 aRequestedLocale, aKnownLocales,
340 pLayers, nNumLayers, bIncludeTemplates);
342 if (!bCacheHit)
344 RTL_LOGFILE_CONTEXT_AUTHOR(aLog2, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::readDefaultData() - not in cache");
346 if (bLogDetail) logger.log(detail, "... cache miss - need full merge", "readDefaultData()","configmgr::Backend");
347 if (bLogDetail) logger.log(detail, "... reading schema", "readDefaultData()","configmgr::Backend");
349 SchemaBuilder *schemaBuilder = new SchemaBuilder( mContext, aComponent, aComponentData, aTemplateProvider );
350 uno::Reference<backenduno::XSchemaHandler> schemaHandler = schemaBuilder ;
352 uno::Reference<backenduno::XSchema> schema = this->getSchema(aComponent);
353 schema->readSchema(schemaHandler) ;
356 if (bLogDetail) logger.log(detail, "... merging layers", "readDefaultData()","configmgr::Backend");
357 this->merge(aComponentData, pLayers, nNumLayers, aRequestedLocale, aKnownLocales, aTemplateProvider, pLayersMerged );
358 promoteToDefault(aComponentData);
360 if (mBinaryCache.isCacheEnabled(aOptions.getEntity()))
362 if (bLogDetail) logger.log(detail, "... creating binary cache", "readDefaultData()","configmgr::Backend");
363 bool bWriteSuccess = mBinaryCache.writeComponentData( aComponentData, getServiceFactory(),
364 aComponent, aSchemaVersion,
365 aOptions.getEntity(), aKnownLocales,
366 pLayers, nNumLayers );
368 if (!bWriteSuccess)
370 logger.info("Binary cache write failed - disabling binary cache","readDefaultData()","configmgr::Backend");
371 mBinaryCache.disableCache();
374 else if (bLogDetail)
375 logger.log(detail, "... cache hit", "readDefaultData()","configmgr::Backend");
377 else if (pLayersMerged)
378 *pLayersMerged = nNumLayers;
380 return aComponentData.hasSchema();
382 //------------------------------------------------------------------------------
384 static rtl::OUString getLayerURL(const uno::Reference<backenduno::XLayer> & aLayer)
388 namespace beans = com::sun::star::beans;
389 uno::Reference< beans::XPropertySet > xLayerProps( aLayer, uno::UNO_QUERY );
390 if (xLayerProps.is())
392 uno::Any aPropVal = xLayerProps->getPropertyValue( OUSTR("URL") );
393 rtl::OUString aResult;
394 if (aPropVal >>= aResult)
395 return aResult;
397 OSL_TRACE("Warning - Cannot get location of layer data\n");
399 catch (uno::Exception & e)
401 OSL_TRACE("Warning - Configuration: Retrieving layer URL failed: [%s]\n", OU2A(e.Message));
403 // TODO: use better fallback, e.g. ServiceName
404 const char * const aFallback = aLayer.is() ? "<Unknown Layer Type>" : "<NULL Layer>";
405 return rtl::OUString::createFromAscii(aFallback);
407 //------------------------------------------------------------------------------
408 static inline
409 rtl::OUString getLayerIdentifier(const uno::Reference<backenduno::XLayer> & aLayer)
411 return getLayerURL(aLayer);
414 //------------------------------------------------------------------------------
415 static void removeLayerData(uno::Reference< backenduno::XLayer > const & xLayer)
417 OSL_ASSERT(xLayer.is());
419 uno::Reference< backenduno::XUpdatableLayer > xLayerRemover(xLayer,uno::UNO_QUERY);
420 if (xLayerRemover.is())
423 xLayerRemover->replaceWith(createEmptyLayer());
425 catch (uno::Exception & e)
427 OSL_TRACE("Warning - Configuration: Could not clear Layer data. Error: [%s]\n", OU2A(e.Message));
429 else
431 if (! FileHelper::tryToRemoveFile(getLayerURL(xLayer),true))
432 OSL_TRACE("Warning - Configuration: Could not remove broken user Layer data: [-Not Updatable-]\n");
435 //------------------------------------------------------------------------------
437 static void discardLayer(uno::Sequence<uno::Reference<backenduno::XLayer> >& layers, sal_Int32 nLayer)
439 OSL_ASSERT(0 <= nLayer && nLayer < layers.getLength());
440 sal_Int32 nNewSize = layers.getLength() - 1;
442 for (sal_Int32 i = nLayer; i<nNewSize; ++i)
443 layers[i] = layers[i+1];
445 layers.realloc(nNewSize);
447 //------------------------------------------------------------------------------
449 namespace {
451 class RecursiveHandler:
452 public cppu::WeakImplHelper1< task::XInteractionHandler >
454 public:
455 explicit RecursiveHandler(
456 uno::Reference< task::XInteractionHandler > const & outer):
457 m_outer(outer) {}
459 virtual void SAL_CALL handle(
460 uno::Reference< task::XInteractionRequest > const & request)
461 throw (uno::RuntimeException)
463 backenduno::MergeRecoveryRequest req;
464 if (request->getRequest() >>= req) {
465 uno::Sequence< uno::Reference< task::XInteractionContinuation > >
466 cs(request->getContinuations());
467 for (sal_Int32 i = 0; i < cs.getLength(); ++i) {
468 uno::Reference< task::XInteractionDisapprove > dis(
469 cs[i], uno::UNO_QUERY);
470 if (dis.is()) {
471 dis->select();
472 break;
475 } else if (m_outer.is()) {
476 m_outer->handle(request);
480 private:
481 RecursiveHandler(RecursiveHandler &); // not defined
482 void operator =(RecursiveHandler &); // not defined
484 virtual ~RecursiveHandler() {}
486 uno::Reference< task::XInteractionHandler > m_outer;
491 bool BackendAccess::approveRecovery(const uno::Any & aMergeException,
492 const uno::Reference<backenduno::XLayer> & aBrokenLayer,
493 bool bUserLayerData)
494 SAL_THROW((com::sun::star::uno::Exception))
496 sal_uInt32 const k_supported_choices = apihelper::CONTINUATION_APPROVE | apihelper::CONTINUATION_DISAPPROVE;
498 sal_uInt32 chosen = apihelper::CONTINUATION_UNKNOWN;
500 apihelper::ConfigurationInteractionHandler handler;
501 try {
502 uno::Reference< task::XInteractionHandler > h(handler.get());
503 if (h.is()) {
504 handler.setRecursive(new RecursiveHandler(h));
505 rtl::Reference< apihelper::SimpleInteractionRequest > req(
506 new apihelper::SimpleInteractionRequest(
507 uno::makeAny(
508 backenduno::MergeRecoveryRequest(
509 rtl::OUString(
510 RTL_CONSTASCII_USTRINGPARAM(
511 "Recover from configuration merge"
512 " failure")),
513 aBrokenLayer, aMergeException,
514 getLayerIdentifier(aBrokenLayer),
515 (bUserLayerData
516 && (uno::Reference< backenduno::XUpdatableLayer >::query(aBrokenLayer).is()
517 || FileHelper::fileExists(
518 getLayerURL(aBrokenLayer)))))),
519 k_supported_choices));
520 h->handle(req.get());
521 chosen = req->getResponse();
523 } catch (uno::Exception & e) {
524 OSL_TRACE("Warning - Configuration: Interaction handler failed: [%s]\n", OU2A(e.Message));
527 switch (chosen)
529 case apihelper::CONTINUATION_APPROVE: return true;
530 case apihelper::CONTINUATION_DISAPPROVE: return false;
531 case apihelper::CONTINUATION_UNKNOWN: break;
533 default: OSL_ENSURE(false,"Unsolicited continuation chosen"); break;
535 // no choice available - default: approve, if user data
536 return bUserLayerData;
538 //------------------------------------------------------------------------------
540 ResultHolder< ComponentInstance > BackendAccess::getNodeData(const ComponentRequest& aRequest,
541 ITemplateDataProvider *_aTemplateProvider,
542 INodeDataListener *aListener)
543 SAL_THROW((com::sun::star::uno::Exception))
545 rtl::OUString const component = aRequest.getComponentName();
546 ITemplateDataProvider * const aTemplateProvider = _aTemplateProvider ? _aTemplateProvider : this;
548 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getNodeData()");
549 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(component) );
551 uno::Sequence<uno::Reference<backenduno::XLayer> > layers =
552 this->getLayers(component, aRequest.getOptions()) ;
554 sal_Int32 const k_NumUserLayers = 1;
556 sal_Int32 nNumDefaultLayers = layers.getLength() - k_NumUserLayers;
557 sal_Int32 nCurrentLayer( -1 );
558 bool bDefaultRecoveryApproved = false;
560 Logger logger(mContext);
561 do try // loop to allow recovery from merge failures
563 MergedComponentData aComponentData;
564 nCurrentLayer = -1;
566 if (!this->readDefaultData(aComponentData, component, aRequest.getOptions(), true,
567 layers.getConstArray(),nNumDefaultLayers,
568 aTemplateProvider, &nCurrentLayer))
570 rtl::OUStringBuffer sMessage;
571 sMessage.appendAscii("Configuration: No data for request. Component \"");
572 sMessage.append(component);
573 sMessage.appendAscii("\" contains no data. ");
575 throw com::sun::star::container::NoSuchElementException(sMessage.makeStringAndClear(),mBackend);
577 OSL_ASSERT(nCurrentLayer == nNumDefaultLayers);
579 sal_Int32 const nNumUserLayers = layers.getLength() - nNumDefaultLayers;
580 if (nNumUserLayers > 0)
582 //Merge User layer (with all locales)
583 logger.finer("... merging user layer", "getNodeData()","configmgr::Backend");
585 std::vector< com::sun::star::lang::Locale > aLocales;
586 merge(aComponentData,
587 layers.getConstArray()+nNumDefaultLayers, nNumUserLayers,
588 localehelper::getAnyLocale(), aLocales, aTemplateProvider );
590 // mark this one as done
591 ++nCurrentLayer;
594 logger.finer("Reading component data finished successfully", "getNodeData()","configmgr::Backend");
596 ComponentInstance retCode(aComponentData.extractSchemaTree(),
597 aComponentData.extractTemplatesTree(),
598 aRequest.getComponentName()) ;
600 //Register listener with notifier
601 if(aListener)
603 mNotifier->addListener(aListener, aRequest);
605 return ResultHolder< ComponentInstance >(retCode) ;
607 catch (com::sun::star::container::NoSuchElementException &) { throw; }
608 catch (com::sun::star::uno::RuntimeException &) { throw; }
609 catch (uno::Exception & )
611 // can only recover if layer merging broke
612 if (nCurrentLayer < 0 || layers.getLength() <= nCurrentLayer)
613 throw;
615 uno::Reference< backenduno::XLayer > xBrokenLayer = layers[nCurrentLayer];
617 bool bUserLayerBroken = (nCurrentLayer == nNumDefaultLayers);
619 if (!bDefaultRecoveryApproved || bUserLayerBroken)
621 logger.info("Parsing data layer failed. Requesting approval for automated recovery", "getNodeData()","configmgr::Backend");
622 uno::Any theError = cppu::getCaughtException();
623 if (!approveRecovery(theError,xBrokenLayer,bUserLayerBroken))
624 cppu::throwException( theError );
627 // now do the recovery
628 discardLayer(layers,nCurrentLayer);
629 if (bUserLayerBroken)
631 logger.info("Recovering from broken user data layer - discarding the data", "getNodeData()","configmgr::Backend");
632 removeLayerData(xBrokenLayer);
634 else
636 logger.info("Recovering from broken default layer - skipping", "getNodeData()","configmgr::Backend");
637 bDefaultRecoveryApproved = true;
638 --nNumDefaultLayers;
641 while (true);
643 //------------------------------------------------------------------------------
645 void BackendAccess::updateNodeData(const UpdateRequest& aUpdate)
646 SAL_THROW((com::sun::star::uno::Exception))
648 rtl::OUString entity = aUpdate.getOptions().getEntity() ;
649 rtl::OUString component =
650 aUpdate.getUpdateRoot().getModuleName();
651 uno::Reference<backenduno::XUpdateHandler> handler ;
653 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::updateNodeData()");
654 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "updating component: %s", RTL_LOGFILE_OU2A(component) );
656 if (entity.getLength() == 0) {
657 handler = mBackend->getOwnUpdateHandler(component) ;
659 else { handler = mBackend->getUpdateHandler(component, entity) ; }
660 UpdateDispatcher dispatcher(handler, aUpdate.getOptions().getLocale()) ;
662 dispatcher.dispatchUpdate(aUpdate.getUpdateRoot(),
663 *aUpdate.getUpdateData()) ;
665 //------------------------------------------------------------------------------
667 ResultHolder< NodeInstance > BackendAccess::getDefaultData(const NodeRequest& aRequest)
668 SAL_THROW((com::sun::star::uno::Exception))
670 rtl::OUString const component = aRequest.getPath().getModuleName();
672 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getDefaultData()");
673 RTL_LOGFILE_CONTEXT_TRACE1(aLog, "request path: %s", RTL_LOGFILE_OU2A(aRequest.getPath().toString()) );
675 uno::Sequence<uno::Reference<backenduno::XLayer> > const layers =
676 this->getLayers(component, aRequest.getOptions()) ;
678 sal_Int32 const nNumUserLayers = 1;
679 sal_Int32 const nNumDefaultLayers = layers.getLength() - nNumUserLayers;
681 MergedComponentData aComponentData;
683 if (!this->readDefaultData(aComponentData, component, aRequest.getOptions(), false,
684 layers.getConstArray(),nNumDefaultLayers,
685 this))
687 rtl::OUStringBuffer sMessage;
688 sMessage.appendAscii("Configuration: No data for request. Component \"");
689 sMessage.append(component);
690 sMessage.appendAscii("\" contains no default data. ");
692 rtl::OUString const sMsg = sMessage.makeStringAndClear();
693 Logger(mContext).finer(sMsg,"getDefaultData()","configmgr::BackendAccess");
694 throw com::sun::star::container::NoSuchElementException(sMsg,mBackend);
697 std::auto_ptr<ISubtree> aResultTree = aComponentData.extractSchemaTree();
699 configuration::AbsolutePath aPath = aRequest.getPath();
700 if( aPath.begin() != aPath.end())
702 for(std::vector<configuration::Path::Component>::const_reverse_iterator it=aPath.begin()+1,endIt=aPath.end();it!=endIt; ++it)
704 std::auto_ptr<INode> aChild=aResultTree->removeChild(it->getName());
705 if(aChild.get()== NULL)
707 rtl::OUStringBuffer sMessage;
708 sMessage.appendAscii("Configuration: No data for request. Element \"");
709 sMessage.append(aPath.toString());
710 sMessage.appendAscii("\" does not exist in the default data. ");
712 rtl::OUString const sMsg = sMessage.makeStringAndClear();
713 Logger(mContext).finest(sMsg,"getDefaultData()","configmgr::BackendAccess");
714 throw com::sun::star::container::NoSuchElementException(sMsg,mBackend);
717 ISubtree *pChildAsSubtree = aChild->asISubtree();
718 if(pChildAsSubtree == NULL)
720 rtl::OUString sMsg = rtl::OUString::createFromAscii("BackendAccess::getDefaultData - Node Expected, Found Property: ").concat(it->getName());
721 Logger(mContext).finer(sMsg,"getDefaultData()","configmgr::BackendAccess");
722 throw backenduno::MalformedDataException(sMsg, mBackend, uno::Any());
724 aResultTree.reset(pChildAsSubtree);
725 aChild.release();
729 NodeInstance retCode(aResultTree, aRequest.getPath()) ;
730 return ResultHolder< NodeInstance >(retCode) ;
732 //------------------------------------------------------------------------------
734 ResultHolder< TemplateInstance > BackendAccess::getTemplateData(const TemplateRequest& aRequest)
735 SAL_THROW((com::sun::star::uno::Exception))
737 rtl::OUString component = aRequest.getComponentName();
739 RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BackendAccess", "jb99855", "configmgr: BackendAccess::getTemplateData()");
740 RTL_LOGFILE_CONTEXT_TRACE2(aLog, "requested template: %s/%s",
741 RTL_LOGFILE_OU2A(aRequest.getComponentName().toString()) ,
742 aRequest.isComponentRequest() ? "*" : RTL_LOGFILE_OU2A(aRequest.getComponentName().toString()) );
744 MergedComponentData aComponentData;
747 SchemaBuilder *schemaBuilder = new SchemaBuilder( mContext, component, aComponentData ) ;
748 uno::Reference<backenduno::XSchemaHandler> handler = schemaBuilder ;
750 uno::Reference<backenduno::XSchema> schema = this->getSchema(component);
752 schema->readTemplates(handler) ;
755 TemplateInstance::Data aResultData;
756 if (aRequest.isComponentRequest())
758 aResultData.reset( aComponentData.extractTemplatesTree().release() );
760 else
762 backenduno::TemplateIdentifier templateId ;
763 templateId.Name = aRequest.getTemplateName();
764 templateId.Component = aRequest.getComponentName();
766 aResultData = aComponentData.extractTemplateNode(templateId.Name);
769 TemplateInstance retCode(aResultData,aRequest.getTemplateName(), aRequest.getComponentName()) ;
770 return ResultHolder< TemplateInstance >(retCode) ;
772 //------------------------------------------------------------------------------
774 uno::Reference< backenduno::XSchema > BackendAccess::getSchema(const rtl::OUString& aComponent)
776 uno::Reference< backenduno::XSchemaSupplier > xSchemaBackend(mBackend, uno::UNO_QUERY_THROW);
777 OSL_ASSERT(xSchemaBackend.is());
779 uno::Reference< backenduno::XSchema > xSchema = xSchemaBackend->getComponentSchema(aComponent) ;
780 if (!xSchema.is())
782 rtl::OUStringBuffer sMessage;
783 sMessage.appendAscii("Configuration: No data for request. Component \"");
784 sMessage.append(aComponent);
785 sMessage.appendAscii("\" is unknown. [No schema available]");
787 rtl::OUString const sMsg = sMessage.makeStringAndClear();
788 Logger(mContext).warning(sMsg,"getSchema()","configmgr::BackendAccess");
789 throw com::sun::star::container::NoSuchElementException(sMsg,xSchemaBackend);
792 return xSchema;
794 //------------------------------------------------------------------------------
796 rtl::OUString BackendAccess::getSchemaVersion(const rtl::OUString& aComponent)
798 uno::Reference< backenduno::XVersionedSchemaSupplier > xSchemaBackend(mBackend, uno::UNO_QUERY);
799 if (xSchemaBackend.is())
800 return xSchemaBackend->getSchemaVersion(aComponent);
801 else
802 return rtl::OUString();
804 //------------------------------------------------------------------------------
806 uno::Sequence< uno::Reference<backenduno::XLayer> > BackendAccess::getLayers(const rtl::OUString& aComponent,const RequestOptions& aOptions)
808 rtl::OUString aEntity = aOptions.getEntity() ;
810 if (aEntity.getLength() == 0)
812 // Use own entity instead
813 return mBackend->listOwnLayers(aComponent) ;
815 else
817 return mBackend->listLayers(aComponent, aEntity) ;
820 //------------------------------------------------------------------------------
821 void BackendAccess::removeRequestListener(INodeDataListener *aListener,
822 const ComponentRequest& aRequest)
823 SAL_THROW(())
826 OSL_PRECOND(aListener, "ERROR: trying to remove a NULL listener");
827 mNotifier->removeListener(aListener, aRequest);
829 //------------------------------------------------------------------------------
830 } } // configmgr.backend