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