1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: backendaccess.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
33 #include "backendaccess.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
65 #define INCLUDED_VECTOR
66 #endif //INCLUDED_VECTOR
68 #ifndef INCLUDED_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
;
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
)
94 , mBinaryCache(xContext
)
96 OSL_ENSURE(mContext
.is(), "BackendAccess: Context is missing");
98 throw lang::NullPointerException(rtl::OUString::createFromAscii("BackendAccess: NULL Context passed"), NULL
);
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 //------------------------------------------------------------------------------
121 //------------------------------------------------------------------------------
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
))
133 //------------------------------------------------------------------------------
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())
150 for (sal_Int32 ix
=1; ix
< nCount
; ++ix
)
151 buf
.append(separator
).append(seq
[ix
]);
154 buf
.appendAscii("<none>");
156 return buf
.makeStringAndClear();
158 //------------------------------------------------------------------------------
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();
170 for (sal_Int32 i1
= 0; i1
< len1
; ++i1
)
172 if (std::find(beg2
,end2
,seq1
[i1
]) != end2
)
173 aResult
[ix
++] = seq1
[i1
];
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)
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
);
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");
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
);
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
);
370 logger
.info("Binary cache write failed - disabling binary cache","readDefaultData()","configmgr::Backend");
371 mBinaryCache
.disableCache();
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
)
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 //------------------------------------------------------------------------------
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
));
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 //------------------------------------------------------------------------------
451 class RecursiveHandler
:
452 public cppu::WeakImplHelper1
< task::XInteractionHandler
>
455 explicit RecursiveHandler(
456 uno::Reference
< task::XInteractionHandler
> const & 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
);
475 } else if (m_outer
.is()) {
476 m_outer
->handle(request
);
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
,
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
;
502 uno::Reference
< task::XInteractionHandler
> h(handler
.get());
504 handler
.setRecursive(new RecursiveHandler(h
));
505 rtl::Reference
< apihelper::SimpleInteractionRequest
> req(
506 new apihelper::SimpleInteractionRequest(
508 backenduno::MergeRecoveryRequest(
510 RTL_CONSTASCII_USTRINGPARAM(
511 "Recover from configuration merge"
513 aBrokenLayer
, aMergeException
,
514 getLayerIdentifier(aBrokenLayer
),
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
));
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
;
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
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
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
)
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
);
636 logger
.info("Recovering from broken default layer - skipping", "getNodeData()","configmgr::Backend");
637 bDefaultRecoveryApproved
= 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
,
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
);
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() );
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
) ;
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
);
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
);
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
) ;
817 return mBackend
->listLayers(aComponent
, aEntity
) ;
820 //------------------------------------------------------------------------------
821 void BackendAccess::removeRequestListener(INodeDataListener
*aListener
,
822 const ComponentRequest
& aRequest
)
826 OSL_PRECOND(aListener
, "ERROR: trying to remove a NULL listener");
827 mNotifier
->removeListener(aListener
, aRequest
);
829 //------------------------------------------------------------------------------
830 } } // configmgr.backend