Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "sal/config.h"
21 : :
22 : : #include <cassert>
23 : : #include <vector>
24 : :
25 : : #include "com/sun/star/lang/DisposedException.hpp"
26 : : #include "com/sun/star/lang/EventObject.hpp"
27 : : #include "com/sun/star/lang/WrappedTargetException.hpp"
28 : : #include "com/sun/star/uno/Any.hxx"
29 : : #include "com/sun/star/uno/Reference.hxx"
30 : : #include "com/sun/star/uno/RuntimeException.hpp"
31 : : #include "com/sun/star/uno/Type.hxx"
32 : : #include "com/sun/star/uno/XInterface.hpp"
33 : : #include "com/sun/star/util/ChangesEvent.hpp"
34 : : #include "com/sun/star/util/ChangesSet.hpp"
35 : : #include "com/sun/star/util/ElementChange.hpp"
36 : : #include "com/sun/star/util/XChangesBatch.hpp"
37 : : #include "com/sun/star/util/XChangesListener.hpp"
38 : : #include "com/sun/star/util/XChangesNotifier.hpp"
39 : : #include "comphelper/sequenceasvector.hxx"
40 : : #include "cppu/unotype.hxx"
41 : : #include "cppuhelper/queryinterface.hxx"
42 : : #include "cppuhelper/weak.hxx"
43 : : #include "osl/mutex.hxx"
44 : : #include "rtl/ref.hxx"
45 : : #include "rtl/ustring.h"
46 : : #include "rtl/ustring.hxx"
47 : :
48 : : #include "broadcaster.hxx"
49 : : #include "childaccess.hxx"
50 : : #include "components.hxx"
51 : : #include "data.hxx"
52 : : #include "lock.hxx"
53 : : #include "modifications.hxx"
54 : : #include "node.hxx"
55 : : #include "path.hxx"
56 : : #include "rootaccess.hxx"
57 : :
58 : : namespace configmgr {
59 : :
60 : : namespace {
61 : :
62 : : namespace css = com::sun::star;
63 : :
64 : : }
65 : :
66 : 105314 : RootAccess::RootAccess(
67 : : Components & components, rtl::OUString const & pathRepresentation,
68 : : rtl::OUString const & locale, bool update):
69 : : Access(components), pathRepresentation_(pathRepresentation),
70 [ + - ][ + - ]: 105314 : locale_(locale), update_(update), finalized_(false), alive_(true)
[ + - ]
71 : : {
72 [ + - ][ + - ]: 105314 : lock_ = lock();
[ + - ]
73 : 105314 : }
74 : :
75 : 1546498 : Path RootAccess::getAbsolutePath() {
76 : 1546498 : getNode();
77 : 1546498 : return path_;
78 : : }
79 : :
80 : 154273 : void RootAccess::initBroadcaster(
81 : : Modifications::Node const & modifications, Broadcaster * broadcaster)
82 : : {
83 : : assert(broadcaster != 0);
84 [ + - ]: 154273 : comphelper::SequenceAsVector< css::util::ElementChange > changes;
85 : : initBroadcasterAndChanges(
86 [ + + ][ + - ]: 154273 : modifications, broadcaster, changesListeners_.empty() ? 0 : &changes);
87 [ + + ]: 154273 : if (!changes.empty()) {
88 [ + - ]: 31840 : css::util::ChangesSet set(changes.getAsConstList());
89 [ + + ]: 127360 : for (ChangesListeners::iterator i(changesListeners_.begin());
90 : 63680 : i != changesListeners_.end(); ++i)
91 : : {
92 : 31840 : cppu::OWeakObject* pSource = static_cast< cppu::OWeakObject * >(this);
93 [ + - ]: 31840 : css::uno::Reference< css::uno::XInterface > xBase( pSource, css::uno::UNO_QUERY );
94 : : broadcaster->addChangesNotification(
95 : 31840 : *i,
96 : : css::util::ChangesEvent(
97 [ + - ][ + - ]: 63680 : pSource, makeAny( xBase ), set));
[ + - + - ]
[ + - ]
98 [ + - ]: 63680 : }
99 : 154273 : }
100 : 154273 : }
101 : :
102 : 17173132 : void RootAccess::acquire() throw () {
103 : 17173132 : Access::acquire();
104 : 17173133 : }
105 : :
106 : 17170583 : void RootAccess::release() throw () {
107 : 17170583 : Access::release();
108 : 17170583 : }
109 : :
110 : 130 : rtl::OUString RootAccess::getAbsolutePathRepresentation() {
111 : 130 : getNode(); // turn pathRepresentation_ into canonic form
112 : 130 : return pathRepresentation_;
113 : : }
114 : :
115 : 724182 : rtl::OUString RootAccess::getLocale() const {
116 : 724182 : return locale_;
117 : : }
118 : :
119 : 209247 : bool RootAccess::isUpdate() const {
120 : 209247 : return update_;
121 : : }
122 : :
123 : 1905 : void RootAccess::setAlive(bool b) {
124 : 1905 : alive_ = b;
125 : 1905 : }
126 : :
127 : 13000 : void RootAccess::addChangesListener(
128 : : css::uno::Reference< css::util::XChangesListener > const & aListener)
129 : : throw (css::uno::RuntimeException)
130 : : {
131 : : assert(thisIs(IS_ANY));
132 : : {
133 [ + - ]: 13000 : osl::MutexGuard g(*lock_);
134 [ + - ]: 13000 : checkLocalizedPropertyAccess();
135 [ - + ]: 13000 : if (!aListener.is()) {
136 : : throw css::uno::RuntimeException(
137 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
138 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
139 : : }
140 [ + - ][ + - ]: 13000 : if (!isDisposed()) {
141 [ + - ]: 13000 : changesListeners_.insert(aListener);
142 : 13000 : return;
143 [ + - ][ - + ]: 13000 : }
144 : : }
145 : : try {
146 [ # # ]: 13000 : aListener->disposing(
147 [ # # ][ # # ]: 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
[ # # ][ # # ]
[ # # ]
148 : 0 : } catch (css::lang::DisposedException &) {}
149 : : }
150 : :
151 : 10156 : void RootAccess::removeChangesListener(
152 : : css::uno::Reference< css::util::XChangesListener > const & aListener)
153 : : throw (css::uno::RuntimeException)
154 : : {
155 : : assert(thisIs(IS_ANY));
156 [ + - ]: 10156 : osl::MutexGuard g(*lock_);
157 [ + - ]: 10156 : checkLocalizedPropertyAccess();
158 [ + - ]: 10156 : ChangesListeners::iterator i(changesListeners_.find(aListener));
159 [ + + ]: 10156 : if (i != changesListeners_.end()) {
160 [ + - ]: 9092 : changesListeners_.erase(i);
161 [ + - ]: 10156 : }
162 : 10156 : }
163 : :
164 : 18631 : void RootAccess::commitChanges()
165 : : throw (css::lang::WrappedTargetException, css::uno::RuntimeException)
166 : : {
167 : : assert(thisIs(IS_UPDATE));
168 [ + - ]: 18631 : if (!alive_)
169 : : {
170 : 18631 : return;
171 : : }
172 [ + - ]: 18631 : Broadcaster bc;
173 : : {
174 [ + - ]: 18631 : osl::MutexGuard g(*lock_);
175 : :
176 [ + - ]: 18631 : checkLocalizedPropertyAccess();
177 : : int finalizedLayer;
178 [ + - ]: 18631 : Modifications globalMods;
179 : : commitChildChanges(
180 [ + - ]: 18631 : ((getComponents().resolvePathRepresentation(
181 : : pathRepresentation_, 0, 0, &finalizedLayer)
182 [ + - ][ + - ]: 37262 : == node_) &&
[ + - ][ # # ]
183 : : finalizedLayer == Data::NO_LAYER),
184 [ + - ][ + - ]: 18631 : &globalMods);
[ + - ]
185 [ + - ][ + - ]: 18631 : getComponents().writeModifications();
186 [ + - ][ + - ]: 18631 : getComponents().initGlobalBroadcaster(globalMods, this, &bc);
[ + - ][ + - ]
187 : : }
188 [ + - ]: 18631 : bc.send();
189 : : }
190 : :
191 : 0 : sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) {
192 : : assert(thisIs(IS_UPDATE));
193 [ # # ]: 0 : osl::MutexGuard g(*lock_);
194 [ # # ]: 0 : checkLocalizedPropertyAccess();
195 : : //TODO: Optimize:
196 [ # # ]: 0 : std::vector< css::util::ElementChange > changes;
197 [ # # ]: 0 : reportChildChanges(&changes);
198 [ # # ]: 0 : return !changes.empty();
199 : : }
200 : :
201 : 0 : css::util::ChangesSet RootAccess::getPendingChanges()
202 : : throw (css::uno::RuntimeException)
203 : : {
204 : : assert(thisIs(IS_UPDATE));
205 [ # # ]: 0 : osl::MutexGuard g(*lock_);
206 [ # # ]: 0 : checkLocalizedPropertyAccess();
207 [ # # ]: 0 : comphelper::SequenceAsVector< css::util::ElementChange > changes;
208 [ # # ]: 0 : reportChildChanges(&changes);
209 [ # # ][ # # ]: 0 : return changes.getAsConstList();
210 : : }
211 : :
212 [ + - ][ + - ]: 103409 : RootAccess::~RootAccess()
213 : : {
214 [ + - ]: 103409 : osl::MutexGuard g(*lock_);
215 [ + - ]: 103409 : if (alive_)
216 [ + - ][ + - ]: 103409 : getComponents().removeRootAccess(this);
[ + - ]
217 [ - + ]: 206818 : }
218 : :
219 : 102742 : Path RootAccess::getRelativePath() {
220 : 102742 : return Path();
221 : : }
222 : :
223 : 48700 : rtl::OUString RootAccess::getRelativePathRepresentation() {
224 : 48700 : return rtl::OUString();
225 : : }
226 : :
227 : 5582337 : rtl::Reference< Node > RootAccess::getNode() {
228 [ + + ]: 5582337 : if (!node_.is()) {
229 : 103017 : rtl::OUString canonic;
230 : : int finalizedLayer;
231 [ + - ]: 103017 : node_ = getComponents().resolvePathRepresentation(
232 [ + - ][ + - ]: 103017 : pathRepresentation_, &canonic, &path_, &finalizedLayer);
[ + - ]
233 [ - + ]: 103017 : if (!node_.is()) {
234 : : throw css::uno::RuntimeException(
235 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot find ")) +
236 : : pathRepresentation_),
237 [ # # ][ # # ]: 0 : 0);
[ # # ]
238 : : // RootAccess::queryInterface indirectly calls
239 : : // RootAccess::getNode, so if this RootAccess were passed out in
240 : : // RuntimeException.Context, client code that called
241 : : // queryInterface on it would cause trouble; therefore,
242 : : // RuntimeException.Context is left null here
243 : : }
244 : 103017 : pathRepresentation_ = canonic;
245 : : assert(!path_.empty() || node_->kind() == Node::KIND_ROOT);
246 [ + + ]: 103017 : if (!path_.empty()) {
247 [ + - ]: 100264 : name_ = path_.back();
248 : : }
249 : 103017 : finalized_ = finalizedLayer != Data::NO_LAYER;
250 : : }
251 : 5582337 : return node_;
252 : : }
253 : :
254 : 250842 : bool RootAccess::isFinalized() {
255 : 250842 : getNode();
256 : 250842 : return finalized_;
257 : : }
258 : :
259 : 0 : rtl::OUString RootAccess::getNameInternal() {
260 : 0 : getNode();
261 : 0 : return name_;
262 : : }
263 : :
264 : 1055126 : rtl::Reference< RootAccess > RootAccess::getRootAccess() {
265 : 1055126 : return this;
266 : : }
267 : :
268 : 205484 : rtl::Reference< Access > RootAccess::getParentAccess() {
269 : 205484 : return rtl::Reference< Access >();
270 : : }
271 : :
272 : 130 : void RootAccess::addTypes(std::vector< css::uno::Type > * types) const {
273 : : assert(types != 0);
274 : 130 : types->push_back(cppu::UnoType< css::util::XChangesNotifier >::get());
275 : 130 : types->push_back(cppu::UnoType< css::util::XChangesBatch >::get());
276 : 130 : }
277 : :
278 : 1161 : void RootAccess::addSupportedServiceNames(
279 : : std::vector< rtl::OUString > * services)
280 : : {
281 : : assert(services != 0);
282 : : services->push_back(
283 : : rtl::OUString(
284 : : RTL_CONSTASCII_USTRINGPARAM(
285 [ + - ]: 1161 : "com.sun.star.configuration.AccessRootElement")));
286 [ + + ]: 1161 : if (update_) {
287 : : services->push_back(
288 : : rtl::OUString(
289 : : RTL_CONSTASCII_USTRINGPARAM(
290 [ + - ]: 1043 : "com.sun.star.configuration.UpdateRootElement")));
291 : : }
292 : 1161 : }
293 : :
294 : 0 : void RootAccess::initDisposeBroadcaster(Broadcaster * broadcaster) {
295 : : assert(broadcaster != 0);
296 [ # # ]: 0 : for (ChangesListeners::iterator i(changesListeners_.begin());
297 : 0 : i != changesListeners_.end(); ++i)
298 : : {
299 : : broadcaster->addDisposeNotification(
300 [ # # ]: 0 : i->get(),
301 [ # # ][ # # ]: 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
[ # # ][ # # ]
[ # # ]
302 : : }
303 : 0 : Access::initDisposeBroadcaster(broadcaster);
304 : 0 : }
305 : :
306 : 0 : void RootAccess::clearListeners() throw() {
307 : 0 : changesListeners_.clear();
308 : 0 : Access::clearListeners();
309 : 0 : }
310 : :
311 : 477459 : css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType)
312 : : throw (css::uno::RuntimeException)
313 : : {
314 : : assert(thisIs(IS_ANY));
315 [ + - ]: 477459 : osl::MutexGuard g(*lock_);
316 [ + - ]: 477459 : checkLocalizedPropertyAccess();
317 [ + - ]: 477459 : css::uno::Any res(Access::queryInterface(aType));
318 [ + + ]: 477459 : if (res.hasValue()) {
319 : : return res;
320 : : }
321 : : res = cppu::queryInterface(
322 [ + - ]: 58022 : aType, static_cast< css::util::XChangesNotifier * >(this));
323 [ + + ]: 58022 : if (res.hasValue()) {
324 : : return res;
325 : : }
326 [ + - ][ + + ]: 28245 : if (!res.hasValue() && update_) {
[ + + ]
327 : : res = cppu::queryInterface(
328 [ + - ]: 25377 : aType, static_cast< css::util::XChangesBatch * >(this));
329 : : }
330 [ + - ]: 477459 : return res;
331 : : }
332 : :
333 : 0 : rtl::OUString RootAccess::getImplementationName()
334 : : throw (css::uno::RuntimeException)
335 : : {
336 : : assert(thisIs(IS_ANY));
337 [ # # ]: 0 : osl::MutexGuard g(*lock_);
338 [ # # ]: 0 : checkLocalizedPropertyAccess();
339 [ # # ][ # # ]: 0 : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("configmgr.RootAccess"));
340 : : }
341 : :
342 : : }
343 : :
344 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|