1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucbhelper.hxx"
30 /**************************************************************************
31 								TODO
32  **************************************************************************
33 
34  *************************************************************************/
35 
36 #include <hash_map>
37 #include <com/sun/star/ucb/ContentAction.hpp>
38 #include <com/sun/star/ucb/CommandInfoChange.hpp>
39 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
42 #include <cppuhelper/interfacecontainer.hxx>
43 
44 #include "osl/diagnose.h"
45 #include "osl/mutex.hxx"
46 #include "rtl/ref.hxx"
47 #include <ucbhelper/contentidentifier.hxx>
48 #include <ucbhelper/contenthelper.hxx>
49 #include <ucbhelper/providerhelper.hxx>
50 #include <ucbhelper/contentinfo.hxx>
51 
52 using namespace com::sun::star;
53 
54 namespace ucbhelper_impl
55 {
56 
57 //=========================================================================
58 //
59 // class PropertyEventSequence.
60 //
61 //=========================================================================
62 
63 class PropertyEventSequence
64 {
65 	uno::Sequence< beans::PropertyChangeEvent > m_aSeq;
66 	sal_uInt32                                  m_nPos;
67 
68 public:
69 	PropertyEventSequence( sal_uInt32 nSize )
70 	: m_aSeq( nSize ), m_nPos( 0 ) {};
71 
72 	void append( const beans::PropertyChangeEvent& rEvt )
73 	{ m_aSeq.getArray()[ m_nPos ] = rEvt; ++m_nPos; }
74 
75 	const uno::Sequence< beans::PropertyChangeEvent >& getEvents()
76 	{ m_aSeq.realloc( m_nPos ); return m_aSeq; }
77 };
78 
79 //=========================================================================
80 //
81 // PropertiesEventListenerMap.
82 //
83 //=========================================================================
84 
85 typedef void* XPropertiesChangeListenerPtr; // -> Compiler problems!
86 
87 struct equalPtr
88 {
89 	bool operator()( const XPropertiesChangeListenerPtr& rp1,
90 					 const XPropertiesChangeListenerPtr& rp2 ) const
91 	{
92 		return ( rp1 == rp2 );
93 	}
94 };
95 
96 struct hashPtr
97 {
98 	size_t operator()( const XPropertiesChangeListenerPtr& rp ) const
99 	{
100 		return (size_t)rp;
101 	}
102 };
103 
104 typedef std::hash_map
105 <
106 	XPropertiesChangeListenerPtr,
107 	PropertyEventSequence*,
108 	hashPtr,
109 	equalPtr
110 >
111 PropertiesEventListenerMap;
112 
113 //=========================================================================
114 //
115 // PropertyChangeListenerContainer.
116 //
117 //=========================================================================
118 
119 struct equalStr
120 {
121 	bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const
122   	{
123 		return !!( s1 == s2 );
124 	}
125 };
126 
127 struct hashStr
128 {
129 	size_t operator()( const rtl::OUString& rName ) const
130 	{
131 		return rName.hashCode();
132 	}
133 };
134 
135 typedef cppu::OMultiTypeInterfaceContainerHelperVar
136 <
137 	rtl::OUString,
138 	hashStr,
139 	equalStr
140 > PropertyChangeListeners;
141 
142 //=========================================================================
143 //
144 // struct ContentImplHelper_Impl
145 //
146 //=========================================================================
147 
148 struct ContentImplHelper_Impl
149 {
150 	rtl::Reference< ::ucbhelper::PropertySetInfo > 	    m_xPropSetInfo;
151 	rtl::Reference< ::ucbhelper::CommandProcessorInfo > m_xCommandsInfo;
152 	cppu::OInterfaceContainerHelper*              m_pDisposeEventListeners;
153 	cppu::OInterfaceContainerHelper*              m_pContentEventListeners;
154 	cppu::OInterfaceContainerHelper*              m_pPropSetChangeListeners;
155 	cppu::OInterfaceContainerHelper*              m_pCommandChangeListeners;
156 	PropertyChangeListeners*    	              m_pPropertyChangeListeners;
157 
158 	ContentImplHelper_Impl()
159 	: m_pDisposeEventListeners( 0 ),
160   	  m_pContentEventListeners( 0 ),
161 	  m_pPropSetChangeListeners( 0 ),
162   	  m_pCommandChangeListeners( 0 ),
163 	  m_pPropertyChangeListeners( 0 ) {}
164 
165 	~ContentImplHelper_Impl()
166 	{
167 		delete m_pDisposeEventListeners;
168 		delete m_pContentEventListeners;
169 		delete m_pPropSetChangeListeners;
170 		delete m_pCommandChangeListeners;
171 		delete m_pPropertyChangeListeners;
172 	}
173 };
174 
175 } // namespace ucbhelper_impl
176 
177 using namespace ucbhelper_impl;
178 
179 //=========================================================================
180 //=========================================================================
181 //
182 // ContentImplHelper Implementation.
183 //
184 //=========================================================================
185 //=========================================================================
186 
187 namespace ucbhelper {
188 
189 ContentImplHelper::ContentImplHelper(
190 			const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
191 			const rtl::Reference< ContentProviderImplHelper >& rxProvider,
192 			const uno::Reference<
193             com::sun::star::ucb::XContentIdentifier >& Identifier )
194 : m_pImpl( new ContentImplHelper_Impl ),
195   m_xSMgr( rxSMgr ),
196   m_xIdentifier( Identifier ),
197   m_xProvider( rxProvider ),
198   m_nCommandId( 0 )
199 {
200 }
201 
202 //=========================================================================
203 // virtual
204 ContentImplHelper::~ContentImplHelper()
205 {
206 	delete m_pImpl;
207 }
208 
209 //=========================================================================
210 //
211 // XInterface methods.
212 //
213 //=========================================================================
214 
215 void SAL_CALL ContentImplHelper::acquire()
216 	throw()
217 {
218 	cppu::OWeakObject::acquire();
219 }
220 
221 void SAL_CALL ContentImplHelper::release()
222 	throw()
223 {
224     // #144882# - Call to OWeakObject::release may destroy m_xProvider.
225     //            Prevent this.
226     rtl::Reference< ContentProviderImplHelper > xKeepProviderAlive(
227         m_xProvider );
228 
229     {
230         osl::MutexGuard aGuard( m_xProvider->m_aMutex );
231         OWeakObject::release();
232     }
233 }
234 
235 uno::Any SAL_CALL ContentImplHelper::queryInterface( const uno::Type & rType )
236 	throw( uno::RuntimeException )
237 {
238 	com::sun::star::uno::Any aRet = cppu::queryInterface( rType,
239 			static_cast< lang::XTypeProvider * >(this),
240 			static_cast< lang::XServiceInfo * >(this),
241 			static_cast< lang::XComponent * >(this),
242 			static_cast< com::sun::star::ucb::XContent * >(this),
243 			static_cast< com::sun::star::ucb::XCommandProcessor * >(this),
244 			static_cast< beans::XPropertiesChangeNotifier * >(this),
245 			static_cast< com::sun::star::ucb::XCommandInfoChangeNotifier * >(this),
246 			static_cast< beans::XPropertyContainer * >(this),
247 			static_cast< beans::XPropertySetInfoChangeNotifier * >(this),
248 			static_cast< container::XChild * >(this));
249 	return aRet.hasValue() ? aRet : cppu::OWeakObject::queryInterface( rType );
250 }
251 
252 //=========================================================================
253 //
254 // XTypeProvider methods.
255 //
256 //=========================================================================
257 
258 XTYPEPROVIDER_IMPL_10( ContentImplHelper,
259 					   lang::XTypeProvider,
260 					   lang::XServiceInfo,
261 					   lang::XComponent,
262 					   com::sun::star::ucb::XContent,
263 					   com::sun::star::ucb::XCommandProcessor,
264 					   beans::XPropertiesChangeNotifier,
265 					   com::sun::star::ucb::XCommandInfoChangeNotifier,
266 					   beans::XPropertyContainer,
267 					   beans::XPropertySetInfoChangeNotifier,
268 					   container::XChild );
269 
270 //=========================================================================
271 //
272 // XServiceInfo methods.
273 //
274 //=========================================================================
275 
276 // virtual
277 sal_Bool SAL_CALL ContentImplHelper::supportsService(
278 											const rtl::OUString& ServiceName )
279 	throw( uno::RuntimeException )
280 {
281 	uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
282 	const rtl::OUString* pArray = aSNL.getConstArray();
283 	for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
284 	{
285 		if ( pArray[ i ] == ServiceName )
286 			return sal_True;
287 	}
288 
289 	return sal_False;
290 }
291 
292 //=========================================================================
293 //
294 // XComponent methods.
295 //
296 //=========================================================================
297 
298 // virtual
299 void SAL_CALL ContentImplHelper::dispose()
300 	throw( uno::RuntimeException )
301 {
302 	osl::MutexGuard aGuard( m_aMutex );
303 
304 	if ( m_pImpl->m_pDisposeEventListeners &&
305 	     m_pImpl->m_pDisposeEventListeners->getLength() )
306 	{
307 		lang::EventObject aEvt;
308 		aEvt.Source = static_cast< lang::XComponent * >( this );
309 		m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
310 	}
311 
312 	if ( m_pImpl->m_pContentEventListeners &&
313 	     m_pImpl->m_pContentEventListeners->getLength() )
314 	{
315 		lang::EventObject aEvt;
316 		aEvt.Source = static_cast< com::sun::star::ucb::XContent * >( this );
317 		m_pImpl->m_pContentEventListeners->disposeAndClear( aEvt );
318 	}
319 
320 	if ( m_pImpl->m_pPropSetChangeListeners &&
321 	     m_pImpl->m_pPropSetChangeListeners->getLength() )
322 	{
323 		lang::EventObject aEvt;
324 		aEvt.Source
325             = static_cast< beans::XPropertySetInfoChangeNotifier * >( this );
326 		m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
327 	}
328 
329 	if ( m_pImpl->m_pCommandChangeListeners &&
330 	     m_pImpl->m_pCommandChangeListeners->getLength() )
331 	{
332 		lang::EventObject aEvt;
333 		aEvt.Source = static_cast<  com::sun::star::ucb::XCommandInfoChangeNotifier * >( this );
334 		m_pImpl->m_pCommandChangeListeners->disposeAndClear( aEvt );
335 	}
336 
337 	if ( m_pImpl->m_pPropertyChangeListeners )
338 	{
339 		lang::EventObject aEvt;
340 		aEvt.Source
341             = static_cast< beans::XPropertiesChangeNotifier * >( this );
342 		m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
343 	}
344 }
345 
346 //=========================================================================
347 // virtual
348 void SAL_CALL ContentImplHelper::addEventListener(
349         const uno::Reference< lang::XEventListener >& Listener )
350 	throw( uno::RuntimeException )
351 {
352 	osl::MutexGuard aGuard( m_aMutex );
353 
354 	if ( !m_pImpl->m_pDisposeEventListeners )
355 		m_pImpl->m_pDisposeEventListeners
356 			= new cppu::OInterfaceContainerHelper( m_aMutex );
357 
358 	m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
359 }
360 
361 //=========================================================================
362 // virtual
363 void SAL_CALL ContentImplHelper::removeEventListener(
364         const uno::Reference< lang::XEventListener >& Listener )
365 	throw( uno::RuntimeException )
366 {
367 	osl::MutexGuard aGuard( m_aMutex );
368 
369 	if ( m_pImpl->m_pDisposeEventListeners )
370 		m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
371 }
372 
373 //=========================================================================
374 //
375 // XContent methods.
376 //
377 //=========================================================================
378 
379 // virtual
380 uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL
381 ContentImplHelper::getIdentifier()
382 	throw( uno::RuntimeException )
383 {
384 	return m_xIdentifier;
385 }
386 
387 //=========================================================================
388 // virtual
389 void SAL_CALL ContentImplHelper::addContentEventListener(
390         const uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener )
391 	throw( uno::RuntimeException )
392 {
393 	osl::MutexGuard aGuard( m_aMutex );
394 
395 	if ( !m_pImpl->m_pContentEventListeners )
396 		m_pImpl->m_pContentEventListeners
397 			= new cppu::OInterfaceContainerHelper( m_aMutex );
398 
399 	m_pImpl->m_pContentEventListeners->addInterface( Listener );
400 }
401 
402 //=========================================================================
403 // virtual
404 void SAL_CALL ContentImplHelper::removeContentEventListener(
405         const uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener )
406 	throw( uno::RuntimeException )
407 {
408 	osl::MutexGuard aGuard( m_aMutex );
409 
410 	if ( m_pImpl->m_pContentEventListeners )
411 		m_pImpl->m_pContentEventListeners->removeInterface( Listener );
412 }
413 
414 //=========================================================================
415 //
416 // XCommandProcessor methods.
417 //
418 //=========================================================================
419 
420 // virtual
421 sal_Int32 SAL_CALL ContentImplHelper::createCommandIdentifier()
422 	throw( uno::RuntimeException )
423 {
424 	osl::MutexGuard aGuard( m_aMutex );
425 
426 	// Just increase counter on every call to generate an identifier.
427 	return ++m_nCommandId;
428 }
429 
430 //=========================================================================
431 //
432 // XPropertiesChangeNotifier methods.
433 //
434 //=========================================================================
435 
436 // virtual
437 void SAL_CALL ContentImplHelper::addPropertiesChangeListener(
438         const uno::Sequence< rtl::OUString >& PropertyNames,
439         const uno::Reference< beans::XPropertiesChangeListener >& Listener )
440 	throw( uno::RuntimeException )
441 {
442 	osl::MutexGuard aGuard( m_aMutex );
443 
444 	if ( !m_pImpl->m_pPropertyChangeListeners )
445 		m_pImpl->m_pPropertyChangeListeners
446 			= new PropertyChangeListeners( m_aMutex );
447 
448 	sal_Int32 nCount = PropertyNames.getLength();
449 	if ( !nCount )
450 	{
451 		// Note: An empty sequence means a listener for "all" properties.
452 		m_pImpl->m_pPropertyChangeListeners->addInterface(
453             rtl::OUString(), Listener );
454 	}
455 	else
456 	{
457 		const rtl::OUString* pSeq = PropertyNames.getConstArray();
458 
459 		for ( sal_Int32 n = 0; n < nCount; ++n )
460 		{
461 			const rtl::OUString& rName = pSeq[ n ];
462 			if ( rName.getLength() )
463 				m_pImpl->m_pPropertyChangeListeners->addInterface(
464                     rName, Listener );
465 		}
466 	}
467 }
468 
469 //=========================================================================
470 // virtual
471 void SAL_CALL ContentImplHelper::removePropertiesChangeListener(
472         const uno::Sequence< rtl::OUString >& PropertyNames,
473         const uno::Reference< beans::XPropertiesChangeListener >& Listener )
474 	throw( uno::RuntimeException )
475 {
476 	osl::MutexGuard aGuard( m_aMutex );
477 
478 	if ( !m_pImpl->m_pPropertyChangeListeners )
479 		return;
480 
481 	sal_Int32 nCount = PropertyNames.getLength();
482 	if ( !nCount )
483 	{
484 		// Note: An empty sequence means a listener for "all" properties.
485 		m_pImpl->m_pPropertyChangeListeners->removeInterface(
486             rtl::OUString(), Listener );
487 	}
488 	else
489 	{
490 		const rtl::OUString* pSeq = PropertyNames.getConstArray();
491 
492 		for ( sal_Int32 n = 0; n < nCount; ++n )
493 		{
494 			const rtl::OUString& rName = pSeq[ n ];
495 			if ( rName.getLength() )
496 				m_pImpl->m_pPropertyChangeListeners->removeInterface(
497                     rName, Listener );
498 		}
499 	}
500 }
501 
502 //=========================================================================
503 //
504 // XCommandInfoChangeNotifier methods.
505 //
506 //=========================================================================
507 
508 // virtual
509 void SAL_CALL ContentImplHelper::addCommandInfoChangeListener(
510         const uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >& Listener )
511 	throw( uno::RuntimeException )
512 {
513 	osl::MutexGuard aGuard( m_aMutex );
514 
515 	if ( !m_pImpl->m_pCommandChangeListeners )
516 		m_pImpl->m_pCommandChangeListeners
517 			= new cppu::OInterfaceContainerHelper( m_aMutex );
518 
519 	m_pImpl->m_pCommandChangeListeners->addInterface( Listener );
520 }
521 
522 //=========================================================================
523 // virtual
524 void SAL_CALL ContentImplHelper::removeCommandInfoChangeListener(
525         const uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >& Listener )
526 	throw( uno::RuntimeException )
527 {
528 	osl::MutexGuard aGuard( m_aMutex );
529 
530 	if ( m_pImpl->m_pCommandChangeListeners )
531 		m_pImpl->m_pCommandChangeListeners->removeInterface( Listener );
532 }
533 
534 //=========================================================================
535 //
536 // XPropertyContainer methods.
537 //
538 //=========================================================================
539 
540 // virtual
541 void SAL_CALL ContentImplHelper::addProperty(
542         const rtl::OUString& Name,
543         sal_Int16 Attributes,
544         const uno::Any& DefaultValue )
545 	throw( beans::PropertyExistException,
546 		   beans::IllegalTypeException,
547 		   lang::IllegalArgumentException,
548 		   uno::RuntimeException )
549 {
550 	osl::MutexGuard aGuard( m_aMutex );
551 
552 	//////////////////////////////////////////////////////////////////////
553 	// Make sure a property with the requested name does not already
554 	// exist in dynamic and static(!) properties.
555 	//////////////////////////////////////////////////////////////////////
556 
557 	// @@@ Need real command environment here, but where to get it from?
558 	//     XPropertyContainer interface should be replaced by
559 	//     XCommandProcessor commands!
560 	uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv;
561 
562 	if ( getPropertySetInfo( xEnv )->hasPropertyByName( Name ) )
563 	{
564 		// Property does already exist.
565 		throw beans::PropertyExistException();
566 	}
567 
568 	//////////////////////////////////////////////////////////////////////
569 	// Add a new dynamic property.
570 	//////////////////////////////////////////////////////////////////////
571 
572 	// Open/create persistent property set.
573     uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xSet(
574 									getAdditionalPropertySet( sal_True ) );
575 
576 	OSL_ENSURE( xSet.is(),
577                 "ContentImplHelper::addProperty - No property set!" );
578 
579 	if ( xSet.is() )
580 	{
581 		uno::Reference< beans::XPropertyContainer > xContainer(
582             xSet, uno::UNO_QUERY );
583 
584 		OSL_ENSURE(
585             xContainer.is(),
586             "ContentImplHelper::addProperty - No property container!" );
587 
588 		if ( xContainer.is() )
589 		{
590 			// Property is always removeable.
591 			Attributes |= beans::PropertyAttribute::REMOVEABLE;
592 
593 			try
594 			{
595 				xContainer->addProperty( Name, Attributes, DefaultValue );
596 			}
597 			catch ( beans::PropertyExistException const & )
598 			{
599 				OSL_ENSURE( sal_False,
600 							"ContentImplHelper::addProperty - Exists!" );
601 				throw;
602 			}
603 			catch ( beans::IllegalTypeException const & )
604 			{
605 				OSL_ENSURE( sal_False,
606 							"ContentImplHelper::addProperty - Wrong Type!" );
607 				throw;
608 			}
609 			catch ( lang::IllegalArgumentException const & )
610 			{
611 				OSL_ENSURE( sal_False,
612 							"ContentImplHelper::addProperty - Illegal Arg!" );
613 				throw;
614 			}
615 
616 			// Success!
617 
618 			if ( m_pImpl->m_xPropSetInfo.is() )
619 			{
620 				// Info cached in propertyset info is invalid now!
621 				m_pImpl->m_xPropSetInfo->reset();
622 			}
623 
624 			// Notify propertyset info change listeners.
625 			if ( m_pImpl->m_pPropSetChangeListeners &&
626 				 m_pImpl->m_pPropSetChangeListeners->getLength() )
627 			{
628 				beans::PropertySetInfoChangeEvent evt(
629 							static_cast< cppu::OWeakObject * >( this ),
630 							Name,
631 							-1, // No handle available
632 							beans::PropertySetInfoChange::PROPERTY_INSERTED );
633 				notifyPropertySetInfoChange( evt );
634 			}
635 		}
636 	}
637 }
638 
639 //=========================================================================
640 // virtual
641 void SAL_CALL ContentImplHelper::removeProperty( const rtl::OUString& Name )
642 	throw( beans::UnknownPropertyException,
643 		   beans::NotRemoveableException,
644 		   uno::RuntimeException )
645 {
646 	osl::MutexGuard aGuard( m_aMutex );
647 
648 	try
649 	{
650 		// @@@ Need real command environment here, but where to get it from?
651 		//     XPropertyContainer interface should be replaced by
652 		//     XCommandProcessor commands!
653 		uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv;
654 
655 		beans::Property aProp
656             = getPropertySetInfo( xEnv )->getPropertyByName( Name );
657 
658 		if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) )
659 		{
660 			// Not removeable!
661 			throw beans::NotRemoveableException();
662 		}
663 	}
664 	catch ( beans::UnknownPropertyException const & )
665 	{
666 		OSL_ENSURE( sal_False, "ContentImplHelper::removeProperty - Unknown!" );
667 		throw;
668 	}
669 
670 	//////////////////////////////////////////////////////////////////////
671 	// Try to remove property from dynamic property set.
672 	//////////////////////////////////////////////////////////////////////
673 
674 	// Open persistent property set, if exists.
675     uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xSet(
676         getAdditionalPropertySet( sal_False ) );
677 	if ( xSet.is() )
678 	{
679 		uno::Reference< beans::XPropertyContainer > xContainer(
680             xSet, uno::UNO_QUERY );
681 
682 		OSL_ENSURE(
683             xContainer.is(),
684             "ContentImplHelper::removeProperty - No property container!" );
685 
686 		if ( xContainer.is() )
687 		{
688 			try
689 			{
690 				xContainer->removeProperty( Name );
691 			}
692 			catch ( beans::UnknownPropertyException const & )
693 			{
694 				OSL_ENSURE( sal_False,
695 							"ContentImplHelper::removeProperty - Unknown!" );
696 				throw;
697 			}
698 			catch ( beans::NotRemoveableException const & )
699 			{
700 				OSL_ENSURE(
701                     sal_False,
702                     "ContentImplHelper::removeProperty - Unremoveable!" );
703 				throw;
704 			}
705 
706 			xContainer = 0;
707 
708 			// Success!
709 
710 			if ( xSet->getPropertySetInfo()->getProperties().getLength() == 0 )
711 			{
712 				// Remove empty propertyset from registry.
713     			uno::Reference< com::sun::star::ucb::XPropertySetRegistry >
714                     xReg = xSet->getRegistry();
715 				if ( xReg.is() )
716 				{
717 					rtl::OUString aKey( xSet->getKey() );
718 					xSet = 0;
719 					xReg->removePropertySet( aKey );
720 				}
721 			}
722 
723 			if ( m_pImpl->m_xPropSetInfo.is() )
724 			{
725 				// Info cached in propertyset info is invalid now!
726 				m_pImpl->m_xPropSetInfo->reset();
727 			}
728 
729 			// Notify propertyset info change listeners.
730 			if ( m_pImpl->m_pPropSetChangeListeners &&
731 				 m_pImpl->m_pPropSetChangeListeners->getLength() )
732 			{
733 				beans::PropertySetInfoChangeEvent evt(
734 							static_cast< cppu::OWeakObject * >( this ),
735 							Name,
736 							-1, // No handle available
737 							beans::PropertySetInfoChange::PROPERTY_REMOVED );
738 				notifyPropertySetInfoChange( evt );
739 			}
740 		}
741 	}
742 }
743 
744 //=========================================================================
745 //
746 // XPropertySetInfoChangeNotifier methods.
747 //
748 //=========================================================================
749 
750 // virtual
751 void SAL_CALL ContentImplHelper::addPropertySetInfoChangeListener(
752         const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
753 	throw( uno::RuntimeException )
754 {
755 	osl::MutexGuard aGuard( m_aMutex );
756 
757 	if ( !m_pImpl->m_pPropSetChangeListeners )
758 		m_pImpl->m_pPropSetChangeListeners
759 			= new cppu::OInterfaceContainerHelper( m_aMutex );
760 
761 	m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
762 }
763 
764 //=========================================================================
765 // virtual
766 void SAL_CALL ContentImplHelper::removePropertySetInfoChangeListener(
767         const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
768 	throw( uno::RuntimeException )
769 {
770 	osl::MutexGuard aGuard( m_aMutex );
771 
772 	if ( m_pImpl->m_pPropSetChangeListeners )
773 		m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
774 }
775 
776 //=========================================================================
777 //
778 // XChild methods.
779 //
780 //=========================================================================
781 
782 // virtual
783 uno::Reference< uno::XInterface > SAL_CALL ContentImplHelper::getParent()
784 	throw( uno::RuntimeException )
785 {
786     uno::Reference< uno::XInterface > xParent;
787 	rtl::OUString aURL = getParentURL();
788 
789 	if ( aURL.getLength() )
790 	{
791 		uno::Reference< com::sun::star::ucb::XContentIdentifier > xId(
792             new ContentIdentifier( m_xSMgr, aURL ) );
793         try
794         {
795             xParent.set( m_xProvider->queryContent( xId ) );
796         }
797         catch ( com::sun::star::ucb::IllegalIdentifierException const & )
798         {
799         }
800 	}
801 
802     return xParent;
803 }
804 
805 //=========================================================================
806 // virtual
807 void SAL_CALL ContentImplHelper::setParent(
808 									const uno::Reference< uno::XInterface >& )
809 	throw( lang::NoSupportException, uno::RuntimeException )
810 {
811 	throw lang::NoSupportException();
812 }
813 
814 //=========================================================================
815 //
816 // Non-interface methods
817 //
818 //=========================================================================
819 
820 uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
821 ContentImplHelper::getAdditionalPropertySet( sal_Bool bCreate )
822 {
823 	// Get propertyset from provider.
824 	return m_xProvider->getAdditionalPropertySet(
825 							m_xIdentifier->getContentIdentifier(), bCreate );
826 }
827 
828 //=========================================================================
829 sal_Bool ContentImplHelper::renameAdditionalPropertySet(
830     const rtl::OUString& rOldKey,
831     const rtl::OUString& rNewKey,
832     sal_Bool bRecursive )
833 {
834 	return m_xProvider->renameAdditionalPropertySet(
835 											rOldKey, rNewKey, bRecursive );
836 }
837 
838 //=========================================================================
839 sal_Bool ContentImplHelper::copyAdditionalPropertySet(
840     const rtl::OUString& rSourceKey,
841     const rtl::OUString& rTargetKey,
842     sal_Bool bRecursive )
843 {
844 	return m_xProvider->copyAdditionalPropertySet(
845 										rSourceKey, rTargetKey, bRecursive );
846 }
847 
848 //=========================================================================
849 sal_Bool ContentImplHelper::removeAdditionalPropertySet( sal_Bool bRecursive )
850 {
851 	return m_xProvider->removeAdditionalPropertySet(
852 					m_xIdentifier->getContentIdentifier(), bRecursive );
853 }
854 
855 //=========================================================================
856 void ContentImplHelper::notifyPropertiesChange(
857     const uno::Sequence< beans::PropertyChangeEvent >& evt ) const
858 {
859 	if ( !m_pImpl->m_pPropertyChangeListeners )
860 		return;
861 
862 	sal_Int32 nCount = evt.getLength();
863 	if ( nCount )
864 	{
865 		// First, notify listeners interested in changes of every property.
866 		cppu::OInterfaceContainerHelper* pAllPropsContainer
867 			= m_pImpl->m_pPropertyChangeListeners->getContainer(
868                 rtl::OUString() );
869 		if ( pAllPropsContainer )
870 		{
871 			cppu::OInterfaceIteratorHelper aIter( *pAllPropsContainer );
872 			while ( aIter.hasMoreElements() )
873 			{
874 				// Propagate event.
875 				uno::Reference< beans::XPropertiesChangeListener > xListener(
876                     aIter.next(), uno::UNO_QUERY );
877 				if ( xListener.is() )
878 					xListener->propertiesChange( evt );
879 			}
880 		}
881 
882 		PropertiesEventListenerMap aListeners;
883 
884 		const beans::PropertyChangeEvent* pEvents = evt.getConstArray();
885 
886 		for ( sal_Int32 n = 0; n < nCount; ++n )
887 		{
888 			const beans::PropertyChangeEvent& rEvent = pEvents[ n ];
889 			const rtl::OUString& rName = rEvent.PropertyName;
890 
891 			cppu::OInterfaceContainerHelper* pPropsContainer
892 				= m_pImpl->m_pPropertyChangeListeners->getContainer( rName );
893 			if ( pPropsContainer )
894 			{
895 				cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
896 				while ( aIter.hasMoreElements() )
897 				{
898 					PropertyEventSequence* p = NULL;
899 
900 					beans::XPropertiesChangeListener* pListener =
901 						static_cast< beans::XPropertiesChangeListener * >(
902 															aIter.next() );
903 					PropertiesEventListenerMap::iterator it =
904 							aListeners.find( pListener );
905 					if ( it == aListeners.end() )
906 					{
907 						// Not in map - create and insert new entry.
908 						p = new PropertyEventSequence( nCount );
909 						aListeners[ pListener ] = p;
910 					}
911 					else
912 						p = (*it).second;
913 
914 					if ( p )
915 						p->append( rEvent );
916 				}
917 			}
918 		}
919 
920 		// Notify listeners.
921 		PropertiesEventListenerMap::iterator it = aListeners.begin();
922 		while ( !aListeners.empty() )
923 		{
924 			beans::XPropertiesChangeListener* pListener =
925                 static_cast< beans::XPropertiesChangeListener * >( (*it).first );
926 			PropertyEventSequence* pSeq = (*it).second;
927 
928 			// Remove current element.
929 			aListeners.erase( it );
930 
931 			// Propagate event.
932 			pListener->propertiesChange( pSeq->getEvents() );
933 
934 			delete pSeq;
935 
936 			it = aListeners.begin();
937 		}
938 	}
939 }
940 
941 //=========================================================================
942 void ContentImplHelper::notifyPropertySetInfoChange(
943     const beans::PropertySetInfoChangeEvent& evt ) const
944 {
945 	if ( !m_pImpl->m_pPropSetChangeListeners )
946 		return;
947 
948 	// Notify event listeners.
949 	cppu::OInterfaceIteratorHelper aIter( *m_pImpl->m_pPropSetChangeListeners );
950 	while ( aIter.hasMoreElements() )
951 	{
952 		// Propagate event.
953 		uno::Reference< beans::XPropertySetInfoChangeListener >
954             xListener( aIter.next(), uno::UNO_QUERY );
955 		if ( xListener.is() )
956 			xListener->propertySetInfoChange( evt );
957 	}
958 }
959 
960 //=========================================================================
961 void ContentImplHelper::notifyCommandInfoChange(
962     const com::sun::star::ucb::CommandInfoChangeEvent& evt ) const
963 {
964 	if ( !m_pImpl->m_pCommandChangeListeners )
965 		return;
966 
967 	// Notify event listeners.
968 	cppu::OInterfaceIteratorHelper aIter(
969         *m_pImpl->m_pCommandChangeListeners );
970 	while ( aIter.hasMoreElements() )
971 	{
972 		// Propagate event.
973 		uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >
974             xListener( aIter.next(), uno::UNO_QUERY );
975 		if ( xListener.is() )
976 			xListener->commandInfoChange( evt );
977 	}
978 }
979 
980 //=========================================================================
981 void ContentImplHelper::notifyContentEvent(
982     const com::sun::star::ucb::ContentEvent& evt ) const
983 {
984 	if ( !m_pImpl->m_pContentEventListeners )
985 		return;
986 
987 	// Notify event listeners.
988 	cppu::OInterfaceIteratorHelper aIter( *m_pImpl->m_pContentEventListeners );
989 	while ( aIter.hasMoreElements() )
990 	{
991 		// Propagate event.
992 		uno::Reference<
993             com::sun::star::ucb::XContentEventListener > xListener(
994                 aIter.next(), uno::UNO_QUERY );
995 		if ( xListener.is() )
996 			xListener->contentEvent( evt );
997 	}
998 }
999 
1000 //=========================================================================
1001 void ContentImplHelper::inserted()
1002 {
1003 	// Content is not yet registered at provider.
1004 	m_xProvider->registerNewContent( this );
1005 
1006 	// If the parent content is currently not instanciated, there can be
1007 	// no listeners interested in changes ;-)
1008 
1009 	rtl::Reference< ContentImplHelper > xParent
1010 				= m_xProvider->queryExistingContent( getParentURL() );
1011 
1012 	if ( xParent.is() )
1013 	{
1014 		com::sun::star::ucb::ContentEvent aEvt(
1015             static_cast< cppu::OWeakObject * >( xParent.get() ), // Source
1016             com::sun::star::ucb::ContentAction::INSERTED,		 // Action
1017             this,									             // Content
1018             xParent->getIdentifier() );				             // Id
1019 		xParent->notifyContentEvent( aEvt );
1020 	}
1021 }
1022 
1023 //=========================================================================
1024 void ContentImplHelper::deleted()
1025 {
1026 	uno::Reference< com::sun::star::ucb::XContent > xThis = this;
1027 
1028 	rtl::Reference< ContentImplHelper > xParent
1029 					= m_xProvider->queryExistingContent( getParentURL() );
1030 
1031 	if ( xParent.is() )
1032 	{
1033 		// Let parent notify "REMOVED" event.
1034 		com::sun::star::ucb::ContentEvent aEvt(
1035             static_cast< cppu::OWeakObject * >( xParent.get() ),
1036             com::sun::star::ucb::ContentAction::REMOVED,
1037             this,
1038             xParent->getIdentifier()	);
1039 		xParent->notifyContentEvent( aEvt );
1040 	}
1041 
1042 	// Notify "DELETED" event.
1043 	com::sun::star::ucb::ContentEvent aEvt1(
1044         static_cast< cppu::OWeakObject * >( this ),
1045         com::sun::star::ucb::ContentAction::DELETED,
1046         this,
1047         getIdentifier() );
1048 	notifyContentEvent( aEvt1 );
1049 
1050 	m_xProvider->removeContent( this );
1051 }
1052 
1053 //=========================================================================
1054 sal_Bool ContentImplHelper::exchange(
1055     const uno::Reference< com::sun::star::ucb::XContentIdentifier >& rNewId )
1056 {
1057 	uno::Reference< com::sun::star::ucb::XContent > xThis = this;
1058 
1059 	osl::ClearableMutexGuard aGuard( m_aMutex );
1060 
1061 	rtl::Reference< ContentImplHelper > xContent
1062         = m_xProvider->queryExistingContent( rNewId );
1063 	if ( xContent.is() )
1064 	{
1065 		// @@@
1066 		// Big trouble. Another object with the new identity exists.
1067 		// How shall I mutate to / merge with the other object?
1068 		return sal_False;
1069 	}
1070 
1071 	uno::Reference< com::sun::star::ucb::XContentIdentifier > xOldId
1072         = getIdentifier();
1073 
1074 	// Re-insert at provider.
1075 	m_xProvider->removeContent( this );
1076 	m_xIdentifier = rNewId;
1077 	m_xProvider->registerNewContent( this );
1078 
1079 	aGuard.clear();
1080 
1081 	// Notify "EXCHANGED" event.
1082 	com::sun::star::ucb::ContentEvent aEvt(
1083         static_cast< cppu::OWeakObject * >( this ),
1084         com::sun::star::ucb::ContentAction::EXCHANGED,
1085         this,
1086         xOldId );
1087 	notifyContentEvent( aEvt );
1088 	return sal_True;
1089 }
1090 
1091 //=========================================================================
1092 uno::Reference< com::sun::star::ucb::XCommandInfo >
1093 ContentImplHelper::getCommandInfo(
1094     const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv,
1095     sal_Bool bCache )
1096 {
1097 	osl::MutexGuard aGuard( m_aMutex );
1098 
1099 	if ( !m_pImpl->m_xCommandsInfo.is() )
1100 		m_pImpl->m_xCommandsInfo
1101 			= new CommandProcessorInfo( m_xSMgr, xEnv, this );
1102 	else if ( !bCache )
1103 		m_pImpl->m_xCommandsInfo->reset();
1104 
1105 	return uno::Reference< com::sun::star::ucb::XCommandInfo >(
1106         m_pImpl->m_xCommandsInfo.get() );
1107 }
1108 
1109 //=========================================================================
1110 uno::Reference< beans::XPropertySetInfo >
1111 ContentImplHelper::getPropertySetInfo(
1112     const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv,
1113     sal_Bool bCache )
1114 {
1115 	osl::MutexGuard aGuard( m_aMutex );
1116 
1117 	if ( !m_pImpl->m_xPropSetInfo.is() )
1118 		m_pImpl->m_xPropSetInfo
1119 			= new PropertySetInfo( m_xSMgr, xEnv, this );
1120 	else if ( !bCache )
1121 		m_pImpl->m_xPropSetInfo->reset();
1122 
1123 	return uno::Reference< beans::XPropertySetInfo >(
1124 									m_pImpl->m_xPropSetInfo.get() );
1125 }
1126 
1127 } // namespace ucbhelper
1128