blob: 59fb673a911f73476e55a3f8f2dc9abf9feb87a1 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_stoc.hxx"
#include <cppuhelper/queryinterface.hxx>
#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
#include <cppuhelper/implementationentry.hxx>
#endif
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/reflection/XTypeDescription.hpp>
#include "com/sun/star/uno/RuntimeException.hpp"
using namespace com::sun::star;
using namespace com::sun::star::lang;
using namespace com::sun::star::registry;
using namespace cppu;
using namespace osl;
using namespace rtl;
#include "base.hxx"
namespace stoc_corefl
{
static const sal_Int32 CACHE_SIZE = 256;
#define SERVICENAME "com.sun.star.reflection.CoreReflection"
#define IMPLNAME "com.sun.star.comp.stoc.CoreReflection"
// can be static, as every client of the core reflection keeps a reference to the
// core reflection, so refcounting can be done here.
static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
static Sequence< OUString > core_getSupportedServiceNames()
{
static Sequence < OUString > *pNames = 0;
if( ! pNames )
{
MutexGuard guard( Mutex::getGlobalMutex() );
if( !pNames )
{
static Sequence< OUString > seqNames(1);
seqNames.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) );
pNames = &seqNames;
}
}
return *pNames;
}
static OUString core_getImplementationName()
{
static OUString *pImplName = 0;
if( ! pImplName )
{
MutexGuard guard( Mutex::getGlobalMutex() );
if( ! pImplName )
{
static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
pImplName = &implName;
}
}
return *pImplName;
}
//__________________________________________________________________________________________________
IdlReflectionServiceImpl::IdlReflectionServiceImpl(
const Reference< XComponentContext > & xContext )
: OComponentHelper( _aComponentMutex )
, _xMgr( xContext->getServiceManager(), UNO_QUERY )
, _aElements( CACHE_SIZE )
{
g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
xContext->getValueByName( OUString( RTL_CONSTASCII_USTRINGPARAM(
"/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) >>= _xTDMgr;
OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" );
}
//__________________________________________________________________________________________________
IdlReflectionServiceImpl::~IdlReflectionServiceImpl()
{
TRACE( "> IdlReflectionServiceImpl dtor <\n" );
g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}
// XInterface
//__________________________________________________________________________________________________
Any IdlReflectionServiceImpl::queryInterface( const Type & rType )
throw(::com::sun::star::uno::RuntimeException)
{
Any aRet( ::cppu::queryInterface(
rType,
static_cast< XIdlReflection * >( this ),
static_cast< XHierarchicalNameAccess * >( this ),
static_cast< XServiceInfo * >( this ) ) );
return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
}
//__________________________________________________________________________________________________
void IdlReflectionServiceImpl::acquire() throw()
{
OComponentHelper::acquire();
}
//__________________________________________________________________________________________________
void IdlReflectionServiceImpl::release() throw()
{
OComponentHelper::release();
}
// XTypeProvider
//__________________________________________________________________________________________________
Sequence< Type > IdlReflectionServiceImpl::getTypes()
throw (::com::sun::star::uno::RuntimeException)
{
static OTypeCollection * s_pTypes = 0;
if (! s_pTypes)
{
MutexGuard aGuard( _aComponentMutex );
if (! s_pTypes)
{
static OTypeCollection s_aTypes(
::getCppuType( (const Reference< XIdlReflection > *)0 ),
::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ),
::getCppuType( (const Reference< XServiceInfo > *)0 ),
OComponentHelper::getTypes() );
s_pTypes = &s_aTypes;
}
}
return s_pTypes->getTypes();
}
//__________________________________________________________________________________________________
Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId()
throw (::com::sun::star::uno::RuntimeException)
{
static OImplementationId * s_pId = 0;
if (! s_pId)
{
MutexGuard aGuard( _aComponentMutex );
if (! s_pId)
{
static OImplementationId s_aId;
s_pId = &s_aId;
}
}
return s_pId->getImplementationId();
}
// XComponent
//__________________________________________________________________________________________________
void IdlReflectionServiceImpl::dispose()
throw(::com::sun::star::uno::RuntimeException)
{
TRACE( "> disposing corereflection... <" );
OComponentHelper::dispose();
MutexGuard aGuard( _aComponentMutex );
_aElements.clear();
#ifdef TEST_LIST_CLASSES
OSL_ENSURE( g_aClassNames.size() == 0, "### idl classes still alive!" );
ClassNameList::const_iterator iPos( g_aClassNames.begin() );
while (iPos != g_aClassNames.end())
{
OUString aName( *iPos );
++iPos;
}
#endif
}
// XServiceInfo
//__________________________________________________________________________________________________
OUString IdlReflectionServiceImpl::getImplementationName()
throw(::com::sun::star::uno::RuntimeException)
{
return core_getImplementationName();
}
//__________________________________________________________________________________________________
sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName )
throw(::com::sun::star::uno::RuntimeException)
{
const Sequence< OUString > & rSNL = getSupportedServiceNames();
const OUString * pArray = rSNL.getConstArray();
for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
{
if (pArray[nPos] == rServiceName)
return sal_True;
}
return sal_False;
}
//__________________________________________________________________________________________________
Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames()
throw(::com::sun::star::uno::RuntimeException)
{
return core_getSupportedServiceNames();
}
// XIdlReflection
//__________________________________________________________________________________________________
Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj )
throw(::com::sun::star::uno::RuntimeException)
{
return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >());
}
//__________________________________________________________________________________________________
inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass(
typelib_TypeDescription * pTypeDescr )
{
OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" );
switch (pTypeDescr->eTypeClass)
{
case typelib_TypeClass_VOID:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_FLOAT:
case typelib_TypeClass_DOUBLE:
case typelib_TypeClass_STRING:
case typelib_TypeClass_ANY:
return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
case TypeClass_ENUM:
return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_UNION:
case typelib_TypeClass_EXCEPTION:
return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
case typelib_TypeClass_ARRAY:
case typelib_TypeClass_SEQUENCE:
return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
case typelib_TypeClass_INTERFACE:
return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
case typelib_TypeClass_TYPE:
return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
default:
#if OSL_DEBUG_LEVEL > 1
OSL_TRACE( "### corereflection type unsupported: " );
OString aName( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
OSL_TRACE( aName.getStr() );
OSL_TRACE( "\n" );
#endif
return Reference< XIdlClass >();
}
}
//__________________________________________________________________________________________________
Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName )
throw(::com::sun::star::uno::RuntimeException)
{
Reference< XIdlClass > xRet;
Any aAny( _aElements.getValue( rTypeName ) );
if (aAny.hasValue())
{
if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
xRet = *(const Reference< XIdlClass > *)aAny.getValue();
}
else
{
// try to get _type_ by name
typelib_TypeDescription * pTD = 0;
typelib_typedescription_getByName( &pTD, rTypeName.pData );
if (pTD)
{
if ((xRet = constructClass( pTD )).is())
_aElements.setValue( rTypeName, makeAny( xRet ) ); // update
typelib_typedescription_release( pTD );
}
}
return xRet;
}
// XHierarchicalNameAccess
//__________________________________________________________________________________________________
Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName )
throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException)
{
Any aRet( _aElements.getValue( rName ) );
if (! aRet.hasValue())
{
// first look for constants exclusivly!
aRet = _xTDMgr->getByHierarchicalName( rName );
if (aRet.getValueTypeClass() == TypeClass_INTERFACE) // if no constant,
// i.e. XTypeDescription for a type
{
// type retrieved from tdmgr
OSL_ASSERT( (*(Reference< XInterface > *)aRet.getValue())->queryInterface(
::getCppuType( (const Reference< XTypeDescription > *)0 ) ).hasValue() );
// if you are interested in a type then CALL forName()!!!
// this way is NOT recommended for types, because this method looks for constants first
// if td manager found some type, it will be in the cache (hopefully.. we just got it)
// so the second retrieving via c typelib callback chain should succeed...
// try to get _type_ by name
typelib_TypeDescription * pTD = 0;
typelib_typedescription_getByName( &pTD, rName.pData );
aRet.clear(); // kick XTypeDescription interface
if (pTD)
{
Reference< XIdlClass > xIdlClass( constructClass( pTD ) );
aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) );
typelib_typedescription_release( pTD );
}
}
// else is constant
// update
if (aRet.hasValue())
_aElements.setValue( rName, aRet );
else
{
throw NoSuchElementException( rName, Reference< XInterface >() );
}
}
return aRet;
}
//__________________________________________________________________________________________________
sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName )
throw(::com::sun::star::uno::RuntimeException)
{
try
{
return getByHierarchicalName( rName ).hasValue();
}
catch (NoSuchElementException &)
{
}
return sal_False;
}
//__________________________________________________________________________________________________
Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr )
throw(::com::sun::star::uno::RuntimeException)
{
Reference< XIdlClass > xRet;
OUString aName( pTypeDescr->pTypeName );
Any aAny( _aElements.getValue( aName ) );
if (aAny.hasValue())
{
if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
xRet = *(const Reference< XIdlClass > *)aAny.getValue();
}
else
{
if (pTypeDescr && (xRet = constructClass( pTypeDescr )).is())
_aElements.setValue( aName, makeAny( xRet ) ); // update
}
return xRet;
}
//__________________________________________________________________________________________________
Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef )
throw(::com::sun::star::uno::RuntimeException)
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, pRef );
if (pTD)
{
Reference< XIdlClass > xRet = forType( pTD );
TYPELIB_DANGER_RELEASE( pTD );
return xRet;
}
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("IdlReflectionServiceImpl::forType() failed!") ),
(XWeak *)(OWeakObject *)this );
}
//__________________________________________________________________________________________________
const Mapping & IdlReflectionServiceImpl::getCpp2Uno()
throw(::com::sun::star::uno::RuntimeException)
{
if (! _aCpp2Uno.is())
{
MutexGuard aGuard( getMutexAccess() );
if (! _aCpp2Uno.is())
{
_aCpp2Uno = Mapping(
OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ),
OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ) );
OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" );
if (! _aCpp2Uno.is())
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get c++ to uno mapping!") ),
(XWeak *)(OWeakObject *)this );
}
}
}
return _aCpp2Uno;
}
//__________________________________________________________________________________________________
const Mapping & IdlReflectionServiceImpl::getUno2Cpp()
throw(::com::sun::star::uno::RuntimeException)
{
if (! _aUno2Cpp.is())
{
MutexGuard aGuard( getMutexAccess() );
if (! _aUno2Cpp.is())
{
_aUno2Cpp = Mapping(
OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ),
OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ) );
OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" );
if (! _aUno2Cpp.is())
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get uno to c++ mapping!") ),
(XWeak *)(OWeakObject *)this );
}
}
}
return _aUno2Cpp;
}
//__________________________________________________________________________________________________
uno_Interface * IdlReflectionServiceImpl::mapToUno(
const Any & rObj, typelib_InterfaceTypeDescription * pTo )
throw(::com::sun::star::uno::RuntimeException)
{
Reference< XInterface > xObj;
if (extract( rObj, pTo, xObj, this ))
return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo );
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
(XWeak *)(OWeakObject *)this );
}
//==================================================================================================
Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create(
const Reference< XComponentContext > & xContext )
throw(::com::sun::star::uno::Exception)
{
return Reference< XInterface >( (XWeak *)(OWeakObject *)new IdlReflectionServiceImpl( xContext ) );
}
}
//##################################################################################################
//##################################################################################################
//##################################################################################################
using namespace stoc_corefl;
static struct ImplementationEntry g_entries[] =
{
{
IdlReflectionServiceImpl_create, core_getImplementationName,
core_getSupportedServiceNames, createSingleComponentFactory,
&g_moduleCount.modCnt , 0
},
{ 0, 0, 0, 0, 0, 0 }
};
extern "C"
{
sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
{
return g_moduleCount.canUnload( &g_moduleCount , pTime );
}
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
void * SAL_CALL component_getFactory(
const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}
}