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