xref: /trunk/main/stoc/source/tdmanager/tdmgr.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_stoc.hxx"
30 #include <osl/diagnose.h>
31 #include <osl/mutex.hxx>
32 #include "rtl/ustrbuf.hxx"
33 #include <cppuhelper/factory.hxx>
34 #ifndef _CPPUHELPER_IMPLBASE5_HXX_
35 #include <cppuhelper/compbase5.hxx>
36 #endif
37 #include <cppuhelper/implbase1.hxx>
38 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
39 #include <cppuhelper/implementationentry.hxx>
40 #endif
41 #include "tdmgr_common.hxx"
42 #include "tdmgr_tdenumeration.hxx"
43 #include "lrucache.hxx"
44 
45 #include <com/sun/star/lang/XServiceInfo.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <com/sun/star/lang/XEventListener.hpp>
48 #include <com/sun/star/lang/XTypeProvider.hpp>
49 #include <com/sun/star/lang/XComponent.hpp>
50 #include <com/sun/star/lang/XInitialization.hpp>
51 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
52 #include <com/sun/star/container/XSet.hpp>
53 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
54 #include <com/sun/star/reflection/XTypeDescription.hpp>
55 #include <com/sun/star/reflection/XArrayTypeDescription.hpp>
56 #include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
57 #include <com/sun/star/reflection/XInterfaceTypeDescription.hpp>
58 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
59 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
60 #include <com/sun/star/registry/XRegistryKey.hpp>
61 #include "com/sun/star/uno/RuntimeException.hpp"
62 
63 #include <algorithm>
64 #include <vector>
65 
66 using namespace std;
67 using namespace cppu;
68 using namespace rtl;
69 using namespace osl;
70 using namespace com::sun::star;
71 using namespace com::sun::star::uno;
72 using namespace com::sun::star::lang;
73 using namespace com::sun::star::reflection;
74 using namespace com::sun::star::container;
75 using namespace com::sun::star::registry;
76 
77 
78 
79 static const sal_Int32 CACHE_SIZE = 512;
80 
81 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionManager"
82 #define IMPLNAME    "com.sun.star.comp.stoc.TypeDescriptionManager"
83 
84 //--------------------------------------------------------------------------------------------------
85 // exported via tdmgr_common.hxx
86 extern rtl_StandardModuleCount g_moduleCount;
87 
88 namespace stoc_bootstrap
89 {
90 Sequence< OUString > SAL_CALL tdmgr_getSupportedServiceNames()
91 {
92     static Sequence < OUString > *pNames = 0;
93     if( ! pNames )
94     {
95         MutexGuard guard( Mutex::getGlobalMutex() );
96         if( !pNames )
97         {
98             static Sequence< OUString > seqNames(1);
99             seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
100             pNames = &seqNames;
101         }
102     }
103     return *pNames;
104 }
105 
106 OUString SAL_CALL tdmgr_getImplementationName()
107 {
108     static OUString *pImplName = 0;
109     if( ! pImplName )
110     {
111         MutexGuard guard( Mutex::getGlobalMutex() );
112         if( ! pImplName )
113         {
114             static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
115             pImplName = &implName;
116         }
117     }
118     return *pImplName;
119 }
120 }
121 
122 namespace stoc_tdmgr
123 {
124 typedef vector< Reference< XHierarchicalNameAccess > > ProviderVector;
125 
126 class EnumerationImpl;
127 class ManagerImpl;
128 
129 //==================================================================================================
130 class EventListenerImpl : public ImplHelper1< XEventListener >
131 {
132     ManagerImpl *       _pMgr;
133 
134 public:
135     EventListenerImpl( ManagerImpl * pMgr )
136         : _pMgr( pMgr )
137         {
138             ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt );
139         }
140     virtual ~EventListenerImpl();
141 
142     // lifetime delegated to manager
143     virtual void SAL_CALL acquire() throw();
144     virtual void SAL_CALL release() throw();
145 
146     // XEventListener
147     virtual void SAL_CALL disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException);
148 };
149 
150 EventListenerImpl::~EventListenerImpl()
151 {
152     ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt );
153 }
154 
155 //==================================================================================================
156 class ManagerImpl
157     : public WeakComponentImplHelper5< XServiceInfo,
158                                        XSet,
159                                        XHierarchicalNameAccess,
160                                        XTypeDescriptionEnumerationAccess,
161                                        XInitialization >
162 {
163     friend class EnumerationImpl;
164     friend class EventListenerImpl;
165 
166     Mutex                               _aComponentMutex;
167     Reference< XComponentContext >      _xContext;
168     EventListenerImpl                   _aEventListener;
169 
170     // elements
171     sal_Bool                            _bCaching;
172     LRU_CacheAnyByOUString              _aElements;
173     // provider chain
174     ProviderVector                      _aProviders;
175 
176     inline Any getSimpleType( const OUString & rName );
177 
178     Reference< XTypeDescription > getInstantiatedStruct(OUString const & name);
179 
180 protected:
181     virtual void SAL_CALL disposing();
182 
183 public:
184     ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize );
185     virtual ~ManagerImpl();
186 
187     // XInitialization
188     virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException);
189 
190     // XServiceInfo
191     virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
192     virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException);
193     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
194 
195     // XElementAccess
196     virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException);
197     virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
198 
199     // XEnumerationAccess
200     virtual Reference< XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException);
201 
202     // XSet
203     virtual sal_Bool SAL_CALL has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException);
204     virtual void SAL_CALL insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
205     virtual void SAL_CALL remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
206 
207     // XHierarchicalNameAccess
208     virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
209     virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
210 
211     // XTypeDescriptionEnumerationAccess
212     virtual ::com::sun::star::uno::Reference<
213         ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL
214     createTypeDescriptionEnumeration(
215         const ::rtl::OUString& moduleName,
216         const ::com::sun::star::uno::Sequence<
217             ::com::sun::star::uno::TypeClass >& types,
218         ::com::sun::star::reflection::TypeDescriptionSearchDepth depth )
219             throw ( ::com::sun::star::reflection::NoSuchTypeNameException,
220                     ::com::sun::star::reflection::InvalidTypeNameException,
221                     ::com::sun::star::uno::RuntimeException );
222 };
223 
224 //==================================================================================================
225 class EnumerationImpl
226     : public WeakImplHelper1< XEnumeration >
227 {
228     ManagerImpl *       _pMgr;
229     size_t              _nPos;
230 
231 public:
232     EnumerationImpl( ManagerImpl * pManager );
233     virtual ~EnumerationImpl();
234 
235     // XEnumeration
236     virtual sal_Bool SAL_CALL hasMoreElements() throw(::com::sun::star::uno::RuntimeException);
237     virtual Any SAL_CALL nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
238 };
239 
240 //##################################################################################################
241 
242 // lifetime delegated to manager
243 //__________________________________________________________________________________________________
244 void EventListenerImpl::acquire() throw()
245 {
246     _pMgr->acquire();
247 }
248 //__________________________________________________________________________________________________
249 void EventListenerImpl::release() throw()
250 {
251     _pMgr->release();
252 }
253 
254 // XEventListener
255 //__________________________________________________________________________________________________
256 void EventListenerImpl::disposing( const EventObject & rEvt )
257     throw(::com::sun::star::uno::RuntimeException)
258 {
259     _pMgr->remove( makeAny( rEvt.Source ) );
260 }
261 
262 //##################################################################################################
263 
264 //__________________________________________________________________________________________________
265 EnumerationImpl::EnumerationImpl( ManagerImpl * pManager )
266     : _pMgr( pManager )
267     , _nPos( 0 )
268 {
269     _pMgr->acquire();
270 }
271 //__________________________________________________________________________________________________
272 EnumerationImpl::~EnumerationImpl()
273 {
274     _pMgr->release();
275 }
276 
277 // XEnumeration
278 //__________________________________________________________________________________________________
279 sal_Bool EnumerationImpl::hasMoreElements()
280     throw(::com::sun::star::uno::RuntimeException)
281 {
282     MutexGuard aGuard( _pMgr->_aComponentMutex );
283     return (_nPos < _pMgr->_aProviders.size());
284 }
285 //__________________________________________________________________________________________________
286 Any EnumerationImpl::nextElement()
287     throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
288 {
289     MutexGuard aGuard( _pMgr->_aComponentMutex );
290     if (_nPos >= _pMgr->_aProviders.size())
291     {
292         throw NoSuchElementException(
293             OUString( RTL_CONSTASCII_USTRINGPARAM("there is no further element!") ),
294             (XWeak *)(OWeakObject *)this );
295     }
296     return makeAny( _pMgr->_aProviders[_nPos++] );
297 }
298 
299 //##################################################################################################
300 
301 //__________________________________________________________________________________________________
302 ManagerImpl::ManagerImpl(
303     Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize )
304     : WeakComponentImplHelper5<
305         XServiceInfo, XSet, XHierarchicalNameAccess,
306         XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex )
307     , _xContext( xContext )
308     , _aEventListener( this )
309     , _bCaching( sal_True )
310     , _aElements( nCacheSize )
311 {
312     ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt );
313 }
314 //__________________________________________________________________________________________________
315 ManagerImpl::~ManagerImpl()
316 {
317     OSL_ENSURE( _aProviders.size() == 0, "### still providers left!" );
318     OSL_TRACE( "> TypeDescriptionManager shut down. <\n" );
319     ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt );
320 }
321 //__________________________________________________________________________________________________
322 void ManagerImpl::disposing()
323 {
324     // called on disposing the tdmgr instance (supposedly from context)
325     _bCaching = sal_False;
326     _aElements.clear();
327     _xContext.clear();
328     _aProviders.clear();
329 }
330 
331 // XInitialization
332 //__________________________________________________________________________________________________
333 void ManagerImpl::initialize(
334     const Sequence< Any > & args )
335     throw (Exception, RuntimeException)
336 {
337     // additional providers
338     Any const * pProviders = args.getConstArray();
339     for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos )
340     {
341         Reference< XHierarchicalNameAccess > xHA( pProviders[ nPos ], UNO_QUERY );
342         OSL_ENSURE( xHA.is(), "### no td provider!" );
343 
344         if (xHA.is())
345         {
346             try
347             {
348                 insert( makeAny( xHA ) );
349             }
350             catch (IllegalArgumentException &)
351             {
352             }
353             catch (ElementExistException &)
354             {
355             }
356         }
357     }
358 }
359 
360 // XServiceInfo
361 //__________________________________________________________________________________________________
362 OUString ManagerImpl::getImplementationName()
363     throw(::com::sun::star::uno::RuntimeException)
364 {
365     return stoc_bootstrap::tdmgr_getImplementationName();
366 }
367 //__________________________________________________________________________________________________
368 sal_Bool ManagerImpl::supportsService( const OUString & rServiceName )
369     throw(::com::sun::star::uno::RuntimeException)
370 {
371     const Sequence< OUString > & rSNL = getSupportedServiceNames();
372     const OUString * pArray = rSNL.getConstArray();
373     for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
374     {
375         if (pArray[nPos] == rServiceName)
376             return sal_True;
377     }
378     return sal_False;
379 }
380 //__________________________________________________________________________________________________
381 Sequence< OUString > ManagerImpl::getSupportedServiceNames()
382     throw(::com::sun::star::uno::RuntimeException)
383 {
384     return stoc_bootstrap::tdmgr_getSupportedServiceNames();
385 }
386 
387 // XElementAccess
388 //__________________________________________________________________________________________________
389 Type ManagerImpl::getElementType()
390     throw(::com::sun::star::uno::RuntimeException)
391 {
392     return ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 );
393 }
394 //__________________________________________________________________________________________________
395 sal_Bool ManagerImpl::hasElements()
396     throw(::com::sun::star::uno::RuntimeException)
397 {
398     MutexGuard aGuard( _aComponentMutex );
399     return (_aProviders.size() > 0);
400 }
401 
402 // XEnumerationAccess
403 //__________________________________________________________________________________________________
404 Reference< XEnumeration > ManagerImpl::createEnumeration()
405     throw(::com::sun::star::uno::RuntimeException)
406 {
407     return new EnumerationImpl( this );
408 }
409 
410 // XSet
411 //__________________________________________________________________________________________________
412 sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement )
413     throw(::com::sun::star::uno::RuntimeException)
414 {
415     Reference< XHierarchicalNameAccess > xElem;
416     if (rElement >>= xElem)
417     {
418         MutexGuard aGuard( _aComponentMutex );
419         return (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end());
420     }
421     return sal_False;
422 }
423 
424 //__________________________________________________________________________________________________
425 void SAL_CALL ManagerImpl::insert( const Any & rElement )
426     throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
427 {
428     Reference< XHierarchicalNameAccess > xElem;
429     if (! (rElement >>= xElem) || !xElem.is())
430     {
431         throw IllegalArgumentException(
432             OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ),
433             (XWeak *)(OWeakObject *)this, 0 );
434     }
435 
436     MutexGuard aGuard( _aComponentMutex );
437     if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end())
438     {
439         throw ElementExistException(
440             OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ),
441             (XWeak *)(OWeakObject *)this );
442     }
443 
444     if (! _aProviders.empty())
445     {
446         // check whether all types are compatible, if possible:
447         Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess(
448             xElem, UNO_QUERY );
449         OSL_ENSURE( xTDEnumAccess.is(),
450                     "### providers ought to implement "
451                     "reflection::XTypeDescriptionEnumerationAccess!" );
452         if (xTDEnumAccess.is())
453         {
454             try
455             {
456                 TypeClass ar [] = {
457                     TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE,
458                     TypeClass_STRUCT, TypeClass_EXCEPTION,
459                     /* TypeClass_UNION, TypeClass_ARRAY not supported */
460                     TypeClass_INTERFACE,
461                     TypeClass_SERVICE,
462                     TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE,
463                     TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS,
464                     TypeClass_SINGLETON
465                 };
466                 Reference<reflection::XTypeDescriptionEnumeration> xTDEnum(
467                     xTDEnumAccess->createTypeDescriptionEnumeration(
468                         OUString() /* all modules */,
469                         Sequence<TypeClass>( ar, ARLEN(ar) ),
470                         reflection::TypeDescriptionSearchDepth_INFINITE ) );
471 
472                 while (xTDEnum->hasMoreElements())
473                 {
474                     Reference<reflection::XTypeDescription> xNewTD;
475                     try
476                     {
477                         xNewTD = xTDEnum->nextTypeDescription();
478                     }
479                     catch (container::NoSuchElementException & exc)
480                     {
481                         throw lang::IllegalArgumentException(
482                             OUSTR("NoSuchElementException occured: ") +
483                             exc.Message, static_cast<OWeakObject *>(this),
484                             -1 /* unknown */ );
485                     }
486 
487                     try
488                     {
489                         OUString newName( xNewTD->getName() );
490                         Reference<reflection::XTypeDescription> xExistingTD(
491                             getByHierarchicalName( newName ), UNO_QUERY );
492                         OSL_ASSERT( xExistingTD.is() );
493                         // existing, check whether compatible:
494                         if (xExistingTD.is())
495                         {
496                             try
497                             {
498                                 check( xNewTD, xExistingTD );
499                             }
500                             catch (IncompatibleTypeException & exc)
501                             {
502                                 throw lang::IllegalArgumentException(
503                                     OUSTR("Rejecting types due to "
504                                           "incompatibility!  ") + exc.m_cause,
505                                     static_cast<OWeakObject *>(this), 0 );
506                             }
507                         }
508                     }
509                     catch (container::NoSuchElementException &)
510                     {
511                         // type not in: ok
512                     }
513                 }
514             }
515             catch (reflection::NoSuchTypeNameException & exc)
516             {
517                 throw lang::IllegalArgumentException(
518                     OUSTR("NoSuchTypeNameException occured: ") + exc.Message,
519                     static_cast<OWeakObject *>(this), -1 /* unknown */ );
520             }
521             catch (reflection::InvalidTypeNameException & exc)
522             {
523                 throw lang::IllegalArgumentException(
524                     OUSTR("InvalidTypeNameException occured: ") + exc.Message,
525                     static_cast<OWeakObject *>(this), -1 /* unknown */ );
526             }
527         }
528     }
529 
530     _aProviders.push_back( xElem );
531     Reference< XComponent > xComp( xElem, UNO_QUERY );
532     if (xComp.is())
533         xComp->addEventListener( &_aEventListener );
534 }
535 //__________________________________________________________________________________________________
536 void SAL_CALL ManagerImpl::remove( const Any & rElement )
537     throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
538 {
539     if (!rBHelper.bDisposed && !rBHelper.bInDispose)
540     {
541         Reference< XHierarchicalNameAccess > xElem;
542         if (! (rElement >>= xElem))
543         {
544             throw IllegalArgumentException(
545                 OUString( RTL_CONSTASCII_USTRINGPARAM("no type description provider given!") ),
546                 (XWeak *)(OWeakObject *)this, 0 );
547         }
548 
549         MutexGuard aGuard( _aComponentMutex );
550         ProviderVector::iterator iFind( find( _aProviders.begin(), _aProviders.end(), xElem ) );
551         if (iFind == _aProviders.end())
552         {
553             throw NoSuchElementException(
554                 OUString( RTL_CONSTASCII_USTRINGPARAM("provider not found!") ),
555                 (XWeak *)(OWeakObject *)this );
556         }
557         _aProviders.erase( iFind );
558     }
559 
560     Reference< XComponent > xComp;
561     if (rElement >>= xComp)
562         xComp->removeEventListener( &_aEventListener );
563 }
564 
565 // XTypeDescriptionEnumerationAccess
566 //__________________________________________________________________________________________________
567 // virtual
568 Reference< XTypeDescriptionEnumeration > SAL_CALL
569 ManagerImpl::createTypeDescriptionEnumeration(
570         const OUString & moduleName,
571         const Sequence< TypeClass > & types,
572         TypeDescriptionSearchDepth depth )
573     throw ( NoSuchTypeNameException,
574             InvalidTypeNameException,
575             RuntimeException )
576 {
577     MutexGuard aGuard( _aComponentMutex );
578 
579     TDEnumerationAccessStack aStack;
580     ProviderVector::const_iterator it = _aProviders.begin();
581     const ProviderVector::const_iterator end = _aProviders.end();
582     while ( it != end )
583     {
584         Reference< XTypeDescriptionEnumerationAccess >xEnumAccess(
585             (*it), UNO_QUERY );
586         OSL_ENSURE( xEnumAccess.is(),
587                     "### no XTypeDescriptionEnumerationAccess!" );
588         if ( xEnumAccess.is() )
589             aStack.push( xEnumAccess );
590 
591         it++;
592     }
593 
594     return Reference< XTypeDescriptionEnumeration >(
595         new TypeDescriptionEnumerationImpl( moduleName,
596                                             types,
597                                             depth,
598                                             aStack ) );
599 }
600 
601 
602 //##################################################################################################
603 //##################################################################################################
604 //##################################################################################################
605 
606 
607 //==================================================================================================
608 class SimpleTypeDescriptionImpl
609     : public WeakImplHelper1< XTypeDescription >
610 {
611     TypeClass _eTC;
612     OUString  _aName;
613 
614 public:
615     SimpleTypeDescriptionImpl( TypeClass eTC, const OUString & rName )
616         : _eTC( eTC )
617         , _aName( rName )
618         {}
619 
620     // XTypeDescription
621     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
622     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
623 };
624 
625 // XTypeDescription
626 //__________________________________________________________________________________________________
627 TypeClass SimpleTypeDescriptionImpl::getTypeClass()
628     throw(::com::sun::star::uno::RuntimeException)
629 {
630     return _eTC;
631 }
632 //__________________________________________________________________________________________________
633 OUString SimpleTypeDescriptionImpl::getName()
634     throw(::com::sun::star::uno::RuntimeException)
635 {
636     return _aName;
637 }
638 
639 //==================================================================================================
640 class SequenceTypeDescriptionImpl
641     : public WeakImplHelper1< XIndirectTypeDescription >
642 {
643     Reference< XTypeDescription > _xElementTD;
644 
645 public:
646     SequenceTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD )
647         : _xElementTD( xElementTD )
648         {}
649 
650     // XTypeDescription
651     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
652     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
653 
654     // XIndirectTypeDescription
655     virtual Reference< XTypeDescription > SAL_CALL getReferencedType() throw(::com::sun::star::uno::RuntimeException);
656 };
657 
658 // XTypeDescription
659 //__________________________________________________________________________________________________
660 TypeClass SequenceTypeDescriptionImpl::getTypeClass()
661     throw(::com::sun::star::uno::RuntimeException)
662 {
663     return TypeClass_SEQUENCE;
664 }
665 //__________________________________________________________________________________________________
666 OUString SequenceTypeDescriptionImpl::getName()
667     throw(::com::sun::star::uno::RuntimeException)
668 {
669     return (OUString( RTL_CONSTASCII_USTRINGPARAM("[]") ) + _xElementTD->getName());
670 }
671 
672 // XIndirectTypeDescription
673 //__________________________________________________________________________________________________
674 Reference< XTypeDescription > SequenceTypeDescriptionImpl::getReferencedType()
675     throw(::com::sun::star::uno::RuntimeException)
676 {
677     return _xElementTD;
678 }
679 
680 //==================================================================================================
681 class ArrayTypeDescriptionImpl
682     : public WeakImplHelper1< XArrayTypeDescription >
683 {
684     Reference< XTypeDescription > _xElementTD;
685     Mutex                         _aDimensionMutex;
686     sal_Int32                     _nDimensions;
687     Sequence< sal_Int32 >         _seqDimensions;
688     OUString                      _sDimensions;
689 
690     void initDimensions(const OUString& rSDimensions);
691 public:
692     ArrayTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD,
693                               sal_Int32 nDimensions, const OUString& rSDimensions )
694         : _xElementTD( xElementTD )
695         , _nDimensions( nDimensions )
696         , _seqDimensions( Sequence< sal_Int32 >(nDimensions) )
697         , _sDimensions( rSDimensions )
698         {
699             initDimensions( rSDimensions );
700         }
701     virtual ~ArrayTypeDescriptionImpl() {}
702 
703     // XTypeDescription
704     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
705     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
706 
707     // XArrayTypeDescription
708     virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException);
709     virtual sal_Int32 SAL_CALL getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException);
710     virtual Sequence< sal_Int32 > SAL_CALL getDimensions() throw(::com::sun::star::uno::RuntimeException);
711 };
712 //__________________________________________________________________________________________________
713 static sal_Int32 unicodeToInteger( sal_Int8 base, const sal_Unicode *s )
714 {
715     sal_Int32    r = 0;
716     sal_Int32    negative = 0;
717 
718     if (*s == '-')
719     {
720         negative = 1;
721         s++;
722     }
723     if (base == 8 && *s == '0')
724         s++;
725     else if (base == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
726         s += 2;
727 
728     for (; *s; s++)
729     {
730         if (*s <= '9' && *s >= '0')
731             r = (r * base) + (*s - '0');
732         else if (base > 10 && *s <= 'f' && *s >= 'a')
733             r = (r * base) + (*s - 'a' + 10);
734         else if (base > 10 && *s <= 'F' && *s >= 'A')
735             r = (r * base) + (*s - 'A' + 10);
736         else
737             break;
738     }
739     if (negative) r *= -1;
740     return r;
741 }
742 //__________________________________________________________________________________________________
743 void ArrayTypeDescriptionImpl::initDimensions(const OUString& rSDimensions)
744 {
745     MutexGuard aGuard( _aDimensionMutex );
746 
747     sal_Int32 *  pDimensions = _seqDimensions.getArray();
748     OUString tmp(rSDimensions);
749     sal_Unicode* p = (sal_Unicode*)tmp.getStr()+1;
750     sal_Unicode* pOffset = p;
751     sal_Int32 len = tmp.getLength() - 1 ;
752     sal_Int32 i = 0;
753 
754     while ( len > 0)
755     {
756         pOffset++;
757         if (*pOffset == ']')
758         {
759             *pOffset = '\0';
760             pOffset += 2;
761             len -= 3;
762             pDimensions[i++] = unicodeToInteger(10, p);
763             p = pOffset;
764         } else
765             len--;
766     }
767 }
768 
769 // XTypeDescription
770 //__________________________________________________________________________________________________
771 TypeClass ArrayTypeDescriptionImpl::getTypeClass()
772     throw(::com::sun::star::uno::RuntimeException)
773 {
774     return TypeClass_ARRAY;
775 }
776 //__________________________________________________________________________________________________
777 OUString ArrayTypeDescriptionImpl::getName()
778     throw(::com::sun::star::uno::RuntimeException)
779 {
780     return (_xElementTD->getName() + _sDimensions);
781 }
782 
783 // XArrayTypeDescription
784 //__________________________________________________________________________________________________
785 Reference< XTypeDescription > ArrayTypeDescriptionImpl::getType()
786     throw(::com::sun::star::uno::RuntimeException)
787 {
788     return _xElementTD;
789 }
790 
791 //__________________________________________________________________________________________________
792 sal_Int32 ArrayTypeDescriptionImpl::getNumberOfDimensions()
793     throw(::com::sun::star::uno::RuntimeException)
794 {
795     return _nDimensions;
796 }
797 
798 //__________________________________________________________________________________________________
799 Sequence< sal_Int32 > ArrayTypeDescriptionImpl::getDimensions()
800     throw(::com::sun::star::uno::RuntimeException)
801 {
802     return _seqDimensions;
803 }
804 
805 //##################################################################################################
806 //##################################################################################################
807 //##################################################################################################
808 
809 
810 //__________________________________________________________________________________________________
811 inline Any ManagerImpl::getSimpleType( const OUString & rName )
812 {
813     Any aRet;
814 
815     if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("string") ))
816         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_STRING, rName ) );
817     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("long") ))
818         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_LONG, rName ) );
819     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned long") ))
820         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_LONG, rName ) );
821     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("boolean") ))
822         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BOOLEAN, rName ) );
823     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("char") ))
824         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_CHAR, rName ) );
825     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") ))
826         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BYTE, rName ) );
827     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("short") ))
828         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_SHORT, rName ) );
829     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned short") ))
830         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_SHORT, rName ) );
831     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hyper") ))
832         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_HYPER, rName ) );
833     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned hyper") ))
834         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_HYPER, rName ) );
835     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") ))
836         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_FLOAT, rName ) );
837     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("double") ))
838         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_DOUBLE, rName ) );
839     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("any") ))
840         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_ANY, rName ) );
841     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("void") ))
842         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_VOID, rName ) );
843     else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("type") ))
844         aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_TYPE, rName ) );
845 
846     return aRet;
847 }
848 
849 namespace {
850 
851 Reference< XTypeDescription > resolveTypedefs(
852     Reference< XTypeDescription > const & type)
853 {
854     Reference< XTypeDescription > resolved(type);
855     while (resolved->getTypeClass() == TypeClass_TYPEDEF) {
856         resolved = Reference< XIndirectTypeDescription >(
857             type, UNO_QUERY_THROW)->getReferencedType();
858     }
859     return resolved;
860 }
861 
862 bool isNonVoidNonExceptionType(Reference< XTypeDescription > const & type) {
863     switch (type->getTypeClass()) {
864     case TypeClass_BOOLEAN:
865     case TypeClass_BYTE:
866     case TypeClass_SHORT:
867     case TypeClass_UNSIGNED_SHORT:
868     case TypeClass_LONG:
869     case TypeClass_UNSIGNED_LONG:
870     case TypeClass_HYPER:
871     case TypeClass_UNSIGNED_HYPER:
872     case TypeClass_FLOAT:
873     case TypeClass_DOUBLE:
874     case TypeClass_CHAR:
875     case TypeClass_STRING:
876     case TypeClass_TYPE:
877     case TypeClass_ANY:
878     case TypeClass_SEQUENCE:
879     case TypeClass_ENUM:
880     case TypeClass_STRUCT:
881     case TypeClass_INTERFACE:
882         return true;
883 
884     default:
885         return false;
886     }
887 }
888 
889 class InstantiatedStruct: public WeakImplHelper1< XStructTypeDescription > {
890 public:
891     InstantiatedStruct(
892         Reference< XStructTypeDescription > const & structType,
893         std::vector< Reference< XTypeDescription > > const & arguments);
894 
895     virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException)
896     { return TypeClass_STRUCT; }
897 
898     virtual OUString SAL_CALL getName() throw (RuntimeException);
899 
900     virtual Reference< XTypeDescription > SAL_CALL getBaseType()
901         throw (RuntimeException)
902     { return m_struct->getBaseType(); }
903 
904     virtual Sequence< Reference< XTypeDescription > > SAL_CALL getMemberTypes()
905         throw (RuntimeException);
906 
907     virtual Sequence< OUString > SAL_CALL getMemberNames()
908         throw (RuntimeException)
909     { return m_struct->getMemberNames(); }
910 
911     virtual Sequence< OUString > SAL_CALL getTypeParameters()
912         throw (RuntimeException)
913     { return Sequence< OUString >(); }
914 
915     virtual Sequence< Reference< XTypeDescription > > SAL_CALL
916     getTypeArguments() throw (RuntimeException)
917     { return m_arguments; }
918 
919 private:
920     Reference< XStructTypeDescription > m_struct;
921     Sequence< Reference< XTypeDescription > > m_arguments;
922 };
923 
924 InstantiatedStruct::InstantiatedStruct(
925     Reference< XStructTypeDescription > const & structType,
926     std::vector< Reference< XTypeDescription > > const & arguments):
927     m_struct(structType),
928     m_arguments(static_cast< sal_Int32 >(arguments.size()))
929 {
930     for (std::vector< Reference< XTypeDescription > >::size_type i = 0;
931          i < arguments.size(); ++i)
932     {
933         m_arguments[static_cast< sal_Int32 >(i)] = arguments[i];
934     }
935 }
936 
937 OUString InstantiatedStruct::getName() throw (RuntimeException) {
938     OUStringBuffer buf(m_struct->getName());
939     buf.append(static_cast< sal_Unicode >('<'));
940     for (sal_Int32 i = 0; i < m_arguments.getLength(); ++i) {
941         if (i != 0) {
942             buf.append(static_cast< sal_Unicode >(','));
943         }
944         buf.append(m_arguments[i]->getName());
945     }
946     buf.append(static_cast< sal_Unicode >('>'));
947     return buf.makeStringAndClear();
948 }
949 
950 Sequence< Reference< XTypeDescription > > InstantiatedStruct::getMemberTypes()
951     throw (RuntimeException)
952 {
953     Sequence< Reference< XTypeDescription > > types(m_struct->getMemberTypes());
954     for (sal_Int32 i = 0; i < types.getLength(); ++i) {
955         if (types[i]->getTypeClass() == TypeClass_UNKNOWN) {
956             Sequence< OUString > parameters(m_struct->getTypeParameters());
957             OSL_ASSERT(parameters.getLength() == m_arguments.getLength());
958             for (sal_Int32 j = 0; j < parameters.getLength(); ++j) {
959                 if (parameters[j] == types[i]->getName()) {
960                     types[i] = m_arguments[j];
961                     break;
962                 }
963             }
964         }
965     }
966     return types;
967 }
968 
969 }
970 
971 Reference< XTypeDescription > ManagerImpl::getInstantiatedStruct(
972     OUString const & name)
973 {
974     sal_Int32 i = name.indexOf('<');
975     OSL_ASSERT(i >= 0);
976     Reference< XStructTypeDescription > structType(
977         getByHierarchicalName(name.copy(0, i)), UNO_QUERY);
978     std::vector< Reference< XTypeDescription > > args;
979     bool good = structType.is();
980     if (good) {
981         do {
982             ++i; // skip '<' or ','
983             sal_Int32 j = i;
984             for (sal_Int32 level = 0; j != name.getLength(); ++j) {
985                 sal_Unicode c = name[j];
986                 if (c == ',') {
987                     if (level == 0) {
988                         break;
989                     }
990                 } else if (c == '<') {
991                     ++level;
992                 } else if (c == '>') {
993                     if (level == 0) {
994                         break;
995                     }
996                     --level;
997                 }
998             }
999             if (j != name.getLength()) {
1000                 Reference< XTypeDescription > type(
1001                     getByHierarchicalName(name.copy(i, j - i)), UNO_QUERY);
1002                 if (isNonVoidNonExceptionType(resolveTypedefs(type))) {
1003                     args.push_back(type);
1004                 } else {
1005                     good = false;
1006                     break;
1007                 }
1008             }
1009             i = j;
1010         } while (i != name.getLength() && name[i] != '>');
1011         good = good && i == name.getLength() - 1
1012             && name[i] == '>' && !args.empty();
1013     }
1014     // args.size() cannot exceed SAL_MAX_INT32, as each argument consumes at
1015     // least one position within an rtl::OUString (which is no longer than
1016     // SAL_MAX_INT32):
1017     if (!good
1018         || (args.size()
1019             != sal::static_int_cast< sal_uInt32 >(
1020                 structType->getTypeParameters().getLength())))
1021     {
1022         throw NoSuchElementException(name, static_cast< OWeakObject * >(this));
1023     }
1024     return new InstantiatedStruct(structType, args);
1025 }
1026 
1027 // XHierarchicalNameAccess
1028 //__________________________________________________________________________________________________
1029 Any ManagerImpl::getByHierarchicalName( const OUString & rName )
1030     throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
1031 {
1032     Any aRet;
1033     if (_bCaching)
1034         aRet = _aElements.getValue( rName );
1035     if (rName.getLength() && !aRet.hasValue())
1036     {
1037         sal_Int32 nIndex;
1038         if (rName[0] == '[') // test for sequence
1039         {
1040             Reference< XTypeDescription > xElemType(
1041                 getByHierarchicalName( rName.copy( 2 ) ),
1042                 UNO_QUERY_THROW );
1043             aRet <<= Reference< XTypeDescription >(
1044                 new SequenceTypeDescriptionImpl( xElemType ) );
1045         }
1046         else if (rName[rName.getLength()-1] == ']') // test for array
1047         {
1048             sal_Int32 nIndex2 = 0, nTokens = 0;
1049             do { rName.getToken( 0, '[', nIndex2 ); nTokens++; } while( nIndex2 != -1 );
1050             sal_Int32 nDims = nTokens - 1;
1051             sal_Int32 dimOffset = rName.indexOf('[');
1052             Reference< XTypeDescription > xElemType(
1053                 getByHierarchicalName( rName.copy( 0, dimOffset ) ),
1054                 UNO_QUERY_THROW );
1055             aRet <<= Reference< XTypeDescription >(
1056                 new ArrayTypeDescriptionImpl(
1057                     xElemType, nDims, rName.copy(dimOffset) ) );
1058         }
1059         // test for interface member names:
1060         else if ((nIndex = rName.indexOf( ':' )) >= 0)
1061         {
1062             Reference< XInterfaceTypeDescription > xIfaceTD(
1063                 getByHierarchicalName( rName.copy( 0, nIndex ) ),
1064                 UNO_QUERY_THROW );
1065             const Sequence< Reference< XInterfaceMemberTypeDescription > > &
1066                 rMembers = xIfaceTD->getMembers();
1067             const Reference< XInterfaceMemberTypeDescription > * pMembers =
1068                 rMembers.getConstArray();
1069 
1070             for ( sal_Int32 nPos = rMembers.getLength(); nPos--; )
1071             {
1072                 if (rName == pMembers[nPos]->getName())
1073                 {
1074                     aRet <<= Reference< XTypeDescription >(
1075                         pMembers[nPos], UNO_QUERY_THROW );
1076                     break;
1077                 }
1078             }
1079             if (! aRet.hasValue())
1080             {
1081                 // member not found:
1082                 throw NoSuchElementException(
1083                     rName, static_cast< OWeakObject * >(this) );
1084             }
1085         }
1086         // test for instantiated polymorphic struct types:
1087         else if (rName.indexOf('<') >= 0)
1088         {
1089             aRet <<= getInstantiatedStruct(rName);
1090         }
1091         else if (rName.indexOf( '.' ) < 0) // test for simple/ build in types
1092         {
1093             aRet = getSimpleType( rName );
1094         }
1095 
1096         if (! aRet.hasValue())
1097         {
1098             // last, try callback chain
1099             for ( ProviderVector::const_iterator iPos( _aProviders.begin() );
1100                   iPos != _aProviders.end(); ++iPos )
1101             {
1102                 try
1103                 {
1104                     if ((aRet = (*iPos)->getByHierarchicalName(
1105                              rName )).hasValue())
1106                     {
1107                         break;
1108                     }
1109                 }
1110                 catch (NoSuchElementException &)
1111                 {
1112                 }
1113             }
1114         }
1115 
1116         // update cache
1117         if (_bCaching && aRet.hasValue())
1118             _aElements.setValue( rName, aRet );
1119     }
1120 
1121     if (! aRet.hasValue())
1122     {
1123         throw NoSuchElementException(
1124             rName, static_cast< OWeakObject * >(this) );
1125     }
1126     return aRet;
1127 }
1128 //__________________________________________________________________________________________________
1129 sal_Bool ManagerImpl::hasByHierarchicalName( const OUString & rName )
1130     throw(::com::sun::star::uno::RuntimeException)
1131 {
1132     try
1133     {
1134         return getByHierarchicalName( rName ).hasValue();
1135     }
1136     catch (NoSuchElementException &)
1137     {
1138     }
1139     return sal_False;
1140 }
1141 }
1142 
1143 namespace stoc_bootstrap
1144 {
1145 //==================================================================================================
1146 Reference< XInterface > SAL_CALL ManagerImpl_create(
1147     Reference< XComponentContext > const & xContext )
1148     SAL_THROW( (::com::sun::star::uno::Exception) )
1149 {
1150     sal_Int32 nCacheSize = CACHE_SIZE;
1151     if (xContext.is()) {
1152         xContext->getValueByName(
1153             OUString(
1154                 RTL_CONSTASCII_USTRINGPARAM(
1155                     "/implementations/" IMPLNAME "/CacheSize"))) >>=
1156             nCacheSize;
1157     }
1158 
1159     return Reference< XInterface >( *new stoc_tdmgr::ManagerImpl( xContext, nCacheSize ) );
1160 }
1161 
1162 }
1163 
1164