Update ooo320-m1
[ooovba.git] / stoc / source / tdmanager / tdmgr.cxx
blobc6c5470c0764188f2b39d3f0af29f1b75096b32c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdmgr.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
33 #include <osl/diagnose.h>
34 #include <osl/mutex.hxx>
35 #include "rtl/ustrbuf.hxx"
36 #include <cppuhelper/factory.hxx>
37 #ifndef _CPPUHELPER_IMPLBASE5_HXX_
38 #include <cppuhelper/compbase5.hxx>
39 #endif
40 #include <cppuhelper/implbase1.hxx>
41 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
42 #include <cppuhelper/implementationentry.hxx>
43 #endif
44 #include "tdmgr_common.hxx"
45 #include "tdmgr_tdenumeration.hxx"
46 #include "lrucache.hxx"
48 #include <com/sun/star/lang/XServiceInfo.hpp>
49 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
50 #include <com/sun/star/lang/XEventListener.hpp>
51 #include <com/sun/star/lang/XTypeProvider.hpp>
52 #include <com/sun/star/lang/XComponent.hpp>
53 #include <com/sun/star/lang/XInitialization.hpp>
54 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
55 #include <com/sun/star/container/XSet.hpp>
56 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
57 #include <com/sun/star/reflection/XTypeDescription.hpp>
58 #include <com/sun/star/reflection/XArrayTypeDescription.hpp>
59 #include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
60 #include <com/sun/star/reflection/XInterfaceTypeDescription.hpp>
61 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
62 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
63 #include <com/sun/star/registry/XRegistryKey.hpp>
64 #include "com/sun/star/uno/RuntimeException.hpp"
66 #include <algorithm>
67 #include <vector>
69 using namespace std;
70 using namespace cppu;
71 using namespace rtl;
72 using namespace osl;
73 using namespace com::sun::star;
74 using namespace com::sun::star::uno;
75 using namespace com::sun::star::lang;
76 using namespace com::sun::star::reflection;
77 using namespace com::sun::star::container;
78 using namespace com::sun::star::registry;
82 static const sal_Int32 CACHE_SIZE = 512;
84 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionManager"
85 #define IMPLNAME "com.sun.star.comp.stoc.TypeDescriptionManager"
87 //--------------------------------------------------------------------------------------------------
88 // exported via tdmgr_common.hxx
89 extern rtl_StandardModuleCount g_moduleCount;
91 namespace stoc_bootstrap
93 Sequence< OUString > SAL_CALL tdmgr_getSupportedServiceNames()
95 static Sequence < OUString > *pNames = 0;
96 if( ! pNames )
98 MutexGuard guard( Mutex::getGlobalMutex() );
99 if( !pNames )
101 static Sequence< OUString > seqNames(1);
102 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
103 pNames = &seqNames;
106 return *pNames;
109 OUString SAL_CALL tdmgr_getImplementationName()
111 static OUString *pImplName = 0;
112 if( ! pImplName )
114 MutexGuard guard( Mutex::getGlobalMutex() );
115 if( ! pImplName )
117 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
118 pImplName = &implName;
121 return *pImplName;
125 namespace stoc_tdmgr
127 typedef vector< Reference< XHierarchicalNameAccess > > ProviderVector;
129 class EnumerationImpl;
130 class ManagerImpl;
132 //==================================================================================================
133 class EventListenerImpl : public ImplHelper1< XEventListener >
135 ManagerImpl * _pMgr;
137 public:
138 EventListenerImpl( ManagerImpl * pMgr )
139 : _pMgr( pMgr )
141 ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt );
143 virtual ~EventListenerImpl();
145 // lifetime delegated to manager
146 virtual void SAL_CALL acquire() throw();
147 virtual void SAL_CALL release() throw();
149 // XEventListener
150 virtual void SAL_CALL disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException);
153 EventListenerImpl::~EventListenerImpl()
155 ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt );
158 //==================================================================================================
159 class ManagerImpl
160 : public WeakComponentImplHelper5< XServiceInfo,
161 XSet,
162 XHierarchicalNameAccess,
163 XTypeDescriptionEnumerationAccess,
164 XInitialization >
166 friend class EnumerationImpl;
167 friend class EventListenerImpl;
169 Mutex _aComponentMutex;
170 Reference< XComponentContext > _xContext;
171 EventListenerImpl _aEventListener;
173 // elements
174 sal_Bool _bCaching;
175 LRU_CacheAnyByOUString _aElements;
176 // provider chain
177 ProviderVector _aProviders;
179 inline Any getSimpleType( const OUString & rName );
181 Reference< XTypeDescription > getInstantiatedStruct(OUString const & name);
183 protected:
184 virtual void SAL_CALL disposing();
186 public:
187 ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize );
188 virtual ~ManagerImpl();
190 // XInitialization
191 virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException);
193 // XServiceInfo
194 virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
195 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException);
196 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
198 // XElementAccess
199 virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException);
200 virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
202 // XEnumerationAccess
203 virtual Reference< XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException);
205 // XSet
206 virtual sal_Bool SAL_CALL has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException);
207 virtual void SAL_CALL insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
208 virtual void SAL_CALL remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
210 // XHierarchicalNameAccess
211 virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
212 virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
214 // XTypeDescriptionEnumerationAccess
215 virtual ::com::sun::star::uno::Reference<
216 ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL
217 createTypeDescriptionEnumeration(
218 const ::rtl::OUString& moduleName,
219 const ::com::sun::star::uno::Sequence<
220 ::com::sun::star::uno::TypeClass >& types,
221 ::com::sun::star::reflection::TypeDescriptionSearchDepth depth )
222 throw ( ::com::sun::star::reflection::NoSuchTypeNameException,
223 ::com::sun::star::reflection::InvalidTypeNameException,
224 ::com::sun::star::uno::RuntimeException );
227 //==================================================================================================
228 class EnumerationImpl
229 : public WeakImplHelper1< XEnumeration >
231 ManagerImpl * _pMgr;
232 size_t _nPos;
234 public:
235 EnumerationImpl( ManagerImpl * pManager );
236 virtual ~EnumerationImpl();
238 // XEnumeration
239 virtual sal_Bool SAL_CALL hasMoreElements() throw(::com::sun::star::uno::RuntimeException);
240 virtual Any SAL_CALL nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
243 //##################################################################################################
245 // lifetime delegated to manager
246 //__________________________________________________________________________________________________
247 void EventListenerImpl::acquire() throw()
249 _pMgr->acquire();
251 //__________________________________________________________________________________________________
252 void EventListenerImpl::release() throw()
254 _pMgr->release();
257 // XEventListener
258 //__________________________________________________________________________________________________
259 void EventListenerImpl::disposing( const EventObject & rEvt )
260 throw(::com::sun::star::uno::RuntimeException)
262 _pMgr->remove( makeAny( rEvt.Source ) );
265 //##################################################################################################
267 //__________________________________________________________________________________________________
268 EnumerationImpl::EnumerationImpl( ManagerImpl * pManager )
269 : _pMgr( pManager )
270 , _nPos( 0 )
272 _pMgr->acquire();
274 //__________________________________________________________________________________________________
275 EnumerationImpl::~EnumerationImpl()
277 _pMgr->release();
280 // XEnumeration
281 //__________________________________________________________________________________________________
282 sal_Bool EnumerationImpl::hasMoreElements()
283 throw(::com::sun::star::uno::RuntimeException)
285 MutexGuard aGuard( _pMgr->_aComponentMutex );
286 return (_nPos < _pMgr->_aProviders.size());
288 //__________________________________________________________________________________________________
289 Any EnumerationImpl::nextElement()
290 throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
292 MutexGuard aGuard( _pMgr->_aComponentMutex );
293 if (_nPos >= _pMgr->_aProviders.size())
295 throw NoSuchElementException(
296 OUString( RTL_CONSTASCII_USTRINGPARAM("there is no further element!") ),
297 (XWeak *)(OWeakObject *)this );
299 return makeAny( _pMgr->_aProviders[_nPos++] );
302 //##################################################################################################
304 //__________________________________________________________________________________________________
305 ManagerImpl::ManagerImpl(
306 Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize )
307 : WeakComponentImplHelper5<
308 XServiceInfo, XSet, XHierarchicalNameAccess,
309 XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex )
310 , _xContext( xContext )
311 , _aEventListener( this )
312 , _bCaching( sal_True )
313 , _aElements( nCacheSize )
315 ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt );
317 //__________________________________________________________________________________________________
318 ManagerImpl::~ManagerImpl()
320 OSL_ENSURE( _aProviders.size() == 0, "### still providers left!" );
321 OSL_TRACE( "> TypeDescriptionManager shut down. <\n" );
322 ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt );
324 //__________________________________________________________________________________________________
325 void ManagerImpl::disposing()
327 // called on disposing the tdmgr instance (supposedly from context)
328 _bCaching = sal_False;
329 _aElements.clear();
330 _xContext.clear();
331 _aProviders.clear();
334 // XInitialization
335 //__________________________________________________________________________________________________
336 void ManagerImpl::initialize(
337 const Sequence< Any > & args )
338 throw (Exception, RuntimeException)
340 // additional providers
341 Any const * pProviders = args.getConstArray();
342 for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos )
344 Reference< XHierarchicalNameAccess > xHA( pProviders[ nPos ], UNO_QUERY );
345 OSL_ENSURE( xHA.is(), "### no td provider!" );
347 if (xHA.is())
351 insert( makeAny( xHA ) );
353 catch (IllegalArgumentException &)
356 catch (ElementExistException &)
363 // XServiceInfo
364 //__________________________________________________________________________________________________
365 OUString ManagerImpl::getImplementationName()
366 throw(::com::sun::star::uno::RuntimeException)
368 return stoc_bootstrap::tdmgr_getImplementationName();
370 //__________________________________________________________________________________________________
371 sal_Bool ManagerImpl::supportsService( const OUString & rServiceName )
372 throw(::com::sun::star::uno::RuntimeException)
374 const Sequence< OUString > & rSNL = getSupportedServiceNames();
375 const OUString * pArray = rSNL.getConstArray();
376 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
378 if (pArray[nPos] == rServiceName)
379 return sal_True;
381 return sal_False;
383 //__________________________________________________________________________________________________
384 Sequence< OUString > ManagerImpl::getSupportedServiceNames()
385 throw(::com::sun::star::uno::RuntimeException)
387 return stoc_bootstrap::tdmgr_getSupportedServiceNames();
390 // XElementAccess
391 //__________________________________________________________________________________________________
392 Type ManagerImpl::getElementType()
393 throw(::com::sun::star::uno::RuntimeException)
395 return ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 );
397 //__________________________________________________________________________________________________
398 sal_Bool ManagerImpl::hasElements()
399 throw(::com::sun::star::uno::RuntimeException)
401 MutexGuard aGuard( _aComponentMutex );
402 return (_aProviders.size() > 0);
405 // XEnumerationAccess
406 //__________________________________________________________________________________________________
407 Reference< XEnumeration > ManagerImpl::createEnumeration()
408 throw(::com::sun::star::uno::RuntimeException)
410 return new EnumerationImpl( this );
413 // XSet
414 //__________________________________________________________________________________________________
415 sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement )
416 throw(::com::sun::star::uno::RuntimeException)
418 Reference< XHierarchicalNameAccess > xElem;
419 if (rElement >>= xElem)
421 MutexGuard aGuard( _aComponentMutex );
422 return (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end());
424 return sal_False;
427 //__________________________________________________________________________________________________
428 void SAL_CALL ManagerImpl::insert( const Any & rElement )
429 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
431 Reference< XHierarchicalNameAccess > xElem;
432 if (! (rElement >>= xElem) || !xElem.is())
434 throw IllegalArgumentException(
435 OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ),
436 (XWeak *)(OWeakObject *)this, 0 );
439 MutexGuard aGuard( _aComponentMutex );
440 if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end())
442 throw ElementExistException(
443 OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ),
444 (XWeak *)(OWeakObject *)this );
447 if (! _aProviders.empty())
449 // check whether all types are compatible, if possible:
450 Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess(
451 xElem, UNO_QUERY );
452 OSL_ENSURE( xTDEnumAccess.is(),
453 "### providers ought to implement "
454 "reflection::XTypeDescriptionEnumerationAccess!" );
455 if (xTDEnumAccess.is())
459 TypeClass ar [] = {
460 TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE,
461 TypeClass_STRUCT, TypeClass_EXCEPTION,
462 /* TypeClass_UNION, TypeClass_ARRAY not supported */
463 TypeClass_INTERFACE,
464 TypeClass_SERVICE,
465 TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE,
466 TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS,
467 TypeClass_SINGLETON
469 Reference<reflection::XTypeDescriptionEnumeration> xTDEnum(
470 xTDEnumAccess->createTypeDescriptionEnumeration(
471 OUString() /* all modules */,
472 Sequence<TypeClass>( ar, ARLEN(ar) ),
473 reflection::TypeDescriptionSearchDepth_INFINITE ) );
475 while (xTDEnum->hasMoreElements())
477 Reference<reflection::XTypeDescription> xNewTD;
480 xNewTD = xTDEnum->nextTypeDescription();
482 catch (container::NoSuchElementException & exc)
484 throw lang::IllegalArgumentException(
485 OUSTR("NoSuchElementException occured: ") +
486 exc.Message, static_cast<OWeakObject *>(this),
487 -1 /* unknown */ );
492 OUString newName( xNewTD->getName() );
493 Reference<reflection::XTypeDescription> xExistingTD(
494 getByHierarchicalName( newName ), UNO_QUERY );
495 OSL_ASSERT( xExistingTD.is() );
496 // existing, check whether compatible:
497 if (xExistingTD.is())
501 check( xNewTD, xExistingTD );
503 catch (IncompatibleTypeException & exc)
505 throw lang::IllegalArgumentException(
506 OUSTR("Rejecting types due to "
507 "incompatibility! ") + exc.m_cause,
508 static_cast<OWeakObject *>(this), 0 );
512 catch (container::NoSuchElementException &)
514 // type not in: ok
518 catch (reflection::NoSuchTypeNameException & exc)
520 throw lang::IllegalArgumentException(
521 OUSTR("NoSuchTypeNameException occured: ") + exc.Message,
522 static_cast<OWeakObject *>(this), -1 /* unknown */ );
524 catch (reflection::InvalidTypeNameException & exc)
526 throw lang::IllegalArgumentException(
527 OUSTR("InvalidTypeNameException occured: ") + exc.Message,
528 static_cast<OWeakObject *>(this), -1 /* unknown */ );
533 _aProviders.push_back( xElem );
534 Reference< XComponent > xComp( xElem, UNO_QUERY );
535 if (xComp.is())
536 xComp->addEventListener( &_aEventListener );
538 //__________________________________________________________________________________________________
539 void SAL_CALL ManagerImpl::remove( const Any & rElement )
540 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
542 if (!rBHelper.bDisposed && !rBHelper.bInDispose)
544 Reference< XHierarchicalNameAccess > xElem;
545 if (! (rElement >>= xElem))
547 throw IllegalArgumentException(
548 OUString( RTL_CONSTASCII_USTRINGPARAM("no type description provider given!") ),
549 (XWeak *)(OWeakObject *)this, 0 );
552 MutexGuard aGuard( _aComponentMutex );
553 ProviderVector::iterator iFind( find( _aProviders.begin(), _aProviders.end(), xElem ) );
554 if (iFind == _aProviders.end())
556 throw NoSuchElementException(
557 OUString( RTL_CONSTASCII_USTRINGPARAM("provider not found!") ),
558 (XWeak *)(OWeakObject *)this );
560 _aProviders.erase( iFind );
563 Reference< XComponent > xComp;
564 if (rElement >>= xComp)
565 xComp->removeEventListener( &_aEventListener );
568 // XTypeDescriptionEnumerationAccess
569 //__________________________________________________________________________________________________
570 // virtual
571 Reference< XTypeDescriptionEnumeration > SAL_CALL
572 ManagerImpl::createTypeDescriptionEnumeration(
573 const OUString & moduleName,
574 const Sequence< TypeClass > & types,
575 TypeDescriptionSearchDepth depth )
576 throw ( NoSuchTypeNameException,
577 InvalidTypeNameException,
578 RuntimeException )
580 MutexGuard aGuard( _aComponentMutex );
582 TDEnumerationAccessStack aStack;
583 ProviderVector::const_iterator it = _aProviders.begin();
584 const ProviderVector::const_iterator end = _aProviders.end();
585 while ( it != end )
587 Reference< XTypeDescriptionEnumerationAccess >xEnumAccess(
588 (*it), UNO_QUERY );
589 OSL_ENSURE( xEnumAccess.is(),
590 "### no XTypeDescriptionEnumerationAccess!" );
591 if ( xEnumAccess.is() )
592 aStack.push( xEnumAccess );
594 it++;
597 return Reference< XTypeDescriptionEnumeration >(
598 new TypeDescriptionEnumerationImpl( moduleName,
599 types,
600 depth,
601 aStack ) );
605 //##################################################################################################
606 //##################################################################################################
607 //##################################################################################################
610 //==================================================================================================
611 class SimpleTypeDescriptionImpl
612 : public WeakImplHelper1< XTypeDescription >
614 TypeClass _eTC;
615 OUString _aName;
617 public:
618 SimpleTypeDescriptionImpl( TypeClass eTC, const OUString & rName )
619 : _eTC( eTC )
620 , _aName( rName )
623 // XTypeDescription
624 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
625 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
628 // XTypeDescription
629 //__________________________________________________________________________________________________
630 TypeClass SimpleTypeDescriptionImpl::getTypeClass()
631 throw(::com::sun::star::uno::RuntimeException)
633 return _eTC;
635 //__________________________________________________________________________________________________
636 OUString SimpleTypeDescriptionImpl::getName()
637 throw(::com::sun::star::uno::RuntimeException)
639 return _aName;
642 //==================================================================================================
643 class SequenceTypeDescriptionImpl
644 : public WeakImplHelper1< XIndirectTypeDescription >
646 Reference< XTypeDescription > _xElementTD;
648 public:
649 SequenceTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD )
650 : _xElementTD( xElementTD )
653 // XTypeDescription
654 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
655 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
657 // XIndirectTypeDescription
658 virtual Reference< XTypeDescription > SAL_CALL getReferencedType() throw(::com::sun::star::uno::RuntimeException);
661 // XTypeDescription
662 //__________________________________________________________________________________________________
663 TypeClass SequenceTypeDescriptionImpl::getTypeClass()
664 throw(::com::sun::star::uno::RuntimeException)
666 return TypeClass_SEQUENCE;
668 //__________________________________________________________________________________________________
669 OUString SequenceTypeDescriptionImpl::getName()
670 throw(::com::sun::star::uno::RuntimeException)
672 return (OUString( RTL_CONSTASCII_USTRINGPARAM("[]") ) + _xElementTD->getName());
675 // XIndirectTypeDescription
676 //__________________________________________________________________________________________________
677 Reference< XTypeDescription > SequenceTypeDescriptionImpl::getReferencedType()
678 throw(::com::sun::star::uno::RuntimeException)
680 return _xElementTD;
683 //==================================================================================================
684 class ArrayTypeDescriptionImpl
685 : public WeakImplHelper1< XArrayTypeDescription >
687 Reference< XTypeDescription > _xElementTD;
688 Mutex _aDimensionMutex;
689 sal_Int32 _nDimensions;
690 Sequence< sal_Int32 > _seqDimensions;
691 OUString _sDimensions;
693 void initDimensions(const OUString& rSDimensions);
694 public:
695 ArrayTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD,
696 sal_Int32 nDimensions, const OUString& rSDimensions )
697 : _xElementTD( xElementTD )
698 , _nDimensions( nDimensions )
699 , _seqDimensions( Sequence< sal_Int32 >(nDimensions) )
700 , _sDimensions( rSDimensions )
702 initDimensions( rSDimensions );
704 virtual ~ArrayTypeDescriptionImpl() {}
706 // XTypeDescription
707 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
708 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
710 // XArrayTypeDescription
711 virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException);
712 virtual sal_Int32 SAL_CALL getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException);
713 virtual Sequence< sal_Int32 > SAL_CALL getDimensions() throw(::com::sun::star::uno::RuntimeException);
715 //__________________________________________________________________________________________________
716 static sal_Int32 unicodeToInteger( sal_Int8 base, const sal_Unicode *s )
718 sal_Int32 r = 0;
719 sal_Int32 negative = 0;
721 if (*s == '-')
723 negative = 1;
724 s++;
726 if (base == 8 && *s == '0')
727 s++;
728 else if (base == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
729 s += 2;
731 for (; *s; s++)
733 if (*s <= '9' && *s >= '0')
734 r = (r * base) + (*s - '0');
735 else if (base > 10 && *s <= 'f' && *s >= 'a')
736 r = (r * base) + (*s - 'a' + 10);
737 else if (base > 10 && *s <= 'F' && *s >= 'A')
738 r = (r * base) + (*s - 'A' + 10);
739 else
740 break;
742 if (negative) r *= -1;
743 return r;
745 //__________________________________________________________________________________________________
746 void ArrayTypeDescriptionImpl::initDimensions(const OUString& rSDimensions)
748 MutexGuard aGuard( _aDimensionMutex );
750 sal_Int32 * pDimensions = _seqDimensions.getArray();
751 OUString tmp(rSDimensions);
752 sal_Unicode* p = (sal_Unicode*)tmp.getStr()+1;
753 sal_Unicode* pOffset = p;
754 sal_Int32 len = tmp.getLength() - 1 ;
755 sal_Int32 i = 0;
757 while ( len > 0)
759 pOffset++;
760 if (*pOffset == ']')
762 *pOffset = '\0';
763 pOffset += 2;
764 len -= 3;
765 pDimensions[i++] = unicodeToInteger(10, p);
766 p = pOffset;
767 } else
768 len--;
772 // XTypeDescription
773 //__________________________________________________________________________________________________
774 TypeClass ArrayTypeDescriptionImpl::getTypeClass()
775 throw(::com::sun::star::uno::RuntimeException)
777 return TypeClass_ARRAY;
779 //__________________________________________________________________________________________________
780 OUString ArrayTypeDescriptionImpl::getName()
781 throw(::com::sun::star::uno::RuntimeException)
783 return (_xElementTD->getName() + _sDimensions);
786 // XArrayTypeDescription
787 //__________________________________________________________________________________________________
788 Reference< XTypeDescription > ArrayTypeDescriptionImpl::getType()
789 throw(::com::sun::star::uno::RuntimeException)
791 return _xElementTD;
794 //__________________________________________________________________________________________________
795 sal_Int32 ArrayTypeDescriptionImpl::getNumberOfDimensions()
796 throw(::com::sun::star::uno::RuntimeException)
798 return _nDimensions;
801 //__________________________________________________________________________________________________
802 Sequence< sal_Int32 > ArrayTypeDescriptionImpl::getDimensions()
803 throw(::com::sun::star::uno::RuntimeException)
805 return _seqDimensions;
808 //##################################################################################################
809 //##################################################################################################
810 //##################################################################################################
813 //__________________________________________________________________________________________________
814 inline Any ManagerImpl::getSimpleType( const OUString & rName )
816 Any aRet;
818 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("string") ))
819 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_STRING, rName ) );
820 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("long") ))
821 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_LONG, rName ) );
822 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned long") ))
823 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_LONG, rName ) );
824 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("boolean") ))
825 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BOOLEAN, rName ) );
826 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("char") ))
827 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_CHAR, rName ) );
828 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") ))
829 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BYTE, rName ) );
830 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("short") ))
831 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_SHORT, rName ) );
832 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned short") ))
833 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_SHORT, rName ) );
834 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hyper") ))
835 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_HYPER, rName ) );
836 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned hyper") ))
837 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_HYPER, rName ) );
838 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") ))
839 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_FLOAT, rName ) );
840 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("double") ))
841 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_DOUBLE, rName ) );
842 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("any") ))
843 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_ANY, rName ) );
844 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("void") ))
845 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_VOID, rName ) );
846 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("type") ))
847 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_TYPE, rName ) );
849 return aRet;
852 namespace {
854 Reference< XTypeDescription > resolveTypedefs(
855 Reference< XTypeDescription > const & type)
857 Reference< XTypeDescription > resolved(type);
858 while (resolved->getTypeClass() == TypeClass_TYPEDEF) {
859 resolved = Reference< XIndirectTypeDescription >(
860 type, UNO_QUERY_THROW)->getReferencedType();
862 return resolved;
865 bool isNonVoidNonExceptionType(Reference< XTypeDescription > const & type) {
866 switch (type->getTypeClass()) {
867 case TypeClass_BOOLEAN:
868 case TypeClass_BYTE:
869 case TypeClass_SHORT:
870 case TypeClass_UNSIGNED_SHORT:
871 case TypeClass_LONG:
872 case TypeClass_UNSIGNED_LONG:
873 case TypeClass_HYPER:
874 case TypeClass_UNSIGNED_HYPER:
875 case TypeClass_FLOAT:
876 case TypeClass_DOUBLE:
877 case TypeClass_CHAR:
878 case TypeClass_STRING:
879 case TypeClass_TYPE:
880 case TypeClass_ANY:
881 case TypeClass_SEQUENCE:
882 case TypeClass_ENUM:
883 case TypeClass_STRUCT:
884 case TypeClass_INTERFACE:
885 return true;
887 default:
888 return false;
892 class InstantiatedStruct: public WeakImplHelper1< XStructTypeDescription > {
893 public:
894 InstantiatedStruct(
895 Reference< XStructTypeDescription > const & structType,
896 std::vector< Reference< XTypeDescription > > const & arguments);
898 virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException)
899 { return TypeClass_STRUCT; }
901 virtual OUString SAL_CALL getName() throw (RuntimeException);
903 virtual Reference< XTypeDescription > SAL_CALL getBaseType()
904 throw (RuntimeException)
905 { return m_struct->getBaseType(); }
907 virtual Sequence< Reference< XTypeDescription > > SAL_CALL getMemberTypes()
908 throw (RuntimeException);
910 virtual Sequence< OUString > SAL_CALL getMemberNames()
911 throw (RuntimeException)
912 { return m_struct->getMemberNames(); }
914 virtual Sequence< OUString > SAL_CALL getTypeParameters()
915 throw (RuntimeException)
916 { return Sequence< OUString >(); }
918 virtual Sequence< Reference< XTypeDescription > > SAL_CALL
919 getTypeArguments() throw (RuntimeException)
920 { return m_arguments; }
922 private:
923 Reference< XStructTypeDescription > m_struct;
924 Sequence< Reference< XTypeDescription > > m_arguments;
927 InstantiatedStruct::InstantiatedStruct(
928 Reference< XStructTypeDescription > const & structType,
929 std::vector< Reference< XTypeDescription > > const & arguments):
930 m_struct(structType),
931 m_arguments(static_cast< sal_Int32 >(arguments.size()))
933 for (std::vector< Reference< XTypeDescription > >::size_type i = 0;
934 i < arguments.size(); ++i)
936 m_arguments[static_cast< sal_Int32 >(i)] = arguments[i];
940 OUString InstantiatedStruct::getName() throw (RuntimeException) {
941 OUStringBuffer buf(m_struct->getName());
942 buf.append(static_cast< sal_Unicode >('<'));
943 for (sal_Int32 i = 0; i < m_arguments.getLength(); ++i) {
944 if (i != 0) {
945 buf.append(static_cast< sal_Unicode >(','));
947 buf.append(m_arguments[i]->getName());
949 buf.append(static_cast< sal_Unicode >('>'));
950 return buf.makeStringAndClear();
953 Sequence< Reference< XTypeDescription > > InstantiatedStruct::getMemberTypes()
954 throw (RuntimeException)
956 Sequence< Reference< XTypeDescription > > types(m_struct->getMemberTypes());
957 for (sal_Int32 i = 0; i < types.getLength(); ++i) {
958 if (types[i]->getTypeClass() == TypeClass_UNKNOWN) {
959 Sequence< OUString > parameters(m_struct->getTypeParameters());
960 OSL_ASSERT(parameters.getLength() == m_arguments.getLength());
961 for (sal_Int32 j = 0; j < parameters.getLength(); ++j) {
962 if (parameters[j] == types[i]->getName()) {
963 types[i] = m_arguments[j];
964 break;
969 return types;
974 Reference< XTypeDescription > ManagerImpl::getInstantiatedStruct(
975 OUString const & name)
977 sal_Int32 i = name.indexOf('<');
978 OSL_ASSERT(i >= 0);
979 Reference< XStructTypeDescription > structType(
980 getByHierarchicalName(name.copy(0, i)), UNO_QUERY);
981 std::vector< Reference< XTypeDescription > > args;
982 bool good = structType.is();
983 if (good) {
984 do {
985 ++i; // skip '<' or ','
986 sal_Int32 j = i;
987 for (sal_Int32 level = 0; j != name.getLength(); ++j) {
988 sal_Unicode c = name[j];
989 if (c == ',') {
990 if (level == 0) {
991 break;
993 } else if (c == '<') {
994 ++level;
995 } else if (c == '>') {
996 if (level == 0) {
997 break;
999 --level;
1002 if (j != name.getLength()) {
1003 Reference< XTypeDescription > type(
1004 getByHierarchicalName(name.copy(i, j - i)), UNO_QUERY);
1005 if (isNonVoidNonExceptionType(resolveTypedefs(type))) {
1006 args.push_back(type);
1007 } else {
1008 good = false;
1009 break;
1012 i = j;
1013 } while (i != name.getLength() && name[i] != '>');
1014 good = good && i == name.getLength() - 1
1015 && name[i] == '>' && !args.empty();
1017 // args.size() cannot exceed SAL_MAX_INT32, as each argument consumes at
1018 // least one position within an rtl::OUString (which is no longer than
1019 // SAL_MAX_INT32):
1020 if (!good
1021 || (args.size()
1022 != sal::static_int_cast< sal_uInt32 >(
1023 structType->getTypeParameters().getLength())))
1025 throw NoSuchElementException(name, static_cast< OWeakObject * >(this));
1027 return new InstantiatedStruct(structType, args);
1030 // XHierarchicalNameAccess
1031 //__________________________________________________________________________________________________
1032 Any ManagerImpl::getByHierarchicalName( const OUString & rName )
1033 throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
1035 Any aRet;
1036 if (_bCaching)
1037 aRet = _aElements.getValue( rName );
1038 if (rName.getLength() && !aRet.hasValue())
1040 sal_Int32 nIndex;
1041 if (rName[0] == '[') // test for sequence
1043 Reference< XTypeDescription > xElemType(
1044 getByHierarchicalName( rName.copy( 2 ) ),
1045 UNO_QUERY_THROW );
1046 aRet <<= Reference< XTypeDescription >(
1047 new SequenceTypeDescriptionImpl( xElemType ) );
1049 else if (rName[rName.getLength()-1] == ']') // test for array
1051 sal_Int32 nIndex2 = 0, nTokens = 0;
1052 do { rName.getToken( 0, '[', nIndex2 ); nTokens++; } while( nIndex2 != -1 );
1053 sal_Int32 nDims = nTokens - 1;
1054 sal_Int32 dimOffset = rName.indexOf('[');
1055 Reference< XTypeDescription > xElemType(
1056 getByHierarchicalName( rName.copy( 0, dimOffset ) ),
1057 UNO_QUERY_THROW );
1058 aRet <<= Reference< XTypeDescription >(
1059 new ArrayTypeDescriptionImpl(
1060 xElemType, nDims, rName.copy(dimOffset) ) );
1062 // test for interface member names:
1063 else if ((nIndex = rName.indexOf( ':' )) >= 0)
1065 Reference< XInterfaceTypeDescription > xIfaceTD(
1066 getByHierarchicalName( rName.copy( 0, nIndex ) ),
1067 UNO_QUERY_THROW );
1068 const Sequence< Reference< XInterfaceMemberTypeDescription > > &
1069 rMembers = xIfaceTD->getMembers();
1070 const Reference< XInterfaceMemberTypeDescription > * pMembers =
1071 rMembers.getConstArray();
1073 for ( sal_Int32 nPos = rMembers.getLength(); nPos--; )
1075 if (rName == pMembers[nPos]->getName())
1077 aRet <<= Reference< XTypeDescription >(
1078 pMembers[nPos], UNO_QUERY_THROW );
1079 break;
1082 if (! aRet.hasValue())
1084 // member not found:
1085 throw NoSuchElementException(
1086 rName, static_cast< OWeakObject * >(this) );
1089 // test for instantiated polymorphic struct types:
1090 else if (rName.indexOf('<') >= 0)
1092 aRet <<= getInstantiatedStruct(rName);
1094 else if (rName.indexOf( '.' ) < 0) // test for simple/ build in types
1096 aRet = getSimpleType( rName );
1099 if (! aRet.hasValue())
1101 // last, try callback chain
1102 for ( ProviderVector::const_iterator iPos( _aProviders.begin() );
1103 iPos != _aProviders.end(); ++iPos )
1107 if ((aRet = (*iPos)->getByHierarchicalName(
1108 rName )).hasValue())
1110 break;
1113 catch (NoSuchElementException &)
1119 // update cache
1120 if (_bCaching && aRet.hasValue())
1121 _aElements.setValue( rName, aRet );
1124 if (! aRet.hasValue())
1126 throw NoSuchElementException(
1127 rName, static_cast< OWeakObject * >(this) );
1129 return aRet;
1131 //__________________________________________________________________________________________________
1132 sal_Bool ManagerImpl::hasByHierarchicalName( const OUString & rName )
1133 throw(::com::sun::star::uno::RuntimeException)
1137 return getByHierarchicalName( rName ).hasValue();
1139 catch (NoSuchElementException &)
1142 return sal_False;
1146 namespace stoc_bootstrap
1148 //==================================================================================================
1149 Reference< XInterface > SAL_CALL ManagerImpl_create(
1150 Reference< XComponentContext > const & xContext )
1151 SAL_THROW( (::com::sun::star::uno::Exception) )
1153 sal_Int32 nCacheSize = CACHE_SIZE;
1154 if (xContext.is()) {
1155 xContext->getValueByName(
1156 OUString(
1157 RTL_CONSTASCII_USTRINGPARAM(
1158 "/implementations/" IMPLNAME "/CacheSize"))) >>=
1159 nCacheSize;
1162 return Reference< XInterface >( *new stoc_tdmgr::ManagerImpl( xContext, nCacheSize ) );