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