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/container/XChild.hpp>
26 : #include <com/sun/star/lang/NoSupportException.hpp>
27 : #include <com/sun/star/lang/XUnoTunnel.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/Sequence.hxx>
32 : #include <com/sun/star/uno/Type.hxx>
33 : #include <com/sun/star/uno/XInterface.hpp>
34 : #include <cppu/unotype.hxx>
35 : #include <cppuhelper/queryinterface.hxx>
36 : #include <cppuhelper/weak.hxx>
37 : #include <comphelper/servicehelper.hxx>
38 : #include <osl/mutex.hxx>
39 : #include <rtl/ref.hxx>
40 : #include <rtl/string.h>
41 : #include <rtl/ustrbuf.hxx>
42 : #include <rtl/ustring.h>
43 : #include <rtl/ustring.hxx>
44 : #include <sal/types.h>
45 :
46 : #include "access.hxx"
47 : #include "childaccess.hxx"
48 : #include "components.hxx"
49 : #include "data.hxx"
50 : #include "groupnode.hxx"
51 : #include "localizedpropertynode.hxx"
52 : #include "localizedvaluenode.hxx"
53 : #include "lock.hxx"
54 : #include "modifications.hxx"
55 : #include "node.hxx"
56 : #include "path.hxx"
57 : #include "propertynode.hxx"
58 : #include "rootaccess.hxx"
59 : #include "setnode.hxx"
60 : #include "type.hxx"
61 :
62 : namespace configmgr {
63 :
64 : namespace
65 : {
66 : class theChildAccessUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theChildAccessUnoTunnelId > {};
67 : }
68 :
69 6242 : css::uno::Sequence< sal_Int8 > ChildAccess::getTunnelId()
70 : {
71 6242 : return theChildAccessUnoTunnelId::get().getSeq();
72 : }
73 :
74 61508222 : ChildAccess::ChildAccess(
75 : Components & components, rtl::Reference< RootAccess > const & root,
76 : rtl::Reference< Access > const & parent, OUString const & name,
77 : rtl::Reference< Node > const & node):
78 : Access(components), root_(root), parent_(parent), name_(name), node_(node),
79 61508222 : inTransaction_(false)
80 : {
81 61508222 : lock_ = lock();
82 : assert(root.is() && parent.is() && node.is());
83 61508222 : }
84 :
85 3121 : ChildAccess::ChildAccess(
86 : Components & components, rtl::Reference< RootAccess > const & root,
87 : rtl::Reference< Node > const & node):
88 3121 : Access(components), root_(root), node_(node), inTransaction_(false)
89 : {
90 3121 : lock_ = lock();
91 : assert(root.is() && node.is());
92 3121 : }
93 :
94 635910 : Path ChildAccess::getAbsolutePath() {
95 635910 : rtl::Reference< Access > parent(getParentAccess());
96 : assert(parent.is());
97 635910 : Path path(parent->getAbsolutePath());
98 635910 : path.push_back(name_);
99 635910 : return path;
100 : }
101 :
102 383358 : Path ChildAccess::getRelativePath() {
103 383358 : Path path;
104 766716 : rtl::Reference< Access > parent(getParentAccess());
105 383358 : if (parent.is()) {
106 383358 : path = parent->getRelativePath();
107 : }
108 383358 : path.push_back(name_);
109 766716 : return path;
110 : }
111 :
112 21820 : OUString ChildAccess::getRelativePathRepresentation() {
113 21820 : OUStringBuffer path;
114 43640 : rtl::Reference< Access > parent(getParentAccess());
115 21820 : if (parent.is()) {
116 21820 : path.append(parent->getRelativePathRepresentation());
117 21820 : if (!path.isEmpty()) {
118 11616 : path.append('/');
119 : }
120 : }
121 21820 : path.append(Data::createSegment(node_->getTemplateName(), name_));
122 43640 : return path.makeStringAndClear();
123 : }
124 :
125 270098554 : rtl::Reference< Node > ChildAccess::getNode() {
126 270098554 : return node_;
127 : }
128 :
129 1061988 : bool ChildAccess::isFinalized() {
130 2123976 : return node_->getFinalized() != Data::NO_LAYER ||
131 3185964 : (parent_.is() && parent_->isFinalized());
132 : }
133 :
134 2194062 : OUString ChildAccess::getNameInternal() {
135 2194062 : return name_;
136 : }
137 :
138 34080791 : rtl::Reference< RootAccess > ChildAccess::getRootAccess() {
139 34080791 : return root_;
140 : }
141 :
142 2362886 : rtl::Reference< Access > ChildAccess::getParentAccess() {
143 2362886 : return parent_;
144 : }
145 :
146 628200161 : void ChildAccess::acquire() throw () {
147 628200161 : Access::acquire();
148 628200161 : }
149 :
150 628199805 : void ChildAccess::release() throw () {
151 628199805 : Access::release();
152 628199805 : }
153 :
154 0 : css::uno::Reference< css::uno::XInterface > ChildAccess::getParent()
155 : throw (css::uno::RuntimeException, std::exception)
156 : {
157 : assert(thisIs(IS_ANY));
158 0 : osl::MutexGuard g(*lock_);
159 0 : checkLocalizedPropertyAccess();
160 0 : return static_cast< cppu::OWeakObject * >(parent_.get());
161 : }
162 :
163 0 : void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &)
164 : throw (css::lang::NoSupportException, css::uno::RuntimeException, std::exception)
165 : {
166 : assert(thisIs(IS_ANY));
167 0 : osl::MutexGuard g(*lock_);
168 0 : checkLocalizedPropertyAccess();
169 : throw css::lang::NoSupportException(
170 0 : "setParent", static_cast< cppu::OWeakObject * >(this));
171 : }
172 :
173 3121 : sal_Int64 ChildAccess::getSomething(
174 : css::uno::Sequence< sal_Int8 > const & aIdentifier)
175 : throw (css::uno::RuntimeException, std::exception)
176 : {
177 : assert(thisIs(IS_ANY));
178 3121 : osl::MutexGuard g(*lock_);
179 3121 : checkLocalizedPropertyAccess();
180 6242 : return aIdentifier == getTunnelId()
181 6242 : ? reinterpret_cast< sal_Int64 >(this) : 0;
182 : }
183 :
184 3122 : void ChildAccess::bind(
185 : rtl::Reference< RootAccess > const & root,
186 : rtl::Reference< Access > const & parent, OUString const & name)
187 : throw ()
188 : {
189 : assert(!parent_.is() && root.is() && parent.is() && !name.isEmpty());
190 3122 : root_ = root;
191 3122 : parent_ = parent;
192 3122 : name_ = name;
193 3122 : }
194 :
195 1360 : void ChildAccess::unbind() throw () {
196 : assert(parent_.is());
197 1360 : parent_->releaseChild(name_);
198 1360 : parent_.clear();
199 1360 : inTransaction_ = true;
200 1360 : }
201 :
202 252632 : void ChildAccess::committed() {
203 252632 : inTransaction_ = false;
204 252632 : }
205 :
206 83042 : void ChildAccess::setNode(rtl::Reference< Node > const & node) {
207 83042 : node_ = node;
208 83042 : }
209 :
210 110140 : void ChildAccess::setProperty(
211 : css::uno::Any const & value, Modifications * localModifications)
212 : {
213 : assert(localModifications != 0);
214 110140 : Type type = TYPE_ERROR;
215 110140 : bool nillable = false;
216 110140 : switch (node_->kind()) {
217 : case Node::KIND_PROPERTY:
218 : {
219 106372 : PropertyNode * prop = static_cast< PropertyNode * >(node_.get());
220 106372 : type = prop->getStaticType();
221 106372 : nillable = prop->isNillable();
222 : }
223 106372 : break;
224 : case Node::KIND_LOCALIZED_PROPERTY:
225 : {
226 1884 : OUString locale(getRootAccess()->getLocale());
227 1884 : if (!Components::allLocales(locale)) {
228 1884 : rtl::Reference< ChildAccess > child(getChild(locale));
229 1884 : if (child.is()) {
230 1884 : child->setProperty(value, localModifications);
231 : } else {
232 : insertLocalizedValueChild(
233 0 : locale, value, localModifications);
234 : }
235 112021 : return;
236 0 : }
237 : }
238 0 : break;
239 : case Node::KIND_LOCALIZED_VALUE:
240 : {
241 : LocalizedPropertyNode * locprop =
242 1884 : static_cast< LocalizedPropertyNode * >(getParentNode().get());
243 1884 : type = locprop->getStaticType();
244 1884 : nillable = locprop->isNillable();
245 : }
246 1884 : break;
247 : default:
248 0 : break;
249 : }
250 108256 : checkValue(value, type, nillable);
251 108253 : getParentAccess()->markChildAsModified(this);
252 108253 : changedValue_.reset(new css::uno::Any(value));
253 108253 : localModifications->add(getRelativePath());
254 : }
255 :
256 :
257 55559687 : css::uno::Any ChildAccess::asValue()
258 : {
259 55559687 : if (changedValue_.get() != 0) {
260 3491 : return *changedValue_;
261 : }
262 55556196 : css::uno::Any value;
263 55556196 : if (!asSimpleValue(node_, value, getComponents()))
264 : {
265 54385308 : if (node_->kind() == Node::KIND_LOCALIZED_PROPERTY)
266 : {
267 300419 : OUString locale(getRootAccess()->getLocale());
268 300419 : if (!Components::allLocales(locale)) {
269 187558 : rtl::Reference< ChildAccess > child(getChild("*" + locale));
270 : // As a last resort, return a nil value even though it may be
271 : // illegal for the given property:
272 187558 : if (child.is())
273 126579 : return child->asValue();
274 173840 : }
275 : }
276 108517458 : value = css::uno::makeAny(
277 : css::uno::Reference< css::uno::XInterface >(
278 54258729 : static_cast< cppu::OWeakObject * >(this)));
279 : }
280 55429617 : return value;
281 : }
282 :
283 : /// Can we quickly extract a simple value into value ? if so returns true
284 111437486 : bool ChildAccess::asSimpleValue(const rtl::Reference< Node > &rNode,
285 : css::uno::Any &value,
286 : Components &components)
287 : {
288 111437486 : switch (rNode->kind()) {
289 : case Node::KIND_PROPERTY:
290 2570879 : value = static_cast< PropertyNode * >(rNode.get())->getValue(components);
291 2570879 : return true;
292 : case Node::KIND_LOCALIZED_VALUE:
293 230865 : value = static_cast< LocalizedValueNode * >(rNode.get())->getValue();
294 230865 : return true;
295 : default:
296 108635742 : return false;
297 : }
298 : }
299 :
300 251273 : void ChildAccess::commitChanges(bool valid, Modifications * globalModifications)
301 : {
302 : assert(globalModifications != 0);
303 251273 : commitChildChanges(valid, globalModifications);
304 251273 : if (valid && changedValue_.get() != 0) {
305 108253 : Path path(getAbsolutePath());
306 108253 : getComponents().addModification(path);
307 108253 : globalModifications->add(path);
308 108253 : switch (node_->kind()) {
309 : case Node::KIND_PROPERTY:
310 106369 : static_cast< PropertyNode * >(node_.get())->setValue(
311 212738 : Data::NO_LAYER, *changedValue_);
312 106369 : break;
313 : case Node::KIND_LOCALIZED_VALUE:
314 1884 : static_cast< LocalizedValueNode * >(node_.get())->setValue(
315 3768 : Data::NO_LAYER, *changedValue_);
316 1884 : break;
317 : default:
318 : assert(false); // this cannot happen
319 0 : break;
320 108253 : }
321 : }
322 251273 : changedValue_.reset();
323 251273 : }
324 :
325 184532961 : ChildAccess::~ChildAccess() {
326 61510987 : osl::MutexGuard g(*lock_);
327 61510987 : if (parent_.is()) {
328 61509628 : parent_->releaseChild(name_);
329 61510987 : }
330 123021974 : }
331 :
332 0 : void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const {
333 : assert(types != 0);
334 0 : types->push_back(cppu::UnoType< css::container::XChild >::get());
335 0 : types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get());
336 0 : }
337 :
338 9104 : void ChildAccess::addSupportedServiceNames(
339 : std::vector< OUString > * services)
340 : {
341 : assert(services != 0);
342 : services->push_back(
343 18208 : getParentNode()->kind() == Node::KIND_GROUP
344 : ? OUString("com.sun.star.configuration.GroupElement")
345 9104 : : OUString("com.sun.star.configuration.SetElement"));
346 9104 : }
347 :
348 54344031 : css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType)
349 : throw (css::uno::RuntimeException, std::exception)
350 : {
351 : assert(thisIs(IS_ANY));
352 54344031 : osl::MutexGuard g(*lock_);
353 54344031 : checkLocalizedPropertyAccess();
354 108688062 : css::uno::Any res(Access::queryInterface(aType));
355 54344031 : return res.hasValue()
356 : ? res
357 : : cppu::queryInterface(
358 : aType, static_cast< css::container::XChild * >(this),
359 108688062 : static_cast< css::lang::XUnoTunnel * >(this));
360 : }
361 :
362 : }
363 :
364 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|