1*3a7cf181SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*3a7cf181SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*3a7cf181SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*3a7cf181SAndrew Rist * distributed with this work for additional information 6*3a7cf181SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*3a7cf181SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*3a7cf181SAndrew Rist * "License"); you may not use this file except in compliance 9*3a7cf181SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*3a7cf181SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*3a7cf181SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*3a7cf181SAndrew Rist * software distributed under the License is distributed on an 15*3a7cf181SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*3a7cf181SAndrew Rist * KIND, either express or implied. See the License for the 17*3a7cf181SAndrew Rist * specific language governing permissions and limitations 18*3a7cf181SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*3a7cf181SAndrew Rist *************************************************************/ 21*3a7cf181SAndrew Rist 22*3a7cf181SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "precompiled_configmgr.hxx" 25cdf0e10cSrcweir #include "sal/config.h" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <vector> 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include "com/sun/star/container/XChild.hpp" 30cdf0e10cSrcweir #include "com/sun/star/lang/NoSupportException.hpp" 31cdf0e10cSrcweir #include "com/sun/star/lang/XUnoTunnel.hpp" 32cdf0e10cSrcweir #include "com/sun/star/uno/Any.hxx" 33cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx" 34cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp" 35cdf0e10cSrcweir #include "com/sun/star/uno/Sequence.hxx" 36cdf0e10cSrcweir #include "com/sun/star/uno/Type.hxx" 37cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp" 38cdf0e10cSrcweir #include "cppu/unotype.hxx" 39cdf0e10cSrcweir #include "cppuhelper/queryinterface.hxx" 40cdf0e10cSrcweir #include "cppuhelper/weak.hxx" 41cdf0e10cSrcweir #include "osl/diagnose.h" 42cdf0e10cSrcweir #include "osl/mutex.hxx" 43cdf0e10cSrcweir #include "rtl/ref.hxx" 44cdf0e10cSrcweir #include "rtl/string.h" 45cdf0e10cSrcweir #include "rtl/ustrbuf.hxx" 46cdf0e10cSrcweir #include "rtl/ustring.h" 47cdf0e10cSrcweir #include "rtl/ustring.hxx" 48cdf0e10cSrcweir #include "rtl/uuid.h" 49cdf0e10cSrcweir #include "sal/types.h" 50cdf0e10cSrcweir 51cdf0e10cSrcweir #include "access.hxx" 52cdf0e10cSrcweir #include "childaccess.hxx" 53cdf0e10cSrcweir #include "components.hxx" 54cdf0e10cSrcweir #include "data.hxx" 55cdf0e10cSrcweir #include "groupnode.hxx" 56cdf0e10cSrcweir #include "localizedpropertynode.hxx" 57cdf0e10cSrcweir #include "localizedvaluenode.hxx" 58cdf0e10cSrcweir #include "lock.hxx" 59cdf0e10cSrcweir #include "modifications.hxx" 60cdf0e10cSrcweir #include "node.hxx" 61cdf0e10cSrcweir #include "path.hxx" 62cdf0e10cSrcweir #include "propertynode.hxx" 63cdf0e10cSrcweir #include "rootaccess.hxx" 64cdf0e10cSrcweir #include "setnode.hxx" 65cdf0e10cSrcweir #include "type.hxx" 66cdf0e10cSrcweir 67cdf0e10cSrcweir namespace configmgr { 68cdf0e10cSrcweir 69cdf0e10cSrcweir namespace { 70cdf0e10cSrcweir 71cdf0e10cSrcweir namespace css = com::sun::star; 72cdf0e10cSrcweir 73cdf0e10cSrcweir } 74cdf0e10cSrcweir 75cdf0e10cSrcweir css::uno::Sequence< sal_Int8 > ChildAccess::getTunnelId() { 76cdf0e10cSrcweir static css::uno::Sequence< sal_Int8 > id; 77cdf0e10cSrcweir if (id.getLength() == 0) { 78cdf0e10cSrcweir css::uno::Sequence< sal_Int8 > uuid(16); 79cdf0e10cSrcweir rtl_createUuid( 80cdf0e10cSrcweir reinterpret_cast< sal_uInt8 * >(uuid.getArray()), 0, false); 81cdf0e10cSrcweir id = uuid; 82cdf0e10cSrcweir } 83cdf0e10cSrcweir return id; 84cdf0e10cSrcweir } 85cdf0e10cSrcweir 86cdf0e10cSrcweir ChildAccess::ChildAccess( 87cdf0e10cSrcweir Components & components, rtl::Reference< RootAccess > const & root, 88cdf0e10cSrcweir rtl::Reference< Access > const & parent, rtl::OUString const & name, 89cdf0e10cSrcweir rtl::Reference< Node > const & node): 90cdf0e10cSrcweir Access(components), root_(root), parent_(parent), name_(name), node_(node), 91cdf0e10cSrcweir inTransaction_(false) 92cdf0e10cSrcweir { 93cdf0e10cSrcweir OSL_ASSERT(root.is() && parent.is() && node.is()); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir 96cdf0e10cSrcweir ChildAccess::ChildAccess( 97cdf0e10cSrcweir Components & components, rtl::Reference< RootAccess > const & root, 98cdf0e10cSrcweir rtl::Reference< Node > const & node): 99cdf0e10cSrcweir Access(components), root_(root), node_(node), inTransaction_(false) 100cdf0e10cSrcweir { 101cdf0e10cSrcweir OSL_ASSERT(root.is() && node.is()); 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir Path ChildAccess::getAbsolutePath() { 105cdf0e10cSrcweir OSL_ASSERT(getParentAccess().is()); 106cdf0e10cSrcweir Path path(getParentAccess()->getAbsolutePath()); 107cdf0e10cSrcweir path.push_back(name_); 108cdf0e10cSrcweir return path; 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir Path ChildAccess::getRelativePath() { 112cdf0e10cSrcweir Path path; 113cdf0e10cSrcweir rtl::Reference< Access > parent(getParentAccess()); 114cdf0e10cSrcweir if (parent.is()) { 115cdf0e10cSrcweir path = parent->getRelativePath(); 116cdf0e10cSrcweir } 117cdf0e10cSrcweir path.push_back(name_); 118cdf0e10cSrcweir return path; 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir rtl::OUString ChildAccess::getRelativePathRepresentation() { 122cdf0e10cSrcweir rtl::OUStringBuffer path; 123cdf0e10cSrcweir rtl::Reference< Access > parent(getParentAccess()); 124cdf0e10cSrcweir if (parent.is()) { 125cdf0e10cSrcweir path.append(parent->getRelativePathRepresentation()); 126cdf0e10cSrcweir if (path.getLength() != 0) { 127cdf0e10cSrcweir path.append(sal_Unicode('/')); 128cdf0e10cSrcweir } 129cdf0e10cSrcweir } 130cdf0e10cSrcweir path.append(Data::createSegment(node_->getTemplateName(), name_)); 131cdf0e10cSrcweir return path.makeStringAndClear(); 132cdf0e10cSrcweir } 133cdf0e10cSrcweir 134cdf0e10cSrcweir rtl::Reference< Node > ChildAccess::getNode() { 135cdf0e10cSrcweir return node_; 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir bool ChildAccess::isFinalized() { 139cdf0e10cSrcweir return node_->getFinalized() != Data::NO_LAYER || 140cdf0e10cSrcweir (parent_.is() && parent_->isFinalized()); 141cdf0e10cSrcweir } 142cdf0e10cSrcweir 143cdf0e10cSrcweir rtl::OUString ChildAccess::getNameInternal() { 144cdf0e10cSrcweir return name_; 145cdf0e10cSrcweir } 146cdf0e10cSrcweir 147cdf0e10cSrcweir rtl::Reference< RootAccess > ChildAccess::getRootAccess() { 148cdf0e10cSrcweir return root_; 149cdf0e10cSrcweir } 150cdf0e10cSrcweir 151cdf0e10cSrcweir rtl::Reference< Access > ChildAccess::getParentAccess() { 152cdf0e10cSrcweir return parent_; 153cdf0e10cSrcweir } 154cdf0e10cSrcweir 155cdf0e10cSrcweir void ChildAccess::acquire() throw () { 156cdf0e10cSrcweir Access::acquire(); 157cdf0e10cSrcweir } 158cdf0e10cSrcweir 159cdf0e10cSrcweir void ChildAccess::release() throw () { 160cdf0e10cSrcweir Access::release(); 161cdf0e10cSrcweir } 162cdf0e10cSrcweir 163cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > ChildAccess::getParent() 164cdf0e10cSrcweir throw (css::uno::RuntimeException) 165cdf0e10cSrcweir { 166cdf0e10cSrcweir OSL_ASSERT(thisIs(IS_ANY)); 167cdf0e10cSrcweir osl::MutexGuard g(lock); 168cdf0e10cSrcweir checkLocalizedPropertyAccess(); 169cdf0e10cSrcweir return static_cast< cppu::OWeakObject * >(parent_.get()); 170cdf0e10cSrcweir } 171cdf0e10cSrcweir 172cdf0e10cSrcweir void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &) 173cdf0e10cSrcweir throw (css::lang::NoSupportException, css::uno::RuntimeException) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir OSL_ASSERT(thisIs(IS_ANY)); 176cdf0e10cSrcweir osl::MutexGuard g(lock); 177cdf0e10cSrcweir checkLocalizedPropertyAccess(); 178cdf0e10cSrcweir throw css::lang::NoSupportException( 179cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("setParent")), 180cdf0e10cSrcweir static_cast< cppu::OWeakObject * >(this)); 181cdf0e10cSrcweir } 182cdf0e10cSrcweir 183cdf0e10cSrcweir sal_Int64 ChildAccess::getSomething( 184cdf0e10cSrcweir css::uno::Sequence< sal_Int8 > const & aIdentifier) 185cdf0e10cSrcweir throw (css::uno::RuntimeException) 186cdf0e10cSrcweir { 187cdf0e10cSrcweir OSL_ASSERT(thisIs(IS_ANY)); 188cdf0e10cSrcweir osl::MutexGuard g(lock); 189cdf0e10cSrcweir checkLocalizedPropertyAccess(); 190cdf0e10cSrcweir return aIdentifier == getTunnelId() 191cdf0e10cSrcweir ? reinterpret_cast< sal_Int64 >(this) : 0; 192cdf0e10cSrcweir } 193cdf0e10cSrcweir 194cdf0e10cSrcweir void ChildAccess::bind( 195cdf0e10cSrcweir rtl::Reference< RootAccess > const & root, 196cdf0e10cSrcweir rtl::Reference< Access > const & parent, rtl::OUString const & name) 197cdf0e10cSrcweir throw () 198cdf0e10cSrcweir { 199cdf0e10cSrcweir OSL_ASSERT( 200cdf0e10cSrcweir !parent_.is() && root.is() && parent.is() && name.getLength() != 0); 201cdf0e10cSrcweir root_ = root; 202cdf0e10cSrcweir parent_ = parent; 203cdf0e10cSrcweir name_ = name; 204cdf0e10cSrcweir } 205cdf0e10cSrcweir 206cdf0e10cSrcweir void ChildAccess::unbind() throw () { 207cdf0e10cSrcweir OSL_ASSERT(parent_.is()); 208cdf0e10cSrcweir parent_->releaseChild(name_); 209cdf0e10cSrcweir parent_.clear(); 210cdf0e10cSrcweir inTransaction_ = true; 211cdf0e10cSrcweir } 212cdf0e10cSrcweir 213cdf0e10cSrcweir void ChildAccess::committed() { 214cdf0e10cSrcweir inTransaction_ = false; 215cdf0e10cSrcweir } 216cdf0e10cSrcweir 217cdf0e10cSrcweir void ChildAccess::setNode(rtl::Reference< Node > const & node) { 218cdf0e10cSrcweir node_ = node; 219cdf0e10cSrcweir } 220cdf0e10cSrcweir 221cdf0e10cSrcweir void ChildAccess::setProperty( 222cdf0e10cSrcweir css::uno::Any const & value, Modifications * localModifications) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir OSL_ASSERT(localModifications != 0); 225cdf0e10cSrcweir Type type = TYPE_ERROR; 226cdf0e10cSrcweir bool nillable = false; 227cdf0e10cSrcweir switch (node_->kind()) { 228cdf0e10cSrcweir case Node::KIND_PROPERTY: 229cdf0e10cSrcweir { 230cdf0e10cSrcweir PropertyNode * prop = dynamic_cast< PropertyNode * >(node_.get()); 231cdf0e10cSrcweir type = prop->getStaticType(); 232cdf0e10cSrcweir nillable = prop->isNillable(); 233cdf0e10cSrcweir } 234cdf0e10cSrcweir break; 235cdf0e10cSrcweir case Node::KIND_LOCALIZED_PROPERTY: 236cdf0e10cSrcweir { 237cdf0e10cSrcweir rtl::OUString locale(getRootAccess()->getLocale()); 238cdf0e10cSrcweir if (!Components::allLocales(locale)) { 239cdf0e10cSrcweir rtl::Reference< ChildAccess > child(getChild(locale)); 240cdf0e10cSrcweir if (child.is()) { 241cdf0e10cSrcweir child->setProperty(value, localModifications); 242cdf0e10cSrcweir } else { 243cdf0e10cSrcweir insertLocalizedValueChild( 244cdf0e10cSrcweir locale, value, localModifications); 245cdf0e10cSrcweir } 246cdf0e10cSrcweir return; 247cdf0e10cSrcweir } 248cdf0e10cSrcweir } 249cdf0e10cSrcweir break; 250cdf0e10cSrcweir case Node::KIND_LOCALIZED_VALUE: 251cdf0e10cSrcweir { 252cdf0e10cSrcweir LocalizedPropertyNode * locprop = 253cdf0e10cSrcweir dynamic_cast< LocalizedPropertyNode * >(getParentNode().get()); 254cdf0e10cSrcweir type = locprop->getStaticType(); 255cdf0e10cSrcweir nillable = locprop->isNillable(); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir break; 258cdf0e10cSrcweir default: 259cdf0e10cSrcweir break; 260cdf0e10cSrcweir } 261cdf0e10cSrcweir checkValue(value, type, nillable); 262cdf0e10cSrcweir getParentAccess()->markChildAsModified(this); 263cdf0e10cSrcweir changedValue_.reset(new css::uno::Any(value)); 264cdf0e10cSrcweir localModifications->add(getRelativePath()); 265cdf0e10cSrcweir } 266cdf0e10cSrcweir 267cdf0e10cSrcweir css::uno::Any ChildAccess::asValue() { 268cdf0e10cSrcweir if (changedValue_.get() != 0) { 269cdf0e10cSrcweir return *changedValue_; 270cdf0e10cSrcweir } 271cdf0e10cSrcweir switch (node_->kind()) { 272cdf0e10cSrcweir case Node::KIND_PROPERTY: 273cdf0e10cSrcweir return dynamic_cast< PropertyNode * >(node_.get())->getValue( 274cdf0e10cSrcweir getComponents()); 275cdf0e10cSrcweir case Node::KIND_LOCALIZED_PROPERTY: 276cdf0e10cSrcweir { 277cdf0e10cSrcweir rtl::OUString locale(getRootAccess()->getLocale()); 278cdf0e10cSrcweir if (!Components::allLocales(locale)) { 279cdf0e10cSrcweir // Find best match using an adaption of RFC 4647 lookup matching 280cdf0e10cSrcweir // rules, removing "-" or "_" delimited segments from the end; 281cdf0e10cSrcweir // defaults are the "en-US" locale, the "en" locale, the empty 282cdf0e10cSrcweir // string locale, the first child (if any), or a nil value (even 283cdf0e10cSrcweir // though it may be illegal for the given property), in that 284cdf0e10cSrcweir // order: 285cdf0e10cSrcweir rtl::Reference< ChildAccess > child; 286cdf0e10cSrcweir for (;;) { 287cdf0e10cSrcweir child = getChild(locale); 288cdf0e10cSrcweir if (child.is() || locale.getLength() == 0) { 289cdf0e10cSrcweir break; 290cdf0e10cSrcweir } 291cdf0e10cSrcweir sal_Int32 i = locale.getLength() - 1; 292cdf0e10cSrcweir while (i > 0 && locale[i] != '-' && locale[i] != '_') { 293cdf0e10cSrcweir --i; 294cdf0e10cSrcweir } 295cdf0e10cSrcweir if (i == 0) { 296cdf0e10cSrcweir break; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir locale = locale.copy(0, i); 299cdf0e10cSrcweir } 300cdf0e10cSrcweir if (!child.is()) { 301cdf0e10cSrcweir child = getChild( 302cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US"))); 303cdf0e10cSrcweir if (!child.is()) { 304cdf0e10cSrcweir child = getChild( 305cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en"))); 306cdf0e10cSrcweir if (!child.is()) { 307cdf0e10cSrcweir child = getChild(rtl::OUString()); 308cdf0e10cSrcweir if (!child.is()) { 309cdf0e10cSrcweir std::vector< rtl::Reference< ChildAccess > > 310cdf0e10cSrcweir all(getAllChildren()); 311cdf0e10cSrcweir if (!all.empty()) { 312cdf0e10cSrcweir child = all.front(); 313cdf0e10cSrcweir } 314cdf0e10cSrcweir } 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } 317cdf0e10cSrcweir } 318cdf0e10cSrcweir return child.is() ? child->asValue() : css::uno::Any(); 319cdf0e10cSrcweir } 320cdf0e10cSrcweir } 321cdf0e10cSrcweir break; 322cdf0e10cSrcweir case Node::KIND_LOCALIZED_VALUE: 323cdf0e10cSrcweir return dynamic_cast< LocalizedValueNode * >(node_.get())->getValue(); 324cdf0e10cSrcweir default: 325cdf0e10cSrcweir break; 326cdf0e10cSrcweir } 327cdf0e10cSrcweir return css::uno::makeAny( 328cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >( 329cdf0e10cSrcweir static_cast< cppu::OWeakObject * >(this))); 330cdf0e10cSrcweir } 331cdf0e10cSrcweir 332cdf0e10cSrcweir void ChildAccess::commitChanges(bool valid, Modifications * globalModifications) 333cdf0e10cSrcweir { 334cdf0e10cSrcweir OSL_ASSERT(globalModifications != 0); 335cdf0e10cSrcweir commitChildChanges(valid, globalModifications); 336cdf0e10cSrcweir if (valid && changedValue_.get() != 0) { 337cdf0e10cSrcweir Path path(getAbsolutePath()); 338cdf0e10cSrcweir getComponents().addModification(path); 339cdf0e10cSrcweir globalModifications->add(path); 340cdf0e10cSrcweir switch (node_->kind()) { 341cdf0e10cSrcweir case Node::KIND_PROPERTY: 342cdf0e10cSrcweir dynamic_cast< PropertyNode * >(node_.get())->setValue( 343cdf0e10cSrcweir Data::NO_LAYER, *changedValue_); 344cdf0e10cSrcweir break; 345cdf0e10cSrcweir case Node::KIND_LOCALIZED_VALUE: 346cdf0e10cSrcweir dynamic_cast< LocalizedValueNode * >(node_.get())->setValue( 347cdf0e10cSrcweir Data::NO_LAYER, *changedValue_); 348cdf0e10cSrcweir break; 349cdf0e10cSrcweir default: 350cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen 351cdf0e10cSrcweir break; 352cdf0e10cSrcweir } 353cdf0e10cSrcweir } 354cdf0e10cSrcweir changedValue_.reset(); 355cdf0e10cSrcweir } 356cdf0e10cSrcweir 357cdf0e10cSrcweir ChildAccess::~ChildAccess() { 358cdf0e10cSrcweir osl::MutexGuard g(lock); 359cdf0e10cSrcweir if (parent_.is()) { 360cdf0e10cSrcweir parent_->releaseChild(name_); 361cdf0e10cSrcweir } 362cdf0e10cSrcweir } 363cdf0e10cSrcweir 364cdf0e10cSrcweir void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const { 365cdf0e10cSrcweir OSL_ASSERT(types != 0); 366cdf0e10cSrcweir types->push_back(cppu::UnoType< css::container::XChild >::get()); 367cdf0e10cSrcweir types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get()); 368cdf0e10cSrcweir } 369cdf0e10cSrcweir 370cdf0e10cSrcweir void ChildAccess::addSupportedServiceNames( 371cdf0e10cSrcweir std::vector< rtl::OUString > * services) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir OSL_ASSERT(services != 0); 374cdf0e10cSrcweir services->push_back( 375cdf0e10cSrcweir getParentNode()->kind() == Node::KIND_GROUP 376cdf0e10cSrcweir ? rtl::OUString( 377cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 378cdf0e10cSrcweir "com.sun.star.configuration.GroupElement")) 379cdf0e10cSrcweir : rtl::OUString( 380cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 381cdf0e10cSrcweir "com.sun.star.configuration.SetElement"))); 382cdf0e10cSrcweir } 383cdf0e10cSrcweir 384cdf0e10cSrcweir css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType) 385cdf0e10cSrcweir throw (css::uno::RuntimeException) 386cdf0e10cSrcweir { 387cdf0e10cSrcweir OSL_ASSERT(thisIs(IS_ANY)); 388cdf0e10cSrcweir osl::MutexGuard g(lock); 389cdf0e10cSrcweir checkLocalizedPropertyAccess(); 390cdf0e10cSrcweir css::uno::Any res(Access::queryInterface(aType)); 391cdf0e10cSrcweir return res.hasValue() 392cdf0e10cSrcweir ? res 393cdf0e10cSrcweir : cppu::queryInterface( 394cdf0e10cSrcweir aType, static_cast< css::container::XChild * >(this), 395cdf0e10cSrcweir static_cast< css::lang::XUnoTunnel * >(this)); 396cdf0e10cSrcweir } 397cdf0e10cSrcweir 398cdf0e10cSrcweir } 399