1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 //  #define TEST_LIST_CLASSES
28 //  #define TRACE(x) OSL_TRACE(x)
29 #define TRACE(x)
30 
31 #include <osl/diagnose.h>
32 #include <osl/mutex.hxx>
33 #include <uno/mapping.hxx>
34 #include <uno/dispatcher.h>
35 #include <cppuhelper/weak.hxx>
36 #include <cppuhelper/factory.hxx>
37 #include <cppuhelper/component.hxx>
38 #include <cppuhelper/typeprovider.hxx>
39 
40 #include "lrucache.hxx"
41 
42 #ifdef TEST_LIST_CLASSES
43 #include <list>
44 #include <algorithm>
45 #endif
46 #include <hash_map>
47 
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
51 
52 #include <com/sun/star/reflection/XIdlClass.hpp>
53 #include <com/sun/star/reflection/XIdlReflection.hpp>
54 #include <com/sun/star/reflection/XIdlField.hpp>
55 #include <com/sun/star/reflection/XIdlField2.hpp>
56 #include <com/sun/star/reflection/XIdlMethod.hpp>
57 
58 using namespace std;
59 using namespace osl;
60 using namespace rtl;
61 using namespace cppu;
62 using namespace com::sun::star::uno;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::reflection;
65 using namespace com::sun::star::container;
66 
67 
68 namespace stoc_corefl
69 {
70 
71 #ifdef TEST_LIST_CLASSES
72 typedef list< OUString > ClassNameList;
73 extern ClassNameList g_aClassNames;
74 #endif
75 
76 //--------------------------------------------------------------------------------------------------
77 Mutex & getMutexAccess();
78 
79 //--------------------------------------------------------------------------------------------------
80 inline bool td_equals( typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType )
81 {
82 	return (pTD->pWeakRef == pType ||
83 			(pTD->pTypeName->length == pType->pTypeName->length &&
84 			 rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0));
85 }
86 //--------------------------------------------------------------------------------------------------
87 inline typelib_TypeDescription * getTypeByName( const OUString & rName )
88 {
89 	typelib_TypeDescription * pTypeDescr = 0;
90 	typelib_typedescription_getByName( &pTypeDescr, rName.pData );
91 	if (! pTypeDescr->bComplete)
92 		typelib_typedescription_complete( &pTypeDescr );
93 	return pTypeDescr;
94 }
95 
96 typedef std::hash_map< OUString, WeakReference< XIdlField >,
97 	FctHashOUString, equal_to< OUString > > OUString2Field;
98 typedef std::hash_map< OUString, WeakReference< XIdlMethod >,
99 	FctHashOUString, equal_to< OUString > > OUString2Method;
100 
101 //==================================================================================================
102 class IdlReflectionServiceImpl
103 	: public OComponentHelper
104 	, public XIdlReflection
105 	, public XHierarchicalNameAccess
106 	, public XServiceInfo
107 {
108 	Mutex									_aComponentMutex;
109 	Reference< XMultiServiceFactory >		_xMgr;
110 	Reference< XHierarchicalNameAccess >	_xTDMgr;
111 
112 	// caching
113 	LRU_CacheAnyByOUString					_aElements;
114 
115     Mapping						_aCpp2Uno;
116 	Mapping						_aUno2Cpp;
117 
118 	inline Reference< XIdlClass > constructClass( typelib_TypeDescription * pTypeDescr );
119 public:
120 	Reference< XHierarchicalNameAccess > getTDMgr() const
121 		{ return _xTDMgr; }
122 	Reference< XMultiServiceFactory > getSMgr() const
123 		{ return _xMgr; }
124 
125     const Mapping & getCpp2Uno() throw(::com::sun::star::uno::RuntimeException);
126 	const Mapping & getUno2Cpp() throw(::com::sun::star::uno::RuntimeException);
127 	uno_Interface * mapToUno( const Any & rObj, typelib_InterfaceTypeDescription * pTo ) throw(::com::sun::star::uno::RuntimeException);
128 
129 	// ctor/ dtor
130 	IdlReflectionServiceImpl( const Reference< XComponentContext > & xContext );
131 	virtual ~IdlReflectionServiceImpl();
132 
133 	// XInterface
134 	virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
135 	virtual void SAL_CALL acquire() throw();
136 	virtual void SAL_CALL release() throw();
137 
138 	// some XComponent part from OComponentHelper
139 	virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
140 
141 	// XServiceInfo
142 	virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
143 	virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException);
144 	virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
145 
146 	// XTypeProvider
147 	virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException);
148 	virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException);
149 
150 	// XIdlReflection
151 	virtual Reference< XIdlClass > SAL_CALL forName( const OUString & rTypeName ) throw(::com::sun::star::uno::RuntimeException);
152 	virtual Reference< XIdlClass > SAL_CALL getType( const Any & rObj ) throw(::com::sun::star::uno::RuntimeException);
153 
154 	// XHierarchicalNameAccess
155 	virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
156 	virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
157 
158 	Reference< XIdlClass > forType( typelib_TypeDescription * pTypeDescr ) throw(::com::sun::star::uno::RuntimeException);
159 	Reference< XIdlClass > forType( typelib_TypeDescriptionReference * pRef ) throw(::com::sun::star::uno::RuntimeException);
160 };
161 
162 //==================================================================================================
163 class IdlClassImpl
164 	: public WeakImplHelper1< XIdlClass >
165 {
166 	IdlReflectionServiceImpl *	_pReflection;
167 
168 	OUString					_aName;
169 	TypeClass					_eTypeClass;
170 
171 	typelib_TypeDescription *	_pTypeDescr;
172 
173 public:
174 	typelib_TypeDescription *	getTypeDescr() const
175 		{ return _pTypeDescr; }
176 	IdlReflectionServiceImpl *	getReflection() const
177 		{ return _pReflection; }
178 	Reference< XMultiServiceFactory > getSMgr() const
179 		{ return _pReflection->getSMgr(); }
180 	Reference< XHierarchicalNameAccess > getTDMgr() const
181 		{ return getReflection()->getTDMgr(); }
182 
183 	// Ctor
184 	IdlClassImpl( IdlReflectionServiceImpl * pReflection,
185 				  const OUString & rName, typelib_TypeClass eTypeClass,
186 				  typelib_TypeDescription * pTypeDescr );
187 	virtual ~IdlClassImpl();
188 
189 	// XIdlClassImpl default implementation
190     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
191     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
192     virtual sal_Bool SAL_CALL equals( const Reference< XIdlClass >& xType ) throw(::com::sun::star::uno::RuntimeException);
193 
194     virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException);
195     virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException);
196 
197 	// def impl ????
198     virtual Sequence< Reference< XIdlClass > > SAL_CALL getClasses() throw(::com::sun::star::uno::RuntimeException);
199     virtual Reference< XIdlClass > SAL_CALL getClass( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
200     virtual Sequence< Reference< XIdlClass > > SAL_CALL getInterfaces() throw(::com::sun::star::uno::RuntimeException);
201 
202 	// structs, interfaces
203     virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException);
204 	// structs
205     virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
206     virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException);
207 	// interfaces
208     virtual Uik SAL_CALL getUik() throw(::com::sun::star::uno::RuntimeException);
209     virtual Reference< XIdlMethod > SAL_CALL getMethod( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
210     virtual Sequence< Reference< XIdlMethod > > SAL_CALL getMethods() throw(::com::sun::star::uno::RuntimeException);
211 	// array
212     virtual Reference< XIdlClass > SAL_CALL getComponentType() throw(::com::sun::star::uno::RuntimeException);
213     virtual Reference< XIdlArray > SAL_CALL getArray() throw(::com::sun::star::uno::RuntimeException);
214 };
215 
216 //==================================================================================================
217 class InterfaceIdlClassImpl
218 	: public IdlClassImpl
219 {
220 	typedef pair< OUString, typelib_TypeDescription * > MemberInit;
221 
222 	Sequence< Reference< XIdlClass > >		_xSuperClasses;
223 
224 	MemberInit *							_pSortedMemberInit; // first methods, then attributes
225 	OUString2Field							_aName2Field;
226 	OUString2Method							_aName2Method;
227 	sal_Int32								_nMethods;
228 	sal_Int32								_nAttributes;
229 
230 	void initMembers();
231 
232 public:
233 	typelib_InterfaceTypeDescription * getTypeDescr() const
234 		{ return (typelib_InterfaceTypeDescription *)IdlClassImpl::getTypeDescr(); }
235 
236 	// ctor/ dtor
237 	InterfaceIdlClassImpl( IdlReflectionServiceImpl * pReflection,
238 						   const OUString & rName, typelib_TypeClass eTypeClass,
239 						   typelib_TypeDescription * pTypeDescr )
240 		: IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr )
241 		, _pSortedMemberInit( 0 )
242 		, _nMethods( 0 )
243 		, _nAttributes( 0 )
244 		{}
245 	virtual ~InterfaceIdlClassImpl();
246 
247 	// IdlClassImpl modifications
248     virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException);
249     virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException);
250     virtual Uik SAL_CALL getUik() throw(::com::sun::star::uno::RuntimeException);
251     virtual Reference< XIdlMethod > SAL_CALL getMethod( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
252     virtual Sequence< Reference< XIdlMethod > > SAL_CALL getMethods() throw(::com::sun::star::uno::RuntimeException);
253     virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
254     virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException);
255     virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException);
256 };
257 
258 //==================================================================================================
259 class CompoundIdlClassImpl
260 	: public IdlClassImpl
261 {
262 	Reference< XIdlClass >					_xSuperClass;
263 
264 	Sequence< Reference< XIdlField > > *	_pFields;
265 	OUString2Field							_aName2Field;
266 
267 public:
268 	typelib_CompoundTypeDescription * getTypeDescr() const
269 		{ return (typelib_CompoundTypeDescription *)IdlClassImpl::getTypeDescr(); }
270 
271 	// ctor/ dtor
272 	CompoundIdlClassImpl( IdlReflectionServiceImpl * pReflection,
273 						  const OUString & rName, typelib_TypeClass eTypeClass,
274 						  typelib_TypeDescription * pTypeDescr )
275 		: IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr )
276 		, _pFields( 0 )
277 		{}
278 	virtual ~CompoundIdlClassImpl();
279 
280 	// IdlClassImpl modifications
281     virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException);
282     virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException);
283     virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
284     virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException);
285 };
286 
287 //==================================================================================================
288 class ArrayIdlClassImpl
289 	: public IdlClassImpl
290 	, public XIdlArray
291 {
292 public:
293 	typelib_IndirectTypeDescription * getTypeDescr() const
294 		{ return (typelib_IndirectTypeDescription *)IdlClassImpl::getTypeDescr(); }
295 
296 	// ctor
297 	ArrayIdlClassImpl( IdlReflectionServiceImpl * pReflection,
298 					   const OUString & rName, typelib_TypeClass eTypeClass,
299 					   typelib_TypeDescription * pTypeDescr )
300 		: IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr )
301 		{}
302 
303 	virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
304 	virtual void SAL_CALL acquire() throw();
305 	virtual void SAL_CALL release() throw();
306 
307 	// XTypeProvider
308 	virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException);
309 	virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException);
310 
311 	// IdlClassImpl modifications
312     virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException);
313     virtual Reference< XIdlClass > SAL_CALL getComponentType() throw(::com::sun::star::uno::RuntimeException);
314     virtual Reference< XIdlArray > SAL_CALL getArray() throw(::com::sun::star::uno::RuntimeException);
315 
316 	// XIdlArray
317     virtual void SAL_CALL realloc( Any & rArray, sal_Int32 nLen ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
318     virtual sal_Int32 SAL_CALL getLen( const Any & rArray ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
319     virtual Any SAL_CALL get( const Any & rArray, sal_Int32 nIndex ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
320     virtual void SAL_CALL set( Any & rArray, sal_Int32 nIndex, const Any & rNewValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
321 };
322 
323 //==================================================================================================
324 class EnumIdlClassImpl
325 	: public IdlClassImpl
326 {
327 	Sequence< Reference< XIdlField > > * _pFields;
328 	OUString2Field						 _aName2Field;
329 
330 public:
331 	typelib_EnumTypeDescription * getTypeDescr() const
332 		{ return (typelib_EnumTypeDescription *)IdlClassImpl::getTypeDescr(); }
333 
334 	// ctor/ dtor
335 	EnumIdlClassImpl( IdlReflectionServiceImpl * pReflection,
336 					  const OUString & rName, typelib_TypeClass eTypeClass,
337 					  typelib_TypeDescription * pTypeDescr )
338 		: IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr )
339 		, _pFields( 0 )
340 		{}
341 	virtual ~EnumIdlClassImpl();
342 
343 	// IdlClassImpl modifications
344     virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);
345     virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException);
346     virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException);
347 };
348 
349 //==================================================================================================
350 class IdlMemberImpl
351 	: public WeakImplHelper1< XIdlMember >
352 {
353 	IdlReflectionServiceImpl *	_pReflection;
354 	OUString					_aName;
355 
356 	typelib_TypeDescription *	_pTypeDescr;
357 	typelib_TypeDescription *	_pDeclTypeDescr;
358 
359 protected:
360 	Reference< XIdlClass >		_xDeclClass;
361 
362 public:
363 	IdlReflectionServiceImpl *	getReflection() const
364 		{ return _pReflection; }
365 	Reference< XMultiServiceFactory > getSMgr() const
366 		{ return _pReflection->getSMgr(); }
367 	typelib_TypeDescription *	getTypeDescr() const
368 		{ return _pTypeDescr; }
369 	typelib_TypeDescription *	getDeclTypeDescr() const
370 		{ return _pDeclTypeDescr; }
371 
372 	// ctor/ dtor
373 	IdlMemberImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
374 				   typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr );
375 	virtual ~IdlMemberImpl();
376 
377 	// XIdlMember
378     virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException);
379     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
380 };
381 
382 //--------------------------------------------------------------------------------------------------
383 // coerces to type descr pTo else queries for it: the interface pointer is returned via rDest
384 // ## type to XidlClass coercion possible
385 inline sal_Bool extract(
386 	const Any & rObj, typelib_InterfaceTypeDescription * pTo,
387 	Reference< XInterface > & rDest,
388 	IdlReflectionServiceImpl * pRefl )
389 {
390 	rDest.clear();
391 	if (0 != pTo)
392 	{
393         if (! rObj.hasValue())
394             return sal_True;
395 		if (rObj.getValueTypeClass() == TypeClass_INTERFACE)
396 		{
397 			return ::uno_type_assignData(
398 				&rDest, ((typelib_TypeDescription *)pTo)->pWeakRef,
399 				const_cast< void * >( rObj.getValue() ), rObj.getValueTypeRef(),
400 				reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
401                 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
402                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
403 		}
404 		else if (rObj.getValueTypeClass() == TypeClass_TYPE)
405 		{
406 			rDest = pRefl->forType( reinterpret_cast< const Type * >( rObj.getValue() )->getTypeLibType() );
407 			return rDest.is();
408 		}
409 	}
410 	return sal_False;
411 }
412 //--------------------------------------------------------------------------------------------------
413 inline sal_Bool coerce_assign(
414 	void * pDest, typelib_TypeDescription * pTD, const Any & rSource,
415 	IdlReflectionServiceImpl * pRefl )
416 {
417     if (pTD->eTypeClass == typelib_TypeClass_INTERFACE)
418     {
419         Reference< XInterface > xVal;
420         if (extract( rSource, (typelib_InterfaceTypeDescription *)pTD, xVal, pRefl ))
421         {
422             if (*(XInterface **)pDest)
423                 (*(XInterface **)pDest)->release();
424             *(XInterface **)pDest = xVal.get();
425             if (*(XInterface **)pDest)
426                 (*(XInterface **)pDest)->acquire();
427             return sal_True;
428         }
429         return sal_False;
430     }
431     else if (pTD->eTypeClass == typelib_TypeClass_ANY)
432     {
433         return uno_assignData(
434             pDest, pTD,
435             (void *)&rSource, pTD,
436             reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
437             reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
438             reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
439     }
440     else
441     {
442         return uno_type_assignData(
443             pDest, pTD->pWeakRef,
444             (void *)rSource.getValue(), rSource.getValueTypeRef(),
445             reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
446             reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
447             reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
448     }
449 }
450 
451 }
452 
453 
454