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_extensions.hxx"
26 #include "genericpropertyhandler.hxx"
27 #include "formmetadata.hxx"
28 #include "handlerhelper.hxx"
29 
30 /** === begin UNO includes === **/
31 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
32 #include <com/sun/star/reflection/XEnumTypeDescription.hpp>
33 #include <com/sun/star/beans/XIntrospection.hpp>
34 #include <com/sun/star/inspection/PropertyControlType.hpp>
35 #include <com/sun/star/inspection/XHyperlinkControl.hpp>
36 #include <com/sun/star/awt/XActionListener.hpp>
37 #include <com/sun/star/util/XURLTransformer.hpp>
38 #include <com/sun/star/frame/XDispatchProvider.hpp>
39 /** === end UNO includes === **/
40 #include <tools/debug.hxx>
41 #include <comphelper/extract.hxx>
42 
43 #include <algorithm>
44 
45 //------------------------------------------------------------------------
createRegistryInfo_GenericPropertyHandler()46 extern "C" void SAL_CALL createRegistryInfo_GenericPropertyHandler()
47 {
48 	::pcr::OAutoRegistration< ::pcr::GenericPropertyHandler > aAutoRegistration;
49 }
50 
51 //........................................................................
52 namespace pcr
53 {
54 //........................................................................
55 
56     using namespace ::com::sun::star::uno;
57     using namespace ::com::sun::star::beans;
58     using namespace ::com::sun::star::script;
59     using namespace ::com::sun::star::frame;
60     using namespace ::com::sun::star::lang;
61     using namespace ::com::sun::star::util;
62     using namespace ::com::sun::star::container;
63     using namespace ::com::sun::star::reflection;
64     using namespace ::com::sun::star::inspection;
65     using ::com::sun::star::awt::XActionListener;
66     using ::com::sun::star::awt::ActionEvent;
67 
68     //====================================================================
69 	//= EnumRepresentation
70 	//====================================================================
71     class EnumRepresentation : public IPropertyEnumRepresentation
72     {
73     private:
74         oslInterlockedCount                 m_refCount;
75         Reference< XEnumTypeDescription >   m_xTypeDescription;
76         Type                                m_aEnumType;
77 
78     public:
79         EnumRepresentation( const Reference< XComponentContext >& _rxContext, const Type& _rEnumType );
80 
81         // IPropertyEnumRepresentation implementqation
82         virtual ::std::vector< ::rtl::OUString >
83                                     SAL_CALL getDescriptions() const;
84         virtual void                SAL_CALL getValueFromDescription( const ::rtl::OUString& _rDescription, ::com::sun::star::uno::Any& _out_rValue ) const;
85         virtual ::rtl::OUString     SAL_CALL getDescriptionForValue( const ::com::sun::star::uno::Any& _rEnumValue ) const;
86 
87         // IReference implementqation
88         virtual oslInterlockedCount SAL_CALL acquire();
89         virtual oslInterlockedCount SAL_CALL release();
90 
91     private:
92         void            impl_getValues( Sequence< sal_Int32 >& _out_rValues ) const;
93 
94     private:
95         EnumRepresentation();                                       // never implemented
96         EnumRepresentation( const EnumRepresentation& );            // never implemented
97         EnumRepresentation& operator=( const EnumRepresentation& ); // never implemented
98     };
99 
100 	//--------------------------------------------------------------------
EnumRepresentation(const Reference<XComponentContext> & _rxContext,const Type & _rEnumType)101     EnumRepresentation::EnumRepresentation( const Reference< XComponentContext >& _rxContext, const Type& _rEnumType )
102         :m_refCount( 0 )
103         ,m_aEnumType( _rEnumType )
104     {
105         try
106         {
107             if ( _rxContext.is() )
108             {
109                 Reference< XHierarchicalNameAccess > xTypeDescProv(
110                     _rxContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
111                     UNO_QUERY_THROW );
112 
113                 m_xTypeDescription = Reference< XEnumTypeDescription >( xTypeDescProv->getByHierarchicalName( m_aEnumType.getTypeName() ), UNO_QUERY_THROW );
114             }
115         }
116         catch( const Exception& )
117         {
118         	OSL_ENSURE( sal_False, "EnumRepresentation::EnumRepresentation: caught an exception!" );
119         }
120     }
121 
122     //--------------------------------------------------------------------
getDescriptions() const123     ::std::vector< ::rtl::OUString > EnumRepresentation::getDescriptions() const
124     {
125         Sequence< ::rtl::OUString > aNames;
126         try
127         {
128             if ( m_xTypeDescription.is() )
129                 aNames = m_xTypeDescription->getEnumNames();
130         }
131         catch( const Exception& )
132         {
133             OSL_ENSURE( sal_False, "EnumRepresentation::getDescriptions: caught an exception!" );
134         }
135 
136         return ::std::vector< ::rtl::OUString >( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() );
137     }
138 
139     //--------------------------------------------------------------------
impl_getValues(Sequence<sal_Int32> & _out_rValues) const140     void EnumRepresentation::impl_getValues( Sequence< sal_Int32 >& _out_rValues ) const
141     {
142         _out_rValues.realloc( 0 );
143         try
144         {
145             if  ( m_xTypeDescription.is() )
146                 _out_rValues = m_xTypeDescription->getEnumValues();
147         }
148         catch( const Exception& )
149         {
150             OSL_ENSURE( sal_False, "EnumRepresentation::impl_getValues: caught an exception!" );
151         }
152     }
153 
154     //--------------------------------------------------------------------
getValueFromDescription(const::rtl::OUString & _rDescription,Any & _out_rValue) const155     void EnumRepresentation::getValueFromDescription( const ::rtl::OUString& _rDescription, Any& _out_rValue ) const
156     {
157         ::std::vector< ::rtl::OUString > aDescriptions( getDescriptions() );
158 
159         sal_Int32 index = ::std::find( aDescriptions.begin(), aDescriptions.end(),
160             _rDescription ) - aDescriptions.begin();
161 
162         Sequence< sal_Int32 > aValues;
163         impl_getValues( aValues );
164 
165         if ( ( index >= 0 ) && ( index < aValues.getLength() ) )
166             _out_rValue = ::cppu::int2enum( aValues[ index ], m_aEnumType );
167         else
168         {
169             DBG_ERROR( "EnumRepresentation::getValueFromDescription: cannot convert!" );
170             _out_rValue.clear();
171         }
172     }
173 
174     //--------------------------------------------------------------------
getDescriptionForValue(const Any & _rEnumValue) const175     ::rtl::OUString EnumRepresentation::getDescriptionForValue( const Any& _rEnumValue ) const
176     {
177         ::rtl::OUString sDescription;
178 
179         sal_Int32 nAsInt = 0;
180         OSL_VERIFY( ::cppu::enum2int( nAsInt, _rEnumValue ) );
181 
182         Sequence< sal_Int32 > aValues;
183         impl_getValues( aValues );
184 
185         sal_Int32 index = ::std::find( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(),
186             nAsInt ) - aValues.getConstArray();
187 
188         ::std::vector< ::rtl::OUString > aDescriptions( getDescriptions() );
189         if ( ( index >= 0 ) && ( index < (sal_Int32)aDescriptions.size() ) )
190             sDescription = aDescriptions[ index ];
191         else
192         {
193              DBG_ERROR( "EnumRepresentation::getDescriptionForValue: cannot convert!" );
194         }
195         return sDescription;
196     }
197 
198     //--------------------------------------------------------------------
acquire()199     oslInterlockedCount SAL_CALL EnumRepresentation::acquire()
200     {
201         return osl_incrementInterlockedCount( &m_refCount );
202     }
203 
204     //--------------------------------------------------------------------
release()205     oslInterlockedCount SAL_CALL EnumRepresentation::release()
206     {
207         if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
208         {
209            delete this;
210            return 0;
211         }
212         return m_refCount;
213     }
214 
215     //====================================================================
216 	//= UrlClickHandler
217 	//====================================================================
218     typedef ::cppu::WeakImplHelper1 <   XActionListener
219                                     >   UrlClickHandler_Base;
220     class UrlClickHandler : public UrlClickHandler_Base
221     {
222         ComponentContext    m_aContext;
223     public:
224         UrlClickHandler( const ComponentContext& _rContext, const Reference< XHyperlinkControl >& _rxControl );
225 
226     protected:
227         ~UrlClickHandler();
228 
229         // XActionListener
230         virtual void SAL_CALL actionPerformed( const ActionEvent& rEvent ) throw (RuntimeException);
231 
232         // XEventListener
233         virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
234 
235     protected:
236         void impl_dispatch_throw( const ::rtl::OUString& _rURL );
237     };
238 
239 	//--------------------------------------------------------------------
DBG_NAME(UrlClickHandler)240     DBG_NAME( UrlClickHandler )
241 	//--------------------------------------------------------------------
242     UrlClickHandler::UrlClickHandler( const ComponentContext& _rContext, const Reference< XHyperlinkControl >& _rxControl )
243         :m_aContext( _rContext )
244     {
245         if ( !_rxControl.is() )
246             throw NullPointerException();
247 
248         osl_incrementInterlockedCount( &m_refCount );
249         {
250             _rxControl->addActionListener( this );
251         }
252         osl_decrementInterlockedCount( &m_refCount );
253         OSL_ENSURE( m_refCount > 0, "UrlClickHandler::UrlClickHandler: leaking!" );
254 
255         DBG_CTOR( UrlClickHandler, NULL );
256     }
257 
258     //--------------------------------------------------------------------
~UrlClickHandler()259     UrlClickHandler::~UrlClickHandler()
260     {
261         DBG_DTOR( UrlClickHandler, NULL );
262     }
263 
264     //--------------------------------------------------------------------
actionPerformed(const ActionEvent & rEvent)265     void SAL_CALL UrlClickHandler::actionPerformed( const ActionEvent& rEvent ) throw (RuntimeException)
266     {
267         Reference< XPropertyControl > xControl( rEvent.Source, UNO_QUERY_THROW );
268         Any aControlValue( xControl->getValue() );
269 
270         ::rtl::OUString sURL;
271         if ( aControlValue.hasValue() && !( aControlValue >>= sURL ) )
272             throw RuntimeException( ::rtl::OUString(), *this );
273 
274         if ( !sURL.getLength() )
275             return;
276 
277         impl_dispatch_throw( sURL );
278     }
279 
280     //--------------------------------------------------------------------
disposing(const EventObject &)281     void SAL_CALL UrlClickHandler::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
282     {
283         // not interested in
284     }
285 
286     //--------------------------------------------------------------------
impl_dispatch_throw(const::rtl::OUString & _rURL)287     void UrlClickHandler::impl_dispatch_throw( const ::rtl::OUString& _rURL )
288     {
289         Reference< XURLTransformer > xTransformer( m_aContext.createComponent( "com.sun.star.util.URLTransformer" ), UNO_QUERY_THROW );
290         URL aURL; aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OpenHyperlink" ) );
291         xTransformer->parseStrict( aURL );
292 
293         Reference< XDispatchProvider > xDispProv( m_aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW );
294         Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aURL, ::rtl::OUString(), 0 ), UNO_QUERY_THROW );
295 
296         Sequence< PropertyValue > aDispatchArgs(1);
297         aDispatchArgs[0].Name   = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
298         aDispatchArgs[0].Value  <<= _rURL;
299 
300         xDispatch->dispatch( aURL, aDispatchArgs );
301     }
302 
303     //====================================================================
304 	//= GenericPropertyHandler
305 	//====================================================================
DBG_NAME(GenericPropertyHandler)306     DBG_NAME( GenericPropertyHandler )
307 	//--------------------------------------------------------------------
308     GenericPropertyHandler::GenericPropertyHandler( const Reference< XComponentContext >& _rxContext )
309         :GenericPropertyHandler_Base( m_aMutex )
310         ,m_aContext( _rxContext )
311         ,m_aPropertyListeners( m_aMutex )
312         ,m_bPropertyMapInitialized( false )
313     {
314         DBG_CTOR( GenericPropertyHandler, NULL );
315 
316 		m_xTypeConverter = Reference< XTypeConverter >(
317 			m_aContext.createComponent( "com.sun.star.script.Converter" ),
318 			UNO_QUERY_THROW
319 		);
320     }
321 
322 	//--------------------------------------------------------------------
~GenericPropertyHandler()323     GenericPropertyHandler::~GenericPropertyHandler()
324     {
325         DBG_DTOR( GenericPropertyHandler, NULL );
326     }
327 
328     //--------------------------------------------------------------------
getImplementationName()329     ::rtl::OUString SAL_CALL GenericPropertyHandler::getImplementationName(  ) throw (RuntimeException)
330     {
331         return getImplementationName_static();
332     }
333 
334     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & ServiceName)335     ::sal_Bool SAL_CALL GenericPropertyHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
336     {
337         StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() );
338         return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
339     }
340 
341     //--------------------------------------------------------------------
getSupportedServiceNames()342     Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupportedServiceNames(  ) throw (RuntimeException)
343     {
344         return getSupportedServiceNames_static();
345     }
346 
347     //--------------------------------------------------------------------
getImplementationName_static()348     ::rtl::OUString SAL_CALL GenericPropertyHandler::getImplementationName_static(  ) throw (RuntimeException)
349     {
350         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.GenericPropertyHandler" ) );
351     }
352 
353     //--------------------------------------------------------------------
getSupportedServiceNames_static()354     Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
355     {
356         Sequence< ::rtl::OUString > aSupported( 1 );
357         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.inspection.GenericPropertyHandler" ) );
358         return aSupported;
359     }
360 
361     //--------------------------------------------------------------------
Create(const Reference<XComponentContext> & _rxContext)362     Reference< XInterface > SAL_CALL GenericPropertyHandler::Create( const Reference< XComponentContext >& _rxContext )
363     {
364         return *( new GenericPropertyHandler( _rxContext ) );
365     }
366 
367     //--------------------------------------------------------------------
inspect(const Reference<XInterface> & _rxIntrospectee)368     void SAL_CALL GenericPropertyHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
369     {
370         ::osl::MutexGuard aGuard( m_aMutex );
371 
372         if ( !_rxIntrospectee.is() )
373             throw NullPointerException();
374 
375         // revoke old property change listeners
376         ::cppu::OInterfaceIteratorHelper iterRemove( m_aPropertyListeners );
377         ::cppu::OInterfaceIteratorHelper iterReAdd( m_aPropertyListeners ); // this holds a copy of the container ...
378         while ( iterRemove.hasMoreElements() )
379             m_xComponent->removePropertyChangeListener( ::rtl::OUString(), static_cast< XPropertyChangeListener* >( iterRemove.next() ) );
380 
381         m_xComponentIntrospectionAccess.clear();
382         m_xComponent.clear();
383         m_xPropertyState.clear();
384 
385         // create an introspection adapter for the component
386         Reference< XIntrospection > xIntrospection;
387         if ( !m_aContext.createComponent( "com.sun.star.beans.Introspection", xIntrospection ) )
388             throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create an instance of the service com.sun.star.beans.Introspection." ) ), *this );
389 
390         Reference< XIntrospectionAccess > xIntrospectionAccess( xIntrospection->inspect( makeAny( _rxIntrospectee ) ) );
391         if ( !xIntrospectionAccess.is() )
392             throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The introspection service could not handle the given component." ) ), *this );
393 
394         m_xComponent = Reference< XPropertySet >( xIntrospectionAccess->queryAdapter( XPropertySet::static_type() ), UNO_QUERY_THROW );
395         // now that we survived so far, remember m_xComponentIntrospectionAccess
396         m_xComponentIntrospectionAccess = xIntrospectionAccess;
397         m_xPropertyState = m_xPropertyState.query( m_xComponent );
398 
399         m_bPropertyMapInitialized = false;
400         m_aProperties.clear();
401 
402         // re-add the property change listeners
403         while ( iterReAdd.hasMoreElements() )
404             m_xComponent->addPropertyChangeListener( ::rtl::OUString(), static_cast< XPropertyChangeListener* >( iterReAdd.next() ) );
405     }
406 
407     //--------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & _rPropertyName)408     Any SAL_CALL GenericPropertyHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
409     {
410         ::osl::MutexGuard aGuard( m_aMutex );
411         if ( !m_xComponent.is() )
412             throw UnknownPropertyException();
413 
414         return m_xComponent->getPropertyValue( _rPropertyName );
415     }
416 
417     //--------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rValue)418     void SAL_CALL GenericPropertyHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
419     {
420         ::osl::MutexGuard aGuard( m_aMutex );
421         if ( !m_xComponent.is() )
422             throw UnknownPropertyException();
423 
424         m_xComponent->setPropertyValue( _rPropertyName, _rValue );
425     }
426 
427     //--------------------------------------------------------------------
impl_getEnumConverter(const Type & _rEnumType)428     ::rtl::Reference< IPropertyEnumRepresentation > GenericPropertyHandler::impl_getEnumConverter( const Type& _rEnumType )
429     {
430         ::rtl::Reference< IPropertyEnumRepresentation >& rConverter = m_aEnumConverters[ _rEnumType ];
431         if ( !rConverter.is() )
432             rConverter = new EnumRepresentation( m_aContext.getUNOContext(), _rEnumType );
433         return rConverter;
434     }
435 
436     //--------------------------------------------------------------------
convertToPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rControlValue)437     Any SAL_CALL GenericPropertyHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
438     {
439         ::osl::MutexGuard aGuard( m_aMutex );
440         const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
441 
442         PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
443         if ( pos == m_aProperties.end() )
444             throw UnknownPropertyException();
445 
446         Any aPropertyValue;
447         if ( !_rControlValue.hasValue() )
448             // NULL is converted to NULL
449             return aPropertyValue;
450 
451         if ( pos->second.Type.getTypeClass() == TypeClass_ENUM )
452         {
453             ::rtl::OUString sControlValue;
454             OSL_VERIFY( _rControlValue >>= sControlValue );
455             impl_getEnumConverter( pos->second.Type )->getValueFromDescription( sControlValue, aPropertyValue );
456         }
457         else
458             aPropertyValue = PropertyHandlerHelper::convertToPropertyValue( m_aContext.getContext(),m_xTypeConverter, pos->second, _rControlValue );
459 
460         return aPropertyValue;
461     }
462 
463     //--------------------------------------------------------------------
convertToControlValue(const::rtl::OUString & _rPropertyName,const Any & _rPropertyValue,const Type & _rControlValueType)464     Any SAL_CALL GenericPropertyHandler::convertToControlValue( const ::rtl::OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
465     {
466         ::osl::MutexGuard aGuard( m_aMutex );
467         const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
468 
469         PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
470         if ( pos == m_aProperties.end() )
471             throw UnknownPropertyException();
472 
473         Any aControlValue;
474         if ( !_rPropertyValue.hasValue() )
475             // NULL is converted to NULL
476             return aControlValue;
477 
478         if ( pos->second.Type.getTypeClass() == TypeClass_ENUM )
479         {
480             aControlValue <<= impl_getEnumConverter( pos->second.Type )->getDescriptionForValue( _rPropertyValue );
481         }
482         else
483             aControlValue = PropertyHandlerHelper::convertToControlValue( m_aContext.getContext(),m_xTypeConverter, _rPropertyValue, _rControlValueType );
484         return aControlValue;
485     }
486 
487     //--------------------------------------------------------------------
getPropertyState(const::rtl::OUString & _rPropertyName)488     PropertyState SAL_CALL GenericPropertyHandler::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
489     {
490         ::osl::MutexGuard aGuard( m_aMutex );
491         PropertyState eState = PropertyState_DIRECT_VALUE;
492         if ( m_xPropertyState.is() )
493             eState = m_xPropertyState->getPropertyState( _rPropertyName );
494         return eState;
495     }
496 
497     //--------------------------------------------------------------------
addPropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)498     void SAL_CALL GenericPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
499     {
500         if ( !_rxListener.is() )
501             throw NullPointerException();
502 
503         ::osl::MutexGuard aGuard( m_aMutex );
504         m_aPropertyListeners.addInterface( _rxListener );
505         if ( m_xComponent.is() )
506         {
507             try
508             {
509                 m_xComponent->addPropertyChangeListener( ::rtl::OUString(), _rxListener );
510             }
511             catch( const UnknownPropertyException& )
512             {
513                 OSL_ENSURE( false, "GenericPropertyHandler::addPropertyChangeListener:\nThe inspected component does not allow registering for all properties at once! This violates the interface contract!" );
514             }
515         }
516     }
517 
518     //--------------------------------------------------------------------
removePropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)519     void SAL_CALL GenericPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
520     {
521         ::osl::MutexGuard aGuard( m_aMutex );
522         if ( m_xComponent.is() )
523         {
524             try
525             {
526                 m_xComponent->removePropertyChangeListener( ::rtl::OUString(), _rxListener );
527             }
528             catch( const UnknownPropertyException& )
529             {
530                 OSL_ENSURE( false, "GenericPropertyHandler::removePropertyChangeListener:\nThe inspected component does not allow de-registering for all properties at once! This violates the interface contract!" );
531             }
532         }
533         m_aPropertyListeners.removeInterface( _rxListener );
534     }
535 
536     //--------------------------------------------------------------------
impl_ensurePropertyMap()537     void GenericPropertyHandler::impl_ensurePropertyMap()
538     {
539         if ( !m_bPropertyMapInitialized )
540         {
541             m_bPropertyMapInitialized = true;
542             try
543             {
544                 Reference< XPropertySetInfo > xPSI;
545                 if ( m_xComponent.is() )
546                     xPSI = m_xComponent->getPropertySetInfo();
547                 Sequence< Property > aProperties;
548                 if ( xPSI.is() )
549                     aProperties = xPSI->getProperties();
550                 DBG_ASSERT( aProperties.getLength(), "GenericPropertyHandler::getSupportedProperties: no properties!" );
551 
552                 for ( const Property* pProperties = aProperties.getConstArray();
553                       pProperties != aProperties.getConstArray() + aProperties.getLength();
554                       ++pProperties
555                     )
556                 {
557                     switch ( pProperties->Type.getTypeClass() )
558                     {
559                     case TypeClass_BOOLEAN:
560                     case TypeClass_BYTE:
561                     case TypeClass_SHORT:
562                     case TypeClass_UNSIGNED_SHORT:
563                     case TypeClass_LONG:
564                     case TypeClass_UNSIGNED_LONG:
565                     case TypeClass_HYPER:
566                     case TypeClass_UNSIGNED_HYPER:
567                     case TypeClass_FLOAT:
568                     case TypeClass_DOUBLE:
569                     case TypeClass_ENUM:
570                     case TypeClass_STRING:
571                         // allowed, we can handle this type
572                         break;
573 
574                     case TypeClass_SEQUENCE:
575                     {
576                         TypeClass eElementTypeClass = ::comphelper::getSequenceElementType( pProperties->Type ).getTypeClass();
577                         if  (   ( eElementTypeClass != TypeClass_STRING )
578                             &&  ( eElementTypeClass != TypeClass_BYTE )
579                             &&  ( eElementTypeClass != TypeClass_SHORT )
580                             &&  ( eElementTypeClass != TypeClass_UNSIGNED_SHORT )
581                             &&  ( eElementTypeClass != TypeClass_LONG )
582                             &&  ( eElementTypeClass != TypeClass_UNSIGNED_LONG )
583                             )
584                             // can only handle the above
585                             continue;
586                     }
587                     break;
588 
589                     default:
590                         // next property, we don't support this type
591                         continue;
592                     }
593 
594                     m_aProperties.insert( PropertyMap::value_type( pProperties->Name, *pProperties ) );
595                 }
596             }
597             catch( const Exception& )
598             {
599             	OSL_ENSURE( sal_False, "GenericPropertyHandler::impl_ensurePropertyMap: caught an exception!" );
600             }
601         }
602     }
603 
604     //--------------------------------------------------------------------
getSupportedProperties()605     Sequence< Property > SAL_CALL GenericPropertyHandler::getSupportedProperties() throw (RuntimeException)
606     {
607         ::osl::MutexGuard aGuard( m_aMutex );
608         const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
609 
610         Sequence< Property > aReturn( m_aProperties.size() );
611         ::std::transform( m_aProperties.begin(), m_aProperties.end(),
612             aReturn.getArray(), ::std::select2nd< PropertyMap::value_type >() );
613         return aReturn;
614     }
615 
616     //--------------------------------------------------------------------
getSupersededProperties()617     Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupersededProperties( ) throw (RuntimeException)
618     {
619         // no superseded properties at all. This handler offers the very basic PropertyHandler
620         // functionality, so it's much more likely that other handlers want to supersede
621         // *our* properties ....
622         return Sequence< ::rtl::OUString >( );
623     }
624 
625     //--------------------------------------------------------------------
getActuatingProperties()626     Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getActuatingProperties( ) throw (RuntimeException)
627     {
628         // This basic PropertyHandler implementation is too dumb^Wgeneric to know
629         // anything about property dependencies
630         return Sequence< ::rtl::OUString >( );
631     }
632 
633     //--------------------------------------------------------------------
describePropertyLine(const::rtl::OUString & _rPropertyName,const Reference<XPropertyControlFactory> & _rxControlFactory)634     LineDescriptor SAL_CALL GenericPropertyHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
635         const Reference< XPropertyControlFactory >& _rxControlFactory )
636         throw (UnknownPropertyException, NullPointerException, RuntimeException)
637     {
638         if ( !_rxControlFactory.is() )
639             throw NullPointerException();
640 
641         ::osl::MutexGuard aGuard( m_aMutex );
642         const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
643 
644         PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
645         if ( pos == m_aProperties.end() )
646             throw UnknownPropertyException();
647 
648         LineDescriptor aDescriptor;
649         aDescriptor.DisplayName = _rPropertyName;
650         switch ( pos->second.Type.getTypeClass() )
651         {
652         case TypeClass_ENUM:
653             aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory,
654                 impl_getEnumConverter( pos->second.Type )->getDescriptions(),
655                 PropertyHandlerHelper::requiresReadOnlyControl( pos->second.Attributes ),
656                 sal_False );
657             break;
658         case TypeClass_STRING:
659         {
660             // some special handling for URL properties
661             bool bIsURLProperty = ( _rPropertyName.getLength() >= 3 ) && _rPropertyName.matchAsciiL( "URL", 3, _rPropertyName.getLength() - 3 );
662             if ( bIsURLProperty )
663             {
664                 aDescriptor.Control = _rxControlFactory->createPropertyControl(
665                     PropertyControlType::HyperlinkField, PropertyHandlerHelper::requiresReadOnlyControl( pos->second.Attributes ) );
666 
667                 Reference< XHyperlinkControl > xControl( aDescriptor.Control, UNO_QUERY_THROW );
668                 Reference< XActionListener > xEnsureDelete( new UrlClickHandler( m_aContext, xControl ) );
669             }
670         }
671         break;
672         default:
673             break;
674         }
675         // fallback
676         if ( !aDescriptor.Control.is() )
677             PropertyHandlerHelper::describePropertyLine( pos->second, aDescriptor, _rxControlFactory );
678 
679         aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "General" ) );
680         return aDescriptor;
681     }
682 
683     //--------------------------------------------------------------------
isComposable(const::rtl::OUString &)684     ::sal_Bool SAL_CALL GenericPropertyHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
685     {
686         return sal_False;
687     }
688 
689     //--------------------------------------------------------------------
onInteractivePropertySelection(const::rtl::OUString &,sal_Bool,Any &,const Reference<XObjectInspectorUI> &)690     InteractiveSelectionResult SAL_CALL GenericPropertyHandler::onInteractivePropertySelection( const ::rtl::OUString& /*_rPropertyName*/, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/ ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
691     {
692         DBG_ERROR( "GenericPropertyHandler::onInteractivePropertySelection: I'm too dumb to know anything about property browse buttons!" );
693         return InteractiveSelectionResult_Cancelled;
694     }
695 
696     //--------------------------------------------------------------------
actuatingPropertyChanged(const::rtl::OUString &,const Any &,const Any &,const Reference<XObjectInspectorUI> &,sal_Bool)697     void SAL_CALL GenericPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
698     {
699         DBG_ERROR( "GenericPropertyHandler::actuatingPropertyChanged: no no no, I did not register for any actuating properties!" );
700     }
701 
702     //--------------------------------------------------------------------
suspend(sal_Bool)703     sal_Bool SAL_CALL GenericPropertyHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
704     {
705         return sal_True;
706     }
707 
708     //--------------------------------------------------------------------
disposing()709     void SAL_CALL GenericPropertyHandler::disposing()
710     {
711         m_aPropertyListeners.clear();
712             // not disposeAndClear: the listeners are (virtually) listeners at our introspectee, not
713             // at this handler instance
714     }
715 
716     //--------------------------------------------------------------------
717     IMPLEMENT_FORWARD_XCOMPONENT( GenericPropertyHandler, GenericPropertyHandler_Base );
718 
719 //........................................................................
720 }   // namespace pcr
721 //........................................................................
722 
723