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