1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
28 #include "com/sun/star/beans/Optional.hpp"
29 #include "com/sun/star/beans/UnknownPropertyException.hpp"
30 #include "com/sun/star/beans/XPropertySet.hpp"
31 #include "com/sun/star/container/NoSuchElementException.hpp"
32 #include "com/sun/star/lang/WrappedTargetException.hpp"
33 #include "com/sun/star/uno/Any.hxx"
34 #include "com/sun/star/uno/Exception.hpp"
35 #include "com/sun/star/uno/Reference.hxx"
36 #include "com/sun/star/uno/RuntimeException.hpp"
37 #include "com/sun/star/uno/XComponentContext.hpp"
38 #include "com/sun/star/uno/XInterface.hpp"
39 #include "osl/conditn.hxx"
40 #include "osl/file.hxx"
41 #include "osl/mutex.hxx"
42 #include "rtl/bootstrap.hxx"
43 #include "rtl/logfile.h"
44 #include "rtl/ref.hxx"
45 #include "rtl/string.h"
46 #include "rtl/ustrbuf.hxx"
47 #include "rtl/ustring.h"
48 #include "rtl/ustring.hxx"
49 #include "rtl/instance.hxx"
50 #include "sal/log.hxx"
51 #include "sal/types.h"
52 #include "salhelper/thread.hxx"
54 #include "additions.hxx"
55 #include "components.hxx"
58 #include "modifications.hxx"
60 #include "nodemap.hxx"
61 #include "parsemanager.hxx"
62 #include "partial.hxx"
63 #include "rootaccess.hxx"
64 #include "writemodfile.hxx"
65 #include "xcdparser.hxx"
66 #include "xcuparser.hxx"
67 #include "xcsparser.hxx"
73 struct UnresolvedListItem
{
75 rtl::Reference
< ParseManager
> manager
;
78 OUString
const & theName
,
79 rtl::Reference
< ParseManager
> theManager
):
80 name(theName
), manager(theManager
) {}
83 typedef std::list
< UnresolvedListItem
> UnresolvedList
;
86 OUString
const & url
, int layer
, Data
& data
, Partial
const * partial
,
87 Modifications
* modifications
, Additions
* additions
)
89 css::container::NoSuchElementException
, css::uno::RuntimeException
))
91 assert(partial
== 0 && modifications
== 0 && additions
== 0);
92 (void) partial
; (void) modifications
; (void) additions
;
93 bool ok
= rtl::Reference
< ParseManager
>(
94 new ParseManager(url
, new XcsParser(layer
, data
)))->parse(0);
96 (void) ok
; // avoid warnings
100 OUString
const & url
, int layer
, Data
& data
, Partial
const * partial
,
101 Modifications
* modifications
, Additions
* additions
)
103 css::container::NoSuchElementException
, css::uno::RuntimeException
))
105 bool ok
= rtl::Reference
< ParseManager
>(
108 new XcuParser(layer
, data
, partial
, modifications
, additions
)))->
111 (void) ok
; // avoid warnings
114 OUString
expand(OUString
const & str
) {
116 rtl::Bootstrap::expandMacros(s
); //TODO: detect failure
120 bool canRemoveFromLayer(int layer
, rtl::Reference
< Node
> const & node
) {
122 if (node
->getLayer() > layer
&& node
->getLayer() < Data::NO_LAYER
) {
125 switch (node
->kind()) {
126 case Node::KIND_LOCALIZED_PROPERTY
:
127 case Node::KIND_GROUP
:
128 for (NodeMap::const_iterator
i(node
->getMembers().begin());
129 i
!= node
->getMembers().end(); ++i
)
131 if (!canRemoveFromLayer(layer
, i
->second
)) {
137 return node
->getMembers().empty();
138 default: // Node::KIND_PROPERTY, Node::KIND_LOCALIZED_VALUE
145 class Components::WriteThread
: public salhelper::Thread
{
148 rtl::Reference
< WriteThread
> * reference
, Components
& components
,
149 OUString
const & url
, Data
const & data
);
151 void flush() { delay_
.set(); }
154 virtual ~WriteThread() {}
156 virtual void execute();
158 rtl::Reference
< WriteThread
> * reference_
;
159 Components
& components_
;
162 osl::Condition delay_
;
163 boost::shared_ptr
<osl::Mutex
> lock_
;
166 Components::WriteThread::WriteThread(
167 rtl::Reference
< WriteThread
> * reference
, Components
& components
,
168 OUString
const & url
, Data
const & data
):
169 Thread("configmgrWriter"), reference_(reference
), components_(components
),
170 url_(url
), data_(data
)
173 assert(reference
!= 0);
176 void Components::WriteThread::execute() {
177 TimeValue t
= { 1, 0 }; // 1 sec
178 delay_
.wait(&t
); // must not throw; result_error is harmless and ignored
179 osl::MutexGuard
g(*lock_
); // must not throw
182 writeModFile(components_
, url_
, data_
);
183 } catch (css::uno::RuntimeException
& e
) {
184 // Ignore write errors, instead of aborting:
187 "error writing modifications: \"" << e
.Message
<< '"');
196 class theComponentsSingleton
:
197 public rtl::StaticWithArg
<
199 css::uno::Reference
< css::uno::XComponentContext
>,
200 theComponentsSingleton
>
204 Components
& Components::getSingleton(
205 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
207 assert(context
.is());
208 return theComponentsSingleton::get(context
);
211 bool Components::allLocales(OUString
const & locale
) {
212 return locale
== "*";
215 rtl::Reference
< Node
> Components::resolvePathRepresentation(
216 OUString
const & pathRepresentation
,
217 OUString
* canonicRepresentation
, Path
* path
, int * finalizedLayer
)
220 return data_
.resolvePathRepresentation(
221 pathRepresentation
, canonicRepresentation
, path
, finalizedLayer
);
224 rtl::Reference
< Node
> Components::getTemplate(
225 int layer
, OUString
const & fullName
) const
227 return data_
.getTemplate(layer
, fullName
);
230 void Components::addRootAccess(rtl::Reference
< RootAccess
> const & access
) {
231 roots_
.insert(access
.get());
234 void Components::removeRootAccess(RootAccess
* access
) {
235 roots_
.erase(access
);
238 void Components::initGlobalBroadcaster(
239 Modifications
const & modifications
,
240 rtl::Reference
< RootAccess
> const & exclude
, Broadcaster
* broadcaster
)
242 //TODO: Iterate only over roots w/ listeners:
243 for (WeakRootSet::iterator
i(roots_
.begin()); i
!= roots_
.end(); ++i
) {
244 rtl::Reference
< RootAccess
> root
;
245 if ((*i
)->acquireCounting() > 1) {
246 root
.set(*i
); // must not throw
248 (*i
)->releaseNondeleting();
250 if (root
!= exclude
) {
251 Path
path(root
->getAbsolutePath());
252 Modifications::Node
const * mods
= &modifications
.getRoot();
253 for (Path::iterator
j(path
.begin()); j
!= path
.end(); ++j
) {
254 Modifications::Node::Children::const_iterator
k(
255 mods
->children
.find(*j
));
256 if (k
== mods
->children
.end()) {
262 //TODO: If the complete tree of which root is a part is deleted,
263 // or replaced, mods will be null, but some of the listeners
264 // from within root should probably fire nonetheless:
266 root
->initBroadcaster(*mods
, broadcaster
);
273 void Components::addModification(Path
const & path
) {
274 data_
.modifications
.add(path
);
277 bool Components::hasModifications() const
279 return data_
.modifications
.getRoot().children
.begin() !=
280 data_
.modifications
.getRoot().children
.end();
283 void Components::writeModifications() {
285 if (!hasModifications() || modificationFileUrl_
.isEmpty())
288 if (!writeThread_
.is()) {
289 writeThread_
= new WriteThread(
290 &writeThread_
, *this, modificationFileUrl_
, data_
);
291 writeThread_
->launch();
295 void Components::flushModifications() {
296 rtl::Reference
< WriteThread
> thread
;
298 osl::MutexGuard
g(*lock_
);
299 thread
= writeThread_
;
307 void Components::insertExtensionXcsFile(
308 bool shared
, OUString
const & fileUri
)
310 int layer
= getExtensionLayer(shared
);
312 parseXcsFile(fileUri
, layer
, data_
, 0, 0, 0);
313 } catch (css::container::NoSuchElementException
& e
) {
314 throw css::uno::RuntimeException(
315 (OUString("insertExtensionXcsFile does not exist: ") +
317 css::uno::Reference
< css::uno::XInterface
>());
321 void Components::insertExtensionXcuFile(
322 bool shared
, OUString
const & fileUri
, Modifications
* modifications
)
324 assert(modifications
!= 0);
325 int layer
= getExtensionLayer(shared
) + 1;
326 Additions
* adds
= data_
.addExtensionXcuAdditions(fileUri
, layer
);
328 parseXcuFile(fileUri
, layer
, data_
, 0, modifications
, adds
);
329 } catch (css::container::NoSuchElementException
& e
) {
330 data_
.removeExtensionXcuAdditions(fileUri
);
331 throw css::uno::RuntimeException(
332 (OUString("insertExtensionXcuFile does not exist: ") +
334 css::uno::Reference
< css::uno::XInterface
>());
338 void Components::removeExtensionXcuFile(
339 OUString
const & fileUri
, Modifications
* modifications
)
341 //TODO: Ideally, exactly the data coming from the specified xcu file would
342 // be removed. However, not enough information is recorded in the in-memory
343 // data structures to do so. So, as a workaround, all those set elements
344 // that were freshly added by the xcu and have afterwards been left
345 // unchanged or have only had their properties changed in the user layer are
346 // removed (and nothing else). The heuristic to determine
347 // whether a node has been left unchanged is to check the layer ID (as
348 // usual) and additionally to check that the node does not recursively
349 // contain any non-empty sets (multiple extension xcu files are merged into
350 // one layer, so checking layer ID alone is not enough). Since
351 // item->additions records all additions of set members in textual order,
352 // the latter check works well when iterating through item->additions in
354 assert(modifications
!= 0);
355 rtl::Reference
< Data::ExtensionXcu
> item(
356 data_
.removeExtensionXcuAdditions(fileUri
));
358 for (Additions::reverse_iterator
i(item
->additions
.rbegin());
359 i
!= item
->additions
.rend(); ++i
)
361 rtl::Reference
< Node
> parent
;
362 NodeMap
const * map
= &data_
.getComponents();
363 rtl::Reference
< Node
> node
;
364 for (Path::const_iterator
j(i
->begin()); j
!= i
->end(); ++j
) {
366 node
= Data::findNode(Data::NO_LAYER
, *map
, *j
);
370 map
= &node
->getMembers();
374 if (parent
->kind() == Node::KIND_SET
) {
376 node
->kind() == Node::KIND_GROUP
||
377 node
->kind() == Node::KIND_SET
);
378 if (canRemoveFromLayer(item
->layer
, node
)) {
379 parent
->getMembers().erase(i
->back());
380 data_
.modifications
.remove(*i
);
381 modifications
->add(*i
);
386 writeModifications();
390 void Components::insertModificationXcuFile(
391 OUString
const & fileUri
,
392 std::set
< OUString
> const & includedPaths
,
393 std::set
< OUString
> const & excludedPaths
,
394 Modifications
* modifications
)
396 assert(modifications
!= 0);
397 Partial
part(includedPaths
, excludedPaths
);
400 &parseXcuFile
, fileUri
, Data::NO_LAYER
, data_
, &part
, modifications
,
402 } catch (css::container::NoSuchElementException
& e
) {
405 "error inserting non-existing \"" << fileUri
<< "\": \""
406 << e
.Message
<< '"');
410 css::beans::Optional
< css::uno::Any
> Components::getExternalValue(
411 OUString
const & descriptor
)
413 sal_Int32 i
= descriptor
.indexOf(' ');
415 throw css::uno::RuntimeException(
416 (OUString("bad external value descriptor ") +
418 css::uno::Reference
< css::uno::XInterface
>());
420 //TODO: Do not make calls with mutex locked:
421 OUString
name(descriptor
.copy(0, i
));
422 ExternalServices::iterator
j(externalServices_
.find(name
));
423 if (j
== externalServices_
.end()) {
424 css::uno::Reference
< css::uno::XInterface
> service
;
426 service
= context_
->getServiceManager()->createInstanceWithContext(
428 } catch (css::uno::RuntimeException
&) {
429 // Assuming these exceptions are real errors:
431 } catch (css::uno::Exception
& e
) {
432 // Assuming these exceptions indicate that the service is not
436 "createInstance(" << name
<< ") failed with \"" << e
.Message
439 css::uno::Reference
< css::beans::XPropertySet
> propset
;
441 propset
= css::uno::Reference
< css::beans::XPropertySet
>(
442 service
, css::uno::UNO_QUERY_THROW
);
444 j
= externalServices_
.insert(
445 ExternalServices::value_type(name
, propset
)).first
;
447 css::beans::Optional
< css::uno::Any
> value
;
448 if (j
->second
.is()) {
450 if (!(j
->second
->getPropertyValue(descriptor
.copy(i
+ 1)) >>=
453 throw css::uno::RuntimeException(
454 (OUString("cannot obtain external value through ") +
456 css::uno::Reference
< css::uno::XInterface
>());
458 } catch (css::beans::UnknownPropertyException
& e
) {
459 throw css::uno::RuntimeException(
460 (OUString("unknown external value descriptor ID: ") +
462 css::uno::Reference
< css::uno::XInterface
>());
463 } catch (css::lang::WrappedTargetException
& e
) {
464 throw css::uno::RuntimeException(
465 (OUString("cannot obtain external value: ") +
467 css::uno::Reference
< css::uno::XInterface
>());
473 Components::Components(
474 css::uno::Reference
< css::uno::XComponentContext
> const & context
):
475 context_(context
), sharedExtensionLayer_(-1), userExtensionLayer_(-1)
477 assert(context
.is());
481 OUString("${CONFIGURATION_LAYERS}")));
482 RTL_LOGFILE_TRACE("configmgr : begin parsing");
484 for (sal_Int32 i
= 0;;) {
485 while (i
!= conf
.getLength() && conf
[i
] == ' ') {
488 if (i
== conf
.getLength()) {
491 if (!modificationFileUrl_
.isEmpty()) {
492 throw css::uno::RuntimeException(
493 OUString("CONFIGURATION_LAYERS: \"user\" followed by further"
495 css::uno::Reference
< css::uno::XInterface
>());
499 if (c
== conf
.getLength() || conf
[c
] == ' ') {
500 throw css::uno::RuntimeException(
501 OUString("CONFIGURATION_LAYERS: missing \":\""),
502 css::uno::Reference
< css::uno::XInterface
>());
504 if (conf
[c
] == ':') {
508 sal_Int32 n
= conf
.indexOf(' ', c
+ 1);
510 n
= conf
.getLength();
512 OUString
type(conf
.copy(i
, c
- i
));
513 OUString
url(conf
.copy(c
+ 1, n
- c
- 1));
514 if ( type
== "xcsxcu" ) {
515 parseXcsXcuLayer(layer
, url
);
516 layer
+= 2; //TODO: overflow
517 } else if ( type
== "bundledext" )
519 parseXcsXcuIniLayer(layer
, url
, false);
520 layer
+= 2; //TODO: overflow
521 } else if ( type
== "sharedext" ) {
522 if (sharedExtensionLayer_
!= -1) {
523 throw css::uno::RuntimeException(
524 OUString("CONFIGURATION_LAYERS: multiple \"sharedext\""
526 css::uno::Reference
< css::uno::XInterface
>());
528 sharedExtensionLayer_
= layer
;
529 parseXcsXcuIniLayer(layer
, url
, true);
530 layer
+= 2; //TODO: overflow
531 } else if ( type
== "userext" ) {
532 if (userExtensionLayer_
!= -1) {
533 throw css::uno::RuntimeException(
534 OUString("CONFIGURATION_LAYERS: multiple \"userext\""
536 css::uno::Reference
< css::uno::XInterface
>());
538 userExtensionLayer_
= layer
;
539 parseXcsXcuIniLayer(layer
, url
, true);
540 layer
+= 2; //TODO: overflow
541 } else if ( type
== "module" ) {
542 parseModuleLayer(layer
, url
);
543 ++layer
; //TODO: overflow
544 } else if ( type
== "res" ) {
545 parseResLayer(layer
, url
);
546 ++layer
; //TODO: overflow
547 } else if ( type
== "user" ) {
549 throw css::uno::RuntimeException(
550 OUString("CONFIGURATION_LAYERS: empty \"user\" URL"),
551 css::uno::Reference
< css::uno::XInterface
>());
553 modificationFileUrl_
= url
;
554 parseModificationLayer(url
);
556 throw css::uno::RuntimeException(
557 (OUString("CONFIGURATION_LAYERS: unknown layer type \"") +
560 css::uno::Reference
< css::uno::XInterface
>());
564 RTL_LOGFILE_TRACE("configmgr : end parsing");
567 Components::~Components()
569 flushModifications();
570 for (WeakRootSet::iterator
i(roots_
.begin()); i
!= roots_
.end(); ++i
) {
571 (*i
)->setAlive(false);
575 void Components::parseFileLeniently(
576 FileParser
* parseFile
, OUString
const & url
, int layer
, Data
& data
,
577 Partial
const * partial
, Modifications
* modifications
,
578 Additions
* additions
)
580 assert(parseFile
!= 0);
582 (*parseFile
)(url
, layer
, data
, partial
, modifications
, additions
);
583 } catch (css::container::NoSuchElementException
&) {
585 } catch (css::uno::Exception
& e
) { //TODO: more specific exception catching
586 // Ignore invalid XML files, instead of completely preventing OOo from
590 "error reading \"" << url
<< "\": \"" << e
.Message
<< '"');
594 void Components::parseFiles(
595 int layer
, OUString
const & extension
, FileParser
* parseFile
,
596 OUString
const & url
, bool recursive
)
598 osl::Directory
dir(url
);
599 switch (dir
.open()) {
600 case osl::FileBase::E_None
:
602 case osl::FileBase::E_NOENT
:
608 throw css::uno::RuntimeException(
609 (OUString("cannot open directory ") +
611 css::uno::Reference
< css::uno::XInterface
>());
614 osl::DirectoryItem i
;
615 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
616 if (rc
== osl::FileBase::E_NOENT
) {
619 if (rc
!= osl::FileBase::E_None
) {
620 throw css::uno::RuntimeException(
621 (OUString("cannot iterate directory ") +
623 css::uno::Reference
< css::uno::XInterface
>());
625 osl::FileStatus
stat(
626 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
627 osl_FileStatus_Mask_FileURL
);
628 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
629 throw css::uno::RuntimeException(
630 (OUString("cannot stat in directory ") +
632 css::uno::Reference
< css::uno::XInterface
>());
634 if (stat
.getFileType() == osl::FileStatus::Directory
) { //TODO: symlinks
635 parseFiles(layer
, extension
, parseFile
, stat
.getFileURL(), true);
637 OUString
file(stat
.getFileName());
638 if (file
.getLength() >= extension
.getLength() &&
639 file
.match(extension
, file
.getLength() - extension
.getLength()))
643 parseFile
, stat
.getFileURL(), layer
, data_
, 0, 0, 0);
644 } catch (css::container::NoSuchElementException
& e
) {
645 throw css::uno::RuntimeException(
646 (OUString("stat'ed file does not exist: ") +
648 css::uno::Reference
< css::uno::XInterface
>());
655 void Components::parseFileList(
656 int layer
, FileParser
* parseFile
, OUString
const & urls
,
657 bool recordAdditions
)
659 for (sal_Int32 i
= 0;;) {
660 OUString
url(urls
.getToken(0, ' ', i
));
661 if (!url
.isEmpty()) {
662 Additions
* adds
= 0;
663 if (recordAdditions
) {
664 adds
= data_
.addExtensionXcuAdditions(url
, layer
);
667 parseFileLeniently(parseFile
, url
, layer
, data_
, 0, 0, adds
);
668 } catch (css::container::NoSuchElementException
& e
) {
670 "configmgr", "file does not exist: \"" << e
.Message
<< '"');
672 data_
.removeExtensionXcuAdditions(url
);
682 void Components::parseXcdFiles(int layer
, OUString
const & url
) {
683 osl::Directory
dir(url
);
684 switch (dir
.open()) {
685 case osl::FileBase::E_None
:
687 case osl::FileBase::E_NOENT
:
690 throw css::uno::RuntimeException(
691 (OUString("cannot open directory ") +
693 css::uno::Reference
< css::uno::XInterface
>());
695 UnresolvedList unres
;
696 std::set
< OUString
> existingDeps
;
697 std::set
< OUString
> processedDeps
;
699 osl::DirectoryItem i
;
700 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
701 if (rc
== osl::FileBase::E_NOENT
) {
704 if (rc
!= osl::FileBase::E_None
) {
705 throw css::uno::RuntimeException(
706 (OUString("cannot iterate directory ") +
708 css::uno::Reference
< css::uno::XInterface
>());
710 osl::FileStatus
stat(
711 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
712 osl_FileStatus_Mask_FileURL
);
713 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
714 throw css::uno::RuntimeException(
715 (OUString("cannot stat in directory ") +
717 css::uno::Reference
< css::uno::XInterface
>());
719 if (stat
.getFileType() != osl::FileStatus::Directory
) { //TODO: symlinks
720 OUString
file(stat
.getFileName());
721 if (file
.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
723 RTL_CONSTASCII_STRINGPARAM(".xcd"),
724 file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
728 0, file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
729 existingDeps
.insert(name
);
730 rtl::Reference
< ParseManager
> manager
;
732 manager
= new ParseManager(
734 new XcdParser(layer
, processedDeps
, data_
));
735 } catch (css::container::NoSuchElementException
& e
) {
736 throw css::uno::RuntimeException(
737 (OUString("stat'ed file does not exist: ") +
739 css::uno::Reference
< css::uno::XInterface
>());
741 if (manager
->parse(0)) {
742 processedDeps
.insert(name
);
744 unres
.push_back(UnresolvedListItem(name
, manager
));
749 while (!unres
.empty()) {
750 bool resolved
= false;
751 for (UnresolvedList::iterator
i(unres
.begin()); i
!= unres
.end();) {
752 if (i
->manager
->parse(&existingDeps
)) {
753 processedDeps
.insert(i
->name
);
761 throw css::uno::RuntimeException(
762 (OUString("xcd: unresolved dependencies in ") +
764 css::uno::Reference
< css::uno::XInterface
>());
769 void Components::parseXcsXcuLayer(int layer
, OUString
const & url
) {
770 parseXcdFiles(layer
, url
);
772 layer
, OUString(".xcs"),
774 url
+ OUString("/schema"), false);
776 layer
+ 1, OUString(".xcu"),
778 url
+ OUString("/data"), false);
781 void Components::parseXcsXcuIniLayer(
782 int layer
, OUString
const & url
, bool recordAdditions
)
784 // Check if ini file exists (otherwise .override would still read global
785 // SCHEMA/DATA variables, which could interfere with unrelated environment
787 if (rtl::Bootstrap(url
).getHandle() != 0) {
788 OUStringBuffer
prefix("${.override:");
789 for (sal_Int32 i
= 0; i
!= url
.getLength(); ++i
) {
790 sal_Unicode c
= url
[i
];
802 OUString
urls(prefix
.toString() + OUString("SCHEMA}"));
803 rtl::Bootstrap::expandMacros(urls
);
806 parseFileList(layer
, &parseXcsFile
, urls
, false);
808 urls
= prefix
.makeStringAndClear() + OUString("DATA}");
809 rtl::Bootstrap::expandMacros(urls
);
812 parseFileList(layer
+ 1, &parseXcuFile
, urls
, recordAdditions
);
817 void Components::parseModuleLayer(int layer
, OUString
const & url
) {
819 layer
, OUString(".xcu"),
820 &parseXcuFile
, url
, false);
823 void Components::parseResLayer(int layer
, OUString
const & url
) {
825 url
+ OUString("/res"));
826 parseXcdFiles(layer
, resUrl
);
828 layer
, OUString(".xcu"),
829 &parseXcuFile
, resUrl
, false);
832 void Components::parseModificationLayer(OUString
const & url
) {
834 parseFileLeniently(&parseXcuFile
, url
, Data::NO_LAYER
, data_
, 0, 0, 0);
835 } catch (css::container::NoSuchElementException
&) {
837 "configmgr", "user registrymodifications.xcu does not (yet) exist");
838 // Migrate old user layer data (can be removed once migration is no
839 // longer relevant, probably OOo 4; also see hack for xsi namespace in
840 // xmlreader::XmlReader::registerNamespaceIri):
842 Data::NO_LAYER
, OUString(".xcu"),
845 OUString("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
846 ":UserInstallation}/user/registry/data")),
851 int Components::getExtensionLayer(bool shared
) {
852 int layer
= shared
? sharedExtensionLayer_
: userExtensionLayer_
;
854 throw css::uno::RuntimeException(
855 OUString("insert extension xcs/xcu file into undefined layer"),
856 css::uno::Reference
< css::uno::XInterface
>());
863 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */