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