xref: /trunk/main/configmgr/source/rootaccess.cxx (revision 3a7cf181)
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     throw (css::uno::RuntimeException)
223 {
224     OSL_ASSERT(thisIs(IS_ANY));
225     osl::MutexGuard g(lock);
226     checkLocalizedPropertyAccess();
227     css::uno::Any res(Access::queryInterface(aType));
228     if (res.hasValue()) {
229         return res;
230     }
231     res = cppu::queryInterface(
232         aType, static_cast< css::util::XChangesNotifier * >(this));
233     if (res.hasValue()) {
234         return res;
235     }
236     if (!res.hasValue() && update_) {
237         res = cppu::queryInterface(
238             aType, static_cast< css::util::XChangesBatch * >(this));
239     }
240     return res;
241 }
242 
addChangesListener(css::uno::Reference<css::util::XChangesListener> const & aListener)243 void RootAccess::addChangesListener(
244     css::uno::Reference< css::util::XChangesListener > const & aListener)
245     throw (css::uno::RuntimeException)
246 {
247     OSL_ASSERT(thisIs(IS_ANY));
248     {
249         osl::MutexGuard g(lock);
250         checkLocalizedPropertyAccess();
251         if (!aListener.is()) {
252             throw css::uno::RuntimeException(
253                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
254                 static_cast< cppu::OWeakObject * >(this));
255         }
256         if (!isDisposed()) {
257             changesListeners_.insert(aListener);
258             return;
259         }
260     }
261     try {
262         aListener->disposing(
263             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
264     } catch (css::lang::DisposedException &) {}
265 }
266 
removeChangesListener(css::uno::Reference<css::util::XChangesListener> const & aListener)267 void RootAccess::removeChangesListener(
268     css::uno::Reference< css::util::XChangesListener > const & aListener)
269     throw (css::uno::RuntimeException)
270 {
271     OSL_ASSERT(thisIs(IS_ANY));
272     osl::MutexGuard g(lock);
273     checkLocalizedPropertyAccess();
274     ChangesListeners::iterator i(changesListeners_.find(aListener));
275     if (i != changesListeners_.end()) {
276         changesListeners_.erase(i);
277     }
278 }
279 
commitChanges()280 void RootAccess::commitChanges()
281     throw (css::lang::WrappedTargetException, css::uno::RuntimeException)
282 {
283     OSL_ASSERT(thisIs(IS_UPDATE));
284     Broadcaster bc;
285     {
286         osl::MutexGuard g(lock);
287         checkLocalizedPropertyAccess();
288         int finalizedLayer;
289         Modifications globalMods;
290         commitChildChanges(
291             ((getComponents().resolvePathRepresentation(
292                   pathRepresentation_, 0, 0, &finalizedLayer)
293               == node_) &&
294              finalizedLayer == Data::NO_LAYER),
295             &globalMods);
296         getComponents().writeModifications();
297         getComponents().initGlobalBroadcaster(globalMods, this, &bc);
298     }
299     bc.send();
300 }
301 
hasPendingChanges()302 sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) {
303     OSL_ASSERT(thisIs(IS_UPDATE));
304     osl::MutexGuard g(lock);
305     checkLocalizedPropertyAccess();
306     //TODO: Optimize:
307     std::vector< css::util::ElementChange > changes;
308     reportChildChanges(&changes);
309     return !changes.empty();
310 }
311 
getPendingChanges()312 css::util::ChangesSet RootAccess::getPendingChanges()
313     throw (css::uno::RuntimeException)
314 {
315     OSL_ASSERT(thisIs(IS_UPDATE));
316     osl::MutexGuard g(lock);
317     checkLocalizedPropertyAccess();
318     comphelper::SequenceAsVector< css::util::ElementChange > changes;
319     reportChildChanges(&changes);
320     return changes.getAsConstList();
321 }
322 
323 }
324