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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26 
27 #ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_
28 #include "definitioncontainer.hxx"
29 #endif
30 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
31 #include "dbastrings.hrc"
32 #endif
33 #ifndef _DBASHARED_APITOOLS_HXX_
34 #include "apitools.hxx"
35 #endif
36 #ifndef _DBA_CORE_RESOURCE_HXX_
37 #include "core_resource.hxx"
38 #endif
39 #ifndef _DBA_CORE_RESOURCE_HRC_
40 #include "core_resource.hrc"
41 #endif
42 
43 #ifndef _TOOLS_DEBUG_HXX
44 #include <tools/debug.hxx>
45 #endif
46 #ifndef TOOLS_DIAGNOSE_EX_H
47 #include <tools/diagnose_ex.h>
48 #endif
49 #ifndef _COMPHELPER_SEQUENCE_HXX_
50 #include <comphelper/sequence.hxx>
51 #endif
52 #ifndef _COMPHELPER_ENUMHELPER_HXX_
53 #include <comphelper/enumhelper.hxx>
54 #endif
55 #ifndef _COMPHELPER_EXTRACT_HXX_
56 #include <comphelper/extract.hxx>
57 #endif
58 #ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
59 #include <com/sun/star/lang/XComponent.hpp>
60 #endif
61 #ifndef _COM_SUN_STAR_UCB_COMMANDINFO_HPP_
62 #include <com/sun/star/ucb/CommandInfo.hpp>
63 #endif
64 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
65 #include <com/sun/star/beans/XPropertySet.hpp>
66 #endif
67 #ifndef _COM_SUN_STAR_SDB_ERRORCONDITION_HPP_
68 #include <com/sun/star/sdb/ErrorCondition.hpp>
69 #endif
70 #ifndef _COMPHELPER_TYPES_HXX_
71 #include <comphelper/types.hxx>
72 #endif
73 #ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX
74 #include <ucbhelper/contentidentifier.hxx>
75 #endif
76 
77 
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::util;
81 using namespace ::com::sun::star::beans;
82 using namespace ::com::sun::star::container;
83 using namespace ::com::sun::star::sdbcx;
84 using namespace ::com::sun::star::sdb;
85 using namespace ::osl;
86 using namespace ::comphelper;
87 using namespace ::cppu;
88 using namespace ::com::sun::star::ucb;
89 
90 //........................................................................
91 namespace dbaccess
92 {
93 //........................................................................
94 
95 //==========================================================================
96 //= ODefinitionContainer_Impl
97 //==========================================================================
98 //--------------------------------------------------------------------------
erase(TContentPtr _pDefinition)99 void ODefinitionContainer_Impl::erase( TContentPtr _pDefinition )
100 {
101     NamedDefinitions::iterator aPos = find( _pDefinition );
102 	if ( aPos != end() )
103 		m_aDefinitions.erase( aPos );
104 }
105 
106 //--------------------------------------------------------------------------
find(TContentPtr _pDefinition) const107 ODefinitionContainer_Impl::const_iterator ODefinitionContainer_Impl::find( TContentPtr _pDefinition ) const
108 {
109 	return ::std::find_if(
110         m_aDefinitions.begin(),
111         m_aDefinitions.end(),
112         ::std::compose1(
113 			::std::bind2nd( ::std::equal_to< TContentPtr >(), _pDefinition ),
114             ::std::select2nd< NamedDefinitions::value_type >()
115         )
116     );
117 }
118 
119 //--------------------------------------------------------------------------
find(TContentPtr _pDefinition)120 ODefinitionContainer_Impl::iterator ODefinitionContainer_Impl::find( TContentPtr _pDefinition )
121 {
122 	return ::std::find_if(
123         m_aDefinitions.begin(),
124         m_aDefinitions.end(),
125         ::std::compose1(
126 			::std::bind2nd( ::std::equal_to< TContentPtr >(), _pDefinition ),
127             ::std::select2nd< NamedDefinitions::value_type >()
128         )
129     );
130 }
131 
132 //==========================================================================
133 //= ODefinitionContainer
134 //==========================================================================
DBG_NAME(ODefinitionContainer)135 DBG_NAME(ODefinitionContainer)
136 //--------------------------------------------------------------------------
137 ODefinitionContainer::ODefinitionContainer(   const Reference< XMultiServiceFactory >& _xORB
138 											, const Reference< XInterface >&	_xParentContainer
139 											, const TContentPtr& _pImpl
140                                             , bool _bCheckSlash
141 											)
142 	:OContentHelper(_xORB,_xParentContainer,_pImpl)
143     ,m_aApproveListeners(m_aMutex)
144 	,m_aContainerListeners(m_aMutex)
145 	,m_bInPropertyChange(sal_False)
146     ,m_bCheckSlash(_bCheckSlash)
147 {
148 	m_pImpl->m_aProps.bIsDocument = sal_False;
149 	m_pImpl->m_aProps.bIsFolder = sal_True;
150 
151 	const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
152 	ODefinitionContainer_Impl::const_iterator aEnd = rDefinitions.end();
153 	for	(	ODefinitionContainer_Impl::const_iterator aDefinition = rDefinitions.begin();
154 			aDefinition != aEnd;
155 			++aDefinition
156 		)
157 		m_aDocuments.push_back(
158             m_aDocumentMap.insert(
159                 Documents::value_type( aDefinition->first, Documents::mapped_type() ) ).first );
160 
161 	DBG_CTOR(ODefinitionContainer, NULL);
162 }
163 
164 //--------------------------------------------------------------------------
disposing()165 void SAL_CALL ODefinitionContainer::disposing()
166 {
167 	OContentHelper::disposing();
168 
169 	MutexGuard aGuard(m_aMutex);
170 
171 	// say our listeners goobye
172 	EventObject aEvt(*this);
173 	m_aApproveListeners.disposeAndClear(aEvt);
174 	m_aContainerListeners.disposeAndClear(aEvt);
175 
176 	// dispose our elements
177 	Documents::iterator aIter = m_aDocumentMap.begin();
178 	Documents::iterator aEnd = m_aDocumentMap.end();
179 
180 	for	(; aIter != aEnd; ++aIter)
181 	{
182 		Reference<XContent> xProp = aIter->second;
183 		if ( xProp.is() )
184 		{
185 			removeObjectListener(xProp);
186 			::comphelper::disposeComponent(xProp);
187 		}
188 	}
189 
190 	// remove our elements
191 	m_aDocuments.clear();
192 	//  !!! do this before clearing the map which the vector elements refer to !!!
193 	m_aDocumentMap.clear();
194 }
195 
196 //--------------------------------------------------------------------------
~ODefinitionContainer()197 ODefinitionContainer::~ODefinitionContainer()
198 {
199 	DBG_DTOR(ODefinitionContainer, NULL);
200 }
201 
202 IMPLEMENT_FORWARD_XINTERFACE2( ODefinitionContainer,OContentHelper,ODefinitionContainer_Base)
203 IMPLEMENT_TYPEPROVIDER2(ODefinitionContainer,OContentHelper,ODefinitionContainer_Base);
204 // XServiceInfo
205 //--------------------------------------------------------------------------
getImplementationName()206 ::rtl::OUString SAL_CALL ODefinitionContainer::getImplementationName(  ) throw(RuntimeException)
207 {
208 	return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.ODefinitionContainer"));
209 }
210 //--------------------------------------------------------------------------
getSupportedServiceNames()211 Sequence< ::rtl::OUString > SAL_CALL ODefinitionContainer::getSupportedServiceNames(  ) throw(RuntimeException)
212 {
213 	Sequence< ::rtl::OUString > aReturn(2);
214 	aReturn.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DefinitionContainer"));
215 	aReturn.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content"));
216 	return aReturn;
217 }
218 
219 // XNameContainer
220 //--------------------------------------------------------------------------
insertByName(const::rtl::OUString & _rName,const Any & aElement)221 void SAL_CALL ODefinitionContainer::insertByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
222 {
223 	ResettableMutexGuard aGuard(m_aMutex);
224 
225 	// approve the new object
226 	Reference< XContent > xNewElement(aElement,UNO_QUERY);
227 	approveNewObject( _rName, xNewElement );  // will throw if necessary
228 
229     notifyByName( aGuard, _rName, xNewElement, NULL, E_INSERTED, ApproveListeners );
230 	implAppend( _rName, xNewElement );
231 	notifyByName( aGuard, _rName, xNewElement, NULL, E_INSERTED, ContainerListemers );
232 }
233 
234 //--------------------------------------------------------------------------
removeByName(const::rtl::OUString & _rName)235 void SAL_CALL ODefinitionContainer::removeByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
236 {
237 	ResettableMutexGuard aGuard(m_aMutex);
238 
239     // check the arguments
240 	if (!_rName.getLength())
241 		throw IllegalArgumentException();
242 
243 	if (!checkExistence(_rName))
244 		throw NoSuchElementException(_rName,*this);
245 
246 	// the old element (for the notifications)
247 	Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() );
248 
249 	// do the removal
250     notifyByName( aGuard, _rName, NULL, xOldElement, E_REMOVED, ApproveListeners );
251 	implRemove( _rName );
252     notifyByName( aGuard, _rName, NULL, xOldElement, E_REMOVED, ContainerListemers );
253 
254 	removeObjectListener( xOldElement );
255     disposeComponent(xOldElement);
256 }
257 
258 // XNameReplace
259 //--------------------------------------------------------------------------
replaceByName(const::rtl::OUString & _rName,const Any & aElement)260 void SAL_CALL ODefinitionContainer::replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
261 {
262 	ResettableMutexGuard aGuard(m_aMutex);
263 
264 	// let derived classes approve the new object
265 	Reference< XContent > xNewElement(aElement,UNO_QUERY);
266 	approveNewObject( _rName, xNewElement );    // will throw if necessary
267 
268 	// the old element (for the notifications)
269 	Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() );
270 
271 	notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ApproveListeners );
272     implReplace( _rName, xNewElement );
273 	notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ContainerListemers );
274 
275 	// and dispose it
276     disposeComponent(xOldElement);
277 }
278 
279 // -----------------------------------------------------------------------------
280 namespace
281 {
282     typedef Reference< XVeto > ( SAL_CALL XContainerApproveListener::*ContainerApprovalMethod )( const ContainerEvent& );
283 
284     struct RaiseExceptionFromVeto
285     {
286     private:
287         ContainerApprovalMethod m_pMethod;
288         const ContainerEvent&   m_rEvent;
289 
290     public:
RaiseExceptionFromVetodbaccess::__anonb1faff260111::RaiseExceptionFromVeto291         RaiseExceptionFromVeto( ContainerApprovalMethod _pMethod, const ContainerEvent& _rEvent )
292             :m_pMethod( _pMethod )
293             ,m_rEvent( _rEvent )
294         {
295         }
296 
operator ()dbaccess::__anonb1faff260111::RaiseExceptionFromVeto297         void operator()( const Reference< XContainerApproveListener >& _Listener ) const
298         {
299             Reference< XVeto > xVeto = (_Listener.get()->*m_pMethod)( m_rEvent );
300             if ( !xVeto.is() )
301                 return;
302 
303             Any eVetoDetails = xVeto->getDetails();
304 
305             IllegalArgumentException aIllegalArgumentError;
306             if ( eVetoDetails >>= aIllegalArgumentError )
307                 throw aIllegalArgumentError;
308 
309             WrappedTargetException aWrappedError;
310             if ( eVetoDetails >>= aWrappedError )
311                 throw aWrappedError;
312 
313             throw WrappedTargetException( xVeto->getReason(), _Listener.get(), eVetoDetails );
314         }
315     };
316 }
317 
318 // -----------------------------------------------------------------------------
notifyByName(ResettableMutexGuard & _rGuard,const::rtl::OUString & _rName,const Reference<XContent> & _xNewElement,const Reference<XContent> & _xOldElement,ContainerOperation _eOperation,ListenerType _eType)319 void ODefinitionContainer::notifyByName( ResettableMutexGuard& _rGuard, const ::rtl::OUString& _rName,
320         const Reference< XContent >& _xNewElement, const Reference< XContent >& _xOldElement,
321         ContainerOperation _eOperation, ListenerType _eType )
322 {
323     bool bApprove = ( _eType == ApproveListeners );
324 
325     ::cppu::OInterfaceContainerHelper& rContainer( bApprove ? m_aApproveListeners : m_aContainerListeners );
326 	if ( !rContainer.getLength() )
327         return;
328 
329     ContainerEvent aEvent( *this, makeAny( _rName ), makeAny( _xNewElement ), makeAny( _xOldElement ) );
330 
331     _rGuard.clear();
332 	switch ( _eOperation )
333 	{
334 		case E_INSERTED:
335             if ( bApprove )
336                 rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
337                     RaiseExceptionFromVeto( &XContainerApproveListener::approveInsertElement, aEvent ) );
338             else
339                 rContainer.notifyEach( &XContainerListener::elementInserted, aEvent );
340 			break;
341 		case E_REPLACED:
342             if ( bApprove )
343                 rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
344                     RaiseExceptionFromVeto( &XContainerApproveListener::approveReplaceElement, aEvent ) );
345             else
346                 rContainer.notifyEach( &XContainerListener::elementReplaced, aEvent );
347 			break;
348 		case E_REMOVED:
349             if ( bApprove )
350                 rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
351                     RaiseExceptionFromVeto( &XContainerApproveListener::approveRemoveElement, aEvent ) );
352             else
353                 rContainer.notifyEach( &XContainerListener::elementRemoved, aEvent );
354 			break;
355 	}
356 
357     if ( bApprove )
358         _rGuard.reset();
359 }
360 
361 //--------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & _rxListener)362 void SAL_CALL ODefinitionContainer::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
363 {
364 	if (_rxListener.is())
365 		m_aContainerListeners.addInterface(_rxListener);
366 }
367 
368 //--------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & _rxListener)369 void SAL_CALL ODefinitionContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
370 {
371 	if (_rxListener.is())
372 		m_aContainerListeners.removeInterface(_rxListener);
373 }
374 
375 //--------------------------------------------------------------------------
addContainerApproveListener(const Reference<XContainerApproveListener> & _Listener)376 void SAL_CALL ODefinitionContainer::addContainerApproveListener( const Reference< XContainerApproveListener >& _Listener ) throw (RuntimeException)
377 {
378     if ( _Listener.is() )
379         m_aApproveListeners.addInterface( _Listener );
380 }
381 
382 //--------------------------------------------------------------------------
removeContainerApproveListener(const Reference<XContainerApproveListener> & _Listener)383 void SAL_CALL ODefinitionContainer::removeContainerApproveListener( const Reference< XContainerApproveListener >& _Listener ) throw (RuntimeException)
384 {
385     if ( _Listener.is() )
386         m_aApproveListeners.removeInterface( _Listener );
387 }
388 
389 
390 // XElementAccess
391 //--------------------------------------------------------------------------
getElementType()392 Type SAL_CALL ODefinitionContainer::getElementType( ) throw (RuntimeException)
393 {
394 	return ::getCppuType( static_cast< Reference< XContent >* >(NULL) );
395 }
396 
397 //--------------------------------------------------------------------------
hasElements()398 sal_Bool SAL_CALL ODefinitionContainer::hasElements( ) throw (RuntimeException)
399 {
400 	MutexGuard aGuard(m_aMutex);
401 	return !m_aDocuments.empty();
402 }
403 
404 // XEnumerationAccess
405 //--------------------------------------------------------------------------
createEnumeration()406 Reference< XEnumeration > SAL_CALL ODefinitionContainer::createEnumeration(  ) throw(RuntimeException)
407 {
408 	MutexGuard aGuard(m_aMutex);
409 	return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
410 }
411 
412 //--------------------------------------------------------------------------
413 // XIndexAccess
getCount()414 sal_Int32 SAL_CALL ODefinitionContainer::getCount(  ) throw(RuntimeException)
415 {
416 	MutexGuard aGuard(m_aMutex);
417 	return m_aDocuments.size();
418 }
419 
420 //--------------------------------------------------------------------------
getByIndex(sal_Int32 _nIndex)421 Any SAL_CALL ODefinitionContainer::getByIndex( sal_Int32 _nIndex ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
422 {
423 	MutexGuard aGuard(m_aMutex);
424 
425 	if ((_nIndex < 0) || (_nIndex >= (sal_Int32)m_aDocuments.size()))
426 		throw IndexOutOfBoundsException();
427 
428 	Documents::iterator aPos = m_aDocuments[_nIndex];
429 	Reference<XContent> xProp = aPos->second;
430 	if (!xProp.is())
431 	{	// that's the first access to the object
432 		// -> create it
433 		xProp = createObject(aPos->first);
434 		aPos->second = Documents::mapped_type();
435 		// and update the name-access map
436 	}
437 
438 	return makeAny(xProp);
439 }
440 
441 //--------------------------------------------------------------------------
getByName(const::rtl::OUString & _rName)442 Any SAL_CALL ODefinitionContainer::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
443 {
444 	MutexGuard aGuard(m_aMutex);
445 
446 	return makeAny( implGetByName( _rName, sal_True ) );
447 }
448 
449 //--------------------------------------------------------------------------
implGetByName(const::rtl::OUString & _rName,sal_Bool _bReadIfNeccessary)450 Reference< XContent > ODefinitionContainer::implGetByName(const ::rtl::OUString& _rName, sal_Bool _bReadIfNeccessary) throw (NoSuchElementException)
451 {
452 	Documents::iterator aMapPos = m_aDocumentMap.find(_rName);
453 	if (aMapPos == m_aDocumentMap.end())
454 		throw NoSuchElementException(_rName,*this);
455 
456 	Reference< XContent > xProp = aMapPos->second;
457 
458 	if (_bReadIfNeccessary && !xProp.is())
459 	{	// the object has never been accessed before, so we have to read it now
460 		// (that's the expensive part)
461 
462 		// create the object and insert it into the map
463 		xProp = createObject(_rName);
464 		aMapPos->second = xProp;
465 		addObjectListener(xProp);
466 	}
467 
468 	return xProp;
469 }
470 
471 //--------------------------------------------------------------------------
getElementNames()472 Sequence< ::rtl::OUString > SAL_CALL ODefinitionContainer::getElementNames(  ) throw(RuntimeException)
473 {
474 	MutexGuard aGuard(m_aMutex);
475 
476 	Sequence< ::rtl::OUString > aNames(m_aDocumentMap.size());
477 	::rtl::OUString* pNames = aNames.getArray();
478 	Documents::iterator aEnd = m_aDocumentMap.end();
479 	for	(	Documents::iterator aNameIter = m_aDocumentMap.begin();
480 			aNameIter != aEnd;
481 			++pNames, ++aNameIter
482 		)
483 	{
484 		*pNames = aNameIter->first;
485 	}
486 
487 	return aNames;
488 }
489 
490 //--------------------------------------------------------------------------
hasByName(const::rtl::OUString & _rName)491 sal_Bool SAL_CALL ODefinitionContainer::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
492 {
493 	MutexGuard aGuard(m_aMutex);
494 
495 	return checkExistence(_rName);
496 }
497 
498 //--------------------------------------------------------------------------
disposing(const EventObject & _rSource)499 void SAL_CALL ODefinitionContainer::disposing( const EventObject& _rSource ) throw(RuntimeException)
500 {
501 	MutexGuard aGuard(m_aMutex);
502 	Reference< XContent > xSource(_rSource.Source, UNO_QUERY);
503 	// it's one of our documents ....
504 	Documents::iterator aIter = m_aDocumentMap.begin();
505 	Documents::iterator aEnd = m_aDocumentMap.end();
506 	for	(;aIter != aEnd;++aIter )
507 	{
508 		if ( xSource == aIter->second.get() )
509 		{
510 			removeObjectListener(xSource);
511 			// and clear our document map/vector, so the object will be recreated on next access
512 			aIter->second = Documents::mapped_type();
513 		}
514 	}
515 }
516 
517 //--------------------------------------------------------------------------
implRemove(const::rtl::OUString & _rName)518 void ODefinitionContainer::implRemove(const ::rtl::OUString& _rName)
519 {
520 	// from the object maps
521 	Documents::iterator aFind = m_aDocumentMap.find(_rName);
522 	if ( aFind != m_aDocumentMap.end() )
523 	{
524 		m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind));
525 		m_aDocumentMap.erase(aFind);
526 
527 	    getDefinitions().erase( _rName );
528 
529 		notifyDataSourceModified();
530 	}
531 }
532 
533 //--------------------------------------------------------------------------
534 namespace
535 {
lcl_ensureName(const Reference<XContent> & _rxContent,const::rtl::OUString & _rName)536     bool    lcl_ensureName( const Reference< XContent >& _rxContent, const ::rtl::OUString& _rName )
537     {
538         if ( !_rxContent.is() )
539             return true;
540 
541         // ..........................................................
542         // obtain the current name. If it's the same as the new one,
543         // don't do anything
544         try
545         {
546             Reference< XPropertySet > xProps( _rxContent, UNO_QUERY );
547             if ( xProps.is() )
548             {
549                 ::rtl::OUString sCurrentName;
550                 OSL_VERIFY( xProps->getPropertyValue( PROPERTY_NAME ) >>= sCurrentName );
551                 if ( sCurrentName.equals( _rName ) )
552                     return true;
553             }
554         }
555         catch( const Exception& )
556         {
557         	OSL_ENSURE( sal_False, "lcl_ensureName: caught an exception while obtaining the current name!" );
558         }
559 
560         // ..........................................................
561         // set the new name
562         Reference< XRename > xRename( _rxContent, UNO_QUERY );
563         OSL_ENSURE( xRename.is(), "lcl_ensureName: invalid content (not renameable)!" );
564         if ( !xRename.is() )
565             return false;
566         try
567         {
568             xRename->rename( _rName );
569             return true;
570         }
571         catch( const Exception& )
572         {
573         	OSL_ENSURE( sal_False, "lcl_ensureName: caught an exception!" );
574         }
575         return false;
576     }
577 }
578 //--------------------------------------------------------------------------
implAppend(const::rtl::OUString & _rName,const Reference<XContent> & _rxNewObject)579 void ODefinitionContainer::implAppend(const ::rtl::OUString& _rName, const Reference< XContent >& _rxNewObject)
580 {
581 	MutexGuard aGuard(m_aMutex);
582 	try
583 	{
584 		Reference<XChild> xChild(_rxNewObject,UNO_QUERY);
585 		if ( xChild.is() )
586 			xChild->setParent(static_cast<OWeakObject*>(this));
587 
588 	    ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
589 		ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( _rName );
590 		if ( aFind == rDefinitions.end() )
591 		{
592             // ensure that the new object thas the proper name.
593             // Somebody could create an object with name "foo", and insert it as "bar"
594             // into a container. In this case, we need to ensure that the object name
595             // is also "bar"
596             // #i44786# / 2005-03-11 / frank.schoenheit@sun.com
597             lcl_ensureName( _rxNewObject, _rName );
598 
599 			::rtl::Reference< OContentHelper > pContent = OContentHelper::getImplementation( _rxNewObject );
600 			if ( pContent.is() )
601 			{
602 				TContentPtr pImpl = pContent->getImpl();
603                 rDefinitions.erase( pImpl );
604 				pImpl->m_aProps.aTitle = _rName;
605 				rDefinitions.insert( _rName, pImpl );
606 			}
607 		}
608 
609 
610 		m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(_rName,_rxNewObject)).first);
611 		notifyDataSourceModified();
612 		// now update our structures
613 		if ( _rxNewObject.is() )
614 			addObjectListener(_rxNewObject);
615 	}
616 	catch(Exception&)
617 	{
618 		DBG_ERROR("ODefinitionContainer::implAppend: caught something !");
619 	}
620 }
621 
622 //--------------------------------------------------------------------------
implReplace(const::rtl::OUString & _rName,const Reference<XContent> & _rxNewObject)623 void ODefinitionContainer::implReplace(const ::rtl::OUString& _rName, const Reference< XContent >& _rxNewObject)
624 {
625 	DBG_ASSERT(checkExistence(_rName), "ODefinitionContainer::implReplace : invalid name !");
626 
627 	Documents::iterator aFind = m_aDocumentMap.find(_rName);
628 	removeObjectListener(aFind->second);
629 	aFind->second = _rxNewObject;
630 	addObjectListener(aFind->second);
631 }
632 
633 // -----------------------------------------------------------------------------
approveNewObject(const::rtl::OUString & _sName,const Reference<XContent> & _rxObject) const634 void ODefinitionContainer::approveNewObject(const ::rtl::OUString& _sName,const Reference< XContent >& _rxObject) const
635 {
636 	// check the arguments
637 	if ( !_sName.getLength() )
638         throw IllegalArgumentException(
639             DBA_RES( RID_STR_NAME_MUST_NOT_BE_EMPTY ),
640             *this,
641             0 );
642 
643     if ( m_bCheckSlash && _sName.indexOf( '/' ) != -1 )
644         throw IllegalArgumentException(
645             m_aErrorHelper.getErrorMessage( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES ),
646             *this,
647             0 );
648 
649 	if ( !_rxObject.is() )
650         throw IllegalArgumentException(
651             DBA_RES( RID_STR_NO_NULL_OBJECTS_IN_CONTAINER ),
652             *this,
653             0 );
654 
655 	const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
656     if ( rDefinitions.find( _sName ) != rDefinitions.end() )
657         throw ElementExistException(
658             DBA_RES( RID_STR_NAME_ALREADY_USED ),
659             *this );
660 
661     ::rtl::Reference< OContentHelper > pContent( OContentHelper::getImplementation( _rxObject ) );
662     if ( !pContent.is() )
663         throw IllegalArgumentException(
664             DBA_RES( RID_STR_OBJECT_CONTAINER_MISMATCH ),
665             *this,
666             1 );
667 
668     if ( rDefinitions.find( pContent->getImpl() ) != rDefinitions.end() )
669         throw ElementExistException(
670             DBA_RES( RID_STR_OBJECT_ALREADY_CONTAINED ),
671             *this );
672 }
673 
674 // -----------------------------------------------------------------------------
675 // XPropertyChangeListener
propertyChange(const PropertyChangeEvent & evt)676 void SAL_CALL ODefinitionContainer::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException)
677 {
678 	ClearableMutexGuard aGuard(m_aMutex);
679     if(evt.PropertyName == (rtl::OUString) PROPERTY_NAME || evt.PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ))
680 	{
681 		m_bInPropertyChange = sal_True;
682 		try
683 		{
684 			::rtl::OUString sNewName,sOldName;
685 			evt.OldValue >>= sOldName;
686 			evt.NewValue >>= sNewName;
687 			Reference<XContent> xContent( evt.Source, UNO_QUERY );
688 			removeObjectListener( xContent );
689             implRemove( sOldName );
690 			implAppend( sNewName, xContent );
691 		}
692 		catch(const Exception&)
693 		{
694             DBG_UNHANDLED_EXCEPTION();
695 			throw RuntimeException();
696 		}
697 		m_bInPropertyChange = sal_False;
698 	}
699 }
700 // -----------------------------------------------------------------------------
701 // XVetoableChangeListener
vetoableChange(const PropertyChangeEvent & aEvent)702 void SAL_CALL ODefinitionContainer::vetoableChange( const PropertyChangeEvent& aEvent ) throw (PropertyVetoException, RuntimeException)
703 {
704 	MutexGuard aGuard(m_aMutex);
705 
706     if(aEvent.PropertyName == (rtl::OUString) PROPERTY_NAME || aEvent.PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
707 	{
708 		::rtl::OUString sNewName;
709 		aEvent.NewValue >>= sNewName;
710 		if(hasByName(sNewName))
711 			throw PropertyVetoException();
712 	}
713 }
714 // -----------------------------------------------------------------------------
addObjectListener(const Reference<XContent> & _xNewObject)715 void ODefinitionContainer::addObjectListener(const Reference< XContent >& _xNewObject)
716 {
717 	OSL_ENSURE(_xNewObject.is(),"ODefinitionContainer::addObjectListener: Object is null!");
718 	Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY);
719 	if ( xProp.is() )
720 	{
721 		xProp->addPropertyChangeListener(PROPERTY_NAME, this);
722 		xProp->addVetoableChangeListener(PROPERTY_NAME, this);
723 	}
724 }
725 // -----------------------------------------------------------------------------
removeObjectListener(const Reference<XContent> & _xNewObject)726 void ODefinitionContainer::removeObjectListener(const Reference< XContent >& _xNewObject)
727 {
728 	Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY);
729 	if ( xProp.is() )
730 	{
731 		xProp->removePropertyChangeListener(PROPERTY_NAME, this);
732 		xProp->removeVetoableChangeListener(PROPERTY_NAME, this);
733 	}
734 }
735 // -----------------------------------------------------------------------------
checkExistence(const::rtl::OUString & _rName)736 sal_Bool ODefinitionContainer::checkExistence(const ::rtl::OUString& _rName)
737 {
738 	return m_aDocumentMap.find(_rName) != m_aDocumentMap.end();
739 }
740 
741 //........................................................................
742 }
743 // namespace dbaccess
744 //........................................................................
745