xref: /trunk/main/stoc/source/tdmanager/tdmgr.cxx (revision cdf0e10c)
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