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"
76 struct UnresolvedListItem
{
78 rtl::Reference
< ParseManager
> manager
;
81 OUString
const & theName
,
82 rtl::Reference
< ParseManager
> theManager
):
83 name(theName
), manager(theManager
) {}
86 typedef std::list
< UnresolvedListItem
> UnresolvedList
;
89 OUString
const & url
, int layer
, Data
& data
, Partial
const * partial
,
90 Modifications
* modifications
, Additions
* additions
)
92 css::container::NoSuchElementException
, css::uno::RuntimeException
))
94 assert(partial
== 0 && modifications
== 0 && additions
== 0);
95 (void) partial
; (void) modifications
; (void) additions
;
96 bool ok
= rtl::Reference
< ParseManager
>(
97 new ParseManager(url
, new XcsParser(layer
, data
)))->parse(0);
99 (void) ok
; // avoid warnings
103 OUString
const & url
, int layer
, Data
& data
, Partial
const * partial
,
104 Modifications
* modifications
, Additions
* additions
)
106 css::container::NoSuchElementException
, css::uno::RuntimeException
))
108 bool ok
= rtl::Reference
< ParseManager
>(
111 new XcuParser(layer
, data
, partial
, modifications
, additions
)))->
114 (void) ok
; // avoid warnings
117 OUString
expand(OUString
const & str
) {
119 rtl::Bootstrap::expandMacros(s
); //TODO: detect failure
123 bool canRemoveFromLayer(int layer
, rtl::Reference
< Node
> const & node
) {
125 if (node
->getLayer() > layer
&& node
->getLayer() < Data::NO_LAYER
) {
128 switch (node
->kind()) {
129 case Node::KIND_LOCALIZED_PROPERTY
:
130 case Node::KIND_GROUP
:
131 for (NodeMap::const_iterator
i(node
->getMembers().begin());
132 i
!= node
->getMembers().end(); ++i
)
134 if (!canRemoveFromLayer(layer
, i
->second
)) {
140 return node
->getMembers().empty();
141 default: // Node::KIND_PROPERTY, Node::KIND_LOCALIZED_VALUE
148 class Components::WriteThread
: public salhelper::Thread
{
151 rtl::Reference
< WriteThread
> * reference
, Components
& components
,
152 OUString
const & url
, Data
const & data
);
154 void flush() { delay_
.set(); }
157 virtual ~WriteThread() {}
159 virtual void execute();
161 rtl::Reference
< WriteThread
> * reference_
;
162 Components
& components_
;
165 osl::Condition delay_
;
166 boost::shared_ptr
<osl::Mutex
> lock_
;
169 Components::WriteThread::WriteThread(
170 rtl::Reference
< WriteThread
> * reference
, Components
& components
,
171 OUString
const & url
, Data
const & data
):
172 Thread("configmgrWriter"), reference_(reference
), components_(components
),
173 url_(url
), data_(data
)
176 assert(reference
!= 0);
179 void Components::WriteThread::execute() {
180 TimeValue t
= { 1, 0 }; // 1 sec
181 delay_
.wait(&t
); // must not throw; result_error is harmless and ignored
182 osl::MutexGuard
g(*lock_
); // must not throw
185 writeModFile(components_
, url_
, data_
);
186 } catch (css::uno::RuntimeException
& e
) {
187 // Ignore write errors, instead of aborting:
190 "error writing modifications: \"" << e
.Message
<< '"');
199 class theComponentsSingleton
:
200 public rtl::StaticWithArg
<
202 css::uno::Reference
< css::uno::XComponentContext
>,
203 theComponentsSingleton
>
207 Components
& Components::getSingleton(
208 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
210 assert(context
.is());
211 return theComponentsSingleton::get(context
);
214 bool Components::allLocales(OUString
const & locale
) {
215 return locale
== "*";
218 rtl::Reference
< Node
> Components::resolvePathRepresentation(
219 OUString
const & pathRepresentation
,
220 OUString
* canonicRepresentation
, Path
* path
, int * finalizedLayer
)
223 return data_
.resolvePathRepresentation(
224 pathRepresentation
, canonicRepresentation
, path
, finalizedLayer
);
227 rtl::Reference
< Node
> Components::getTemplate(
228 int layer
, OUString
const & fullName
) const
230 return data_
.getTemplate(layer
, fullName
);
233 void Components::addRootAccess(rtl::Reference
< RootAccess
> const & access
) {
234 roots_
.insert(access
.get());
237 void Components::removeRootAccess(RootAccess
* access
) {
238 roots_
.erase(access
);
241 void Components::initGlobalBroadcaster(
242 Modifications
const & modifications
,
243 rtl::Reference
< RootAccess
> const & exclude
, Broadcaster
* broadcaster
)
245 //TODO: Iterate only over roots w/ listeners:
246 for (WeakRootSet::iterator
i(roots_
.begin()); i
!= roots_
.end(); ++i
) {
247 rtl::Reference
< RootAccess
> root
;
248 if ((*i
)->acquireCounting() > 1) {
249 root
.set(*i
); // must not throw
251 (*i
)->releaseNondeleting();
253 if (root
!= exclude
) {
254 Path
path(root
->getAbsolutePath());
255 Modifications::Node
const * mods
= &modifications
.getRoot();
256 for (Path::iterator
j(path
.begin()); j
!= path
.end(); ++j
) {
257 Modifications::Node::Children::const_iterator
k(
258 mods
->children
.find(*j
));
259 if (k
== mods
->children
.end()) {
265 //TODO: If the complete tree of which root is a part is deleted,
266 // or replaced, mods will be null, but some of the listeners
267 // from within root should probably fire nonetheless:
269 root
->initBroadcaster(*mods
, broadcaster
);
276 void Components::addModification(Path
const & path
) {
277 data_
.modifications
.add(path
);
280 bool Components::hasModifications() const
282 return data_
.modifications
.getRoot().children
.begin() !=
283 data_
.modifications
.getRoot().children
.end();
286 void Components::writeModifications() {
288 if (!hasModifications() || modificationFileUrl_
.isEmpty())
291 if (!writeThread_
.is()) {
292 writeThread_
= new WriteThread(
293 &writeThread_
, *this, modificationFileUrl_
, data_
);
294 writeThread_
->launch();
298 void Components::flushModifications() {
299 rtl::Reference
< WriteThread
> thread
;
301 osl::MutexGuard
g(*lock_
);
302 thread
= writeThread_
;
310 void Components::insertExtensionXcsFile(
311 bool shared
, OUString
const & fileUri
)
313 int layer
= getExtensionLayer(shared
);
315 parseXcsFile(fileUri
, layer
, data_
, 0, 0, 0);
316 } catch (css::container::NoSuchElementException
& e
) {
317 throw css::uno::RuntimeException(
318 (OUString("insertExtensionXcsFile does not exist: ") +
320 css::uno::Reference
< css::uno::XInterface
>());
324 void Components::insertExtensionXcuFile(
325 bool shared
, OUString
const & fileUri
, Modifications
* modifications
)
327 assert(modifications
!= 0);
328 int layer
= getExtensionLayer(shared
) + 1;
329 Additions
* adds
= data_
.addExtensionXcuAdditions(fileUri
, layer
);
331 parseXcuFile(fileUri
, layer
, data_
, 0, modifications
, adds
);
332 } catch (css::container::NoSuchElementException
& e
) {
333 data_
.removeExtensionXcuAdditions(fileUri
);
334 throw css::uno::RuntimeException(
335 (OUString("insertExtensionXcuFile does not exist: ") +
337 css::uno::Reference
< css::uno::XInterface
>());
341 void Components::removeExtensionXcuFile(
342 OUString
const & fileUri
, Modifications
* modifications
)
344 //TODO: Ideally, exactly the data coming from the specified xcu file would
345 // be removed. However, not enough information is recorded in the in-memory
346 // data structures to do so. So, as a workaround, all those set elements
347 // that were freshly added by the xcu and have afterwards been left
348 // unchanged or have only had their properties changed in the user layer are
349 // removed (and nothing else). The heuristic to determine
350 // whether a node has been left unchanged is to check the layer ID (as
351 // usual) and additionally to check that the node does not recursively
352 // contain any non-empty sets (multiple extension xcu files are merged into
353 // one layer, so checking layer ID alone is not enough). Since
354 // item->additions records all additions of set members in textual order,
355 // the latter check works well when iterating through item->additions in
357 assert(modifications
!= 0);
358 rtl::Reference
< Data::ExtensionXcu
> item(
359 data_
.removeExtensionXcuAdditions(fileUri
));
361 for (Additions::reverse_iterator
i(item
->additions
.rbegin());
362 i
!= item
->additions
.rend(); ++i
)
364 rtl::Reference
< Node
> parent
;
365 NodeMap
const * map
= &data_
.getComponents();
366 rtl::Reference
< Node
> node
;
367 for (Path::const_iterator
j(i
->begin()); j
!= i
->end(); ++j
) {
369 node
= Data::findNode(Data::NO_LAYER
, *map
, *j
);
373 map
= &node
->getMembers();
377 if (parent
->kind() == Node::KIND_SET
) {
379 node
->kind() == Node::KIND_GROUP
||
380 node
->kind() == Node::KIND_SET
);
381 if (canRemoveFromLayer(item
->layer
, node
)) {
382 parent
->getMembers().erase(i
->back());
383 data_
.modifications
.remove(*i
);
384 modifications
->add(*i
);
389 writeModifications();
393 void Components::insertModificationXcuFile(
394 OUString
const & fileUri
,
395 std::set
< OUString
> const & includedPaths
,
396 std::set
< OUString
> const & excludedPaths
,
397 Modifications
* modifications
)
399 assert(modifications
!= 0);
400 Partial
part(includedPaths
, excludedPaths
);
403 &parseXcuFile
, fileUri
, Data::NO_LAYER
, data_
, &part
, modifications
,
405 } catch (css::container::NoSuchElementException
& e
) {
408 "error inserting non-existing \"" << fileUri
<< "\": \""
409 << e
.Message
<< '"');
413 css::beans::Optional
< css::uno::Any
> Components::getExternalValue(
414 OUString
const & descriptor
)
416 sal_Int32 i
= descriptor
.indexOf(' ');
418 throw css::uno::RuntimeException(
419 (OUString("bad external value descriptor ") +
421 css::uno::Reference
< css::uno::XInterface
>());
423 //TODO: Do not make calls with mutex locked:
424 OUString
name(descriptor
.copy(0, i
));
425 ExternalServices::iterator
j(externalServices_
.find(name
));
426 if (j
== externalServices_
.end()) {
427 css::uno::Reference
< css::uno::XInterface
> service
;
429 service
= context_
->getServiceManager()->createInstanceWithContext(
431 } catch (css::uno::RuntimeException
&) {
432 // Assuming these exceptions are real errors:
434 } catch (css::uno::Exception
& e
) {
435 // Assuming these exceptions indicate that the service is not
439 "createInstance(" << name
<< ") failed with \"" << e
.Message
442 css::uno::Reference
< css::beans::XPropertySet
> propset
;
444 propset
= css::uno::Reference
< css::beans::XPropertySet
>(
445 service
, css::uno::UNO_QUERY_THROW
);
447 j
= externalServices_
.insert(
448 ExternalServices::value_type(name
, propset
)).first
;
450 css::beans::Optional
< css::uno::Any
> value
;
451 if (j
->second
.is()) {
453 if (!(j
->second
->getPropertyValue(descriptor
.copy(i
+ 1)) >>=
456 throw css::uno::RuntimeException(
457 (OUString("cannot obtain external value through ") +
459 css::uno::Reference
< css::uno::XInterface
>());
461 } catch (css::beans::UnknownPropertyException
& e
) {
462 throw css::uno::RuntimeException(
463 (OUString("unknown external value descriptor ID: ") +
465 css::uno::Reference
< css::uno::XInterface
>());
466 } catch (css::lang::WrappedTargetException
& e
) {
467 throw css::uno::RuntimeException(
468 (OUString("cannot obtain external value: ") +
470 css::uno::Reference
< css::uno::XInterface
>());
476 Components::Components(
477 css::uno::Reference
< css::uno::XComponentContext
> const & context
):
478 context_(context
), sharedExtensionLayer_(-1), userExtensionLayer_(-1)
480 assert(context
.is());
484 OUString("${CONFIGURATION_LAYERS}")));
485 RTL_LOGFILE_TRACE("configmgr : begin parsing");
487 for (sal_Int32 i
= 0;;) {
488 while (i
!= conf
.getLength() && conf
[i
] == ' ') {
491 if (i
== conf
.getLength()) {
494 if (!modificationFileUrl_
.isEmpty()) {
495 throw css::uno::RuntimeException(
496 OUString("CONFIGURATION_LAYERS: \"user\" followed by further"
498 css::uno::Reference
< css::uno::XInterface
>());
502 if (c
== conf
.getLength() || conf
[c
] == ' ') {
503 throw css::uno::RuntimeException(
504 OUString("CONFIGURATION_LAYERS: missing \":\""),
505 css::uno::Reference
< css::uno::XInterface
>());
507 if (conf
[c
] == ':') {
511 sal_Int32 n
= conf
.indexOf(' ', c
+ 1);
513 n
= conf
.getLength();
515 OUString
type(conf
.copy(i
, c
- i
));
516 OUString
url(conf
.copy(c
+ 1, n
- c
- 1));
517 if ( type
== "xcsxcu" ) {
518 parseXcsXcuLayer(layer
, url
);
519 layer
+= 2; //TODO: overflow
520 } else if ( type
== "bundledext" )
522 parseXcsXcuIniLayer(layer
, url
, false);
523 layer
+= 2; //TODO: overflow
524 } else if ( type
== "sharedext" ) {
525 if (sharedExtensionLayer_
!= -1) {
526 throw css::uno::RuntimeException(
527 OUString("CONFIGURATION_LAYERS: multiple \"sharedext\""
529 css::uno::Reference
< css::uno::XInterface
>());
531 sharedExtensionLayer_
= layer
;
532 parseXcsXcuIniLayer(layer
, url
, true);
533 layer
+= 2; //TODO: overflow
534 } else if ( type
== "userext" ) {
535 if (userExtensionLayer_
!= -1) {
536 throw css::uno::RuntimeException(
537 OUString("CONFIGURATION_LAYERS: multiple \"userext\""
539 css::uno::Reference
< css::uno::XInterface
>());
541 userExtensionLayer_
= layer
;
542 parseXcsXcuIniLayer(layer
, url
, true);
543 layer
+= 2; //TODO: overflow
544 } else if ( type
== "module" ) {
545 parseModuleLayer(layer
, url
);
546 ++layer
; //TODO: overflow
547 } else if ( type
== "res" ) {
548 parseResLayer(layer
, url
);
549 ++layer
; //TODO: overflow
550 } else if ( type
== "user" ) {
552 throw css::uno::RuntimeException(
553 OUString("CONFIGURATION_LAYERS: empty \"user\" URL"),
554 css::uno::Reference
< css::uno::XInterface
>());
556 modificationFileUrl_
= url
;
557 parseModificationLayer(url
);
560 else if ( type
== "winreg" )
562 if (!url
.isEmpty()) {
565 "winreg URL is not empty, URL handling is not implemented for winreg");
567 OUString aTempFileURL
;
568 if ( dumpWindowsRegistry(&aTempFileURL
) )
570 parseFileLeniently(&parseXcuFile
, aTempFileURL
, layer
, data_
, 0, 0, 0);
572 osl::File::remove(aTempFileURL
);
577 throw css::uno::RuntimeException(
578 (OUString("CONFIGURATION_LAYERS: unknown layer type \"") +
581 css::uno::Reference
< css::uno::XInterface
>());
585 RTL_LOGFILE_TRACE("configmgr : end parsing");
588 Components::~Components()
590 flushModifications();
591 for (WeakRootSet::iterator
i(roots_
.begin()); i
!= roots_
.end(); ++i
) {
592 (*i
)->setAlive(false);
596 void Components::parseFileLeniently(
597 FileParser
* parseFile
, OUString
const & url
, int layer
, Data
& data
,
598 Partial
const * partial
, Modifications
* modifications
,
599 Additions
* additions
)
601 assert(parseFile
!= 0);
603 (*parseFile
)(url
, layer
, data
, partial
, modifications
, additions
);
604 } catch (css::container::NoSuchElementException
&) {
606 } catch (css::uno::Exception
& e
) { //TODO: more specific exception catching
607 // Ignore invalid XML files, instead of completely preventing OOo from
611 "error reading \"" << url
<< "\": \"" << e
.Message
<< '"');
615 void Components::parseFiles(
616 int layer
, OUString
const & extension
, FileParser
* parseFile
,
617 OUString
const & url
, bool recursive
)
619 osl::Directory
dir(url
);
620 switch (dir
.open()) {
621 case osl::FileBase::E_None
:
623 case osl::FileBase::E_NOENT
:
629 throw css::uno::RuntimeException(
630 (OUString("cannot open directory ") +
632 css::uno::Reference
< css::uno::XInterface
>());
635 osl::DirectoryItem i
;
636 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
637 if (rc
== osl::FileBase::E_NOENT
) {
640 if (rc
!= osl::FileBase::E_None
) {
641 throw css::uno::RuntimeException(
642 (OUString("cannot iterate directory ") +
644 css::uno::Reference
< css::uno::XInterface
>());
646 osl::FileStatus
stat(
647 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
648 osl_FileStatus_Mask_FileURL
);
649 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
650 throw css::uno::RuntimeException(
651 (OUString("cannot stat in directory ") +
653 css::uno::Reference
< css::uno::XInterface
>());
655 if (stat
.getFileType() == osl::FileStatus::Directory
) { //TODO: symlinks
656 parseFiles(layer
, extension
, parseFile
, stat
.getFileURL(), true);
658 OUString
file(stat
.getFileName());
659 if (file
.getLength() >= extension
.getLength() &&
660 file
.match(extension
, file
.getLength() - extension
.getLength()))
664 parseFile
, stat
.getFileURL(), layer
, data_
, 0, 0, 0);
665 } catch (css::container::NoSuchElementException
& e
) {
666 throw css::uno::RuntimeException(
667 (OUString("stat'ed file does not exist: ") +
669 css::uno::Reference
< css::uno::XInterface
>());
676 void Components::parseFileList(
677 int layer
, FileParser
* parseFile
, OUString
const & urls
,
678 bool recordAdditions
)
680 for (sal_Int32 i
= 0;;) {
681 OUString
url(urls
.getToken(0, ' ', i
));
682 if (!url
.isEmpty()) {
683 Additions
* adds
= 0;
684 if (recordAdditions
) {
685 adds
= data_
.addExtensionXcuAdditions(url
, layer
);
688 parseFileLeniently(parseFile
, url
, layer
, data_
, 0, 0, adds
);
689 } catch (css::container::NoSuchElementException
& e
) {
691 "configmgr", "file does not exist: \"" << e
.Message
<< '"');
693 data_
.removeExtensionXcuAdditions(url
);
703 void Components::parseXcdFiles(int layer
, OUString
const & url
) {
704 osl::Directory
dir(url
);
705 switch (dir
.open()) {
706 case osl::FileBase::E_None
:
708 case osl::FileBase::E_NOENT
:
711 throw css::uno::RuntimeException(
712 (OUString("cannot open directory ") +
714 css::uno::Reference
< css::uno::XInterface
>());
716 UnresolvedList unres
;
717 std::set
< OUString
> existingDeps
;
718 std::set
< OUString
> processedDeps
;
720 osl::DirectoryItem i
;
721 osl::FileBase::RC rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
722 if (rc
== osl::FileBase::E_NOENT
) {
725 if (rc
!= osl::FileBase::E_None
) {
726 throw css::uno::RuntimeException(
727 (OUString("cannot iterate directory ") +
729 css::uno::Reference
< css::uno::XInterface
>());
731 osl::FileStatus
stat(
732 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
733 osl_FileStatus_Mask_FileURL
);
734 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
735 throw css::uno::RuntimeException(
736 (OUString("cannot stat in directory ") +
738 css::uno::Reference
< css::uno::XInterface
>());
740 if (stat
.getFileType() != osl::FileStatus::Directory
) { //TODO: symlinks
741 OUString
file(stat
.getFileName());
742 if (file
.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
744 RTL_CONSTASCII_STRINGPARAM(".xcd"),
745 file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
749 0, file
.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
750 existingDeps
.insert(name
);
751 rtl::Reference
< ParseManager
> manager
;
753 manager
= new ParseManager(
755 new XcdParser(layer
, processedDeps
, data_
));
756 } catch (css::container::NoSuchElementException
& e
) {
757 throw css::uno::RuntimeException(
758 (OUString("stat'ed file does not exist: ") +
760 css::uno::Reference
< css::uno::XInterface
>());
762 if (manager
->parse(0)) {
763 processedDeps
.insert(name
);
765 unres
.push_back(UnresolvedListItem(name
, manager
));
770 while (!unres
.empty()) {
771 bool resolved
= false;
772 for (UnresolvedList::iterator
i(unres
.begin()); i
!= unres
.end();) {
773 if (i
->manager
->parse(&existingDeps
)) {
774 processedDeps
.insert(i
->name
);
782 throw css::uno::RuntimeException(
783 (OUString("xcd: unresolved dependencies in ") +
785 css::uno::Reference
< css::uno::XInterface
>());
790 void Components::parseXcsXcuLayer(int layer
, OUString
const & url
) {
791 parseXcdFiles(layer
, url
);
793 layer
, OUString(".xcs"),
795 url
+ OUString("/schema"), false);
797 layer
+ 1, OUString(".xcu"),
799 url
+ OUString("/data"), false);
802 void Components::parseXcsXcuIniLayer(
803 int layer
, OUString
const & url
, bool recordAdditions
)
805 // Check if ini file exists (otherwise .override would still read global
806 // SCHEMA/DATA variables, which could interfere with unrelated environment
808 if (rtl::Bootstrap(url
).getHandle() != 0) {
809 OUStringBuffer
prefix("${.override:");
810 for (sal_Int32 i
= 0; i
!= url
.getLength(); ++i
) {
811 sal_Unicode c
= url
[i
];
823 OUString
urls(prefix
.toString() + OUString("SCHEMA}"));
824 rtl::Bootstrap::expandMacros(urls
);
827 parseFileList(layer
, &parseXcsFile
, urls
, false);
829 urls
= prefix
.makeStringAndClear() + OUString("DATA}");
830 rtl::Bootstrap::expandMacros(urls
);
833 parseFileList(layer
+ 1, &parseXcuFile
, urls
, recordAdditions
);
838 void Components::parseModuleLayer(int layer
, OUString
const & url
) {
840 layer
, OUString(".xcu"),
841 &parseXcuFile
, url
, false);
844 void Components::parseResLayer(int layer
, OUString
const & url
) {
846 url
+ OUString("/res"));
847 parseXcdFiles(layer
, resUrl
);
849 layer
, OUString(".xcu"),
850 &parseXcuFile
, resUrl
, false);
853 void Components::parseModificationLayer(OUString
const & url
) {
855 parseFileLeniently(&parseXcuFile
, url
, Data::NO_LAYER
, data_
, 0, 0, 0);
856 } catch (css::container::NoSuchElementException
&) {
858 "configmgr", "user registrymodifications.xcu does not (yet) exist");
859 // Migrate old user layer data (can be removed once migration is no
860 // longer relevant, probably OOo 4; also see hack for xsi namespace in
861 // xmlreader::XmlReader::registerNamespaceIri):
863 Data::NO_LAYER
, OUString(".xcu"),
866 OUString("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
867 ":UserInstallation}/user/registry/data")),
872 int Components::getExtensionLayer(bool shared
) {
873 int layer
= shared
? sharedExtensionLayer_
: userExtensionLayer_
;
875 throw css::uno::RuntimeException(
876 OUString("insert extension xcs/xcu file into undefined layer"),
877 css::uno::Reference
< css::uno::XInterface
>());
884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */