xref: /trunk/main/configmgr/source/rootaccess.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_configmgr.hxx"
25 #include "sal/config.h"
26 
27 #include <vector>
28 
29 #include "com/sun/star/lang/DisposedException.hpp"
30 #include "com/sun/star/lang/EventObject.hpp"
31 #include "com/sun/star/lang/WrappedTargetException.hpp"
32 #include "com/sun/star/uno/Any.hxx"
33 #include "com/sun/star/uno/Reference.hxx"
34 #include "com/sun/star/uno/RuntimeException.hpp"
35 #include "com/sun/star/uno/Type.hxx"
36 #include "com/sun/star/uno/XInterface.hpp"
37 #include "com/sun/star/util/ChangesEvent.hpp"
38 #include "com/sun/star/util/ChangesSet.hpp"
39 #include "com/sun/star/util/ElementChange.hpp"
40 #include "com/sun/star/util/XChangesBatch.hpp"
41 #include "com/sun/star/util/XChangesListener.hpp"
42 #include "com/sun/star/util/XChangesNotifier.hpp"
43 #include "comphelper/sequenceasvector.hxx"
44 #include "cppu/unotype.hxx"
45 #include "cppuhelper/queryinterface.hxx"
46 #include "cppuhelper/weak.hxx"
47 #include "osl/diagnose.h"
48 #include "osl/mutex.hxx"
49 #include "rtl/ref.hxx"
50 #include "rtl/ustring.h"
51 #include "rtl/ustring.hxx"
52 
53 #include "broadcaster.hxx"
54 #include "childaccess.hxx"
55 #include "components.hxx"
56 #include "data.hxx"
57 #include "lock.hxx"
58 #include "modifications.hxx"
59 #include "node.hxx"
60 #include "path.hxx"
61 #include "rootaccess.hxx"
62 
63 namespace configmgr {
64 
65 namespace {
66 
67 namespace css = com::sun::star;
68 
69 }
70 
RootAccess(Components & components,rtl::OUString const & pathRepresentation,rtl::OUString const & locale,bool update)71 RootAccess::RootAccess(
72     Components & components, rtl::OUString const & pathRepresentation,
73     rtl::OUString const & locale, bool update):
74     Access(components), pathRepresentation_(pathRepresentation),
75     locale_(locale), update_(update)
76 {}
77 
getAbsolutePath()78 Path RootAccess::getAbsolutePath() {
79     getNode();
80     return path_;
81 }
82 
initBroadcaster(Modifications::Node const & modifications,Broadcaster * broadcaster)83 void RootAccess::initBroadcaster(
84     Modifications::Node const & modifications, Broadcaster * broadcaster)
85 {
86     OSL_ASSERT(broadcaster != 0);
87     comphelper::SequenceAsVector< css::util::ElementChange > changes;
88     initBroadcasterAndChanges(
89         modifications, broadcaster, changesListeners_.empty() ? 0 : &changes);
90     if (!changes.empty()) {
91         css::util::ChangesSet set(changes.getAsConstList());
92         for (ChangesListeners::iterator i(changesListeners_.begin());
93              i != changesListeners_.end(); ++i)
94         {
95             cppu::OWeakObject* pSource = static_cast< cppu::OWeakObject * >(this);
96             css::uno::Reference< css::uno::XInterface > xBase( pSource, css::uno::UNO_QUERY );
97             broadcaster->addChangesNotification(
98                 *i,
99                 css::util::ChangesEvent(
100                     pSource, makeAny( xBase ), set));
101         }
102     }
103 }
104 
acquire()105 void RootAccess::acquire() throw () {
106     Access::acquire();
107 }
108 
release()109 void RootAccess::release() throw () {
110     Access::release();
111 }
112 
getAbsolutePathRepresentation()113 rtl::OUString RootAccess::getAbsolutePathRepresentation() {
114     getNode(); // turn pathRepresentation_ into canonic form
115     return pathRepresentation_;
116 }
117 
getLocale() const118 rtl::OUString RootAccess::getLocale() const {
119     return locale_;
120 }
121 
isUpdate() const122 bool RootAccess::isUpdate() const {
123     return update_;
124 }
125 
~RootAccess()126 RootAccess::~RootAccess() {
127     osl::MutexGuard g(lock);
128     getComponents().removeRootAccess(this);
129 }
130 
getRelativePath()131 Path RootAccess::getRelativePath() {
132     return Path();
133 }
134 
getRelativePathRepresentation()135 rtl::OUString RootAccess::getRelativePathRepresentation() {
136     return rtl::OUString();
137 }
138 
getNode()139 rtl::Reference< Node > RootAccess::getNode() {
140     if (!node_.is()) {
141         rtl::OUString canonic;
142         int finalizedLayer;
143         node_ = getComponents().resolvePathRepresentation(
144             pathRepresentation_, &canonic, &path_, &finalizedLayer);
145         if (!node_.is()) {
146             throw css::uno::RuntimeException(
147                 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot find ")) +
148                  pathRepresentation_),
149                 0);
150                 // RootAccess::queryInterface indirectly calls
151                 // RootAccess::getNode, so if this RootAccess were passed out in
152                 // RuntimeException.Context, client code that called
153                 // queryInterface on it would cause trouble; therefore,
154                 // RuntimeException.Context is left null here
155         }
156         pathRepresentation_ = canonic;
157         OSL_ASSERT(!path_.empty());
158         name_ = path_.back();
159         finalized_ = finalizedLayer != Data::NO_LAYER;
160     }
161     return node_;
162 }
163 
isFinalized()164 bool RootAccess::isFinalized() {
165     getNode();
166     return finalized_;
167 }
168 
getNameInternal()169 rtl::OUString RootAccess::getNameInternal() {
170     getNode();
171     return name_;
172 }
173 
getRootAccess()174 rtl::Reference< RootAccess > RootAccess::getRootAccess() {
175     return this;
176 }
177 
getParentAccess()178 rtl::Reference< Access > RootAccess::getParentAccess() {
179     return rtl::Reference< Access >();
180 }
181 
addTypes(std::vector<css::uno::Type> * types) const182 void RootAccess::addTypes(std::vector< css::uno::Type > * types) const {
183     OSL_ASSERT(types != 0);
184     types->push_back(cppu::UnoType< css::util::XChangesNotifier >::get());
185     types->push_back(cppu::UnoType< css::util::XChangesBatch >::get());
186 }
187 
addSupportedServiceNames(std::vector<rtl::OUString> * services)188 void RootAccess::addSupportedServiceNames(
189     std::vector< rtl::OUString > * services)
190 {
191     OSL_ASSERT(services != 0);
192     services->push_back(
193         rtl::OUString(
194             RTL_CONSTASCII_USTRINGPARAM(
195                 "com.sun.star.configuration.AccessRootElement")));
196     if (update_) {
197         services->push_back(
198             rtl::OUString(
199                 RTL_CONSTASCII_USTRINGPARAM(
200                     "com.sun.star.configuration.UpdateRootElement")));
201     }
202 }
203 
initDisposeBroadcaster(Broadcaster * broadcaster)204 void RootAccess::initDisposeBroadcaster(Broadcaster * broadcaster) {
205     OSL_ASSERT(broadcaster != 0);
206     for (ChangesListeners::iterator i(changesListeners_.begin());
207          i != changesListeners_.end(); ++i)
208     {
209         broadcaster->addDisposeNotification(
210             i->get(),
211             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
212     }
213     Access::initDisposeBroadcaster(broadcaster);
214 }
215 
clearListeners()216 void RootAccess::clearListeners() throw() {
217     changesListeners_.clear();
218     Access::clearListeners();
219 }
220 
queryInterface(css::uno::Type const & aType)221 css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType)
222 {
223     OSL_ASSERT(thisIs(IS_ANY));
224     osl::MutexGuard g(lock);
225     checkLocalizedPropertyAccess();
226     css::uno::Any res(Access::queryInterface(aType));
227     if (res.hasValue()) {
228         return res;
229     }
230     res = cppu::queryInterface(
231         aType, static_cast< css::util::XChangesNotifier * >(this));
232     if (res.hasValue()) {
233         return res;
234     }
235     if (!res.hasValue() && update_) {
236         res = cppu::queryInterface(
237             aType, static_cast< css::util::XChangesBatch * >(this));
238     }
239     return res;
240 }
241 
addChangesListener(css::uno::Reference<css::util::XChangesListener> const & aListener)242 void RootAccess::addChangesListener(
243     css::uno::Reference< css::util::XChangesListener > const & aListener)
244 {
245     OSL_ASSERT(thisIs(IS_ANY));
246     {
247         osl::MutexGuard g(lock);
248         checkLocalizedPropertyAccess();
249         if (!aListener.is()) {
250             throw css::uno::RuntimeException(
251                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
252                 static_cast< cppu::OWeakObject * >(this));
253         }
254         if (!isDisposed()) {
255             changesListeners_.insert(aListener);
256             return;
257         }
258     }
259     try {
260         aListener->disposing(
261             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
262     } catch (css::lang::DisposedException &) {}
263 }
264 
removeChangesListener(css::uno::Reference<css::util::XChangesListener> const & aListener)265 void RootAccess::removeChangesListener(
266     css::uno::Reference< css::util::XChangesListener > const & aListener)
267 {
268     OSL_ASSERT(thisIs(IS_ANY));
269     osl::MutexGuard g(lock);
270     checkLocalizedPropertyAccess();
271     ChangesListeners::iterator i(changesListeners_.find(aListener));
272     if (i != changesListeners_.end()) {
273         changesListeners_.erase(i);
274     }
275 }
276 
commitChanges()277 void RootAccess::commitChanges()
278 {
279     OSL_ASSERT(thisIs(IS_UPDATE));
280     Broadcaster bc;
281     {
282         osl::MutexGuard g(lock);
283         checkLocalizedPropertyAccess();
284         int finalizedLayer;
285         Modifications globalMods;
286         commitChildChanges(
287             ((getComponents().resolvePathRepresentation(
288                   pathRepresentation_, 0, 0, &finalizedLayer)
289               == node_) &&
290              finalizedLayer == Data::NO_LAYER),
291             &globalMods);
292         getComponents().writeModifications();
293         getComponents().initGlobalBroadcaster(globalMods, this, &bc);
294     }
295     bc.send();
296 }
297 
hasPendingChanges()298 sal_Bool RootAccess::hasPendingChanges() {
299     OSL_ASSERT(thisIs(IS_UPDATE));
300     osl::MutexGuard g(lock);
301     checkLocalizedPropertyAccess();
302     //TODO: Optimize:
303     std::vector< css::util::ElementChange > changes;
304     reportChildChanges(&changes);
305     return !changes.empty();
306 }
307 
getPendingChanges()308 css::util::ChangesSet RootAccess::getPendingChanges()
309 {
310     OSL_ASSERT(thisIs(IS_UPDATE));
311     osl::MutexGuard g(lock);
312     checkLocalizedPropertyAccess();
313     comphelper::SequenceAsVector< css::util::ElementChange > changes;
314     reportChildChanges(&changes);
315     return changes.getAsConstList();
316 }
317 
318 }
319