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 <cppuhelper/queryinterface.hxx>
27 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
28 #include <cppuhelper/implementationentry.hxx>
29 #endif
30 
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <com/sun/star/reflection/XTypeDescription.hpp>
33 #include "com/sun/star/uno/RuntimeException.hpp"
34 
35 using namespace com::sun::star;
36 using namespace com::sun::star::lang;
37 using namespace com::sun::star::registry;
38 using namespace cppu;
39 using namespace osl;
40 using namespace rtl;
41 
42 #include "base.hxx"
43 
44 
45 namespace stoc_corefl
46 {
47 
48 static const sal_Int32 CACHE_SIZE = 256;
49 
50 #define SERVICENAME "com.sun.star.reflection.CoreReflection"
51 #define IMPLNAME	"com.sun.star.comp.stoc.CoreReflection"
52 
53 // can be static, as every client of the core reflection keeps a reference to the
54 // core reflection, so refcounting can be done here.
55 static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
56 
core_getSupportedServiceNames()57 static Sequence< OUString > core_getSupportedServiceNames()
58 {
59 	static Sequence < OUString > *pNames = 0;
60 	if( ! pNames )
61 	{
62 		MutexGuard guard( Mutex::getGlobalMutex() );
63 		if( !pNames )
64 		{
65 			static Sequence< OUString > seqNames(1);
66 			seqNames.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) );
67 			pNames = &seqNames;
68 		}
69 	}
70 	return *pNames;
71 }
72 
core_getImplementationName()73 static OUString core_getImplementationName()
74 {
75 	static OUString *pImplName = 0;
76 	if( ! pImplName )
77 	{
78 		MutexGuard guard( Mutex::getGlobalMutex() );
79 		if( ! pImplName )
80 		{
81 			static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
82 			pImplName = &implName;
83 		}
84 	}
85 	return *pImplName;
86 }
87 //__________________________________________________________________________________________________
IdlReflectionServiceImpl(const Reference<XComponentContext> & xContext)88 IdlReflectionServiceImpl::IdlReflectionServiceImpl(
89     const Reference< XComponentContext > & xContext )
90 	: OComponentHelper( _aComponentMutex )
91 	, _xMgr( xContext->getServiceManager(), UNO_QUERY )
92 	, _aElements( CACHE_SIZE )
93 {
94 	g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
95     xContext->getValueByName( OUString( RTL_CONSTASCII_USTRINGPARAM(
96         "/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) >>= _xTDMgr;
97 	OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" );
98 }
99 //__________________________________________________________________________________________________
~IdlReflectionServiceImpl()100 IdlReflectionServiceImpl::~IdlReflectionServiceImpl()
101 {
102 	TRACE( "> IdlReflectionServiceImpl dtor <\n" );
103 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
104 }
105 
106 // XInterface
107 //__________________________________________________________________________________________________
queryInterface(const Type & rType)108 Any IdlReflectionServiceImpl::queryInterface( const Type & rType )
109 	throw(::com::sun::star::uno::RuntimeException)
110 {
111 	Any aRet( ::cppu::queryInterface(
112 		rType,
113 		static_cast< XIdlReflection * >( this ),
114 		static_cast< XHierarchicalNameAccess * >( this ),
115 		static_cast< XServiceInfo * >( this ) ) );
116 
117 	return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
118 }
119 //__________________________________________________________________________________________________
acquire()120 void IdlReflectionServiceImpl::acquire() throw()
121 {
122 	OComponentHelper::acquire();
123 }
124 //__________________________________________________________________________________________________
release()125 void IdlReflectionServiceImpl::release() throw()
126 {
127 	OComponentHelper::release();
128 }
129 
130 // XTypeProvider
131 //__________________________________________________________________________________________________
getTypes()132 Sequence< Type > IdlReflectionServiceImpl::getTypes()
133 	throw (::com::sun::star::uno::RuntimeException)
134 {
135 	static OTypeCollection * s_pTypes = 0;
136 	if (! s_pTypes)
137 	{
138 		MutexGuard aGuard( _aComponentMutex );
139 		if (! s_pTypes)
140 		{
141 			static OTypeCollection s_aTypes(
142 				::getCppuType( (const Reference< XIdlReflection > *)0 ),
143 				::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ),
144 				::getCppuType( (const Reference< XServiceInfo > *)0 ),
145 				OComponentHelper::getTypes() );
146 			s_pTypes = &s_aTypes;
147 		}
148 	}
149 	return s_pTypes->getTypes();
150 }
151 //__________________________________________________________________________________________________
getImplementationId()152 Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId()
153 	throw (::com::sun::star::uno::RuntimeException)
154 {
155 	static OImplementationId * s_pId = 0;
156 	if (! s_pId)
157 	{
158 		MutexGuard aGuard( _aComponentMutex );
159 		if (! s_pId)
160 		{
161 			static OImplementationId s_aId;
162 			s_pId = &s_aId;
163 		}
164 	}
165 	return s_pId->getImplementationId();
166 }
167 
168 // XComponent
169 //__________________________________________________________________________________________________
dispose()170 void IdlReflectionServiceImpl::dispose()
171 	throw(::com::sun::star::uno::RuntimeException)
172 {
173 	TRACE( "> disposing corereflection... <" );
174 	OComponentHelper::dispose();
175 
176 	MutexGuard aGuard( _aComponentMutex );
177 	_aElements.clear();
178 #ifdef TEST_LIST_CLASSES
179 	OSL_ENSURE( g_aClassNames.size() == 0, "### idl classes still alive!" );
180 	ClassNameList::const_iterator iPos( g_aClassNames.begin() );
181 	while (iPos != g_aClassNames.end())
182 	{
183 		OUString aName( *iPos );
184 		++iPos;
185 	}
186 #endif
187 }
188 
189 // XServiceInfo
190 //__________________________________________________________________________________________________
getImplementationName()191 OUString IdlReflectionServiceImpl::getImplementationName()
192 	throw(::com::sun::star::uno::RuntimeException)
193 {
194 	return core_getImplementationName();
195 }
196 //__________________________________________________________________________________________________
supportsService(const OUString & rServiceName)197 sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName )
198 	throw(::com::sun::star::uno::RuntimeException)
199 {
200 	const Sequence< OUString > & rSNL = getSupportedServiceNames();
201 	const OUString * pArray = rSNL.getConstArray();
202 	for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
203 	{
204 		if (pArray[nPos] == rServiceName)
205 			return sal_True;
206 	}
207 	return sal_False;
208 }
209 //__________________________________________________________________________________________________
getSupportedServiceNames()210 Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames()
211 	throw(::com::sun::star::uno::RuntimeException)
212 {
213 	return core_getSupportedServiceNames();
214 }
215 
216 // XIdlReflection
217 //__________________________________________________________________________________________________
getType(const Any & rObj)218 Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj )
219 	throw(::com::sun::star::uno::RuntimeException)
220 {
221 	return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >());
222 }
223 
224 //__________________________________________________________________________________________________
constructClass(typelib_TypeDescription * pTypeDescr)225 inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass(
226 	typelib_TypeDescription * pTypeDescr )
227 {
228 	OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" );
229 
230 	switch (pTypeDescr->eTypeClass)
231 	{
232 	case typelib_TypeClass_VOID:
233 	case typelib_TypeClass_CHAR:
234 	case typelib_TypeClass_BOOLEAN:
235 	case typelib_TypeClass_BYTE:
236 	case typelib_TypeClass_SHORT:
237 	case typelib_TypeClass_UNSIGNED_SHORT:
238 	case typelib_TypeClass_LONG:
239 	case typelib_TypeClass_UNSIGNED_LONG:
240 	case typelib_TypeClass_HYPER:
241 	case typelib_TypeClass_UNSIGNED_HYPER:
242 	case typelib_TypeClass_FLOAT:
243 	case typelib_TypeClass_DOUBLE:
244 	case typelib_TypeClass_STRING:
245 	case typelib_TypeClass_ANY:
246 		return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
247 
248 	case TypeClass_ENUM:
249 		return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
250 
251 	case typelib_TypeClass_STRUCT:
252 	case typelib_TypeClass_UNION:
253 	case typelib_TypeClass_EXCEPTION:
254 		return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
255 
256 	case typelib_TypeClass_ARRAY:
257 	case typelib_TypeClass_SEQUENCE:
258 		return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
259 
260 	case typelib_TypeClass_INTERFACE:
261 		return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
262 
263 	case typelib_TypeClass_TYPE:
264 		return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
265 
266 	default:
267 #if OSL_DEBUG_LEVEL > 1
268 		OSL_TRACE( "### corereflection type unsupported: " );
269 		OString aName( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
270 		OSL_TRACE( aName.getStr() );
271 		OSL_TRACE( "\n" );
272 #endif
273         return Reference< XIdlClass >();
274 	}
275 }
276 //__________________________________________________________________________________________________
forName(const OUString & rTypeName)277 Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName )
278 	throw(::com::sun::star::uno::RuntimeException)
279 {
280 	Reference< XIdlClass > xRet;
281 	Any aAny( _aElements.getValue( rTypeName ) );
282 
283 	if (aAny.hasValue())
284 	{
285 		if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
286 			xRet = *(const Reference< XIdlClass > *)aAny.getValue();
287 	}
288 	else
289 	{
290 		// try to get _type_ by name
291 		typelib_TypeDescription * pTD = 0;
292 		typelib_typedescription_getByName( &pTD, rTypeName.pData );
293 		if (pTD)
294 		{
295 			if ((xRet = constructClass( pTD )).is())
296 				_aElements.setValue( rTypeName, makeAny( xRet ) ); // update
297 			typelib_typedescription_release( pTD );
298 		}
299 	}
300 
301 	return xRet;
302 }
303 
304 // XHierarchicalNameAccess
305 //__________________________________________________________________________________________________
getByHierarchicalName(const OUString & rName)306 Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName )
307 	throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
308 {
309 	Any aRet( _aElements.getValue( rName ) );
310 	if (! aRet.hasValue())
311 	{
312 		// first look for constants exclusivly!
313 		aRet = _xTDMgr->getByHierarchicalName( rName );
314 		if (aRet.getValueTypeClass() == TypeClass_INTERFACE) // if no constant,
315 															 // i.e. XTypeDescription for a type
316 		{
317 			// type retrieved from tdmgr
318 			OSL_ASSERT( (*(Reference< XInterface > *)aRet.getValue())->queryInterface(
319 				::getCppuType( (const Reference< XTypeDescription > *)0 ) ).hasValue() );
320 
321 			// if you are interested in a type then CALL forName()!!!
322 			// this way is NOT recommended for types, because this method looks for constants first
323 
324 			// if td manager found some type, it will be in the cache (hopefully.. we just got it)
325 			// so the second retrieving via c typelib callback chain should succeed...
326 
327 			// try to get _type_ by name
328 			typelib_TypeDescription * pTD = 0;
329 			typelib_typedescription_getByName( &pTD, rName.pData );
330 
331 			aRet.clear(); // kick XTypeDescription interface
332 
333 			if (pTD)
334 			{
335 				Reference< XIdlClass > xIdlClass( constructClass( pTD ) );
336 				aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) );
337 				typelib_typedescription_release( pTD );
338 			}
339 		}
340 		// else is constant
341 
342 		// update
343 		if (aRet.hasValue())
344 			_aElements.setValue( rName, aRet );
345 		else
346 		{
347 			throw NoSuchElementException( rName, Reference< XInterface >() );
348 		}
349 	}
350 	return aRet;
351 }
352 //__________________________________________________________________________________________________
hasByHierarchicalName(const OUString & rName)353 sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName )
354 	throw(::com::sun::star::uno::RuntimeException)
355 {
356 	try
357 	{
358 		return getByHierarchicalName( rName ).hasValue();
359 	}
360 	catch (NoSuchElementException &)
361 	{
362 	}
363 	return sal_False;
364 }
365 
366 //__________________________________________________________________________________________________
forType(typelib_TypeDescription * pTypeDescr)367 Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr )
368 	throw(::com::sun::star::uno::RuntimeException)
369 {
370 	Reference< XIdlClass > xRet;
371 	OUString aName( pTypeDescr->pTypeName );
372 	Any aAny( _aElements.getValue( aName ) );
373 
374 	if (aAny.hasValue())
375 	{
376 		if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
377 			xRet = *(const Reference< XIdlClass > *)aAny.getValue();
378 	}
379 	else
380 	{
381 		if (pTypeDescr && (xRet = constructClass( pTypeDescr )).is())
382 			_aElements.setValue( aName, makeAny( xRet ) ); // update
383 	}
384 
385 	return xRet;
386 }
387 //__________________________________________________________________________________________________
forType(typelib_TypeDescriptionReference * pRef)388 Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef )
389 	throw(::com::sun::star::uno::RuntimeException)
390 {
391 	typelib_TypeDescription * pTD = 0;
392 	TYPELIB_DANGER_GET( &pTD, pRef );
393 	if (pTD)
394 	{
395 		Reference< XIdlClass > xRet = forType( pTD );
396 		TYPELIB_DANGER_RELEASE( pTD );
397 		return xRet;
398 	}
399 	throw RuntimeException(
400 		OUString( RTL_CONSTASCII_USTRINGPARAM("IdlReflectionServiceImpl::forType() failed!") ),
401 		(XWeak *)(OWeakObject *)this );
402 }
403 
404 //__________________________________________________________________________________________________
getCpp2Uno()405 const Mapping & IdlReflectionServiceImpl::getCpp2Uno()
406 	throw(::com::sun::star::uno::RuntimeException)
407 {
408 	if (! _aCpp2Uno.is())
409 	{
410 		MutexGuard aGuard( getMutexAccess() );
411 		if (! _aCpp2Uno.is())
412 		{
413 			_aCpp2Uno = Mapping(
414                 OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ),
415                 OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ) );
416 			OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" );
417 			if (! _aCpp2Uno.is())
418 			{
419 				throw RuntimeException(
420 					OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get c++ to uno mapping!") ),
421 					(XWeak *)(OWeakObject *)this );
422 			}
423 		}
424 	}
425 	return _aCpp2Uno;
426 }
427 //__________________________________________________________________________________________________
getUno2Cpp()428 const Mapping & IdlReflectionServiceImpl::getUno2Cpp()
429 	throw(::com::sun::star::uno::RuntimeException)
430 {
431 	if (! _aUno2Cpp.is())
432 	{
433 		MutexGuard aGuard( getMutexAccess() );
434 		if (! _aUno2Cpp.is())
435 		{
436 			_aUno2Cpp = Mapping(
437                 OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ),
438                 OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ) );
439 			OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" );
440 			if (! _aUno2Cpp.is())
441 			{
442 				throw RuntimeException(
443 					OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get uno to c++ mapping!") ),
444 					(XWeak *)(OWeakObject *)this );
445 			}
446 		}
447 	}
448 	return _aUno2Cpp;
449 }
450 //__________________________________________________________________________________________________
mapToUno(const Any & rObj,typelib_InterfaceTypeDescription * pTo)451 uno_Interface * IdlReflectionServiceImpl::mapToUno(
452     const Any & rObj, typelib_InterfaceTypeDescription * pTo )
453 	throw(::com::sun::star::uno::RuntimeException)
454 {
455 	Reference< XInterface > xObj;
456 	if (extract( rObj, pTo, xObj, this ))
457 		return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo );
458 
459 	throw RuntimeException(
460 		OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
461 		(XWeak *)(OWeakObject *)this );
462 }
463 
464 //==================================================================================================
IdlReflectionServiceImpl_create(const Reference<XComponentContext> & xContext)465 Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create(
466 	const Reference< XComponentContext > & xContext )
467 	throw(::com::sun::star::uno::Exception)
468 {
469 	return Reference< XInterface >( (XWeak *)(OWeakObject *)new IdlReflectionServiceImpl( xContext ) );
470 }
471 
472 }
473 
474 
475 //##################################################################################################
476 //##################################################################################################
477 //##################################################################################################
478 
479 using namespace stoc_corefl;
480 
481 static struct ImplementationEntry g_entries[] =
482 {
483 	{
484 		IdlReflectionServiceImpl_create, core_getImplementationName,
485 		core_getSupportedServiceNames, createSingleComponentFactory,
486 		&g_moduleCount.modCnt , 0
487 	},
488 	{ 0, 0, 0, 0, 0, 0 }
489 };
490 
491 extern "C"
492 {
component_canUnload(TimeValue * pTime)493 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
494 {
495 	return g_moduleCount.canUnload( &g_moduleCount , pTime );
496 }
497 
498 //==================================================================================================
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)499 void SAL_CALL component_getImplementationEnvironment(
500 	const sal_Char ** ppEnvTypeName, uno_Environment ** )
501 {
502 	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
503 }
504 //==================================================================================================
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)505 void * SAL_CALL component_getFactory(
506 	const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
507 {
508 	return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
509 }
510 }
511