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