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