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