xref: /trunk/main/ucbhelper/source/provider/contenthelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
233     com::sun::star::uno::Any aRet = cppu::queryInterface( rType,
234             static_cast< lang::XTypeProvider * >(this),
235             static_cast< lang::XServiceInfo * >(this),
236             static_cast< lang::XComponent * >(this),
237             static_cast< com::sun::star::ucb::XContent * >(this),
238             static_cast< com::sun::star::ucb::XCommandProcessor * >(this),
239             static_cast< beans::XPropertiesChangeNotifier * >(this),
240             static_cast< com::sun::star::ucb::XCommandInfoChangeNotifier * >(this),
241             static_cast< beans::XPropertyContainer * >(this),
242             static_cast< beans::XPropertySetInfoChangeNotifier * >(this),
243             static_cast< container::XChild * >(this));
244     return aRet.hasValue() ? aRet : cppu::OWeakObject::queryInterface( rType );
245 }
246 
247 //=========================================================================
248 //
249 // XTypeProvider methods.
250 //
251 //=========================================================================
252 
253 XTYPEPROVIDER_IMPL_10( ContentImplHelper,
254                        lang::XTypeProvider,
255                        lang::XServiceInfo,
256                        lang::XComponent,
257                        com::sun::star::ucb::XContent,
258                        com::sun::star::ucb::XCommandProcessor,
259                        beans::XPropertiesChangeNotifier,
260                        com::sun::star::ucb::XCommandInfoChangeNotifier,
261                        beans::XPropertyContainer,
262                        beans::XPropertySetInfoChangeNotifier,
263                        container::XChild );
264 
265 //=========================================================================
266 //
267 // XServiceInfo methods.
268 //
269 //=========================================================================
270 
271 // virtual
supportsService(const rtl::OUString & ServiceName)272 sal_Bool SAL_CALL ContentImplHelper::supportsService(
273                                             const rtl::OUString& ServiceName )
274 {
275     uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
276     const rtl::OUString* pArray = aSNL.getConstArray();
277     for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
278     {
279         if ( pArray[ i ] == ServiceName )
280             return sal_True;
281     }
282 
283     return sal_False;
284 }
285 
286 //=========================================================================
287 //
288 // XComponent methods.
289 //
290 //=========================================================================
291 
292 // virtual
dispose()293 void SAL_CALL ContentImplHelper::dispose()
294 {
295     osl::MutexGuard aGuard( m_aMutex );
296 
297     if ( m_pImpl->m_pDisposeEventListeners &&
298          m_pImpl->m_pDisposeEventListeners->getLength() )
299     {
300         lang::EventObject aEvt;
301         aEvt.Source = static_cast< lang::XComponent * >( this );
302         m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
303     }
304 
305     if ( m_pImpl->m_pContentEventListeners &&
306          m_pImpl->m_pContentEventListeners->getLength() )
307     {
308         lang::EventObject aEvt;
309         aEvt.Source = static_cast< com::sun::star::ucb::XContent * >( this );
310         m_pImpl->m_pContentEventListeners->disposeAndClear( aEvt );
311     }
312 
313     if ( m_pImpl->m_pPropSetChangeListeners &&
314          m_pImpl->m_pPropSetChangeListeners->getLength() )
315     {
316         lang::EventObject aEvt;
317         aEvt.Source
318             = static_cast< beans::XPropertySetInfoChangeNotifier * >( this );
319         m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
320     }
321 
322     if ( m_pImpl->m_pCommandChangeListeners &&
323          m_pImpl->m_pCommandChangeListeners->getLength() )
324     {
325         lang::EventObject aEvt;
326         aEvt.Source = static_cast<  com::sun::star::ucb::XCommandInfoChangeNotifier * >( this );
327         m_pImpl->m_pCommandChangeListeners->disposeAndClear( aEvt );
328     }
329 
330     if ( m_pImpl->m_pPropertyChangeListeners )
331     {
332         lang::EventObject aEvt;
333         aEvt.Source
334             = static_cast< beans::XPropertiesChangeNotifier * >( this );
335         m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
336     }
337 }
338 
339 //=========================================================================
340 // virtual
addEventListener(const uno::Reference<lang::XEventListener> & Listener)341 void SAL_CALL ContentImplHelper::addEventListener(
342         const uno::Reference< lang::XEventListener >& Listener )
343 {
344     osl::MutexGuard aGuard( m_aMutex );
345 
346     if ( !m_pImpl->m_pDisposeEventListeners )
347         m_pImpl->m_pDisposeEventListeners
348             = new cppu::OInterfaceContainerHelper( m_aMutex );
349 
350     m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
351 }
352 
353 //=========================================================================
354 // virtual
removeEventListener(const uno::Reference<lang::XEventListener> & Listener)355 void SAL_CALL ContentImplHelper::removeEventListener(
356         const uno::Reference< lang::XEventListener >& Listener )
357 {
358     osl::MutexGuard aGuard( m_aMutex );
359 
360     if ( m_pImpl->m_pDisposeEventListeners )
361         m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
362 }
363 
364 //=========================================================================
365 //
366 // XContent methods.
367 //
368 //=========================================================================
369 
370 // virtual
371 uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL
getIdentifier()372 ContentImplHelper::getIdentifier()
373 {
374     return m_xIdentifier;
375 }
376 
377 //=========================================================================
378 // virtual
addContentEventListener(const uno::Reference<com::sun::star::ucb::XContentEventListener> & Listener)379 void SAL_CALL ContentImplHelper::addContentEventListener(
380         const uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener )
381 {
382     osl::MutexGuard aGuard( m_aMutex );
383 
384     if ( !m_pImpl->m_pContentEventListeners )
385         m_pImpl->m_pContentEventListeners
386             = new cppu::OInterfaceContainerHelper( m_aMutex );
387 
388     m_pImpl->m_pContentEventListeners->addInterface( Listener );
389 }
390 
391 //=========================================================================
392 // virtual
removeContentEventListener(const uno::Reference<com::sun::star::ucb::XContentEventListener> & Listener)393 void SAL_CALL ContentImplHelper::removeContentEventListener(
394         const uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener )
395 {
396     osl::MutexGuard aGuard( m_aMutex );
397 
398     if ( m_pImpl->m_pContentEventListeners )
399         m_pImpl->m_pContentEventListeners->removeInterface( Listener );
400 }
401 
402 //=========================================================================
403 //
404 // XCommandProcessor methods.
405 //
406 //=========================================================================
407 
408 // virtual
createCommandIdentifier()409 sal_Int32 SAL_CALL ContentImplHelper::createCommandIdentifier()
410 {
411     osl::MutexGuard aGuard( m_aMutex );
412 
413     // Just increase counter on every call to generate an identifier.
414     return ++m_nCommandId;
415 }
416 
417 //=========================================================================
418 //
419 // XPropertiesChangeNotifier methods.
420 //
421 //=========================================================================
422 
423 // virtual
addPropertiesChangeListener(const uno::Sequence<rtl::OUString> & PropertyNames,const uno::Reference<beans::XPropertiesChangeListener> & Listener)424 void SAL_CALL ContentImplHelper::addPropertiesChangeListener(
425         const uno::Sequence< rtl::OUString >& PropertyNames,
426         const uno::Reference< beans::XPropertiesChangeListener >& Listener )
427 {
428     osl::MutexGuard aGuard( m_aMutex );
429 
430     if ( !m_pImpl->m_pPropertyChangeListeners )
431         m_pImpl->m_pPropertyChangeListeners
432             = new PropertyChangeListeners( m_aMutex );
433 
434     sal_Int32 nCount = PropertyNames.getLength();
435     if ( !nCount )
436     {
437         // Note: An empty sequence means a listener for "all" properties.
438         m_pImpl->m_pPropertyChangeListeners->addInterface(
439             rtl::OUString(), Listener );
440     }
441     else
442     {
443         const rtl::OUString* pSeq = PropertyNames.getConstArray();
444 
445         for ( sal_Int32 n = 0; n < nCount; ++n )
446         {
447             const rtl::OUString& rName = pSeq[ n ];
448             if ( rName.getLength() )
449                 m_pImpl->m_pPropertyChangeListeners->addInterface(
450                     rName, Listener );
451         }
452     }
453 }
454 
455 //=========================================================================
456 // virtual
removePropertiesChangeListener(const uno::Sequence<rtl::OUString> & PropertyNames,const uno::Reference<beans::XPropertiesChangeListener> & Listener)457 void SAL_CALL ContentImplHelper::removePropertiesChangeListener(
458         const uno::Sequence< rtl::OUString >& PropertyNames,
459         const uno::Reference< beans::XPropertiesChangeListener >& Listener )
460 {
461     osl::MutexGuard aGuard( m_aMutex );
462 
463     if ( !m_pImpl->m_pPropertyChangeListeners )
464         return;
465 
466     sal_Int32 nCount = PropertyNames.getLength();
467     if ( !nCount )
468     {
469         // Note: An empty sequence means a listener for "all" properties.
470         m_pImpl->m_pPropertyChangeListeners->removeInterface(
471             rtl::OUString(), Listener );
472     }
473     else
474     {
475         const rtl::OUString* pSeq = PropertyNames.getConstArray();
476 
477         for ( sal_Int32 n = 0; n < nCount; ++n )
478         {
479             const rtl::OUString& rName = pSeq[ n ];
480             if ( rName.getLength() )
481                 m_pImpl->m_pPropertyChangeListeners->removeInterface(
482                     rName, Listener );
483         }
484     }
485 }
486 
487 //=========================================================================
488 //
489 // XCommandInfoChangeNotifier methods.
490 //
491 //=========================================================================
492 
493 // virtual
addCommandInfoChangeListener(const uno::Reference<com::sun::star::ucb::XCommandInfoChangeListener> & Listener)494 void SAL_CALL ContentImplHelper::addCommandInfoChangeListener(
495         const uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >& Listener )
496 {
497     osl::MutexGuard aGuard( m_aMutex );
498 
499     if ( !m_pImpl->m_pCommandChangeListeners )
500         m_pImpl->m_pCommandChangeListeners
501             = new cppu::OInterfaceContainerHelper( m_aMutex );
502 
503     m_pImpl->m_pCommandChangeListeners->addInterface( Listener );
504 }
505 
506 //=========================================================================
507 // virtual
removeCommandInfoChangeListener(const uno::Reference<com::sun::star::ucb::XCommandInfoChangeListener> & Listener)508 void SAL_CALL ContentImplHelper::removeCommandInfoChangeListener(
509         const uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >& Listener )
510 {
511     osl::MutexGuard aGuard( m_aMutex );
512 
513     if ( m_pImpl->m_pCommandChangeListeners )
514         m_pImpl->m_pCommandChangeListeners->removeInterface( Listener );
515 }
516 
517 //=========================================================================
518 //
519 // XPropertyContainer methods.
520 //
521 //=========================================================================
522 
523 // virtual
addProperty(const rtl::OUString & Name,sal_Int16 Attributes,const uno::Any & DefaultValue)524 void SAL_CALL ContentImplHelper::addProperty(
525         const rtl::OUString& Name,
526         sal_Int16 Attributes,
527         const uno::Any& DefaultValue )
528 {
529     osl::MutexGuard aGuard( m_aMutex );
530 
531     //////////////////////////////////////////////////////////////////////
532     // Make sure a property with the requested name does not already
533     // exist in dynamic and static(!) properties.
534     //////////////////////////////////////////////////////////////////////
535 
536     // @@@ Need real command environment here, but where to get it from?
537     //     XPropertyContainer interface should be replaced by
538     //     XCommandProcessor commands!
539     uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv;
540 
541     if ( getPropertySetInfo( xEnv )->hasPropertyByName( Name ) )
542     {
543         // Property does already exist.
544         throw beans::PropertyExistException();
545     }
546 
547     //////////////////////////////////////////////////////////////////////
548     // Add a new dynamic property.
549     //////////////////////////////////////////////////////////////////////
550 
551     // Open/create persistent property set.
552     uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xSet(
553                                     getAdditionalPropertySet( sal_True ) );
554 
555     OSL_ENSURE( xSet.is(),
556                 "ContentImplHelper::addProperty - No property set!" );
557 
558     if ( xSet.is() )
559     {
560         uno::Reference< beans::XPropertyContainer > xContainer(
561             xSet, uno::UNO_QUERY );
562 
563         OSL_ENSURE(
564             xContainer.is(),
565             "ContentImplHelper::addProperty - No property container!" );
566 
567         if ( xContainer.is() )
568         {
569             // Property is always removeable.
570             Attributes |= beans::PropertyAttribute::REMOVEABLE;
571 
572             try
573             {
574                 xContainer->addProperty( Name, Attributes, DefaultValue );
575             }
576             catch ( beans::PropertyExistException const & )
577             {
578                 OSL_ENSURE( sal_False,
579                             "ContentImplHelper::addProperty - Exists!" );
580                 throw;
581             }
582             catch ( beans::IllegalTypeException const & )
583             {
584                 OSL_ENSURE( sal_False,
585                             "ContentImplHelper::addProperty - Wrong Type!" );
586                 throw;
587             }
588             catch ( lang::IllegalArgumentException const & )
589             {
590                 OSL_ENSURE( sal_False,
591                             "ContentImplHelper::addProperty - Illegal Arg!" );
592                 throw;
593             }
594 
595             // Success!
596 
597             if ( m_pImpl->m_xPropSetInfo.is() )
598             {
599                 // Info cached in propertyset info is invalid now!
600                 m_pImpl->m_xPropSetInfo->reset();
601             }
602 
603             // Notify propertyset info change listeners.
604             if ( m_pImpl->m_pPropSetChangeListeners &&
605                  m_pImpl->m_pPropSetChangeListeners->getLength() )
606             {
607                 beans::PropertySetInfoChangeEvent evt(
608                             static_cast< cppu::OWeakObject * >( this ),
609                             Name,
610                             -1, // No handle available
611                             beans::PropertySetInfoChange::PROPERTY_INSERTED );
612                 notifyPropertySetInfoChange( evt );
613             }
614         }
615     }
616 }
617 
618 //=========================================================================
619 // virtual
removeProperty(const rtl::OUString & Name)620 void SAL_CALL ContentImplHelper::removeProperty( const rtl::OUString& Name )
621 {
622     osl::MutexGuard aGuard( m_aMutex );
623 
624     try
625     {
626         // @@@ Need real command environment here, but where to get it from?
627         //     XPropertyContainer interface should be replaced by
628         //     XCommandProcessor commands!
629         uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv;
630 
631         beans::Property aProp
632             = getPropertySetInfo( xEnv )->getPropertyByName( Name );
633 
634         if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) )
635         {
636             // Not removeable!
637             throw beans::NotRemoveableException();
638         }
639     }
640     catch ( beans::UnknownPropertyException const & )
641     {
642         OSL_ENSURE( sal_False, "ContentImplHelper::removeProperty - Unknown!" );
643         throw;
644     }
645 
646     //////////////////////////////////////////////////////////////////////
647     // Try to remove property from dynamic property set.
648     //////////////////////////////////////////////////////////////////////
649 
650     // Open persistent property set, if exists.
651     uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xSet(
652         getAdditionalPropertySet( sal_False ) );
653     if ( xSet.is() )
654     {
655         uno::Reference< beans::XPropertyContainer > xContainer(
656             xSet, uno::UNO_QUERY );
657 
658         OSL_ENSURE(
659             xContainer.is(),
660             "ContentImplHelper::removeProperty - No property container!" );
661 
662         if ( xContainer.is() )
663         {
664             try
665             {
666                 xContainer->removeProperty( Name );
667             }
668             catch ( beans::UnknownPropertyException const & )
669             {
670                 OSL_ENSURE( sal_False,
671                             "ContentImplHelper::removeProperty - Unknown!" );
672                 throw;
673             }
674             catch ( beans::NotRemoveableException const & )
675             {
676                 OSL_ENSURE(
677                     sal_False,
678                     "ContentImplHelper::removeProperty - Unremoveable!" );
679                 throw;
680             }
681 
682             xContainer = 0;
683 
684             // Success!
685 
686             if ( xSet->getPropertySetInfo()->getProperties().getLength() == 0 )
687             {
688                 // Remove empty propertyset from registry.
689                 uno::Reference< com::sun::star::ucb::XPropertySetRegistry >
690                     xReg = xSet->getRegistry();
691                 if ( xReg.is() )
692                 {
693                     rtl::OUString aKey( xSet->getKey() );
694                     xSet = 0;
695                     xReg->removePropertySet( aKey );
696                 }
697             }
698 
699             if ( m_pImpl->m_xPropSetInfo.is() )
700             {
701                 // Info cached in propertyset info is invalid now!
702                 m_pImpl->m_xPropSetInfo->reset();
703             }
704 
705             // Notify propertyset info change listeners.
706             if ( m_pImpl->m_pPropSetChangeListeners &&
707                  m_pImpl->m_pPropSetChangeListeners->getLength() )
708             {
709                 beans::PropertySetInfoChangeEvent evt(
710                             static_cast< cppu::OWeakObject * >( this ),
711                             Name,
712                             -1, // No handle available
713                             beans::PropertySetInfoChange::PROPERTY_REMOVED );
714                 notifyPropertySetInfoChange( evt );
715             }
716         }
717     }
718 }
719 
720 //=========================================================================
721 //
722 // XPropertySetInfoChangeNotifier methods.
723 //
724 //=========================================================================
725 
726 // virtual
addPropertySetInfoChangeListener(const uno::Reference<beans::XPropertySetInfoChangeListener> & Listener)727 void SAL_CALL ContentImplHelper::addPropertySetInfoChangeListener(
728         const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
729 {
730     osl::MutexGuard aGuard( m_aMutex );
731 
732     if ( !m_pImpl->m_pPropSetChangeListeners )
733         m_pImpl->m_pPropSetChangeListeners
734             = new cppu::OInterfaceContainerHelper( m_aMutex );
735 
736     m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
737 }
738 
739 //=========================================================================
740 // virtual
removePropertySetInfoChangeListener(const uno::Reference<beans::XPropertySetInfoChangeListener> & Listener)741 void SAL_CALL ContentImplHelper::removePropertySetInfoChangeListener(
742         const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
743 {
744     osl::MutexGuard aGuard( m_aMutex );
745 
746     if ( m_pImpl->m_pPropSetChangeListeners )
747         m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
748 }
749 
750 //=========================================================================
751 //
752 // XChild methods.
753 //
754 //=========================================================================
755 
756 // virtual
getParent()757 uno::Reference< uno::XInterface > SAL_CALL ContentImplHelper::getParent()
758 {
759     uno::Reference< uno::XInterface > xParent;
760     rtl::OUString aURL = getParentURL();
761 
762     if ( aURL.getLength() )
763     {
764         uno::Reference< com::sun::star::ucb::XContentIdentifier > xId(
765             new ContentIdentifier( m_xSMgr, aURL ) );
766         try
767         {
768             xParent.set( m_xProvider->queryContent( xId ) );
769         }
770         catch ( com::sun::star::ucb::IllegalIdentifierException const & )
771         {
772         }
773     }
774 
775     return xParent;
776 }
777 
778 //=========================================================================
779 // virtual
setParent(const uno::Reference<uno::XInterface> &)780 void SAL_CALL ContentImplHelper::setParent(
781                                     const uno::Reference< uno::XInterface >& )
782 {
783     throw lang::NoSupportException();
784 }
785 
786 //=========================================================================
787 //
788 // Non-interface methods
789 //
790 //=========================================================================
791 
792 uno::Reference< com::sun::star::ucb::XPersistentPropertySet >
getAdditionalPropertySet(sal_Bool bCreate)793 ContentImplHelper::getAdditionalPropertySet( sal_Bool bCreate )
794 {
795     // Get propertyset from provider.
796     return m_xProvider->getAdditionalPropertySet(
797                             m_xIdentifier->getContentIdentifier(), bCreate );
798 }
799 
800 //=========================================================================
renameAdditionalPropertySet(const rtl::OUString & rOldKey,const rtl::OUString & rNewKey,sal_Bool bRecursive)801 sal_Bool ContentImplHelper::renameAdditionalPropertySet(
802     const rtl::OUString& rOldKey,
803     const rtl::OUString& rNewKey,
804     sal_Bool bRecursive )
805 {
806     return m_xProvider->renameAdditionalPropertySet(
807                                             rOldKey, rNewKey, bRecursive );
808 }
809 
810 //=========================================================================
copyAdditionalPropertySet(const rtl::OUString & rSourceKey,const rtl::OUString & rTargetKey,sal_Bool bRecursive)811 sal_Bool ContentImplHelper::copyAdditionalPropertySet(
812     const rtl::OUString& rSourceKey,
813     const rtl::OUString& rTargetKey,
814     sal_Bool bRecursive )
815 {
816     return m_xProvider->copyAdditionalPropertySet(
817                                         rSourceKey, rTargetKey, bRecursive );
818 }
819 
820 //=========================================================================
removeAdditionalPropertySet(sal_Bool bRecursive)821 sal_Bool ContentImplHelper::removeAdditionalPropertySet( sal_Bool bRecursive )
822 {
823     return m_xProvider->removeAdditionalPropertySet(
824                     m_xIdentifier->getContentIdentifier(), bRecursive );
825 }
826 
827 //=========================================================================
notifyPropertiesChange(const uno::Sequence<beans::PropertyChangeEvent> & evt) const828 void ContentImplHelper::notifyPropertiesChange(
829     const uno::Sequence< beans::PropertyChangeEvent >& evt ) const
830 {
831     if ( !m_pImpl->m_pPropertyChangeListeners )
832         return;
833 
834     sal_Int32 nCount = evt.getLength();
835     if ( nCount )
836     {
837         // First, notify listeners interested in changes of every property.
838         cppu::OInterfaceContainerHelper* pAllPropsContainer
839             = m_pImpl->m_pPropertyChangeListeners->getContainer(
840                 rtl::OUString() );
841         if ( pAllPropsContainer )
842         {
843             cppu::OInterfaceIteratorHelper aIter( *pAllPropsContainer );
844             while ( aIter.hasMoreElements() )
845             {
846                 // Propagate event.
847                 uno::Reference< beans::XPropertiesChangeListener > xListener(
848                     aIter.next(), uno::UNO_QUERY );
849                 if ( xListener.is() )
850                     xListener->propertiesChange( evt );
851             }
852         }
853 
854         PropertiesEventListenerMap aListeners;
855 
856         const beans::PropertyChangeEvent* pEvents = evt.getConstArray();
857 
858         for ( sal_Int32 n = 0; n < nCount; ++n )
859         {
860             const beans::PropertyChangeEvent& rEvent = pEvents[ n ];
861             const rtl::OUString& rName = rEvent.PropertyName;
862 
863             cppu::OInterfaceContainerHelper* pPropsContainer
864                 = m_pImpl->m_pPropertyChangeListeners->getContainer( rName );
865             if ( pPropsContainer )
866             {
867                 cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
868                 while ( aIter.hasMoreElements() )
869                 {
870                     PropertyEventSequence* p = NULL;
871 
872                     beans::XPropertiesChangeListener* pListener =
873                         static_cast< beans::XPropertiesChangeListener * >(
874                                                             aIter.next() );
875                     PropertiesEventListenerMap::iterator it =
876                             aListeners.find( pListener );
877                     if ( it == aListeners.end() )
878                     {
879                         // Not in map - create and insert new entry.
880                         p = new PropertyEventSequence( nCount );
881                         aListeners[ pListener ] = p;
882                     }
883                     else
884                         p = (*it).second;
885 
886                     if ( p )
887                         p->append( rEvent );
888                 }
889             }
890         }
891 
892         // Notify listeners.
893         PropertiesEventListenerMap::iterator it = aListeners.begin();
894         while ( !aListeners.empty() )
895         {
896             beans::XPropertiesChangeListener* pListener =
897                 static_cast< beans::XPropertiesChangeListener * >( (*it).first );
898             PropertyEventSequence* pSeq = (*it).second;
899 
900             // Remove current element.
901             aListeners.erase( it );
902 
903             // Propagate event.
904             pListener->propertiesChange( pSeq->getEvents() );
905 
906             delete pSeq;
907 
908             it = aListeners.begin();
909         }
910     }
911 }
912 
913 //=========================================================================
notifyPropertySetInfoChange(const beans::PropertySetInfoChangeEvent & evt) const914 void ContentImplHelper::notifyPropertySetInfoChange(
915     const beans::PropertySetInfoChangeEvent& evt ) const
916 {
917     if ( !m_pImpl->m_pPropSetChangeListeners )
918         return;
919 
920     // Notify event listeners.
921     cppu::OInterfaceIteratorHelper aIter( *m_pImpl->m_pPropSetChangeListeners );
922     while ( aIter.hasMoreElements() )
923     {
924         // Propagate event.
925         uno::Reference< beans::XPropertySetInfoChangeListener >
926             xListener( aIter.next(), uno::UNO_QUERY );
927         if ( xListener.is() )
928             xListener->propertySetInfoChange( evt );
929     }
930 }
931 
932 //=========================================================================
notifyCommandInfoChange(const com::sun::star::ucb::CommandInfoChangeEvent & evt) const933 void ContentImplHelper::notifyCommandInfoChange(
934     const com::sun::star::ucb::CommandInfoChangeEvent& evt ) const
935 {
936     if ( !m_pImpl->m_pCommandChangeListeners )
937         return;
938 
939     // Notify event listeners.
940     cppu::OInterfaceIteratorHelper aIter(
941         *m_pImpl->m_pCommandChangeListeners );
942     while ( aIter.hasMoreElements() )
943     {
944         // Propagate event.
945         uno::Reference< com::sun::star::ucb::XCommandInfoChangeListener >
946             xListener( aIter.next(), uno::UNO_QUERY );
947         if ( xListener.is() )
948             xListener->commandInfoChange( evt );
949     }
950 }
951 
952 //=========================================================================
notifyContentEvent(const com::sun::star::ucb::ContentEvent & evt) const953 void ContentImplHelper::notifyContentEvent(
954     const com::sun::star::ucb::ContentEvent& evt ) const
955 {
956     if ( !m_pImpl->m_pContentEventListeners )
957         return;
958 
959     // Notify event listeners.
960     cppu::OInterfaceIteratorHelper aIter( *m_pImpl->m_pContentEventListeners );
961     while ( aIter.hasMoreElements() )
962     {
963         // Propagate event.
964         uno::Reference<
965             com::sun::star::ucb::XContentEventListener > xListener(
966                 aIter.next(), uno::UNO_QUERY );
967         if ( xListener.is() )
968             xListener->contentEvent( evt );
969     }
970 }
971 
972 //=========================================================================
inserted()973 void ContentImplHelper::inserted()
974 {
975     // Content is not yet registered at provider.
976     m_xProvider->registerNewContent( this );
977 
978     // If the parent content is currently not instantiated, there can be
979     // no listeners interested in changes ;-)
980 
981     rtl::Reference< ContentImplHelper > xParent
982                 = m_xProvider->queryExistingContent( getParentURL() );
983 
984     if ( xParent.is() )
985     {
986         com::sun::star::ucb::ContentEvent aEvt(
987             static_cast< cppu::OWeakObject * >( xParent.get() ), // Source
988             com::sun::star::ucb::ContentAction::INSERTED,        // Action
989             this,                                                // Content
990             xParent->getIdentifier() );                          // Id
991         xParent->notifyContentEvent( aEvt );
992     }
993 }
994 
995 //=========================================================================
deleted()996 void ContentImplHelper::deleted()
997 {
998     uno::Reference< com::sun::star::ucb::XContent > xThis = this;
999 
1000     rtl::Reference< ContentImplHelper > xParent
1001                     = m_xProvider->queryExistingContent( getParentURL() );
1002 
1003     if ( xParent.is() )
1004     {
1005         // Let parent notify "REMOVED" event.
1006         com::sun::star::ucb::ContentEvent aEvt(
1007             static_cast< cppu::OWeakObject * >( xParent.get() ),
1008             com::sun::star::ucb::ContentAction::REMOVED,
1009             this,
1010             xParent->getIdentifier()    );
1011         xParent->notifyContentEvent( aEvt );
1012     }
1013 
1014     // Notify "DELETED" event.
1015     com::sun::star::ucb::ContentEvent aEvt1(
1016         static_cast< cppu::OWeakObject * >( this ),
1017         com::sun::star::ucb::ContentAction::DELETED,
1018         this,
1019         getIdentifier() );
1020     notifyContentEvent( aEvt1 );
1021 
1022     m_xProvider->removeContent( this );
1023 }
1024 
1025 //=========================================================================
exchange(const uno::Reference<com::sun::star::ucb::XContentIdentifier> & rNewId)1026 sal_Bool ContentImplHelper::exchange(
1027     const uno::Reference< com::sun::star::ucb::XContentIdentifier >& rNewId )
1028 {
1029     uno::Reference< com::sun::star::ucb::XContent > xThis = this;
1030 
1031     osl::ClearableMutexGuard aGuard( m_aMutex );
1032 
1033     rtl::Reference< ContentImplHelper > xContent
1034         = m_xProvider->queryExistingContent( rNewId );
1035     if ( xContent.is() )
1036     {
1037         // @@@
1038         // Big trouble. Another object with the new identity exists.
1039         // How shall I mutate to / merge with the other object?
1040         return sal_False;
1041     }
1042 
1043     uno::Reference< com::sun::star::ucb::XContentIdentifier > xOldId
1044         = getIdentifier();
1045 
1046     // Re-insert at provider.
1047     m_xProvider->removeContent( this );
1048     m_xIdentifier = rNewId;
1049     m_xProvider->registerNewContent( this );
1050 
1051     aGuard.clear();
1052 
1053     // Notify "EXCHANGED" event.
1054     com::sun::star::ucb::ContentEvent aEvt(
1055         static_cast< cppu::OWeakObject * >( this ),
1056         com::sun::star::ucb::ContentAction::EXCHANGED,
1057         this,
1058         xOldId );
1059     notifyContentEvent( aEvt );
1060     return sal_True;
1061 }
1062 
1063 //=========================================================================
1064 uno::Reference< com::sun::star::ucb::XCommandInfo >
getCommandInfo(const uno::Reference<com::sun::star::ucb::XCommandEnvironment> & xEnv,sal_Bool bCache)1065 ContentImplHelper::getCommandInfo(
1066     const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv,
1067     sal_Bool bCache )
1068 {
1069     osl::MutexGuard aGuard( m_aMutex );
1070 
1071     if ( !m_pImpl->m_xCommandsInfo.is() )
1072         m_pImpl->m_xCommandsInfo
1073             = new CommandProcessorInfo( m_xSMgr, xEnv, this );
1074     else if ( !bCache )
1075         m_pImpl->m_xCommandsInfo->reset();
1076 
1077     return uno::Reference< com::sun::star::ucb::XCommandInfo >(
1078         m_pImpl->m_xCommandsInfo.get() );
1079 }
1080 
1081 //=========================================================================
1082 uno::Reference< beans::XPropertySetInfo >
getPropertySetInfo(const uno::Reference<com::sun::star::ucb::XCommandEnvironment> & xEnv,sal_Bool bCache)1083 ContentImplHelper::getPropertySetInfo(
1084     const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv,
1085     sal_Bool bCache )
1086 {
1087     osl::MutexGuard aGuard( m_aMutex );
1088 
1089     if ( !m_pImpl->m_xPropSetInfo.is() )
1090         m_pImpl->m_xPropSetInfo
1091             = new PropertySetInfo( m_xSMgr, xEnv, this );
1092     else if ( !bCache )
1093         m_pImpl->m_xPropSetInfo->reset();
1094 
1095     return uno::Reference< beans::XPropertySetInfo >(
1096                                     m_pImpl->m_xPropSetInfo.get() );
1097 }
1098 
1099 } // namespace ucbhelper
1100