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 rtl::OUString
const & theName
,
79 rtl::Reference
< ParseManager
> theManager
):
80 name(theName
), manager(theManager
) {}
83 typedef std::list
< UnresolvedListItem
> UnresolvedList
;
86 rtl::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 rtl::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 rtl::OUString
expand(rtl::OUString
const & str
) {
115 rtl::OUString
s(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 rtl::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 rtl::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(rtl::OUString
const & locale
) {
212 return locale
== "*";
215 rtl::Reference
< Node
> Components::resolvePathRepresentation(
216 rtl::OUString
const & pathRepresentation
,
217 rtl::OUString
* canonicRepresentation
, Path
* path
, int * finalizedLayer
)
220 return data_
.resolvePathRepresentation(
221 pathRepresentation
, canonicRepresentation
, path
, finalizedLayer
);
224 rtl::Reference
< Node
> Components::getTemplate(
225 int layer
, rtl::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
, rtl::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(
316 RTL_CONSTASCII_USTRINGPARAM(
317 "insertExtensionXcsFile does not exist: ")) +
319 css::uno::Reference
< css::uno::XInterface
>());
323 void Components::insertExtensionXcuFile(
324 bool shared
, rtl::OUString
const & fileUri
, Modifications
* modifications
)
326 assert(modifications
!= 0);
327 int layer
= getExtensionLayer(shared
) + 1;
328 Additions
* adds
= data_
.addExtensionXcuAdditions(fileUri
, layer
);
330 parseXcuFile(fileUri
, layer
, data_
, 0, modifications
, adds
);
331 } catch (css::container::NoSuchElementException
& e
) {
332 data_
.removeExtensionXcuAdditions(fileUri
);
333 throw css::uno::RuntimeException(
335 RTL_CONSTASCII_USTRINGPARAM(
336 "insertExtensionXcuFile does not exist: ")) +
338 css::uno::Reference
< css::uno::XInterface
>());
342 void Components::removeExtensionXcuFile(
343 rtl::OUString
const & fileUri
, Modifications
* modifications
)
345 //TODO: Ideally, exactly the data coming from the specified xcu file would
346 // be removed. However, not enough information is recorded in the in-memory
347 // data structures to do so. So, as a workaround, all those set elements
348 // that were freshly added by the xcu and have afterwards been left
349 // unchanged or have only had their properties changed in the user layer are
350 // removed (and nothing else). The heuristic to determine
351 // whether a node has been left unchanged is to check the layer ID (as
352 // usual) and additionally to check that the node does not recursively
353 // contain any non-empty sets (multiple extension xcu files are merged into
354 // one layer, so checking layer ID alone is not enough). Since
355 // item->additions records all additions of set members in textual order,
356 // the latter check works well when iterating through item->additions in
358 assert(modifications
!= 0);
359 rtl::Reference
< Data::ExtensionXcu
> item(
360 data_
.removeExtensionXcuAdditions(fileUri
));
362 for (Additions::reverse_iterator
i(item
->additions
.rbegin());
363 i
!= item
->additions
.rend(); ++i
)
365 rtl::Reference
< Node
> parent
;
366 NodeMap
const * map
= &data_
.getComponents();
367 rtl::Reference
< Node
> node
;
368 for (Path::const_iterator
j(i
->begin()); j
!= i
->end(); ++j
) {
370 node
= Data::findNode(Data::NO_LAYER
, *map
, *j
);
374 map
= &node
->getMembers();
378 if (parent
->kind() == Node::KIND_SET
) {
380 node
->kind() == Node::KIND_GROUP
||
381 node
->kind() == Node::KIND_SET
);
382 if (canRemoveFromLayer(item
->layer
, node
)) {
383 parent
->getMembers().erase(i
->back());
384 data_
.modifications
.remove(*i
);
385 modifications
->add(*i
);
390 writeModifications();
394 void Components::insertModificationXcuFile(
395 rtl::OUString
const & fileUri
,
396 std::set
< rtl::OUString
> const & includedPaths
,
397 std::set
< rtl::OUString
> const & excludedPaths
,
398 Modifications
* modifications
)
400 assert(modifications
!= 0);
401 Partial
part(includedPaths
, excludedPaths
);
404 &parseXcuFile
, fileUri
, Data::NO_LAYER
, data_
, &part
, modifications
,
406 } catch (css::container::NoSuchElementException
& e
) {
409 "error inserting non-existing \"" << fileUri
<< "\": \""
410 << e
.Message
<< '"');
414 css::beans::Optional
< css::uno::Any
> Components::getExternalValue(
415 rtl::OUString
const & descriptor
)
417 sal_Int32 i
= descriptor
.indexOf(' ');
419 throw css::uno::RuntimeException(
421 RTL_CONSTASCII_USTRINGPARAM("bad external value descriptor ")) +
423 css::uno::Reference
< css::uno::XInterface
>());
425 //TODO: Do not make calls with mutex locked:
426 rtl::OUString
name(descriptor
.copy(0, i
));
427 ExternalServices::iterator
j(externalServices_
.find(name
));
428 if (j
== externalServices_
.end()) {
429 css::uno::Reference
< css::uno::XInterface
> service
;
431 service
= context_
->getServiceManager()->createInstanceWithContext(
433 } catch (css::uno::RuntimeException
&) {
434 // Assuming these exceptions are real errors:
436 } catch (css::uno::Exception
& e
) {
437 // Assuming these exceptions indicate that the service is not
441 "createInstance(" << name
<< ") failed with \"" << e
.Message
444 css::uno::Reference
< css::beans::XPropertySet
> propset
;
446 propset
= css::uno::Reference
< css::beans::XPropertySet
>(
447 service
, css::uno::UNO_QUERY_THROW
);
449 j
= externalServices_
.insert(
450 ExternalServices::value_type(name
, propset
)).first
;
452 css::beans::Optional
< css::uno::Any
> value
;
453 if (j
->second
.is()) {
455 if (!(j
->second
->getPropertyValue(descriptor
.copy(i
+ 1)) >>=
458 throw css::uno::RuntimeException(
460 RTL_CONSTASCII_USTRINGPARAM(
461 "cannot obtain external value through ")) +
463 css::uno::Reference
< css::uno::XInterface
>());
465 } catch (css::beans::UnknownPropertyException
& e
) {
466 throw css::uno::RuntimeException(
468 RTL_CONSTASCII_USTRINGPARAM(
469 "unknown external value descriptor ID: ")) +
471 css::uno::Reference
< css::uno::XInterface
>());
472 } catch (css::lang::WrappedTargetException
& e
) {
473 throw css::uno::RuntimeException(
475 RTL_CONSTASCII_USTRINGPARAM(
476 "cannot obtain external value: ")) +
478 css::uno::Reference
< css::uno::XInterface
>());
484 Components::Components(
485 css::uno::Reference
< css::uno::XComponentContext
> const & context
):
486 context_(context
), sharedExtensionLayer_(-1), userExtensionLayer_(-1)
488 assert(context
.is());
493 RTL_CONSTASCII_USTRINGPARAM("${CONFIGURATION_LAYERS}"))));
494 RTL_LOGFILE_TRACE("configmgr : begin parsing");
496 for (sal_Int32 i
= 0;;) {
497 while (i
!= conf
.getLength() && conf
[i
] == ' ') {
500 if (i
== conf
.getLength()) {
503 if (!modificationFileUrl_
.isEmpty()) {
504 throw css::uno::RuntimeException(
506 RTL_CONSTASCII_USTRINGPARAM(
507 "CONFIGURATION_LAYERS: \"user\" followed by further"
509 css::uno::Reference
< css::uno::XInterface
>());
513 if (c
== conf
.getLength() || conf
[c
] == ' ') {
514 throw css::uno::RuntimeException(
516 RTL_CONSTASCII_USTRINGPARAM(
517 "CONFIGURATION_LAYERS: missing \":\"")),
518 css::uno::Reference
< css::uno::XInterface
>());
520 if (conf
[c
] == ':') {
524 sal_Int32 n
= conf
.indexOf(' ', c
+ 1);
526 n
= conf
.getLength();
528 rtl::OUString
type(conf
.copy(i
, c
- i
));
529 rtl::OUString
url(conf
.copy(c
+ 1, n
- c
- 1));
530 if ( type
== "xcsxcu" ) {
531 parseXcsXcuLayer(layer
, url
);
532 layer
+= 2; //TODO: overflow
533 } else if ( type
== "bundledext" )
535 parseXcsXcuIniLayer(layer
, url
, false);
536 layer
+= 2; //TODO: overflow
537 } else if ( type
== "sharedext" ) {
538 if (sharedExtensionLayer_
!= -1) {
539 throw css::uno::RuntimeException(
541 RTL_CONSTASCII_USTRINGPARAM(
542 "CONFIGURATION_LAYERS: multiple \"sharedext\""
544 css::uno::Reference
< css::uno::XInterface
>());
546 sharedExtensionLayer_
= layer
;
547 parseXcsXcuIniLayer(layer
, url
, true);
548 layer
+= 2; //TODO: overflow
549 } else if ( type
== "userext" ) {
550 if (userExtensionLayer_
!= -1) {
551 throw css::uno::RuntimeException(
553 RTL_CONSTASCII_USTRINGPARAM(
554 "CONFIGURATION_LAYERS: multiple \"userext\""
556 css::uno::Reference
< css::uno::XInterface
>());
558 userExtensionLayer_
= layer
;
559 parseXcsXcuIniLayer(layer
, url
, true);
560 layer
+= 2; //TODO: overflow
561 } else if ( type
== "module" ) {
562 parseModuleLayer(layer
, url
);
563 ++layer
; //TODO: overflow
564 } else if ( type
== "res" ) {
565 parseResLayer(layer
, url
);
566 ++layer
; //TODO: overflow
567 } else if ( type
== "user" ) {
569 throw css::uno::RuntimeException(
571 RTL_CONSTASCII_USTRINGPARAM(
572 "CONFIGURATION_LAYERS: empty \"user\" URL")),
573 css::uno::Reference
< css::uno::XInterface
>());
575 modificationFileUrl_
= url
;
576 parseModificationLayer(url
);
578 throw css::uno::RuntimeException(
580 RTL_CONSTASCII_USTRINGPARAM(
581 "CONFIGURATION_LAYERS: unknown layer type \"")) +
583 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\""))),
584 css::uno::Reference
< css::uno::XInterface
>());
588 RTL_LOGFILE_TRACE("configmgr : end parsing");
591 Components::~Components()
593 flushModifications();
594 for (WeakRootSet::iterator
i(roots_
.begin()); i
!= roots_
.end(); ++i
) {
595 (*i
)->setAlive(false);
599 void Components::parseFileLeniently(
600 FileParser
* parseFile
, rtl::OUString
const & url
, int layer
, Data
& data
,
601 Partial
const * partial
, Modifications
* modifications
,
602 Additions
* additions
)
604 assert(parseFile
!= 0);
606 (*parseFile
)(url
, layer
, data
, partial
, modifications
, additions
);
607 } catch (css::container::NoSuchElementException
&) {
609 } catch (css::uno::Exception
& e
) { //TODO: more specific exception catching
610 // Ignore invalid XML files, instead of completely preventing OOo from
614 "error reading \"" << url
<< "\": \"" << e
.Message
<< '"');
618 void Components::parseFiles(
619 int layer
, rtl::OUString
const & extension
, FileParser
* parseFile
,
620 rtl::OUString
const & url
, bool recursive
)
622 osl::Directory
dir(url
);
623 switch (dir
.open()) {
624 case osl::FileBase::E_None
:
626 case osl::FileBase::E_NOENT
:
632 throw css::uno::RuntimeException(
634 RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
636 css::uno::Reference
< css::uno::XInterface
>());
639 osl::DirectoryItem i
;
640 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
641 if (rc
== osl::FileBase::E_NOENT
) {
644 if (rc
!= osl::FileBase::E_None
) {
645 throw css::uno::RuntimeException(
647 RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
649 css::uno::Reference
< css::uno::XInterface
>());
651 osl::FileStatus
stat(
652 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
653 osl_FileStatus_Mask_FileURL
);
654 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
655 throw css::uno::RuntimeException(
657 RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
659 css::uno::Reference
< css::uno::XInterface
>());
661 if (stat
.getFileType() == osl::FileStatus::Directory
) { //TODO: symlinks
662 parseFiles(layer
, extension
, parseFile
, stat
.getFileURL(), true);
664 rtl::OUString
file(stat
.getFileName());
665 if (file
.getLength() >= extension
.getLength() &&
666 file
.match(extension
, file
.getLength() - extension
.getLength()))
670 parseFile
, stat
.getFileURL(), layer
, data_
, 0, 0, 0);
671 } catch (css::container::NoSuchElementException
& e
) {
672 throw css::uno::RuntimeException(
674 RTL_CONSTASCII_USTRINGPARAM(
675 "stat'ed file does not exist: ")) +
677 css::uno::Reference
< css::uno::XInterface
>());
684 void Components::parseFileList(
685 int layer
, FileParser
* parseFile
, rtl::OUString
const & urls
,
686 bool recordAdditions
)
688 for (sal_Int32 i
= 0;;) {
689 rtl::OUString
url(urls
.getToken(0, ' ', i
));
690 if (!url
.isEmpty()) {
691 Additions
* adds
= 0;
692 if (recordAdditions
) {
693 adds
= data_
.addExtensionXcuAdditions(url
, layer
);
696 parseFileLeniently(parseFile
, url
, layer
, data_
, 0, 0, adds
);
697 } catch (css::container::NoSuchElementException
& e
) {
699 "configmgr", "file does not exist: \"" << e
.Message
<< '"');
701 data_
.removeExtensionXcuAdditions(url
);
711 void Components::parseXcdFiles(int layer
, rtl::OUString
const & url
) {
712 osl::Directory
dir(url
);
713 switch (dir
.open()) {
714 case osl::FileBase::E_None
:
716 case osl::FileBase::E_NOENT
:
719 throw css::uno::RuntimeException(
721 RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
723 css::uno::Reference
< css::uno::XInterface
>());
725 UnresolvedList unres
;
726 std::set
< OUString
> existingDeps
;
727 std::set
< OUString
> processedDeps
;
729 osl::DirectoryItem i
;
730 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
731 if (rc
== osl::FileBase::E_NOENT
) {
734 if (rc
!= osl::FileBase::E_None
) {
735 throw css::uno::RuntimeException(
737 RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
739 css::uno::Reference
< css::uno::XInterface
>());
741 osl::FileStatus
stat(
742 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
743 osl_FileStatus_Mask_FileURL
);
744 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
745 throw css::uno::RuntimeException(
747 RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
749 css::uno::Reference
< css::uno::XInterface
>());
751 if (stat
.getFileType() != osl::FileStatus::Directory
) { //TODO: symlinks
752 rtl::OUString
file(stat
.getFileName());
753 if (file
.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
755 RTL_CONSTASCII_STRINGPARAM(".xcd"),
756 file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
760 0, file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
761 existingDeps
.insert(name
);
762 rtl::Reference
< ParseManager
> manager
;
764 manager
= new ParseManager(
766 new XcdParser(layer
, processedDeps
, data_
));
767 } catch (css::container::NoSuchElementException
& e
) {
768 throw css::uno::RuntimeException(
770 RTL_CONSTASCII_USTRINGPARAM(
771 "stat'ed file does not exist: ")) +
773 css::uno::Reference
< css::uno::XInterface
>());
775 if (manager
->parse(0)) {
776 processedDeps
.insert(name
);
778 unres
.push_back(UnresolvedListItem(name
, manager
));
783 while (!unres
.empty()) {
784 bool resolved
= false;
785 for (UnresolvedList::iterator
i(unres
.begin()); i
!= unres
.end();) {
786 if (i
->manager
->parse(&existingDeps
)) {
787 processedDeps
.insert(i
->name
);
795 throw css::uno::RuntimeException(
797 RTL_CONSTASCII_USTRINGPARAM(
798 "xcd: unresolved dependencies in ")) +
800 css::uno::Reference
< css::uno::XInterface
>());
805 void Components::parseXcsXcuLayer(int layer
, rtl::OUString
const & url
) {
806 parseXcdFiles(layer
, url
);
808 layer
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcs")),
810 url
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/schema")), false);
812 layer
+ 1, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
814 url
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), false);
817 void Components::parseXcsXcuIniLayer(
818 int layer
, rtl::OUString
const & url
, bool recordAdditions
)
820 // Check if ini file exists (otherwise .override would still read global
821 // SCHEMA/DATA variables, which could interfere with unrelated environment
823 if (rtl::Bootstrap(url
).getHandle() != 0) {
824 rtl::OUStringBuffer
prefix("${.override:");
825 for (sal_Int32 i
= 0; i
!= url
.getLength(); ++i
) {
826 sal_Unicode c
= url
[i
];
838 rtl::OUString
urls(prefix
.toString() + rtl::OUString("SCHEMA}"));
839 rtl::Bootstrap::expandMacros(urls
);
842 parseFileList(layer
, &parseXcsFile
, urls
, false);
844 urls
= prefix
.makeStringAndClear() + rtl::OUString("DATA}");
845 rtl::Bootstrap::expandMacros(urls
);
848 parseFileList(layer
+ 1, &parseXcuFile
, urls
, recordAdditions
);
853 void Components::parseModuleLayer(int layer
, rtl::OUString
const & url
) {
855 layer
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
856 &parseXcuFile
, url
, false);
859 void Components::parseResLayer(int layer
, rtl::OUString
const & url
) {
860 rtl::OUString
resUrl(
861 url
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/res")));
862 parseXcdFiles(layer
, resUrl
);
864 layer
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
865 &parseXcuFile
, resUrl
, false);
868 void Components::parseModificationLayer(rtl::OUString
const & url
) {
870 parseFileLeniently(&parseXcuFile
, url
, Data::NO_LAYER
, data_
, 0, 0, 0);
871 } catch (css::container::NoSuchElementException
&) {
873 "configmgr", "user registrymodifications.xcu does not (yet) exist");
874 // Migrate old user layer data (can be removed once migration is no
875 // longer relevant, probably OOo 4; also see hack for xsi namespace in
876 // xmlreader::XmlReader::registerNamespaceIri):
878 Data::NO_LAYER
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
882 RTL_CONSTASCII_USTRINGPARAM(
883 "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
884 ":UserInstallation}/user/registry/data"))),
889 int Components::getExtensionLayer(bool shared
) {
890 int layer
= shared
? sharedExtensionLayer_
: userExtensionLayer_
;
892 throw css::uno::RuntimeException(
894 RTL_CONSTASCII_USTRINGPARAM(
895 "insert extension xcs/xcu file into undefined layer")),
896 css::uno::Reference
< css::uno::XInterface
>());
903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */