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 <uno/dispatcher.h>
29 #include <uno/mapping.hxx>
30 #include <cppuhelper/factory.hxx>
31 #include <cppuhelper/compbase4.hxx>
32 #include <cppuhelper/implbase2.hxx>
33 #include <cppuhelper/typeprovider.hxx>
34
35 #include <cppuhelper/weakref.hxx>
36
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/XComponent.hpp>
39 #include <com/sun/star/lang/XTypeProvider.hpp>
40 #include <com/sun/star/lang/XInitialization.hpp>
41 #include <com/sun/star/registry/XSimpleRegistry.hpp>
42 #include <com/sun/star/registry/XRegistryKey.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
45 #include "com/sun/star/uno/RuntimeException.hpp"
46
47 #include "registry/reader.hxx"
48 #include "registry/version.h"
49 #include "base.hxx"
50 #include "rdbtdp_tdenumeration.hxx"
51 #include "structtypedescription.hxx"
52
53 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider"
54 #define IMPLNAME "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider"
55
56 using namespace com::sun::star;
57 using namespace com::sun::star::beans;
58 using namespace com::sun::star::registry;
59
60 extern rtl_StandardModuleCount g_moduleCount;
61
62 namespace stoc_bootstrap
63 {
rdbtdp_getSupportedServiceNames()64 uno::Sequence< OUString > rdbtdp_getSupportedServiceNames()
65 {
66 static Sequence < OUString > *pNames = 0;
67 if( ! pNames )
68 {
69 MutexGuard guard( Mutex::getGlobalMutex() );
70 if( !pNames )
71 {
72 static Sequence< OUString > seqNames(1);
73 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
74 pNames = &seqNames;
75 }
76 }
77 return *pNames;
78 }
79
rdbtdp_getImplementationName()80 OUString rdbtdp_getImplementationName()
81 {
82 static OUString *pImplName = 0;
83 if( ! pImplName )
84 {
85 MutexGuard guard( Mutex::getGlobalMutex() );
86 if( ! pImplName )
87 {
88 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
89 pImplName = &implName;
90 }
91 }
92 return *pImplName;
93 }
94 }
95
96 namespace stoc_rdbtdp
97 {
98 struct MutexHolder
99 {
100 Mutex _aComponentMutex;
101 };
102 //==================================================================================================
103 class ProviderImpl
104 : public MutexHolder
105 , public WeakComponentImplHelper4< XServiceInfo,
106 XHierarchicalNameAccess,
107 XTypeDescriptionEnumerationAccess,
108 XInitialization >
109 {
110 // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper
111 // first asking the tdmgr instance, then looking up locally
112 class TypeDescriptionManagerWrapper
113 : public ::cppu::WeakImplHelper2<
114 container::XHierarchicalNameAccess,
115 reflection::XTypeDescriptionEnumerationAccess>
116 {
117 com::sun::star::uno::Reference<container::XHierarchicalNameAccess>
118 m_xTDMgr;
119 com::sun::star::uno::Reference<container::XHierarchicalNameAccess>
120 m_xThisProvider;
121 public:
TypeDescriptionManagerWrapper(ProviderImpl * pProvider)122 TypeDescriptionManagerWrapper( ProviderImpl * pProvider )
123 : m_xTDMgr( pProvider->_xContext->getValueByName(
124 OUString( RTL_CONSTASCII_USTRINGPARAM(
125 "/singletons/com.sun.star.reflection."
126 "theTypeDescriptionManager") ) ),
127 UNO_QUERY_THROW ),
128 m_xThisProvider( pProvider )
129 {}
130 // XHierarchicalNameAccess
131 virtual Any SAL_CALL getByHierarchicalName( OUString const & name );
132 virtual sal_Bool SAL_CALL hasByHierarchicalName( OUString const & name );
133
134 // XTypeDescriptionEnumerationAccess
135 virtual uno::Reference<
136 reflection::XTypeDescriptionEnumeration > SAL_CALL
137 createTypeDescriptionEnumeration(
138 const ::rtl::OUString& moduleName,
139 const uno::Sequence< uno::TypeClass >& types,
140 reflection::TypeDescriptionSearchDepth depth );
141 };
142 friend class TypeDescriptionManagerWrapper;
143
144 com::sun::star::uno::Reference< XComponentContext > _xContext;
145 com::sun::star::uno::WeakReference<XHierarchicalNameAccess> _xTDMgr;
146 com::sun::star::uno::Reference< XHierarchicalNameAccess > getTDMgr() SAL_THROW( () );
147
148 RegistryKeyList _aBaseKeys;
149
150 protected:
151 virtual void SAL_CALL disposing();
152
153 public:
154 ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext );
155 virtual ~ProviderImpl();
156
157 // XInitialization
158 virtual void SAL_CALL initialize( const Sequence< Any > & args );
159
160 // XServiceInfo
161 virtual OUString SAL_CALL getImplementationName();
162 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName );
163 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames();
164
165 // XHierarchicalNameAccess
166 Any getByHierarchicalNameImpl( const OUString & rName );
167
168 virtual Any SAL_CALL getByHierarchicalName( const OUString & rName );
169 virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName );
170
171 // XTypeDescriptionEnumerationAccess
172 virtual ::com::sun::star::uno::Reference<
173 ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL
174 createTypeDescriptionEnumeration(
175 const ::rtl::OUString& moduleName,
176 const ::com::sun::star::uno::Sequence<
177 ::com::sun::star::uno::TypeClass >& types,
178 ::com::sun::star::reflection::TypeDescriptionSearchDepth depth );
179 };
180 //__________________________________________________________________________________________________
ProviderImpl(const com::sun::star::uno::Reference<XComponentContext> & xContext)181 ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext )
182 : WeakComponentImplHelper4<
183 XServiceInfo, XHierarchicalNameAccess,
184 XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex )
185 , _xContext( xContext )
186 {
187 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
188 }
189 //__________________________________________________________________________________________________
~ProviderImpl()190 ProviderImpl::~ProviderImpl()
191 {
192 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
193 }
194
195 //______________________________________________________________________________
getByHierarchicalName(OUString const & name)196 Any ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName(
197 OUString const & name )
198 {
199 try
200 {
201 // first try tdmgr:
202 return m_xTDMgr->getByHierarchicalName( name );
203 }
204 catch (container::NoSuchElementException &)
205 {
206 // then lookup locally:
207 return m_xThisProvider->getByHierarchicalName( name );
208 }
209 }
210
211 //______________________________________________________________________________
hasByHierarchicalName(OUString const & name)212 sal_Bool ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName(
213 OUString const & name )
214 {
215 return m_xTDMgr->hasByHierarchicalName( name ) || m_xThisProvider->hasByHierarchicalName( name );
216 }
217
218 //______________________________________________________________________________
219 uno::Reference< reflection::XTypeDescriptionEnumeration > SAL_CALL
createTypeDescriptionEnumeration(const::rtl::OUString & moduleName,const uno::Sequence<uno::TypeClass> & types,reflection::TypeDescriptionSearchDepth depth)220 ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration(
221 const ::rtl::OUString& moduleName,
222 const uno::Sequence< uno::TypeClass >& types,
223 reflection::TypeDescriptionSearchDepth depth )
224 {
225 try
226 {
227 // first try tdmgr:
228 uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA(
229 m_xTDMgr, uno::UNO_QUERY_THROW );
230 return
231 xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth );
232 }
233 catch (reflection::NoSuchTypeNameException &)
234 {
235 // then lookup locally:
236 uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA(
237 m_xThisProvider, uno::UNO_QUERY_THROW );
238 return
239 xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth );
240 }
241 }
242
243 //__________________________________________________________________________________________________
getTDMgr()244 com::sun::star::uno::Reference< XHierarchicalNameAccess > ProviderImpl::getTDMgr()
245 SAL_THROW( () )
246 {
247 // harden weak reference:
248 com::sun::star::uno::Reference<container::XHierarchicalNameAccess> xTDMgr(
249 _xTDMgr );
250 if (! xTDMgr.is())
251 {
252 xTDMgr.set( new TypeDescriptionManagerWrapper(this) );
253 {
254 MutexGuard guard( _aComponentMutex );
255 _xTDMgr = xTDMgr;
256 }
257 }
258 return xTDMgr;
259 }
260
261 //__________________________________________________________________________________________________
disposing()262 void ProviderImpl::disposing()
263 {
264 _xContext.clear();
265
266 for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() );
267 iPos != _aBaseKeys.end(); ++iPos )
268 {
269 (*iPos)->closeKey();
270 }
271 _aBaseKeys.clear();
272 }
273
274 // XInitialization
275 //__________________________________________________________________________________________________
initialize(const Sequence<Any> & args)276 void ProviderImpl::initialize(
277 const Sequence< Any > & args )
278 {
279 // registries to read from
280 Any const * pRegistries = args.getConstArray();
281 for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos )
282 {
283 com::sun::star::uno::Reference< XSimpleRegistry > xRegistry( pRegistries[ nPos ], UNO_QUERY );
284 if (xRegistry.is() && xRegistry->isValid())
285 {
286 com::sun::star::uno::Reference< XRegistryKey > xKey( xRegistry->getRootKey()->openKey(
287 OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR") ) ) );
288 if (xKey.is() && xKey->isValid())
289 {
290 _aBaseKeys.push_back( xKey );
291 }
292 }
293 }
294 }
295
296 // XServiceInfo
297 //__________________________________________________________________________________________________
getImplementationName()298 OUString ProviderImpl::getImplementationName()
299 {
300 return stoc_bootstrap::rdbtdp_getImplementationName();
301 }
302 //__________________________________________________________________________________________________
supportsService(const OUString & rServiceName)303 sal_Bool ProviderImpl::supportsService( const OUString & rServiceName )
304 {
305 const Sequence< OUString > & rSNL = getSupportedServiceNames();
306 const OUString * pArray = rSNL.getConstArray();
307 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
308 {
309 if (pArray[nPos] == rServiceName)
310 return sal_True;
311 }
312 return sal_False;
313 }
314 //__________________________________________________________________________________________________
getSupportedServiceNames()315 Sequence< OUString > ProviderImpl::getSupportedServiceNames()
316 {
317 return stoc_bootstrap::rdbtdp_getSupportedServiceNames();
318 }
319
320 // XHierarchicalNameAccess
321 //__________________________________________________________________________________________________
getByHierarchicalNameImpl(const OUString & rName)322 Any ProviderImpl::getByHierarchicalNameImpl( const OUString & rName )
323 {
324 Any aRet;
325
326 // read from registry
327 OUString aKey( rName.replace( '.', '/' ) );
328 for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() );
329 !aRet.hasValue() && iPos != _aBaseKeys.end(); ++iPos )
330 {
331 try
332 {
333 com::sun::star::uno::Reference< XRegistryKey > xBaseKey( *iPos );
334 com::sun::star::uno::Reference< XRegistryKey > xKey( xBaseKey->openKey( aKey ) );
335 if (xKey.is())
336 {
337 // closes key in it's dtor (which is
338 // called even in case of exceptions).
339 RegistryKeyCloser aCloser( xKey );
340
341 if ( xKey->isValid() )
342 {
343 if (xKey->getValueType() == RegistryValueType_BINARY)
344 {
345 Sequence< sal_Int8 > aBytes( xKey->getBinaryValue() );
346 com::sun::star::uno::Reference< XTypeDescription > xTD(
347 createTypeDescription( aBytes,
348 getTDMgr(),
349 true ) );
350 if ( xTD.is() )
351 aRet <<= xTD;
352 }
353 }
354 }
355 else // might be a constant
356 {
357 sal_Int32 nIndex = aKey.lastIndexOf( '/' );
358 if (nIndex > 0)
359 {
360 // open module
361 com::sun::star::uno::Reference< XRegistryKey > xKey2( xBaseKey->openKey( aKey.copy( 0, nIndex ) ) );
362 if (xKey2.is())
363 {
364 // closes key in it's dtor (which is
365 // called even in case of exceptions).
366 RegistryKeyCloser aCloser( xKey2 );
367
368 if ( xKey2->isValid() )
369 {
370 if (xKey2->getValueType() == RegistryValueType_BINARY)
371 {
372 Sequence< sal_Int8 > aBytes( xKey2->getBinaryValue() );
373 typereg::Reader aReader(
374 aBytes.getConstArray(), aBytes.getLength(),
375 false, TYPEREG_VERSION_1);
376
377 if (aReader.getTypeClass() == RT_TYPE_MODULE ||
378 aReader.getTypeClass() == RT_TYPE_CONSTANTS ||
379 aReader.getTypeClass() == RT_TYPE_ENUM)
380 {
381 OUString aFieldName( aKey.copy( nIndex+1, aKey.getLength() - nIndex -1 ) );
382 sal_Int16 nPos = aReader.getFieldCount();
383 while (nPos--)
384 {
385 if (aFieldName.equals(
386 aReader.getFieldName(nPos)))
387 break;
388 }
389 if (nPos >= 0)
390 aRet = getRTValue(
391 aReader.getFieldValue(nPos));
392 }
393 }
394 }
395 }
396 }
397 }
398 }
399 catch ( InvalidRegistryException const & )
400 {
401 OSL_ENSURE( sal_False,
402 "ProviderImpl::getByHierarchicalName "
403 "- Caught InvalidRegistryException!" );
404
405 // openKey, closeKey, getValueType, getBinaryValue, isValid
406
407 // Don't stop iteration in this case.
408 }
409 catch ( NoSuchElementException const & )
410 {
411 }
412 }
413 return aRet;
414 }
415
getByHierarchicalName(const OUString & rName)416 Any SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName )
417 {
418 Any aRet( getByHierarchicalNameImpl( rName ) );
419
420 if ( !aRet.hasValue() )
421 throw NoSuchElementException(
422 rName, static_cast< cppu::OWeakObject * >( this ) );
423
424 return aRet;
425 }
426
427 //__________________________________________________________________________________________________
hasByHierarchicalName(const OUString & rName)428 sal_Bool ProviderImpl::hasByHierarchicalName( const OUString & rName )
429 {
430 return getByHierarchicalNameImpl( rName ).hasValue();
431 }
432
433 // XTypeDescriptionEnumerationAccess
434 //__________________________________________________________________________________________________
435 // virtual
436 com::sun::star::uno::Reference< XTypeDescriptionEnumeration > SAL_CALL
createTypeDescriptionEnumeration(const OUString & moduleName,const Sequence<TypeClass> & types,TypeDescriptionSearchDepth depth)437 ProviderImpl::createTypeDescriptionEnumeration(
438 const OUString & moduleName,
439 const Sequence< TypeClass > & types,
440 TypeDescriptionSearchDepth depth )
441 {
442 return com::sun::star::uno::Reference< XTypeDescriptionEnumeration >(
443 TypeDescriptionEnumerationImpl::createInstance( getTDMgr(),
444 moduleName,
445 types,
446 depth,
447 _aBaseKeys ).get() );
448 }
449
450 //__________________________________________________________________________________________________
451 // global helper function
452
resolveTypedefs(com::sun::star::uno::Reference<XTypeDescription> const & type)453 com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs(
454 com::sun::star::uno::Reference< XTypeDescription > const & type)
455 {
456 com::sun::star::uno::Reference< XTypeDescription > resolved(type);
457 while (resolved->getTypeClass() == TypeClass_TYPEDEF) {
458 resolved = com::sun::star::uno::Reference< XIndirectTypeDescription >(
459 resolved, UNO_QUERY_THROW)->getReferencedType();
460 }
461 return resolved;
462 }
463
createTypeDescription(const Sequence<sal_Int8> & rData,const com::sun::star::uno::Reference<XHierarchicalNameAccess> & xNameAccess,bool bReturnEmptyRefForUnknownType)464 com::sun::star::uno::Reference< XTypeDescription > createTypeDescription(
465 const Sequence< sal_Int8 > & rData,
466 const com::sun::star::uno::Reference< XHierarchicalNameAccess > & xNameAccess,
467 bool bReturnEmptyRefForUnknownType )
468 {
469 typereg::Reader aReader(
470 rData.getConstArray(), rData.getLength(), false, TYPEREG_VERSION_1);
471
472 OUString aName( aReader.getTypeName().replace( '/', '.' ) );
473
474 switch (aReader.getTypeClass())
475 {
476 case RT_TYPE_INTERFACE:
477 {
478 sal_uInt16 n = aReader.getSuperTypeCount();
479 com::sun::star::uno::Sequence< rtl::OUString > aBaseTypeNames(n);
480 {for (sal_uInt16 i = 0; i < n; ++i) {
481 aBaseTypeNames[i] = aReader.getSuperTypeName(i).replace(
482 '/', '.');
483 }}
484 sal_uInt16 n2 = aReader.getReferenceCount();
485 com::sun::star::uno::Sequence< rtl::OUString >
486 aOptionalBaseTypeNames(n2);
487 {for (sal_uInt16 i = 0; i < n2; ++i) {
488 OSL_ASSERT(
489 aReader.getReferenceSort(i) == RT_REF_SUPPORTS
490 && aReader.getReferenceFlags(i) == RT_ACCESS_OPTIONAL);
491 aOptionalBaseTypeNames[i] = aReader.getReferenceTypeName(i);
492 }}
493 return com::sun::star::uno::Reference< XTypeDescription >(
494 new InterfaceTypeDescriptionImpl( xNameAccess,
495 aName,
496 aBaseTypeNames,
497 aOptionalBaseTypeNames,
498 rData,
499 aReader.isPublished() ) );
500 }
501
502 case RT_TYPE_MODULE:
503 {
504 com::sun::star::uno::Reference<
505 XTypeDescriptionEnumerationAccess > xTDEA(
506 xNameAccess, UNO_QUERY );
507
508 OSL_ENSURE( xTDEA.is(),
509 "No XTypeDescriptionEnumerationAccess!" );
510
511 return com::sun::star::uno::Reference< XTypeDescription >(
512 new ModuleTypeDescriptionImpl( xTDEA, aName ) );
513 }
514
515 case RT_TYPE_STRUCT:
516 {
517 rtl::OUString superTypeName;
518 if (aReader.getSuperTypeCount() == 1) {
519 superTypeName = aReader.getSuperTypeName(0).replace(
520 '/', '.');
521 }
522 return com::sun::star::uno::Reference< XTypeDescription >(
523 new stoc::registry_tdprovider::StructTypeDescription(
524 xNameAccess, aName, superTypeName, rData,
525 aReader.isPublished()));
526 }
527
528 case RT_TYPE_ENUM:
529 return com::sun::star::uno::Reference< XTypeDescription >(
530 new EnumTypeDescriptionImpl( xNameAccess,
531 aName,
532 getRTValueAsInt32(
533 aReader.getFieldValue( 0 ) ),
534 rData, aReader.isPublished() ) );
535
536 case RT_TYPE_EXCEPTION:
537 {
538 rtl::OUString superTypeName;
539 if (aReader.getSuperTypeCount() == 1) {
540 superTypeName = aReader.getSuperTypeName(0).replace(
541 '/', '.');
542 }
543 return com::sun::star::uno::Reference< XTypeDescription >(
544 new CompoundTypeDescriptionImpl(
545 xNameAccess, TypeClass_EXCEPTION, aName, superTypeName,
546 rData, aReader.isPublished()));
547 }
548
549 case RT_TYPE_TYPEDEF:
550 return com::sun::star::uno::Reference< XTypeDescription >(
551 new TypedefTypeDescriptionImpl( xNameAccess,
552 aName,
553 aReader.getSuperTypeName(0)
554 .replace( '/', '.' ),
555 aReader.isPublished() ) );
556 case RT_TYPE_SERVICE:
557 return com::sun::star::uno::Reference< XTypeDescription >(
558 new ServiceTypeDescriptionImpl(
559 xNameAccess, aName, rData, aReader.isPublished() ) );
560
561 case RT_TYPE_CONSTANTS:
562 return com::sun::star::uno::Reference< XTypeDescription >(
563 new ConstantsTypeDescriptionImpl(
564 aName, rData, aReader.isPublished() ) );
565
566 case RT_TYPE_SINGLETON:
567 return com::sun::star::uno::Reference< XTypeDescription >(
568 new SingletonTypeDescriptionImpl( xNameAccess,
569 aName,
570 aReader.getSuperTypeName(0)
571 .replace( '/', '.' ),
572 aReader.isPublished() ) );
573 case RT_TYPE_INVALID:
574 case RT_TYPE_OBJECT: // deprecated and not used
575 case RT_TYPE_UNION: // deprecated and not used
576 OSL_ENSURE( sal_False, "createTypeDescription - Unsupported Type!" );
577 break;
578
579 default:
580 OSL_ENSURE( sal_False, "createTypeDescription - Unknown Type!" );
581 break;
582 }
583
584 // Unknown type.
585
586 if ( bReturnEmptyRefForUnknownType )
587 return com::sun::star::uno::Reference< XTypeDescription >();
588
589 return com::sun::star::uno::Reference< XTypeDescription >(
590 new TypeDescriptionImpl( TypeClass_UNKNOWN, aName ) );
591 }
592
593 }
594
595 namespace stoc_bootstrap
596 {
597 //==================================================================================================
ProviderImpl_create(com::sun::star::uno::Reference<XComponentContext> const & xContext)598 com::sun::star::uno::Reference< XInterface > SAL_CALL ProviderImpl_create(
599 com::sun::star::uno::Reference< XComponentContext > const & xContext )
600 {
601 return com::sun::star::uno::Reference< XInterface >( *new stoc_rdbtdp::ProviderImpl( xContext ) );
602 }
603 }
604