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