xref: /trunk/main/ucbhelper/source/provider/contenthelper.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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