1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: elementimpl.cxx,v $
10 * $Revision: 1.17.14.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "elementimpl.hxx"
35 #include "apitreeaccess.hxx"
36 #include "apinodeaccess.hxx"
37 #include "apifactory.hxx"
38 #include "noderef.hxx"
39 #include "nodechange.hxx"
40 #include "nodechangeinfo.hxx"
41 #include "translatechanges.hxx"
42 #include "apitypes.hxx"
43 #include "configset.hxx"
44 #include "confignotifier.hxx"
45 #include "confsvccomponent.hxx"
46 #include "committer.hxx"
47 #include <com/sun/star/lang/DisposedException.hpp>
48 #include <com/sun/star/container/XNameContainer.hpp>
49 #include <com/sun/star/configuration/XTemplateContainer.hpp>
50 #include <osl/diagnose.h>
56 //-----------------------------------------------------------------------------------
57 namespace lang
= css::lang
;
58 namespace util
= css::util
;
60 //-----------------------------------------------------------------------------------
63 //-----------------------------------------------------------------------------------
66 //-----------------------------------------------------------------------------------
68 uno::Reference
< uno::XInterface
> implGetParent(NodeAccess
& rNode
, InnerElement
&) throw(uno::RuntimeException
)
70 uno::Reference
<uno::XInterface
> xRet
;
74 GuardedNodeData
<NodeAccess
> impl( rNode
); // no provider lock needed - tree must be prebuilt already
76 rtl::Reference
< configuration::Tree
> aTree(impl
.getTree());
77 configuration::NodeRef aParentNode
= aTree
->getParent(impl
.getNode());
79 uno::Any aAny
= configapi::makeInnerElement( rNode
.getFactory(), aTree
, aParentNode
);
81 if (!(aAny
>>= xRet
)) // no parent available
83 OSL_ASSERT(!xRet
.is()); // make sure we return NULL
84 OSL_ENSURE(!aAny
.hasValue(), "configmgr: BasicElement::getParent: could not extract parent - node is not an object");
87 catch (configuration::Exception
& ex
)
89 ExceptionMapper
e(ex
);
90 e
.setContext( rNode
.getUnoInstance() );
97 //-----------------------------------------------------------------------------------
99 uno::Reference
< uno::XInterface
> implGetParent(NodeAccess
& rNode
, SetElement
& /*rElement*/) throw(uno::RuntimeException
)
101 uno::Reference
<uno::XInterface
> xRet
;
105 // assume shared lock for connected trees
106 GuardedNodeData
<NodeAccess
> impl( rNode
); // no provider lock needed - tree must be prebuilt already
108 rtl::Reference
< configuration::Tree
> aTree(impl
.getTree());
110 rtl::Reference
< configuration::Tree
> aParentTree( aTree
->getContextTree() );
112 if (!configuration::isEmpty(aParentTree
.get()))
114 configuration::NodeRef
aParentNode( aTree
->getContextNodeRef() );
116 // assume shared factory for connected trees
117 uno::Any aAny
= configapi::makeInnerElement( rNode
.getFactory(), aParentTree
, aParentNode
);
119 if (!(aAny
>>= xRet
)) // no parent available
121 // should occur only if the any is void
122 OSL_ENSURE(!aAny
.hasValue(), "configmgr: BasicSetElement::getParent: could not extract parent - node is not an object");
123 OSL_ASSERT(!xRet
.is()); // make sure we return NULL
128 OSL_ASSERT(!xRet
.is()); // make sure we return NULL
131 catch (configuration::Exception
& ex
)
133 ExceptionMapper
e(ex
);
134 e
.setContext( rNode
.getUnoInstance() );
140 //-----------------------------------------------------------------------------------
142 // UNSUPPORTED method
143 void implSetParent(NodeAccess
& rNode
, InnerElement
& /*rElement*/, const uno::Reference
< uno::XInterface
>& /*xParent*/ )
144 throw(lang::NoSupportException
, uno::RuntimeException
)
148 rNode
.checkAlive(); // Does locking internally, checks for disposed nodes
150 // TODO(?): allow for xParent == getParent()
151 throw lang::NoSupportException(
152 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("configmgr: BasicElement::setParent: cannot move Entry")),
153 rNode
.getUnoInstance() );
155 //-----------------------------------------------------------------------------------
157 // preliminary implementation
158 void implSetParent(NodeAccess
& rNode
, SetElement
& rElement
, const uno::Reference
< uno::XInterface
>& xParent
)
159 throw(lang::NoSupportException
, uno::RuntimeException
)
163 //implSetParent(rNode,xParent);
164 // TODO: lock the whole transaction ???? - would need Uno Tunneling ?
165 uno::Reference
< uno::XInterface
> xGotParent( implGetParent(rNode
,rElement
) );
166 uno::Reference
< css::container::XNameContainer
> xOldParent( xGotParent
, uno::UNO_QUERY
);
167 uno::Reference
< css::container::XNameContainer
> xNewParent( xParent
, uno::UNO_QUERY
);
169 if (xGotParent
.is() && !xOldParent
.is())
171 throw lang::NoSupportException(
172 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: this is not element of a container")),
173 rNode
.getUnoInstance() );
175 if (xParent
.is() && !xNewParent
.is())
177 throw lang::NoSupportException(
178 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: new parent is no container")),
179 rNode
.getUnoInstance() );
182 uno::Reference
< uno::XInterface
> xThis(rNode
.getUnoInstance());
183 OSL_ASSERT(xThis
.is());
185 if (xOldParent
!= xNewParent
)
187 rtl::OUString
const sName( implGetName(rNode
,rElement
) );
191 rtl::OUString
const sTemplate( implGetTemplateName(rElement
) );
193 if (sTemplate
.getLength() == 0)
195 throw lang::NoSupportException(
196 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: object has no recognizable type")),
200 uno::Reference
< css::configuration::XTemplateContainer
> xNewTemplate( xParent
, uno::UNO_QUERY
);
201 if (!xNewTemplate
.is())
203 throw lang::NoSupportException(
204 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: new parent has no element template")),
208 if ( sTemplate
!= xNewTemplate
->getElementTemplateName())
210 throw lang::NoSupportException(
211 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: object has wrong type")),
215 if ( xNewParent
->hasByName( sName
) )
217 throw lang::NoSupportException(
218 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: an object of this name already exists in new parent")),
222 // TODO: check for circularity (i.e. that This is not one of new parent's ancestors) !!
229 if ( xOldParent
.is()) xOldParent
->removeByName(sName
);
230 if ( xNewParent
.is()) xNewParent
->insertByName(sName
, uno::makeAny(xThis
));
232 catch (uno::Exception
& e
)
234 e
.Message
= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Config API: implSetParent: changing parent failed: "))
240 xOldParent
->insertByName(sName
, uno::makeAny(xThis
));
242 catch(uno::Exception
& bad
)
244 e
.Message
+= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\n\t ! Could not restore old parent: ")) += bad
.Message
;
247 throw uno::RuntimeException(e
.Message
,xThis
);
252 //-----------------------------------------------------------------------------
256 //-----------------------------------------------------------------------------
257 rtl::OUString
implGetName(NodeAccess
& rNode
, NodeElement
& ) throw(uno::RuntimeException
)
262 GuardedNodeData
<NodeAccess
> impl( rNode
); // maybe passive only ?
264 rtl::Reference
< configuration::Tree
> aTree(impl
.getTree());
265 configuration::NodeRef
aNode(impl
.getNode());
267 sRet
= aTree
->getSimpleNodeName(aNode
.getOffset());
269 catch (configuration::Exception
& ex
)
271 ExceptionMapper
e(ex
);
272 e
.setContext( rNode
.getUnoInstance() );
278 //-----------------------------------------------------------------------------
280 // UNSUPPORTED method
281 void implSetName(NodeAccess
& rNode
, NodeElement
& /*rElement*/, const rtl::OUString
& /*aName*/ ) throw(uno::RuntimeException
)
285 rNode
.checkAlive(); // Does locking internally, checks for disposed nodes
287 // TODO(?): allow for aName == getName()
288 throw uno::RuntimeException(
289 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("configmgr: BasicElement::setName: cannot rename Entry")),
290 rNode
.getUnoInstance() );
292 //-----------------------------------------------------------------------------
294 // TODO: Implementations for elements to be added to a container node
295 void implSetName(NodeAccess
& rNode
, SetElement
& rElement
, const rtl::OUString
& aName
) throw(uno::RuntimeException
)
300 NodeElement
& rDelegate
= rElement
;
301 implSetName(rNode
,rDelegate
,aName
); // delegate to unsupported version
303 //-----------------------------------------------------------------------------
305 // XComponent & XInterface
306 //-----------------------------------------------------------------------------
308 //-----------------------------------------------------------------------------
310 void implDispose( SetElement
& rElement
) throw(uno::RuntimeException
)
314 if (!rElement
.disposeTree(false))
316 throw uno::RuntimeException(
317 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONFIGURATION: Can't dispose an object that has an owner")),
318 rElement
.getUnoInstance() );
321 //-----------------------------------------------------------------------------
323 void implDispose( RootElement
& rElement
) throw(uno::RuntimeException
)
327 if (!rElement
.disposeTree())
329 throw lang::DisposedException(
330 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONFIGURATION: Can't dispose an object that already was disposed")),
331 rElement
.getUnoInstance() );
334 //-----------------------------------------------------------------------------
336 void implDisposeObject( NodeAccess
& ,SetElement
& rElement
) throw(uno::RuntimeException
)
339 // FIXME: should we hold a ref on the element over this ?
340 // call apitreeaccess.hxx (doGetUnoInterface) & hold a ref / unref ?
341 // [or!] - call getApiTree & ref/unref on that ?
342 // [or!] - hold the ref inside the dispose method itself ...
343 rElement
.disposeTree(true);
345 //-----------------------------------------------------------------------------
347 void implDisposeObject( NodeAccess
& , RootElement
& rElement
) throw(uno::RuntimeException
)
351 rElement
.disposeTree();
353 //-----------------------------------------------------------------------------
355 void implDisposeObject( NodeAccess
& rNode
, InnerElement
& ) throw(uno::RuntimeException
)
361 //-----------------------------------------------------------------------------
365 //-----------------------------------------------------------------------------
367 uno::Sequence
<sal_Int8
> implGetImplementationId(NodeAccess
& rNode
, NodeElement
& rElement
)
368 throw(uno::RuntimeException
)
370 DisposeGuard
aLock(rNode
);
371 ServiceImplementationInfo
const* pInfo
= rElement
.getServiceInfo();
373 OSL_ENSURE(pInfo
, "Configuration: Object has no implementation (service) info - cannot get implementation id");
375 throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONFIGURATION: Object has no implementation information - cannot get implementation id")),rElement
.getUnoInstance() );
377 return ServiceComponentImpl::getStaticImplementationId(pInfo
);
379 //-----------------------------------------------------------------------------
382 //-----------------------------------------------------------------------------
384 rtl::OUString
implGetImplementationName( NodeAccess
& rNode
, NodeElement
& rElement
) throw(uno::RuntimeException
)
386 DisposeGuard
aLock(rNode
);
387 ServiceImplementationInfo
const* pInfo
= rElement
.getServiceInfo();
388 OSL_ENSURE(pInfo
, "Configuration: Object has no service info");
390 return ServiceInfoHelper(pInfo
).getImplementationName();
392 //-----------------------------------------------------------------------------
394 sal_Bool
implSupportsService( NodeAccess
& rNode
, NodeElement
& rElement
, const rtl::OUString
& ServiceName
) throw(uno::RuntimeException
)
396 DisposeGuard
aLock(rNode
);
397 ServiceImplementationInfo
const* pInfo
= rElement
.getServiceInfo();
398 OSL_ENSURE(pInfo
, "Configuration: Object has no service info");
400 return ServiceInfoHelper(pInfo
).supportsService(ServiceName
);
402 //-----------------------------------------------------------------------------
404 uno::Sequence
< rtl::OUString
> implGetSupportedServiceNames( NodeAccess
& rNode
, NodeElement
& rElement
) throw(uno::RuntimeException
)
406 DisposeGuard
aLock(rNode
);
407 ServiceImplementationInfo
const* pInfo
= rElement
.getServiceInfo();
408 OSL_ENSURE(pInfo
, "Configuration: Object has no service info");
410 return ServiceInfoHelper(pInfo
).getSupportedServiceNames();
412 //-----------------------------------------------------------------------------
414 // Root only ------------------------------------------------------------------
417 // TODO: Implement locale support
418 //-----------------------------------------------------------------------------
420 lang::Locale
implGetLocale( RootElement
& rElement
) throw(uno::RuntimeException
)
422 GuardedRootElement
aLocked(rElement
);
424 OSL_ENSURE(false,"CONFIGURATION: Locale information is not yetsupported.");
425 return lang::Locale();
427 //-----------------------------------------------------------------------------
429 void implSetLocale( RootElement
& rElement
, const css::lang::Locale
& /*eLocale*/ ) throw(uno::RuntimeException
)
432 // TODO: Implement if possible
433 rElement
.checkAlive();
435 OSL_ENSURE(false,"CONFIGURATION: Changing the set Locale is not supported.");
436 throw uno::RuntimeException(
437 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONFIGURATION: Changing the locale is currently not supported")),
438 rElement
.getUnoInstance()
441 //-----------------------------------------------------------------------------
444 //-----------------------------------------------------------------------------
446 void implCommitChanges( UpdateRootElement
& rElement
) throw(css::lang::WrappedTargetException
, uno::RuntimeException
)
450 // quick check to avoid big locks for nothing (has its own locking)
451 if (!implHasPendingChanges(rElement
)) return;
455 rElement
.getCommitter().commit();
458 catch (configuration::Exception
& ex
)
460 ExceptionMapper
e(ex
);
461 e
.setContext( rElement
.getUnoInstance() );
465 // filter/wrap uno::Exceptions
466 catch (lang::WrappedTargetException
& ) { throw; }
467 catch (uno::RuntimeException
& ) { throw; }
468 catch (uno::Exception
& ex
)
470 uno::Reference
<uno::XInterface
> xContext( rElement
.getUnoInstance() );
471 rtl::OUString
sMessage( RTL_CONSTASCII_USTRINGPARAM("Configuration: can't commit Changes: ") );
472 throw lang::WrappedTargetException( sMessage
+= ex
.Message
, xContext
, uno::makeAny(ex
));
475 //-----------------------------------------------------------------------------
477 sal_Bool
implHasPendingChanges( RootElement
& rElement
) throw(uno::RuntimeException
)
481 GuardedRootElement
aLocked(rElement
);
482 return aLocked
.get().getTree()->hasChanges();
484 catch (configuration::Exception
& ex
)
486 ExceptionMapper
e(ex
);
487 e
.setContext( rElement
.getUnoInstance() );
491 OSL_ENSURE(false,"Unreachable Code");
494 //-----------------------------------------------------------------------------
496 uno::Sequence
< css::util::ElementChange
> implGetPendingChanges( RootElement
& rElement
)
497 throw(uno::RuntimeException
)
499 std::vector
<css::util::ElementChange
> aResult
;
502 GuardedRootElement
aLocked(rElement
);
504 rtl::Reference
< configuration::Tree
> aTree( aLocked
.get().getTree() );
506 configuration::NodeChangesInformation aInfos
;
509 configuration::NodeChanges aChanges
;
510 if (aTree
->collectChanges(aChanges
))
512 aChanges
.getChangesInfos(aInfos
);
516 Factory
& rFactory
= rElement
.getFactory();
518 for(std::vector
< configuration::NodeChangeInformation
>::const_iterator it
= aInfos
.begin(), stop
= aInfos
.end();
522 css::util::ElementChange aChange
;
523 fillChange(aChange
,*it
,aTree
,rFactory
);
524 aResult
.push_back(aChange
);
527 catch (configuration::Exception
& ex
)
529 ExceptionMapper
e(ex
);
530 e
.setContext( rElement
.getUnoInstance() );
534 return makeSequence(aResult
);
536 //-----------------------------------------------------------------------------
538 // Set only -------------------------------------------------------------------------
541 //-----------------------------------------------------------------------------------
543 rtl::OUString
implGetTemplateName(SetElement
& rElement
)
544 throw(uno::RuntimeException
)
548 GuardedTreeElement
aLocked(rElement
);
549 return rElement
.getTemplateInfo()->getPathString();
551 catch (configuration::Exception
& ex
)
553 ExceptionMapper
e(ex
);
554 e
.setContext( rElement
.getUnoInstance() );
558 OSL_ENSURE(false,"Unreachable Code");
559 return rtl::OUString();
561 //-----------------------------------------------------------------------------------
564 //-----------------------------------------------------------------------------------
565 sal_Int64
implGetSomething(SetElement
& rElement
, const uno::Sequence
< sal_Int8
>& aIdentifier
)
566 throw(uno::RuntimeException
)
568 sal_Int64 nSomething
= 0;
571 GuardedTreeElement
aLocked(rElement
);
573 if (!rElement
.getFactory().tunnelSetElement(nSomething
, rElement
, aIdentifier
))
574 OSL_ASSERT(nSomething
== 0);
576 catch (configuration::Exception
& ex
)
578 ExceptionMapper
e(ex
);
579 e
.setContext( rElement
.getUnoInstance() );
585 //-----------------------------------------------------------------------------------
587 } // namespace configapi
589 } // namespace configmgr