1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
21 #include <osl/mutex.hxx>
22 #include <uno/dispatcher.h>
23 #include <uno/mapping.hxx>
24 #include <cppuhelper/factory.hxx>
25 #include <cppuhelper/compbase4.hxx>
26 #include <cppuhelper/implbase2.hxx>
27 #include <cppuhelper/typeprovider.hxx>
29 #include <cppuhelper/weakref.hxx>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <com/sun/star/lang/XTypeProvider.hpp>
34 #include <com/sun/star/lang/XInitialization.hpp>
35 #include <com/sun/star/registry/XSimpleRegistry.hpp>
36 #include <com/sun/star/registry/XRegistryKey.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
39 #include "com/sun/star/uno/RuntimeException.hpp"
41 #include "registry/reader.hxx"
42 #include "registry/version.h"
44 #include "rdbtdp_tdenumeration.hxx"
45 #include "structtypedescription.hxx"
47 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider"
48 #define IMPLNAME "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider"
50 using namespace com::sun::star
;
51 using namespace com::sun::star::beans
;
52 using namespace com::sun::star::registry
;
54 namespace stoc_bootstrap
56 uno::Sequence
< OUString
> rdbtdp_getSupportedServiceNames()
58 Sequence
< OUString
> seqNames(1);
59 seqNames
.getArray()[0] = OUString(SERVICENAME
);
63 OUString
rdbtdp_getImplementationName()
65 return OUString(IMPLNAME
);
73 Mutex _aComponentMutex
;
75 //==================================================================================================
78 , public WeakComponentImplHelper4
< XServiceInfo
,
79 XHierarchicalNameAccess
,
80 XTypeDescriptionEnumerationAccess
,
83 // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper
84 // first asking the tdmgr instance, then looking up locally
85 class TypeDescriptionManagerWrapper
86 : public ::cppu::WeakImplHelper2
<
87 container::XHierarchicalNameAccess
,
88 reflection::XTypeDescriptionEnumerationAccess
>
90 com::sun::star::uno::Reference
<container::XHierarchicalNameAccess
>
92 com::sun::star::uno::Reference
<container::XHierarchicalNameAccess
>
95 TypeDescriptionManagerWrapper( ProviderImpl
* pProvider
)
96 : m_xTDMgr( pProvider
->_xContext
->getValueByName(
98 "/singletons/com.sun.star.reflection."
99 "theTypeDescriptionManager" ) ),
101 m_xThisProvider( pProvider
)
103 // XHierarchicalNameAccess
104 virtual Any SAL_CALL
getByHierarchicalName( OUString
const & name
)
105 throw (container::NoSuchElementException
, RuntimeException
);
106 virtual sal_Bool SAL_CALL
hasByHierarchicalName( OUString
const & name
)
107 throw (RuntimeException
);
109 // XTypeDescriptionEnumerationAccess
110 virtual uno::Reference
<
111 reflection::XTypeDescriptionEnumeration
> SAL_CALL
112 createTypeDescriptionEnumeration(
113 const OUString
& moduleName
,
114 const uno::Sequence
< uno::TypeClass
>& types
,
115 reflection::TypeDescriptionSearchDepth depth
)
116 throw ( reflection::NoSuchTypeNameException
,
117 reflection::InvalidTypeNameException
,
118 uno::RuntimeException
);
120 friend class TypeDescriptionManagerWrapper
;
122 com::sun::star::uno::Reference
< XComponentContext
> _xContext
;
123 com::sun::star::uno::WeakReference
<XHierarchicalNameAccess
> _xTDMgr
;
124 com::sun::star::uno::Reference
< XHierarchicalNameAccess
> getTDMgr() SAL_THROW(());
126 RegistryKeyList _aBaseKeys
;
129 virtual void SAL_CALL
disposing();
132 ProviderImpl( const com::sun::star::uno::Reference
< XComponentContext
> & xContext
);
133 virtual ~ProviderImpl();
136 virtual void SAL_CALL
initialize( const Sequence
< Any
> & args
) throw (Exception
, RuntimeException
);
139 virtual OUString SAL_CALL
getImplementationName() throw(::com::sun::star::uno::RuntimeException
);
140 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
) throw(::com::sun::star::uno::RuntimeException
);
141 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException
);
143 // XHierarchicalNameAccess
144 Any
getByHierarchicalNameImpl( const OUString
& rName
);
146 virtual Any SAL_CALL
getByHierarchicalName( const OUString
& rName
) throw(::com::sun::star::container::NoSuchElementException
, ::com::sun::star::uno::RuntimeException
);
147 virtual sal_Bool SAL_CALL
hasByHierarchicalName( const OUString
& rName
) throw(::com::sun::star::uno::RuntimeException
);
149 // XTypeDescriptionEnumerationAccess
150 virtual ::com::sun::star::uno::Reference
<
151 ::com::sun::star::reflection::XTypeDescriptionEnumeration
> SAL_CALL
152 createTypeDescriptionEnumeration(
153 const OUString
& moduleName
,
154 const ::com::sun::star::uno::Sequence
<
155 ::com::sun::star::uno::TypeClass
>& types
,
156 ::com::sun::star::reflection::TypeDescriptionSearchDepth depth
)
157 throw ( ::com::sun::star::reflection::NoSuchTypeNameException
,
158 ::com::sun::star::reflection::InvalidTypeNameException
,
159 ::com::sun::star::uno::RuntimeException
);
161 //__________________________________________________________________________________________________
162 ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference
< XComponentContext
> & xContext
)
163 : WeakComponentImplHelper4
<
164 XServiceInfo
, XHierarchicalNameAccess
,
165 XTypeDescriptionEnumerationAccess
, XInitialization
>( _aComponentMutex
)
166 , _xContext( xContext
)
168 //__________________________________________________________________________________________________
169 ProviderImpl::~ProviderImpl() {}
171 //______________________________________________________________________________
172 Any
ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName(
173 OUString
const & name
) throw (container::NoSuchElementException
,
179 return m_xTDMgr
->getByHierarchicalName( name
);
181 catch (container::NoSuchElementException
&)
183 // then lookup locally:
184 return m_xThisProvider
->getByHierarchicalName( name
);
188 //______________________________________________________________________________
189 sal_Bool
ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName(
190 OUString
const & name
) throw (RuntimeException
)
192 return m_xTDMgr
->hasByHierarchicalName( name
) || m_xThisProvider
->hasByHierarchicalName( name
);
195 //______________________________________________________________________________
196 uno::Reference
< reflection::XTypeDescriptionEnumeration
> SAL_CALL
197 ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration(
198 const OUString
& moduleName
,
199 const uno::Sequence
< uno::TypeClass
>& types
,
200 reflection::TypeDescriptionSearchDepth depth
)
201 throw ( reflection::NoSuchTypeNameException
,
202 reflection::InvalidTypeNameException
,
203 uno::RuntimeException
)
208 uno::Reference
< reflection::XTypeDescriptionEnumerationAccess
> xTDEA(
209 m_xTDMgr
, uno::UNO_QUERY_THROW
);
211 xTDEA
->createTypeDescriptionEnumeration( moduleName
, types
, depth
);
213 catch (reflection::NoSuchTypeNameException
&)
215 // then lookup locally:
216 uno::Reference
< reflection::XTypeDescriptionEnumerationAccess
> xTDEA(
217 m_xThisProvider
, uno::UNO_QUERY_THROW
);
219 xTDEA
->createTypeDescriptionEnumeration( moduleName
, types
, depth
);
223 //__________________________________________________________________________________________________
224 com::sun::star::uno::Reference
< XHierarchicalNameAccess
> ProviderImpl::getTDMgr()
227 // harden weak reference:
228 com::sun::star::uno::Reference
<container::XHierarchicalNameAccess
> xTDMgr(
232 xTDMgr
.set( new TypeDescriptionManagerWrapper(this) );
234 MutexGuard
guard( _aComponentMutex
);
241 //__________________________________________________________________________________________________
242 void ProviderImpl::disposing()
246 for ( RegistryKeyList::const_iterator
iPos( _aBaseKeys
.begin() );
247 iPos
!= _aBaseKeys
.end(); ++iPos
)
255 //__________________________________________________________________________________________________
256 void ProviderImpl::initialize(
257 const Sequence
< Any
> & args
)
258 throw (Exception
, RuntimeException
)
260 // registries to read from
261 Any
const * pRegistries
= args
.getConstArray();
262 for ( sal_Int32 nPos
= 0; nPos
< args
.getLength(); ++nPos
)
264 com::sun::star::uno::Reference
< XSimpleRegistry
> xRegistry( pRegistries
[ nPos
], UNO_QUERY
);
265 if (xRegistry
.is() && xRegistry
->isValid())
267 com::sun::star::uno::Reference
< XRegistryKey
> xKey( xRegistry
->getRootKey()->openKey(
268 OUString("/UCR") ) );
269 if (xKey
.is() && xKey
->isValid())
271 _aBaseKeys
.push_back( xKey
);
278 //__________________________________________________________________________________________________
279 OUString
ProviderImpl::getImplementationName()
280 throw(::com::sun::star::uno::RuntimeException
)
282 return stoc_bootstrap::rdbtdp_getImplementationName();
284 //__________________________________________________________________________________________________
285 sal_Bool
ProviderImpl::supportsService( const OUString
& rServiceName
)
286 throw(::com::sun::star::uno::RuntimeException
)
288 const Sequence
< OUString
> & rSNL
= getSupportedServiceNames();
289 const OUString
* pArray
= rSNL
.getConstArray();
290 for ( sal_Int32 nPos
= rSNL
.getLength(); nPos
--; )
292 if (pArray
[nPos
] == rServiceName
)
297 //__________________________________________________________________________________________________
298 Sequence
< OUString
> ProviderImpl::getSupportedServiceNames()
299 throw(::com::sun::star::uno::RuntimeException
)
301 return stoc_bootstrap::rdbtdp_getSupportedServiceNames();
304 // XHierarchicalNameAccess
305 //__________________________________________________________________________________________________
306 Any
ProviderImpl::getByHierarchicalNameImpl( const OUString
& rName
)
310 // read from registry
311 OUString
aKey( rName
.replace( '.', '/' ) );
312 for ( RegistryKeyList::const_iterator
iPos( _aBaseKeys
.begin() );
313 !aRet
.hasValue() && iPos
!= _aBaseKeys
.end(); ++iPos
)
317 com::sun::star::uno::Reference
< XRegistryKey
> xBaseKey( *iPos
);
318 com::sun::star::uno::Reference
< XRegistryKey
> xKey( xBaseKey
->openKey( aKey
) );
321 // closes key in it's dtor (which is
322 // called even in case of exceptions).
323 RegistryKeyCloser
aCloser( xKey
);
325 if ( xKey
->isValid() )
327 if (xKey
->getValueType() == RegistryValueType_BINARY
)
329 Sequence
< sal_Int8
> aBytes( xKey
->getBinaryValue() );
330 com::sun::star::uno::Reference
< XTypeDescription
> xTD(
331 createTypeDescription( aBytes
,
339 else // might be a constant
341 sal_Int32 nIndex
= aKey
.lastIndexOf( '/' );
345 com::sun::star::uno::Reference
< XRegistryKey
> xKey2( xBaseKey
->openKey( aKey
.copy( 0, nIndex
) ) );
348 // closes key in it's dtor (which is
349 // called even in case of exceptions).
350 RegistryKeyCloser
aCloser( xKey2
);
352 if ( xKey2
->isValid() )
354 if (xKey2
->getValueType() == RegistryValueType_BINARY
)
356 Sequence
< sal_Int8
> aBytes( xKey2
->getBinaryValue() );
357 typereg::Reader
aReader(
358 aBytes
.getConstArray(), aBytes
.getLength(),
359 false, TYPEREG_VERSION_1
);
361 RTTypeClass tc
= aReader
.getTypeClass();
362 if (tc
== RT_TYPE_MODULE
||
363 tc
== RT_TYPE_CONSTANTS
||
366 OUString
aFieldName( aKey
.copy( nIndex
+1, aKey
.getLength() - nIndex
-1 ) );
367 sal_Int16 nPos
= aReader
.getFieldCount();
370 if (aFieldName
.equals(
371 aReader
.getFieldName(nPos
)))
377 aReader
.getFieldValue(nPos
));
378 if (tc
!= RT_TYPE_ENUM
)
380 aRet
= css::uno::makeAny
<
382 css::reflection::XTypeDescription
> >(
383 new ConstantTypeDescriptionImpl(
394 catch ( InvalidRegistryException
const & )
396 OSL_FAIL( "ProviderImpl::getByHierarchicalName "
397 "- Caught InvalidRegistryException!" );
399 // openKey, closeKey, getValueType, getBinaryValue, isValid
401 // Don't stop iteration in this case.
403 catch ( NoSuchElementException
const & )
410 Any SAL_CALL
ProviderImpl::getByHierarchicalName( const OUString
& rName
)
411 throw(::com::sun::star::uno::RuntimeException
, com::sun::star::container::NoSuchElementException
)
413 Any
aRet( getByHierarchicalNameImpl( rName
) );
415 if ( !aRet
.hasValue() )
416 throw NoSuchElementException(
417 rName
, static_cast< cppu::OWeakObject
* >( this ) );
422 //__________________________________________________________________________________________________
423 sal_Bool
ProviderImpl::hasByHierarchicalName( const OUString
& rName
)
424 throw(::com::sun::star::uno::RuntimeException
)
426 return getByHierarchicalNameImpl( rName
).hasValue();
429 // XTypeDescriptionEnumerationAccess
430 //__________________________________________________________________________________________________
432 com::sun::star::uno::Reference
< XTypeDescriptionEnumeration
> SAL_CALL
433 ProviderImpl::createTypeDescriptionEnumeration(
434 const OUString
& moduleName
,
435 const Sequence
< TypeClass
> & types
,
436 TypeDescriptionSearchDepth depth
)
437 throw ( NoSuchTypeNameException
,
438 InvalidTypeNameException
,
441 return com::sun::star::uno::Reference
< XTypeDescriptionEnumeration
>(
442 TypeDescriptionEnumerationImpl::createInstance( getTDMgr(),
446 _aBaseKeys
).get() );
449 //__________________________________________________________________________________________________
450 // global helper function
452 com::sun::star::uno::Reference
< XTypeDescription
> resolveTypedefs(
453 com::sun::star::uno::Reference
< XTypeDescription
> const & type
)
455 com::sun::star::uno::Reference
< XTypeDescription
> resolved(type
);
456 while (resolved
->getTypeClass() == TypeClass_TYPEDEF
) {
457 resolved
= com::sun::star::uno::Reference
< XIndirectTypeDescription
>(
458 resolved
, UNO_QUERY_THROW
)->getReferencedType();
463 com::sun::star::uno::Reference
< XTypeDescription
> createTypeDescription(
464 const Sequence
< sal_Int8
> & rData
,
465 const com::sun::star::uno::Reference
< XHierarchicalNameAccess
> & xNameAccess
,
466 bool bReturnEmptyRefForUnknownType
)
468 typereg::Reader
aReader(
469 rData
.getConstArray(), rData
.getLength(), false, TYPEREG_VERSION_1
);
471 OUString
aName( aReader
.getTypeName().replace( '/', '.' ) );
473 switch (aReader
.getTypeClass())
475 case RT_TYPE_INTERFACE
:
477 sal_uInt16 n
= aReader
.getSuperTypeCount();
478 com::sun::star::uno::Sequence
< OUString
> aBaseTypeNames(n
);
479 for (sal_uInt16 i
= 0; i
< n
; ++i
) {
480 aBaseTypeNames
[i
] = aReader
.getSuperTypeName(i
).replace(
483 sal_uInt16 n2
= aReader
.getReferenceCount();
484 com::sun::star::uno::Sequence
< OUString
>
485 aOptionalBaseTypeNames(n2
);
486 for (sal_uInt16 i
= 0; i
< n2
; ++i
) {
488 aReader
.getReferenceSort(i
) == RT_REF_SUPPORTS
489 && aReader
.getReferenceFlags(i
) == RT_ACCESS_OPTIONAL
);
490 aOptionalBaseTypeNames
[i
] = aReader
.getReferenceTypeName(i
);
492 return com::sun::star::uno::Reference
< XTypeDescription
>(
493 new InterfaceTypeDescriptionImpl( xNameAccess
,
496 aOptionalBaseTypeNames
,
498 aReader
.isPublished() ) );
503 com::sun::star::uno::Reference
<
504 XTypeDescriptionEnumerationAccess
> xTDEA(
505 xNameAccess
, UNO_QUERY
);
507 OSL_ENSURE( xTDEA
.is(),
508 "No XTypeDescriptionEnumerationAccess!" );
510 return com::sun::star::uno::Reference
< XTypeDescription
>(
511 new ModuleTypeDescriptionImpl( xTDEA
, aName
) );
516 OUString superTypeName
;
517 if (aReader
.getSuperTypeCount() == 1) {
518 superTypeName
= aReader
.getSuperTypeName(0).replace(
521 return com::sun::star::uno::Reference
< XTypeDescription
>(
522 new stoc::registry_tdprovider::StructTypeDescription(
523 xNameAccess
, aName
, superTypeName
, rData
,
524 aReader
.isPublished()));
528 return com::sun::star::uno::Reference
< XTypeDescription
>(
529 new EnumTypeDescriptionImpl( xNameAccess
,
532 aReader
.getFieldValue( 0 ) ),
533 rData
, aReader
.isPublished() ) );
535 case RT_TYPE_EXCEPTION
:
537 OUString superTypeName
;
538 if (aReader
.getSuperTypeCount() == 1) {
539 superTypeName
= aReader
.getSuperTypeName(0).replace(
542 return com::sun::star::uno::Reference
< XTypeDescription
>(
543 new CompoundTypeDescriptionImpl(
544 xNameAccess
, TypeClass_EXCEPTION
, aName
, superTypeName
,
545 rData
, aReader
.isPublished()));
548 case RT_TYPE_TYPEDEF
:
549 return com::sun::star::uno::Reference
< XTypeDescription
>(
550 new TypedefTypeDescriptionImpl( xNameAccess
,
552 aReader
.getSuperTypeName(0)
553 .replace( '/', '.' ),
554 aReader
.isPublished() ) );
555 case RT_TYPE_SERVICE
:
556 return com::sun::star::uno::Reference
< XTypeDescription
>(
557 new ServiceTypeDescriptionImpl(
558 xNameAccess
, aName
, rData
, aReader
.isPublished() ) );
560 case RT_TYPE_CONSTANTS
:
561 return com::sun::star::uno::Reference
< XTypeDescription
>(
562 new ConstantsTypeDescriptionImpl(
563 aName
, rData
, aReader
.isPublished() ) );
565 case RT_TYPE_SINGLETON
:
566 return com::sun::star::uno::Reference
< XTypeDescription
>(
567 new SingletonTypeDescriptionImpl( xNameAccess
,
569 aReader
.getSuperTypeName(0)
570 .replace( '/', '.' ),
571 aReader
.isPublished() ) );
572 case RT_TYPE_INVALID
:
573 case RT_TYPE_OBJECT
: // deprecated and not used
574 case RT_TYPE_UNION
: // deprecated and not used
575 OSL_FAIL( "createTypeDescription - Unsupported Type!" );
579 OSL_FAIL( "createTypeDescription - Unknown Type!" );
585 if ( bReturnEmptyRefForUnknownType
)
586 return com::sun::star::uno::Reference
< XTypeDescription
>();
588 return com::sun::star::uno::Reference
< XTypeDescription
>(
589 new TypeDescriptionImpl( TypeClass_UNKNOWN
, aName
) );
594 namespace stoc_bootstrap
596 //==================================================================================================
597 com::sun::star::uno::Reference
< XInterface
> SAL_CALL
ProviderImpl_create(
598 com::sun::star::uno::Reference
< XComponentContext
> const & xContext
)
599 throw(::com::sun::star::uno::Exception
)
601 return com::sun::star::uno::Reference
< XInterface
>( *new stoc_rdbtdp::ProviderImpl( xContext
) );
605 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */