xref: /aoo41x/main/configmgr/source/components.cxx (revision 910823ae)
13a7cf181SAndrew Rist /**************************************************************
23a7cf181SAndrew Rist  *
33a7cf181SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
43a7cf181SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
53a7cf181SAndrew Rist  * distributed with this work for additional information
63a7cf181SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
73a7cf181SAndrew Rist  * to you under the Apache License, Version 2.0 (the
83a7cf181SAndrew Rist  * "License"); you may not use this file except in compliance
93a7cf181SAndrew Rist  * with the License.  You may obtain a copy of the License at
103a7cf181SAndrew Rist  *
113a7cf181SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
123a7cf181SAndrew Rist  *
133a7cf181SAndrew Rist  * Unless required by applicable law or agreed to in writing,
143a7cf181SAndrew Rist  * software distributed under the License is distributed on an
153a7cf181SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
163a7cf181SAndrew Rist  * KIND, either express or implied.  See the License for the
173a7cf181SAndrew Rist  * specific language governing permissions and limitations
183a7cf181SAndrew Rist  * under the License.
193a7cf181SAndrew Rist  *
203a7cf181SAndrew Rist  *************************************************************/
213a7cf181SAndrew Rist 
223a7cf181SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "precompiled_configmgr.hxx"
25cdf0e10cSrcweir #include "sal/config.h"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <algorithm>
28cdf0e10cSrcweir #include <cstddef>
29cdf0e10cSrcweir #include <list>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "com/sun/star/beans/Optional.hpp"
32cdf0e10cSrcweir #include "com/sun/star/beans/UnknownPropertyException.hpp"
33cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySet.hpp"
34cdf0e10cSrcweir #include "com/sun/star/container/NoSuchElementException.hpp"
35cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetException.hpp"
36cdf0e10cSrcweir #include "com/sun/star/lang/XMultiComponentFactory.hpp"
37cdf0e10cSrcweir #include "com/sun/star/uno/Any.hxx"
38cdf0e10cSrcweir #include "com/sun/star/uno/Exception.hpp"
39cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx"
40cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
41cdf0e10cSrcweir #include "com/sun/star/uno/XComponentContext.hpp"
42cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
43cdf0e10cSrcweir #include "osl/conditn.hxx"
44cdf0e10cSrcweir #include "osl/diagnose.h"
45cdf0e10cSrcweir #include "osl/file.hxx"
46cdf0e10cSrcweir #include "osl/mutex.hxx"
47cdf0e10cSrcweir #include "osl/thread.hxx"
48cdf0e10cSrcweir #include "rtl/bootstrap.hxx"
49cdf0e10cSrcweir #include "rtl/logfile.h"
50cdf0e10cSrcweir #include "rtl/ref.hxx"
51cdf0e10cSrcweir #include "rtl/string.h"
52cdf0e10cSrcweir #include "rtl/textenc.h"
53cdf0e10cSrcweir #include "rtl/ustring.h"
54cdf0e10cSrcweir #include "rtl/ustring.hxx"
55cdf0e10cSrcweir #include "sal/types.h"
56cdf0e10cSrcweir #include "salhelper/simplereferenceobject.hxx"
57cdf0e10cSrcweir 
58cdf0e10cSrcweir #include "additions.hxx"
59cdf0e10cSrcweir #include "components.hxx"
60cdf0e10cSrcweir #include "data.hxx"
61cdf0e10cSrcweir #include "lock.hxx"
62cdf0e10cSrcweir #include "modifications.hxx"
63cdf0e10cSrcweir #include "node.hxx"
64cdf0e10cSrcweir #include "nodemap.hxx"
65cdf0e10cSrcweir #include "parsemanager.hxx"
66cdf0e10cSrcweir #include "partial.hxx"
67cdf0e10cSrcweir #include "rootaccess.hxx"
68cdf0e10cSrcweir #include "writemodfile.hxx"
69cdf0e10cSrcweir #include "xcdparser.hxx"
70cdf0e10cSrcweir #include "xcuparser.hxx"
71cdf0e10cSrcweir #include "xcsparser.hxx"
72cdf0e10cSrcweir 
73cdf0e10cSrcweir namespace configmgr {
74cdf0e10cSrcweir 
75cdf0e10cSrcweir namespace {
76cdf0e10cSrcweir 
77cdf0e10cSrcweir namespace css = com::sun::star;
78cdf0e10cSrcweir 
79cdf0e10cSrcweir struct UnresolvedListItem {
80cdf0e10cSrcweir     rtl::OUString name;
81cdf0e10cSrcweir     rtl::Reference< ParseManager > manager;
82cdf0e10cSrcweir 
UnresolvedListItemconfigmgr::__anon2c4db4280111::UnresolvedListItem83cdf0e10cSrcweir     UnresolvedListItem(
84cdf0e10cSrcweir         rtl::OUString const & theName,
85cdf0e10cSrcweir         rtl::Reference< ParseManager > theManager):
86cdf0e10cSrcweir         name(theName), manager(theManager) {}
87cdf0e10cSrcweir };
88cdf0e10cSrcweir 
89cdf0e10cSrcweir typedef std::list< UnresolvedListItem > UnresolvedList;
90cdf0e10cSrcweir 
parseXcsFile(rtl::OUString const & url,int layer,Data & data,Partial const * partial,Modifications * modifications,Additions * additions)91cdf0e10cSrcweir void parseXcsFile(
92cdf0e10cSrcweir     rtl::OUString const & url, int layer, Data & data, Partial const * partial,
93cdf0e10cSrcweir     Modifications * modifications, Additions * additions)
94cdf0e10cSrcweir     SAL_THROW((
95cdf0e10cSrcweir         css::container::NoSuchElementException, css::uno::RuntimeException))
96cdf0e10cSrcweir {
97cdf0e10cSrcweir     OSL_ASSERT(partial == 0 && modifications == 0 && additions == 0);
98cdf0e10cSrcweir     (void) partial; (void) modifications; (void) additions;
99cdf0e10cSrcweir     OSL_VERIFY(
100cdf0e10cSrcweir         rtl::Reference< ParseManager >(
101cdf0e10cSrcweir             new ParseManager(url, new XcsParser(layer, data)))->parse());
102cdf0e10cSrcweir }
103cdf0e10cSrcweir 
parseXcuFile(rtl::OUString const & url,int layer,Data & data,Partial const * partial,Modifications * modifications,Additions * additions)104cdf0e10cSrcweir void parseXcuFile(
105cdf0e10cSrcweir     rtl::OUString const & url, int layer, Data & data, Partial const * partial,
106cdf0e10cSrcweir     Modifications * modifications, Additions * additions)
107cdf0e10cSrcweir     SAL_THROW((
108cdf0e10cSrcweir         css::container::NoSuchElementException, css::uno::RuntimeException))
109cdf0e10cSrcweir {
110cdf0e10cSrcweir     OSL_VERIFY(
111cdf0e10cSrcweir         rtl::Reference< ParseManager >(
112cdf0e10cSrcweir             new ParseManager(
113cdf0e10cSrcweir                 url,
114cdf0e10cSrcweir                 new XcuParser(
115cdf0e10cSrcweir                     layer, data, partial, modifications, additions)))->
116cdf0e10cSrcweir         parse());
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
expand(rtl::OUString const & str)119cdf0e10cSrcweir rtl::OUString expand(rtl::OUString const & str) {
120cdf0e10cSrcweir     rtl::OUString s(str);
121cdf0e10cSrcweir     rtl::Bootstrap::expandMacros(s); //TODO: detect failure
122cdf0e10cSrcweir     return s;
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
canRemoveFromLayer(int layer,rtl::Reference<Node> const & node)125cdf0e10cSrcweir bool canRemoveFromLayer(int layer, rtl::Reference< Node > const & node) {
126cdf0e10cSrcweir     OSL_ASSERT(node.is());
127cdf0e10cSrcweir     if (node->getLayer() > layer && node->getLayer() < Data::NO_LAYER) {
128cdf0e10cSrcweir         return false;
129cdf0e10cSrcweir     }
130cdf0e10cSrcweir     switch (node->kind()) {
131cdf0e10cSrcweir     case Node::KIND_LOCALIZED_PROPERTY:
132cdf0e10cSrcweir     case Node::KIND_GROUP:
133cdf0e10cSrcweir         for (NodeMap::iterator i(node->getMembers().begin());
134cdf0e10cSrcweir              i != node->getMembers().end(); ++i)
135cdf0e10cSrcweir         {
136cdf0e10cSrcweir             if (!canRemoveFromLayer(layer, i->second)) {
137cdf0e10cSrcweir                 return false;
138cdf0e10cSrcweir             }
139cdf0e10cSrcweir         }
140cdf0e10cSrcweir         return true;
141cdf0e10cSrcweir     case Node::KIND_SET:
142cdf0e10cSrcweir         return node->getMembers().empty();
143cdf0e10cSrcweir     default: // Node::KIND_PROPERTY, Node::KIND_LOCALIZED_VALUE
144cdf0e10cSrcweir         return true;
145cdf0e10cSrcweir     }
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir static bool singletonCreated = false;
149cdf0e10cSrcweir static Components * singleton = 0;
150cdf0e10cSrcweir 
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir class Components::WriteThread:
154cdf0e10cSrcweir     public osl::Thread, public salhelper::SimpleReferenceObject
155cdf0e10cSrcweir {
156cdf0e10cSrcweir public:
operator new(std::size_t size)157cdf0e10cSrcweir     static void * operator new(std::size_t size)
158cdf0e10cSrcweir     { return Thread::operator new(size); }
159cdf0e10cSrcweir 
operator delete(void * pointer)160cdf0e10cSrcweir     static void operator delete(void * pointer)
161cdf0e10cSrcweir     { Thread::operator delete(pointer); }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir     WriteThread(
164cdf0e10cSrcweir         rtl::Reference< WriteThread > * reference, Components & components,
165cdf0e10cSrcweir         rtl::OUString const & url, Data const & data);
166cdf0e10cSrcweir 
flush()167cdf0e10cSrcweir     void flush() { delay_.set(); }
168cdf0e10cSrcweir 
169cdf0e10cSrcweir private:
~WriteThread()170cdf0e10cSrcweir     virtual ~WriteThread() {}
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     virtual void SAL_CALL run();
173cdf0e10cSrcweir 
onTerminated()174cdf0e10cSrcweir     virtual void SAL_CALL onTerminated() { release(); }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     rtl::Reference< WriteThread > * reference_;
177cdf0e10cSrcweir     Components & components_;
178cdf0e10cSrcweir     rtl::OUString url_;
179cdf0e10cSrcweir     Data const & data_;
180cdf0e10cSrcweir     osl::Condition delay_;
181cdf0e10cSrcweir };
182cdf0e10cSrcweir 
WriteThread(rtl::Reference<WriteThread> * reference,Components & components,rtl::OUString const & url,Data const & data)183cdf0e10cSrcweir Components::WriteThread::WriteThread(
184cdf0e10cSrcweir     rtl::Reference< WriteThread > * reference, Components & components,
185cdf0e10cSrcweir     rtl::OUString const & url, Data const & data):
186cdf0e10cSrcweir     reference_(reference), components_(components), url_(url), data_(data)
187cdf0e10cSrcweir {
188cdf0e10cSrcweir     OSL_ASSERT(reference != 0);
189cdf0e10cSrcweir     acquire();
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
run()192cdf0e10cSrcweir void Components::WriteThread::run() {
193cdf0e10cSrcweir     TimeValue t = { 1, 0 }; // 1 sec
194cdf0e10cSrcweir     delay_.wait(&t); // must not throw; result_error is harmless and ignored
195cdf0e10cSrcweir     osl::MutexGuard g(lock); // must not throw
196cdf0e10cSrcweir     try {
197cdf0e10cSrcweir         try {
198cdf0e10cSrcweir             writeModFile(components_, url_, data_);
199cdf0e10cSrcweir         } catch (css::uno::RuntimeException & e) {
200cdf0e10cSrcweir             // Silently ignore write errors, instead of aborting:
201cdf0e10cSrcweir             OSL_TRACE(
202cdf0e10cSrcweir                 "configmgr error writing modifications: %s",
203cdf0e10cSrcweir                 rtl::OUStringToOString(
204cdf0e10cSrcweir                     e.Message, RTL_TEXTENCODING_UTF8).getStr());
205cdf0e10cSrcweir         }
206cdf0e10cSrcweir     } catch (...) {
207cdf0e10cSrcweir         reference_->clear();
208cdf0e10cSrcweir         throw;
209cdf0e10cSrcweir     }
210cdf0e10cSrcweir     reference_->clear();
211cdf0e10cSrcweir }
212cdf0e10cSrcweir 
getSingleton(css::uno::Reference<css::uno::XComponentContext> const & context)213cdf0e10cSrcweir Components & Components::getSingleton(
214cdf0e10cSrcweir     css::uno::Reference< css::uno::XComponentContext > const & context)
215cdf0e10cSrcweir {
216cdf0e10cSrcweir     OSL_ASSERT(context.is());
217cdf0e10cSrcweir     if (!singletonCreated) {
218cdf0e10cSrcweir         singletonCreated = true;
219cdf0e10cSrcweir         static Components theSingleton(context);
220cdf0e10cSrcweir         singleton = &theSingleton;
221cdf0e10cSrcweir     }
222cdf0e10cSrcweir     if (singleton == 0) {
223cdf0e10cSrcweir         throw css::uno::RuntimeException(
224cdf0e10cSrcweir             rtl::OUString(
225cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
226cdf0e10cSrcweir                     "configmgr no Components singleton")),
227cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
228cdf0e10cSrcweir     }
229cdf0e10cSrcweir     return *singleton;
230cdf0e10cSrcweir }
231cdf0e10cSrcweir 
allLocales(rtl::OUString const & locale)232cdf0e10cSrcweir bool Components::allLocales(rtl::OUString const & locale) {
233cdf0e10cSrcweir     return locale.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"));
234cdf0e10cSrcweir }
235cdf0e10cSrcweir 
resolvePathRepresentation(rtl::OUString const & pathRepresentation,rtl::OUString * canonicRepresentation,Path * path,int * finalizedLayer) const236cdf0e10cSrcweir rtl::Reference< Node > Components::resolvePathRepresentation(
237cdf0e10cSrcweir     rtl::OUString const & pathRepresentation,
238cdf0e10cSrcweir     rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer)
239cdf0e10cSrcweir     const
240cdf0e10cSrcweir {
241cdf0e10cSrcweir     return data_.resolvePathRepresentation(
242cdf0e10cSrcweir         pathRepresentation, canonicRepresentation, path, finalizedLayer);
243cdf0e10cSrcweir }
244cdf0e10cSrcweir 
getTemplate(int layer,rtl::OUString const & fullName) const245cdf0e10cSrcweir rtl::Reference< Node > Components::getTemplate(
246cdf0e10cSrcweir     int layer, rtl::OUString const & fullName) const
247cdf0e10cSrcweir {
248cdf0e10cSrcweir     return data_.getTemplate(layer, fullName);
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
addRootAccess(rtl::Reference<RootAccess> const & access)251cdf0e10cSrcweir void Components::addRootAccess(rtl::Reference< RootAccess > const & access) {
252cdf0e10cSrcweir     roots_.insert(access.get());
253cdf0e10cSrcweir }
254cdf0e10cSrcweir 
removeRootAccess(RootAccess * access)255cdf0e10cSrcweir void Components::removeRootAccess(RootAccess * access) {
256cdf0e10cSrcweir     roots_.erase(access);
257cdf0e10cSrcweir }
258cdf0e10cSrcweir 
initGlobalBroadcaster(Modifications const & modifications,rtl::Reference<RootAccess> const & exclude,Broadcaster * broadcaster)259cdf0e10cSrcweir void Components::initGlobalBroadcaster(
260cdf0e10cSrcweir     Modifications const & modifications,
261cdf0e10cSrcweir     rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster)
262cdf0e10cSrcweir {
263cdf0e10cSrcweir     //TODO: Iterate only over roots w/ listeners:
264cdf0e10cSrcweir     for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
265cdf0e10cSrcweir         rtl::Reference< RootAccess > root;
266cdf0e10cSrcweir         if ((*i)->acquireCounting() > 1) {
267cdf0e10cSrcweir             root.set(*i); // must not throw
268cdf0e10cSrcweir         }
269cdf0e10cSrcweir         (*i)->releaseNondeleting();
270cdf0e10cSrcweir         if (root.is()) {
271cdf0e10cSrcweir             if (root != exclude) {
272cdf0e10cSrcweir                 Path path(root->getAbsolutePath());
273cdf0e10cSrcweir                 Modifications::Node const * mods = &modifications.getRoot();
274cdf0e10cSrcweir                 for (Path::iterator j(path.begin()); j != path.end(); ++j) {
275cdf0e10cSrcweir                     Modifications::Node::Children::const_iterator k(
276cdf0e10cSrcweir                         mods->children.find(*j));
277cdf0e10cSrcweir                     if (k == mods->children.end()) {
278cdf0e10cSrcweir                         mods = 0;
279cdf0e10cSrcweir                         break;
280cdf0e10cSrcweir                     }
281cdf0e10cSrcweir                     mods = &k->second;
282cdf0e10cSrcweir                 }
283cdf0e10cSrcweir                 //TODO: If the complete tree of which root is a part is deleted,
284cdf0e10cSrcweir                 // or replaced, mods will be null, but some of the listeners
285cdf0e10cSrcweir                 // from within root should probably fire nonetheless:
286cdf0e10cSrcweir                 if (mods != 0) {
287cdf0e10cSrcweir                     root->initBroadcaster(*mods, broadcaster);
288cdf0e10cSrcweir                 }
289cdf0e10cSrcweir             }
290cdf0e10cSrcweir         }
291cdf0e10cSrcweir     }
292cdf0e10cSrcweir }
293cdf0e10cSrcweir 
addModification(Path const & path)294cdf0e10cSrcweir void Components::addModification(Path const & path) {
295cdf0e10cSrcweir     data_.modifications.add(path);
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
writeModifications()298cdf0e10cSrcweir void Components::writeModifications() {
299cdf0e10cSrcweir     if (!writeThread_.is()) {
300cdf0e10cSrcweir         writeThread_ = new WriteThread(
301cdf0e10cSrcweir             &writeThread_, *this, getModificationFileUrl(), data_);
302cdf0e10cSrcweir         writeThread_->create();
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
flushModifications()306cdf0e10cSrcweir void Components::flushModifications() {
307cdf0e10cSrcweir     rtl::Reference< WriteThread > thread;
308cdf0e10cSrcweir     {
309cdf0e10cSrcweir         osl::MutexGuard g(lock);
310cdf0e10cSrcweir         thread = writeThread_;
311cdf0e10cSrcweir     }
312cdf0e10cSrcweir     if (thread.is()) {
313cdf0e10cSrcweir         thread->flush();
314cdf0e10cSrcweir         thread->join();
315cdf0e10cSrcweir     }
316cdf0e10cSrcweir }
317cdf0e10cSrcweir 
insertExtensionXcsFile(bool shared,rtl::OUString const & fileUri)318cdf0e10cSrcweir void Components::insertExtensionXcsFile(
319cdf0e10cSrcweir     bool shared, rtl::OUString const & fileUri)
320cdf0e10cSrcweir {
321cdf0e10cSrcweir     try {
322cdf0e10cSrcweir         parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0, 0);
323cdf0e10cSrcweir     } catch (css::container::NoSuchElementException & e) {
324cdf0e10cSrcweir         throw css::uno::RuntimeException(
325cdf0e10cSrcweir             (rtl::OUString(
326cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
327cdf0e10cSrcweir                     "insertExtensionXcsFile does not exist: ")) +
328cdf0e10cSrcweir              e.Message),
329cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir }
332cdf0e10cSrcweir 
insertExtensionXcuFile(bool shared,rtl::OUString const & fileUri,Modifications * modifications)333cdf0e10cSrcweir void Components::insertExtensionXcuFile(
334cdf0e10cSrcweir     bool shared, rtl::OUString const & fileUri, Modifications * modifications)
335cdf0e10cSrcweir {
336cdf0e10cSrcweir     OSL_ASSERT(modifications != 0);
337cdf0e10cSrcweir     int layer = shared ? 10 : 14;
338cdf0e10cSrcweir     Additions * adds = data_.addExtensionXcuAdditions(fileUri, layer);
339cdf0e10cSrcweir     try {
340cdf0e10cSrcweir         parseXcuFile(fileUri, layer, data_, 0, modifications, adds);
341cdf0e10cSrcweir     } catch (css::container::NoSuchElementException & e) {
342cdf0e10cSrcweir         data_.removeExtensionXcuAdditions(fileUri);
343cdf0e10cSrcweir         throw css::uno::RuntimeException(
344cdf0e10cSrcweir             (rtl::OUString(
345cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
346cdf0e10cSrcweir                     "insertExtensionXcuFile does not exist: ")) +
347cdf0e10cSrcweir              e.Message),
348cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
349cdf0e10cSrcweir     }
350cdf0e10cSrcweir }
351cdf0e10cSrcweir 
removeExtensionXcuFile(rtl::OUString const & fileUri,Modifications * modifications)352cdf0e10cSrcweir void Components::removeExtensionXcuFile(
353cdf0e10cSrcweir     rtl::OUString const & fileUri, Modifications * modifications)
354cdf0e10cSrcweir {
355cdf0e10cSrcweir     //TODO: Ideally, exactly the data coming from the specified xcu file would
356cdf0e10cSrcweir     // be removed.  However, not enough information is recorded in the in-memory
357cdf0e10cSrcweir     // data structures to do so.  So, as a workaround, all those set elements
358cdf0e10cSrcweir     // that were freshly added by the xcu and have afterwards been left
359cdf0e10cSrcweir     // unchanged or have only had their properties changed in the user layer are
360cdf0e10cSrcweir     // removed (and nothing else).  The heuristic to determine
361cdf0e10cSrcweir     // whether a node has been left unchanged is to check the layer ID (as
362cdf0e10cSrcweir     // usual) and additionally to check that the node does not recursively
363cdf0e10cSrcweir     // contain any non-empty sets (multiple extension xcu files are merged into
364cdf0e10cSrcweir     // one layer, so checking layer ID alone is not enough).  Since
365cdf0e10cSrcweir     // item->additions records all additions of set members in textual order,
366cdf0e10cSrcweir     // the latter check works well when iterating through item->additions in
367cdf0e10cSrcweir     // reverse order.
368cdf0e10cSrcweir     OSL_ASSERT(modifications != 0);
369cdf0e10cSrcweir     rtl::Reference< Data::ExtensionXcu > item(
370cdf0e10cSrcweir         data_.removeExtensionXcuAdditions(fileUri));
371cdf0e10cSrcweir     if (item.is()) {
372cdf0e10cSrcweir         for (Additions::reverse_iterator i(item->additions.rbegin());
373cdf0e10cSrcweir              i != item->additions.rend(); ++i)
374cdf0e10cSrcweir         {
375cdf0e10cSrcweir             rtl::Reference< Node > parent;
376cdf0e10cSrcweir             NodeMap const * map = &data_.components;
377cdf0e10cSrcweir             rtl::Reference< Node > node;
378cdf0e10cSrcweir             for (Path::const_iterator j(i->begin()); j != i->end(); ++j) {
379cdf0e10cSrcweir                 parent = node;
380cdf0e10cSrcweir                 node = Data::findNode(Data::NO_LAYER, *map, *j);
381cdf0e10cSrcweir                 if (!node.is()) {
382cdf0e10cSrcweir                     break;
383cdf0e10cSrcweir                 }
384cdf0e10cSrcweir                 map = &node->getMembers();
385cdf0e10cSrcweir             }
386cdf0e10cSrcweir             if (node.is()) {
387cdf0e10cSrcweir                 OSL_ASSERT(parent.is());
388cdf0e10cSrcweir                 if (parent->kind() == Node::KIND_SET) {
389cdf0e10cSrcweir                     OSL_ASSERT(
390cdf0e10cSrcweir                         node->kind() == Node::KIND_GROUP ||
391cdf0e10cSrcweir                         node->kind() == Node::KIND_SET);
392cdf0e10cSrcweir                     if (canRemoveFromLayer(item->layer, node)) {
393cdf0e10cSrcweir                         parent->getMembers().erase(i->back());
394cdf0e10cSrcweir                         data_.modifications.remove(*i);
395cdf0e10cSrcweir                         modifications->add(*i);
396cdf0e10cSrcweir                     }
397cdf0e10cSrcweir                 }
398cdf0e10cSrcweir             }
399cdf0e10cSrcweir         }
400cdf0e10cSrcweir         writeModifications();
401cdf0e10cSrcweir     }
402cdf0e10cSrcweir }
403cdf0e10cSrcweir 
insertModificationXcuFile(rtl::OUString const & fileUri,std::set<rtl::OUString> const & includedPaths,std::set<rtl::OUString> const & excludedPaths,Modifications * modifications)404cdf0e10cSrcweir void Components::insertModificationXcuFile(
405cdf0e10cSrcweir     rtl::OUString const & fileUri,
406cdf0e10cSrcweir     std::set< rtl::OUString > const & includedPaths,
407cdf0e10cSrcweir     std::set< rtl::OUString > const & excludedPaths,
408cdf0e10cSrcweir     Modifications * modifications)
409cdf0e10cSrcweir {
410cdf0e10cSrcweir     OSL_ASSERT(modifications != 0);
411cdf0e10cSrcweir     Partial part(includedPaths, excludedPaths);
412cdf0e10cSrcweir     try {
413cdf0e10cSrcweir         parseFileLeniently(
414cdf0e10cSrcweir             &parseXcuFile, fileUri, Data::NO_LAYER, data_, &part, modifications,
415cdf0e10cSrcweir             0);
416cdf0e10cSrcweir     } catch (css::container::NoSuchElementException & e) {
417cdf0e10cSrcweir         OSL_TRACE(
418cdf0e10cSrcweir             "configmgr error inserting non-existing %s: %s",
419cdf0e10cSrcweir             rtl::OUStringToOString(fileUri, RTL_TEXTENCODING_UTF8).getStr(),
420cdf0e10cSrcweir             rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
421cdf0e10cSrcweir     }
422cdf0e10cSrcweir }
423cdf0e10cSrcweir 
getExternalValue(rtl::OUString const & descriptor)424cdf0e10cSrcweir css::beans::Optional< css::uno::Any > Components::getExternalValue(
425cdf0e10cSrcweir     rtl::OUString const & descriptor)
426cdf0e10cSrcweir {
427cdf0e10cSrcweir     sal_Int32 i = descriptor.indexOf(' ');
428cdf0e10cSrcweir     if (i <= 0) {
429cdf0e10cSrcweir         throw css::uno::RuntimeException(
430cdf0e10cSrcweir             (rtl::OUString(
431cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("bad external value descriptor ")) +
432cdf0e10cSrcweir              descriptor),
433cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
434cdf0e10cSrcweir     }
435cdf0e10cSrcweir     //TODO: Do not make calls with mutex locked:
436cdf0e10cSrcweir     rtl::OUString name(descriptor.copy(0, i));
437cdf0e10cSrcweir     ExternalServices::iterator j(externalServices_.find(name));
438cdf0e10cSrcweir     if (j == externalServices_.end()) {
439cdf0e10cSrcweir         css::uno::Reference< css::uno::XInterface > service;
440cdf0e10cSrcweir         try {
441cdf0e10cSrcweir             service = css::uno::Reference< css::lang::XMultiComponentFactory >(
442cdf0e10cSrcweir                 context_->getServiceManager(), css::uno::UNO_SET_THROW)->
443cdf0e10cSrcweir                 createInstanceWithContext(name, context_);
444cdf0e10cSrcweir         } catch (css::uno::RuntimeException &) {
445cdf0e10cSrcweir             // Assuming these exceptions are real errors:
446cdf0e10cSrcweir             throw;
447cdf0e10cSrcweir         } catch (css::uno::Exception & e) {
448cdf0e10cSrcweir             // Assuming these exceptions indicate that the service is not
449cdf0e10cSrcweir             // installed:
450cdf0e10cSrcweir             OSL_TRACE(
451cdf0e10cSrcweir                 "createInstance(%s) failed with %s",
452cdf0e10cSrcweir                 rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(),
453cdf0e10cSrcweir                 rtl::OUStringToOString(
454cdf0e10cSrcweir                     e.Message, RTL_TEXTENCODING_UTF8).getStr());
455cdf0e10cSrcweir         }
456cdf0e10cSrcweir         css::uno::Reference< css::beans::XPropertySet > propset;
457cdf0e10cSrcweir         if (service.is()) {
458cdf0e10cSrcweir             propset = css::uno::Reference< css::beans::XPropertySet >(
459cdf0e10cSrcweir                 service, css::uno::UNO_QUERY_THROW);
460cdf0e10cSrcweir         }
461cdf0e10cSrcweir         j = externalServices_.insert(
462cdf0e10cSrcweir             ExternalServices::value_type(name, propset)).first;
463cdf0e10cSrcweir     }
464cdf0e10cSrcweir     css::beans::Optional< css::uno::Any > value;
465cdf0e10cSrcweir     if (j->second.is()) {
466cdf0e10cSrcweir         try {
467cdf0e10cSrcweir             if (!(j->second->getPropertyValue(descriptor.copy(i + 1)) >>=
468cdf0e10cSrcweir                   value))
469cdf0e10cSrcweir             {
470cdf0e10cSrcweir                 throw css::uno::RuntimeException(
471cdf0e10cSrcweir                     (rtl::OUString(
472cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
473cdf0e10cSrcweir                             "cannot obtain external value through ")) +
474cdf0e10cSrcweir                      descriptor),
475cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
476cdf0e10cSrcweir             }
477cdf0e10cSrcweir         } catch (css::beans::UnknownPropertyException & e) {
478cdf0e10cSrcweir             throw css::uno::RuntimeException(
479cdf0e10cSrcweir                 (rtl::OUString(
480cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
481cdf0e10cSrcweir                         "unknwon external value descriptor ID: ")) +
482cdf0e10cSrcweir                  e.Message),
483cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
484cdf0e10cSrcweir         } catch (css::lang::WrappedTargetException & e) {
485cdf0e10cSrcweir             throw css::uno::RuntimeException(
486cdf0e10cSrcweir                 (rtl::OUString(
487cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
488cdf0e10cSrcweir                         "cannot obtain external value: ")) +
489cdf0e10cSrcweir                  e.Message),
490cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
491cdf0e10cSrcweir         }
492cdf0e10cSrcweir     }
493cdf0e10cSrcweir     return value;
494cdf0e10cSrcweir }
495cdf0e10cSrcweir 
Components(css::uno::Reference<css::uno::XComponentContext> const & context)496cdf0e10cSrcweir Components::Components(
497cdf0e10cSrcweir     css::uno::Reference< css::uno::XComponentContext > const & context):
498cdf0e10cSrcweir     context_(context)
499cdf0e10cSrcweir {
500cdf0e10cSrcweir     OSL_ASSERT(context.is());
501cdf0e10cSrcweir     RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "begin parsing");
502cdf0e10cSrcweir     parseXcsXcuLayer(
503cdf0e10cSrcweir         0,
504cdf0e10cSrcweir         expand(
505cdf0e10cSrcweir             rtl::OUString(
506cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
507cdf0e10cSrcweir     parseModuleLayer(
508cdf0e10cSrcweir         2,
509cdf0e10cSrcweir         expand(
510cdf0e10cSrcweir             rtl::OUString(
511cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
512cdf0e10cSrcweir                     "$OOO_BASE_DIR/share/registry/modules"))));
513cdf0e10cSrcweir     parseResLayer(
514cdf0e10cSrcweir         3,
515cdf0e10cSrcweir         expand(
516cdf0e10cSrcweir             rtl::OUString(
517cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
518*910823aeSJürgen Schmidt 	parseXcsXcuIniLayer(
519cdf0e10cSrcweir         7,
520cdf0e10cSrcweir         expand(
521cdf0e10cSrcweir             rtl::OUString(
522cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
523cdf0e10cSrcweir                     "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
524cdf0e10cSrcweir                     ":BUNDLED_EXTENSIONS_USER}/registry/"
525cdf0e10cSrcweir                     "com.sun.star.comp.deployment.configuration."
526cdf0e10cSrcweir                     "PackageRegistryBackend/configmgr.ini"))),
527cdf0e10cSrcweir         false);
528cdf0e10cSrcweir     parseXcsXcuIniLayer(
529cdf0e10cSrcweir         9,
530cdf0e10cSrcweir         expand(
531cdf0e10cSrcweir             rtl::OUString(
532cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
533cdf0e10cSrcweir                     "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
534cdf0e10cSrcweir                     ":SHARED_EXTENSIONS_USER}/registry/"
535cdf0e10cSrcweir                     "com.sun.star.comp.deployment.configuration."
536cdf0e10cSrcweir                     "PackageRegistryBackend/configmgr.ini"))),
537cdf0e10cSrcweir         true);
538cdf0e10cSrcweir     parseXcsXcuLayer(
539cdf0e10cSrcweir         11,
540cdf0e10cSrcweir         expand(
541cdf0e10cSrcweir             rtl::OUString(
542cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
543cdf0e10cSrcweir                     "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
544cdf0e10cSrcweir                     ":UNO_USER_PACKAGES_CACHE}/registry/"
545cdf0e10cSrcweir                     "com.sun.star.comp.deployment.configuration."
546cdf0e10cSrcweir                     "PackageRegistryBackend/registry"))));
547cdf0e10cSrcweir         // can be dropped once old UserInstallation format can no longer exist
548cdf0e10cSrcweir         // (probably OOo 4)
549cdf0e10cSrcweir     parseXcsXcuIniLayer(
550cdf0e10cSrcweir         13,
551cdf0e10cSrcweir         expand(
552cdf0e10cSrcweir             rtl::OUString(
553cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
554cdf0e10cSrcweir                     "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
555cdf0e10cSrcweir                     ":UNO_USER_PACKAGES_CACHE}/registry/"
556cdf0e10cSrcweir                     "com.sun.star.comp.deployment.configuration."
557cdf0e10cSrcweir                     "PackageRegistryBackend/configmgr.ini"))),
558cdf0e10cSrcweir         true);
559cdf0e10cSrcweir     parseModificationLayer();
560cdf0e10cSrcweir     RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "end parsing");
561cdf0e10cSrcweir }
562cdf0e10cSrcweir 
~Components()563cdf0e10cSrcweir Components::~Components() {}
564cdf0e10cSrcweir 
parseFileLeniently(FileParser * parseFile,rtl::OUString const & url,int layer,Data & data,Partial const * partial,Modifications * modifications,Additions * additions)565cdf0e10cSrcweir void Components::parseFileLeniently(
566cdf0e10cSrcweir     FileParser * parseFile, rtl::OUString const & url, int layer, Data & data,
567cdf0e10cSrcweir     Partial const * partial, Modifications * modifications,
568cdf0e10cSrcweir     Additions * additions)
569cdf0e10cSrcweir {
570cdf0e10cSrcweir     OSL_ASSERT(parseFile != 0);
571cdf0e10cSrcweir     try {
572cdf0e10cSrcweir         (*parseFile)(url, layer, data, partial, modifications, additions);
573cdf0e10cSrcweir     } catch (css::container::NoSuchElementException &) {
574cdf0e10cSrcweir         throw;
575cdf0e10cSrcweir     } catch (css::uno::Exception & e) { //TODO: more specific exception catching
576cdf0e10cSrcweir         // Silently ignore invalid XML files, instead of completely preventing
577cdf0e10cSrcweir         // OOo from starting:
578cdf0e10cSrcweir         OSL_TRACE(
579cdf0e10cSrcweir             "configmgr error reading %s: %s",
580cdf0e10cSrcweir             rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr(),
581cdf0e10cSrcweir             rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
582cdf0e10cSrcweir     }
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
parseFiles(int layer,rtl::OUString const & extension,FileParser * parseFile,rtl::OUString const & url,bool recursive)585cdf0e10cSrcweir void Components::parseFiles(
586cdf0e10cSrcweir     int layer, rtl::OUString const & extension, FileParser * parseFile,
587cdf0e10cSrcweir     rtl::OUString const & url, bool recursive)
588cdf0e10cSrcweir {
589cdf0e10cSrcweir     osl::Directory dir(url);
590cdf0e10cSrcweir     switch (dir.open()) {
591cdf0e10cSrcweir     case osl::FileBase::E_None:
592cdf0e10cSrcweir         break;
593cdf0e10cSrcweir     case osl::FileBase::E_NOENT:
594cdf0e10cSrcweir         if (!recursive) {
595cdf0e10cSrcweir             return;
596cdf0e10cSrcweir         }
597cdf0e10cSrcweir         // fall through
598cdf0e10cSrcweir     default:
599cdf0e10cSrcweir         throw css::uno::RuntimeException(
600cdf0e10cSrcweir             (rtl::OUString(
601cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
602cdf0e10cSrcweir              url),
603cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
604cdf0e10cSrcweir     }
605cdf0e10cSrcweir     for (;;) {
606cdf0e10cSrcweir         osl::DirectoryItem i;
607cdf0e10cSrcweir         osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
608cdf0e10cSrcweir         if (rc == osl::FileBase::E_NOENT) {
609cdf0e10cSrcweir             break;
610cdf0e10cSrcweir         }
611cdf0e10cSrcweir         if (rc != osl::FileBase::E_None) {
612cdf0e10cSrcweir             throw css::uno::RuntimeException(
613cdf0e10cSrcweir                 (rtl::OUString(
614cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
615cdf0e10cSrcweir                  url),
616cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
617cdf0e10cSrcweir         }
618cdf0e10cSrcweir         osl::FileStatus stat(
619cdf0e10cSrcweir             FileStatusMask_Type | FileStatusMask_FileName |
620cdf0e10cSrcweir             FileStatusMask_FileURL);
621cdf0e10cSrcweir         if (i.getFileStatus(stat) != osl::FileBase::E_None) {
622cdf0e10cSrcweir             throw css::uno::RuntimeException(
623cdf0e10cSrcweir                 (rtl::OUString(
624cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
625cdf0e10cSrcweir                  url),
626cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
627cdf0e10cSrcweir         }
628cdf0e10cSrcweir         if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
629cdf0e10cSrcweir             parseFiles(layer, extension, parseFile, stat.getFileURL(), true);
630cdf0e10cSrcweir         } else {
631cdf0e10cSrcweir             rtl::OUString file(stat.getFileName());
632cdf0e10cSrcweir             if (file.getLength() >= extension.getLength() &&
633cdf0e10cSrcweir                 file.match(extension, file.getLength() - extension.getLength()))
634cdf0e10cSrcweir             {
635cdf0e10cSrcweir                 try {
636cdf0e10cSrcweir                     parseFileLeniently(
637cdf0e10cSrcweir                         parseFile, stat.getFileURL(), layer, data_, 0, 0, 0);
638cdf0e10cSrcweir                 } catch (css::container::NoSuchElementException & e) {
639cdf0e10cSrcweir                     throw css::uno::RuntimeException(
640cdf0e10cSrcweir                         (rtl::OUString(
641cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
642cdf0e10cSrcweir                                 "stat'ed file does not exist: ")) +
643cdf0e10cSrcweir                          e.Message),
644cdf0e10cSrcweir                         css::uno::Reference< css::uno::XInterface >());
645cdf0e10cSrcweir                 }
646cdf0e10cSrcweir             }
647cdf0e10cSrcweir         }
648cdf0e10cSrcweir     }
649cdf0e10cSrcweir }
650cdf0e10cSrcweir 
parseFileList(int layer,FileParser * parseFile,rtl::OUString const & urls,rtl::Bootstrap const & ini,bool recordAdditions)651cdf0e10cSrcweir void Components::parseFileList(
652cdf0e10cSrcweir     int layer, FileParser * parseFile, rtl::OUString const & urls,
653cdf0e10cSrcweir     rtl::Bootstrap const & ini, bool recordAdditions)
654cdf0e10cSrcweir {
655cdf0e10cSrcweir     for (sal_Int32 i = 0;;) {
656cdf0e10cSrcweir         rtl::OUString url(urls.getToken(0, ' ', i));
657cdf0e10cSrcweir         if (url.getLength() != 0) {
658cdf0e10cSrcweir             ini.expandMacrosFrom(url); //TODO: detect failure
659cdf0e10cSrcweir             Additions * adds = 0;
660cdf0e10cSrcweir             if (recordAdditions) {
661cdf0e10cSrcweir                 adds = data_.addExtensionXcuAdditions(url, layer);
662cdf0e10cSrcweir             }
663cdf0e10cSrcweir             try {
664cdf0e10cSrcweir                 parseFileLeniently(parseFile, url, layer, data_, 0, 0, adds);
665cdf0e10cSrcweir             } catch (css::container::NoSuchElementException & e) {
666cdf0e10cSrcweir                 OSL_TRACE(
667cdf0e10cSrcweir                     "configmgr file does not exist: %s",
668cdf0e10cSrcweir                     rtl::OUStringToOString(
669cdf0e10cSrcweir                         e.Message, RTL_TEXTENCODING_UTF8).getStr());
670cdf0e10cSrcweir                 if (adds != 0) {
671cdf0e10cSrcweir                     data_.removeExtensionXcuAdditions(url);
672cdf0e10cSrcweir                 }
673cdf0e10cSrcweir             }
674cdf0e10cSrcweir         }
675cdf0e10cSrcweir         if (i == -1) {
676cdf0e10cSrcweir             break;
677cdf0e10cSrcweir         }
678cdf0e10cSrcweir     }
679cdf0e10cSrcweir }
680cdf0e10cSrcweir 
parseXcdFiles(int layer,rtl::OUString const & url)681cdf0e10cSrcweir void Components::parseXcdFiles(int layer, rtl::OUString const & url) {
682cdf0e10cSrcweir     osl::Directory dir(url);
683cdf0e10cSrcweir     switch (dir.open()) {
684cdf0e10cSrcweir     case osl::FileBase::E_None:
685cdf0e10cSrcweir         break;
686cdf0e10cSrcweir     case osl::FileBase::E_NOENT:
687cdf0e10cSrcweir         return;
688cdf0e10cSrcweir     default:
689cdf0e10cSrcweir         throw css::uno::RuntimeException(
690cdf0e10cSrcweir             (rtl::OUString(
691cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
692cdf0e10cSrcweir              url),
693cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
694cdf0e10cSrcweir     }
695cdf0e10cSrcweir     UnresolvedList unres;
696cdf0e10cSrcweir     XcdParser::Dependencies deps;
697cdf0e10cSrcweir     for (;;) {
698cdf0e10cSrcweir         osl::DirectoryItem i;
699cdf0e10cSrcweir         osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
700cdf0e10cSrcweir         if (rc == osl::FileBase::E_NOENT) {
701cdf0e10cSrcweir             break;
702cdf0e10cSrcweir         }
703cdf0e10cSrcweir         if (rc != osl::FileBase::E_None) {
704cdf0e10cSrcweir             throw css::uno::RuntimeException(
705cdf0e10cSrcweir                 (rtl::OUString(
706cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
707cdf0e10cSrcweir                  url),
708cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
709cdf0e10cSrcweir         }
710cdf0e10cSrcweir         osl::FileStatus stat(
711cdf0e10cSrcweir             FileStatusMask_Type | FileStatusMask_FileName |
712cdf0e10cSrcweir             FileStatusMask_FileURL);
713cdf0e10cSrcweir         if (i.getFileStatus(stat) != osl::FileBase::E_None) {
714cdf0e10cSrcweir             throw css::uno::RuntimeException(
715cdf0e10cSrcweir                 (rtl::OUString(
716cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
717cdf0e10cSrcweir                  url),
718cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
719cdf0e10cSrcweir         }
720cdf0e10cSrcweir         if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
721cdf0e10cSrcweir             rtl::OUString file(stat.getFileName());
722cdf0e10cSrcweir             if (file.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
723cdf0e10cSrcweir                 file.matchAsciiL(
724cdf0e10cSrcweir                     RTL_CONSTASCII_STRINGPARAM(".xcd"),
725cdf0e10cSrcweir                     file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
726cdf0e10cSrcweir             {
727cdf0e10cSrcweir                 rtl::OUString name(
728cdf0e10cSrcweir                     file.copy(
729cdf0e10cSrcweir                         0, file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
730cdf0e10cSrcweir                 rtl::Reference< ParseManager > manager;
731cdf0e10cSrcweir                 try {
732cdf0e10cSrcweir                     manager = new ParseManager(
733cdf0e10cSrcweir                         stat.getFileURL(), new XcdParser(layer, deps, data_));
734cdf0e10cSrcweir                 } catch (css::container::NoSuchElementException & e) {
735cdf0e10cSrcweir                     throw css::uno::RuntimeException(
736cdf0e10cSrcweir                         (rtl::OUString(
737cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
738cdf0e10cSrcweir                                 "stat'ed file does not exist: ")) +
739cdf0e10cSrcweir                          e.Message),
740cdf0e10cSrcweir                         css::uno::Reference< css::uno::XInterface >());
741cdf0e10cSrcweir                 }
742cdf0e10cSrcweir                 if (manager->parse()) {
743cdf0e10cSrcweir                     deps.insert(name);
744cdf0e10cSrcweir                 } else {
745cdf0e10cSrcweir                     unres.push_back(UnresolvedListItem(name, manager));
746cdf0e10cSrcweir                 }
747cdf0e10cSrcweir             }
748cdf0e10cSrcweir         }
749cdf0e10cSrcweir     }
750cdf0e10cSrcweir     while (!unres.empty()) {
751cdf0e10cSrcweir         bool resolved = false;
752cdf0e10cSrcweir         for (UnresolvedList::iterator i(unres.begin()); i != unres.end();) {
753cdf0e10cSrcweir             if (i->manager->parse()) {
754cdf0e10cSrcweir                 deps.insert(i->name);
755cdf0e10cSrcweir                 unres.erase(i++);
756cdf0e10cSrcweir                 resolved = true;
757cdf0e10cSrcweir             } else {
758cdf0e10cSrcweir                 ++i;
759cdf0e10cSrcweir             }
760cdf0e10cSrcweir         }
761cdf0e10cSrcweir         if (!resolved) {
762cdf0e10cSrcweir             throw css::uno::RuntimeException(
763cdf0e10cSrcweir                 (rtl::OUString(
764cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
765cdf0e10cSrcweir                         "xcd: unresolved dependencies in ")) +
766cdf0e10cSrcweir                  url),
767cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
768cdf0e10cSrcweir         }
769cdf0e10cSrcweir     }
770cdf0e10cSrcweir }
771cdf0e10cSrcweir 
parseXcsXcuLayer(int layer,rtl::OUString const & url)772cdf0e10cSrcweir void Components::parseXcsXcuLayer(int layer, rtl::OUString const & url) {
773cdf0e10cSrcweir     parseXcdFiles(layer, url);
774cdf0e10cSrcweir     parseFiles(
775cdf0e10cSrcweir         layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcs")),
776cdf0e10cSrcweir         &parseXcsFile,
777cdf0e10cSrcweir         url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/schema")), false);
778cdf0e10cSrcweir     parseFiles(
779cdf0e10cSrcweir         layer + 1, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
780cdf0e10cSrcweir         &parseXcuFile,
781cdf0e10cSrcweir         url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), false);
782cdf0e10cSrcweir }
783cdf0e10cSrcweir 
parseXcsXcuIniLayer(int layer,rtl::OUString const & url,bool recordAdditions)784cdf0e10cSrcweir void Components::parseXcsXcuIniLayer(
785cdf0e10cSrcweir     int layer, rtl::OUString const & url, bool recordAdditions)
786cdf0e10cSrcweir {
787cdf0e10cSrcweir     //TODO: rtl::Bootstrap::getFrom "first trie[s] to retrieve the value via the
788cdf0e10cSrcweir     // global function"
789cdf0e10cSrcweir     rtl::Bootstrap ini(url);
790cdf0e10cSrcweir     rtl::OUString urls;
791cdf0e10cSrcweir     if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SCHEMA")), urls))
792cdf0e10cSrcweir     {
793cdf0e10cSrcweir         parseFileList(layer, &parseXcsFile, urls, ini, false);
794cdf0e10cSrcweir     }
795cdf0e10cSrcweir     if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DATA")), urls))
796cdf0e10cSrcweir     {
797cdf0e10cSrcweir         parseFileList(layer + 1, &parseXcuFile, urls, ini, recordAdditions);
798cdf0e10cSrcweir     }
799cdf0e10cSrcweir }
800cdf0e10cSrcweir 
parseModuleLayer(int layer,rtl::OUString const & url)801cdf0e10cSrcweir void Components::parseModuleLayer(int layer, rtl::OUString const & url) {
802cdf0e10cSrcweir     parseFiles(
803cdf0e10cSrcweir         layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
804cdf0e10cSrcweir         &parseXcuFile, url, false);
805cdf0e10cSrcweir }
806cdf0e10cSrcweir 
parseResLayer(int layer,rtl::OUString const & url)807cdf0e10cSrcweir void Components::parseResLayer(int layer, rtl::OUString const & url) {
808cdf0e10cSrcweir     rtl::OUString resUrl(
809cdf0e10cSrcweir         url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/res")));
810cdf0e10cSrcweir     parseXcdFiles(layer, resUrl);
811cdf0e10cSrcweir     parseFiles(
812cdf0e10cSrcweir         layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
813cdf0e10cSrcweir         &parseXcuFile, resUrl, false);
814cdf0e10cSrcweir }
815cdf0e10cSrcweir 
getModificationFileUrl() const816cdf0e10cSrcweir rtl::OUString Components::getModificationFileUrl() const {
817cdf0e10cSrcweir     return expand(
818cdf0e10cSrcweir         rtl::OUString(
819cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM(
820*910823aeSJürgen Schmidt                 "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
821cdf0e10cSrcweir                 ":UserInstallation}/user/registrymodifications.xcu")));
822cdf0e10cSrcweir }
823cdf0e10cSrcweir 
parseModificationLayer()824cdf0e10cSrcweir void Components::parseModificationLayer() {
825cdf0e10cSrcweir     try {
826cdf0e10cSrcweir         parseFileLeniently(
827cdf0e10cSrcweir             &parseXcuFile, getModificationFileUrl(), Data::NO_LAYER, data_, 0,
828cdf0e10cSrcweir             0, 0);
829cdf0e10cSrcweir     } catch (css::container::NoSuchElementException &) {
830cdf0e10cSrcweir         OSL_TRACE(
831cdf0e10cSrcweir             "configmgr user registrymodifications.xcu does not (yet) exist");
832cdf0e10cSrcweir         // Migrate old user layer data (can be removed once migration is no
833cdf0e10cSrcweir         // longer relevant, probably OOo 4; also see hack for xsi namespace in
834cdf0e10cSrcweir         // xmlreader::XmlReader::registerNamespaceIri):
835cdf0e10cSrcweir         parseFiles(
836cdf0e10cSrcweir             Data::NO_LAYER, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
837cdf0e10cSrcweir             &parseXcuFile,
838cdf0e10cSrcweir             expand(
839cdf0e10cSrcweir                 rtl::OUString(
840cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
841*910823aeSJürgen Schmidt                         "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
842cdf0e10cSrcweir                         ":UserInstallation}/user/registry/data"))),
843cdf0e10cSrcweir             false);
844cdf0e10cSrcweir     }
845cdf0e10cSrcweir }
846cdf0e10cSrcweir 
847cdf0e10cSrcweir }
848