/************************************************************** * * 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 #include #ifndef _CPPUHELER_WEAK_HXX_ #include #endif #include #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX__ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SERVICENAME "com.sun.star.script.Invocation" #define IMPLNAME "com.sun.star.comp.stoc.Invocation" using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::script; using namespace com::sun::star::reflection; using namespace com::sun::star::beans; using namespace com::sun::star::registry; using namespace com::sun::star::container; using namespace cppu; using namespace rtl; using namespace osl; namespace stoc_inv { static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; static Sequence< OUString > inv_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 inv_getImplementationName() { static OUString *pImplName = 0; if( ! pImplName ) { MutexGuard guard( Mutex::getGlobalMutex() ); if( ! pImplName ) { static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); pImplName = &implName; } } return *pImplName; } // TODO: Zentral implementieren inline Reference TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl ) { return xRefl->forName( rType.getTypeName() ); } //================================================================================================== class Invocation_Impl : public OWeakObject , public XInvocation2 , public XNameContainer , public XIndexContainer , public XEnumerationAccess , public XExactName , public XMaterialHolder , public XTypeProvider { public: Invocation_Impl( const Any & rAdapted, const Reference &, const Reference &, const Reference & ); virtual ~Invocation_Impl(); // XInterface virtual Any SAL_CALL queryInterface( const Type & aType) throw( RuntimeException ); virtual void SAL_CALL acquire() throw() { OWeakObject::acquire(); } virtual void SAL_CALL release() throw() { OWeakObject::release(); } // XTypeProvider virtual Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(RuntimeException); virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw( RuntimeException); // Methoden von XMaterialHolder virtual Any SAL_CALL getMaterial(void) throw(RuntimeException); // ? XTool virtual void SAL_CALL setMaterial( const Any& rMaterial ); // XInvocation virtual Reference SAL_CALL getIntrospection(void) throw( RuntimeException ); virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ); virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ); virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException ); virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException ); virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException ); // XInvocation2 virtual Sequence< OUString > SAL_CALL getMemberNames( ) throw( RuntimeException ); virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) throw( RuntimeException ); virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) throw( IllegalArgumentException, RuntimeException ); // All Access and Container methods are not thread save // XElementAccess virtual Type SAL_CALL getElementType(void) throw( RuntimeException ) { return _xElementAccess->getElementType(); } virtual sal_Bool SAL_CALL hasElements(void) throw( RuntimeException ) { return _xElementAccess->hasElements(); } // XNameContainer virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) { _xNameContainer->insertByName( Name, Element ); } virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) { _xNameContainer->replaceByName( Name, Element ); } virtual void SAL_CALL removeByName( const OUString& Name ) throw( NoSuchElementException, WrappedTargetException, RuntimeException ) { _xNameContainer->removeByName( Name ); } // XNameAccess virtual Any SAL_CALL getByName( const OUString& Name ) throw( NoSuchElementException, WrappedTargetException, RuntimeException ) { return _xNameAccess->getByName( Name ); } virtual Sequence SAL_CALL getElementNames(void) throw( RuntimeException ) { return _xNameAccess->getElementNames(); } virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) throw( RuntimeException ) { return _xNameAccess->hasByName( Name ); } // XIndexContainer virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { _xIndexContainer->insertByIndex( Index, Element ); } virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { _xIndexContainer->replaceByIndex( Index, Element ); } virtual void SAL_CALL removeByIndex( sal_Int32 Index ) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { _xIndexContainer->removeByIndex( Index ); } // XIndexAccess virtual sal_Int32 SAL_CALL getCount(void) throw( RuntimeException ) { return _xIndexAccess->getCount(); } virtual Any SAL_CALL getByIndex( sal_Int32 Index ) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { return _xIndexAccess->getByIndex( Index ); } // XEnumerationAccess virtual Reference SAL_CALL createEnumeration(void) throw( RuntimeException ) { return _xEnumerationAccess->createEnumeration(); } // XExactName virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) throw( RuntimeException ); //===================================================================================================== private: void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq ); void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName ); void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp ); void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod > xMethod ); Reference xTypeConverter; Reference xIntrospection; Reference xCoreReflection; Any _aMaterial; // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive Reference _xDirect; Reference _xDirect2; Reference _xPropertySet; Reference _xIntrospectionAccess; // supplied Interfaces Reference _xNameContainer; Reference _xNameAccess; Reference _xIndexContainer; Reference _xIndexAccess; Reference _xEnumerationAccess; Reference _xElementAccess; // Reference _xENDirect, _xENIntrospection, _xENNameAccess; }; //================================================================================================== //================================================================================================== //================================================================================================== //-------------------------------------------------------------------------------------------------- Invocation_Impl::Invocation_Impl ( const Any & rAdapted, const Reference & rTC, const Reference & rI, const Reference & rCR ) : xTypeConverter( rTC ) , xIntrospection( rI ) , xCoreReflection( rCR ) { g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); setMaterial( rAdapted ); } Invocation_Impl::~Invocation_Impl() { g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); } //################################################################################################## //### INTERFACE IMPLEMENTATIONS #################################################################### //################################################################################################## Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType ) throw( RuntimeException ) { // PropertySet-Implementation Any a = ::cppu::queryInterface( aType, SAL_STATIC_CAST(XInvocation*, this), SAL_STATIC_CAST(XMaterialHolder*, this), SAL_STATIC_CAST(XTypeProvider *,this) ); if( a.hasValue() ) { return a; } if( aType == getCppuType( (Reference*) NULL ) ) { // Ivocation does not support XExactName, if direct object supports // XInvocation, but not XExactName. if ((_xDirect.is() && _xENDirect.is()) || (!_xDirect.is() && (_xENIntrospection.is() || _xENNameAccess.is()))) { return makeAny( Reference< XExactName >( SAL_STATIC_CAST(XExactName*, this) ) ); } } else if ( aType == getCppuType( (Reference*) NULL ) ) { if( _xNameContainer.is() ) return makeAny( Reference< XNameContainer >( SAL_STATIC_CAST(XNameContainer*, this) ) ); } else if ( aType == getCppuType( (Reference*) NULL ) ) { if( _xNameAccess.is() ) return makeAny( Reference< XNameAccess >( SAL_STATIC_CAST(XNameAccess*, this) ) ); } else if ( aType == getCppuType( (Reference*) NULL ) ) { if (_xIndexContainer.is()) return makeAny( Reference< XIndexContainer >( SAL_STATIC_CAST(XIndexContainer*, this) ) ); } else if ( aType == getCppuType( (Reference*) NULL ) ) { if (_xIndexAccess.is()) return makeAny( Reference< XIndexAccess >( SAL_STATIC_CAST(XIndexAccess*, this) ) ); } else if ( aType == getCppuType( (Reference*) NULL ) ) { if (_xEnumerationAccess.is()) return makeAny( Reference< XEnumerationAccess >( SAL_STATIC_CAST(XEnumerationAccess*, this) ) ); } else if ( aType == getCppuType( (Reference*) NULL ) ) { if (_xElementAccess.is()) { return makeAny( Reference< XElementAccess >( SAL_STATIC_CAST(XElementAccess*, SAL_STATIC_CAST(XNameContainer*, this) ) ) ); } } else if ( aType == getCppuType( (Reference*) NULL ) ) { // Invocation does not support XInvocation2, if direct object supports // XInvocation, but not XInvocation2. if ( ( _xDirect.is() && _xDirect2.is()) || (!_xDirect.is() && _xIntrospectionAccess.is() ) ) { return makeAny( Reference< XInvocation2 >( SAL_STATIC_CAST(XInvocation2*, this) ) ); } } return OWeakObject::queryInterface( aType ); } //-------------------------------------------------------------------------------------------------- Any Invocation_Impl::getMaterial(void) throw(RuntimeException) { // AB, 12.2.1999 Sicherstellen, dass das Material wenn moeglich // aus der direkten Invocation bzw. von der Introspection geholt // wird, da sonst Structs nicht korrekt behandelt werden Reference xMaterialHolder; if( _xDirect.is() ) { xMaterialHolder = Reference::query( _xDirect ); //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder ); } else if( _xIntrospectionAccess.is() ) { xMaterialHolder = Reference::query( _xIntrospectionAccess ); //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder ); } if( xMaterialHolder.is() ) { return xMaterialHolder->getMaterial(); } return _aMaterial; } //-------------------------------------------------------------------------------------------------- void Invocation_Impl::setMaterial( const Any& rMaterial ) { // set the material first and only once Reference xObj; if (rMaterial.getValueType().getTypeClass() == TypeClass_INTERFACE) xObj = *(Reference*)rMaterial.getValue(); _aMaterial = rMaterial; // Ersteinmal alles ausserhalb des guards machen _xDirect = Reference::query( xObj ); if( _xDirect.is() ) { // Objekt direkt befragen _xElementAccess = Reference::query( _xDirect ); _xEnumerationAccess = Reference::query( _xDirect ); _xIndexAccess = Reference::query( _xDirect ); _xIndexContainer = Reference::query( _xDirect ); _xNameAccess = Reference::query( _xDirect ); _xNameContainer = Reference::query( _xDirect ); _xENDirect = Reference::query( _xDirect ); _xDirect2 = Reference::query( _xDirect ); // only once!!! //_xIntrospectionAccess = XIntrospectionAccessRef(); //_xPropertySet = XPropertySetRef(); } else { // Invocation ueber die Introspection machen if (xIntrospection.is()) { _xIntrospectionAccess = xIntrospection->inspect( _aMaterial ); if( _xIntrospectionAccess.is() ) { _xElementAccess = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL ) ) ); _xEnumerationAccess = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL )) ); _xIndexAccess = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL ) ) ); _xIndexContainer = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL ) ) ); _xNameAccess = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL ) ) ); _xNameContainer = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL ) ) ); _xPropertySet = Reference::query( _xIntrospectionAccess->queryAdapter( getCppuType( (Reference*) NULL )) ); _xENIntrospection = Reference::query( _xIntrospectionAccess ); if (_xNameAccess.is()) _xENNameAccess = Reference::query( _xNameAccess ); } } /* only once !!! _xDirect = XInvocationRef(); if( !_xIntrospectionAccess.is() ) { // reset _xElementAccess = XElementAccessRef(); _xEnumerationAccess = XEnumerationAccessRef(); _xIndexAccess = XIndexAccessRef(); _xIndexContainer = XIndexContainerRef(); _xNameAccess = XNameAccessRef(); _xNameContainer = XNameContainerRef(); _xPropertySet = XPropertySetRef(); } */ } } //-------------------------------------------------------------------------------------------------- OUString Invocation_Impl::getExactName( const OUString& rApproximateName ) throw( RuntimeException ) { if (_xENDirect.is()) return _xENDirect->getExactName( rApproximateName ); OUString aRet; if (_xENIntrospection.is()) aRet = _xENIntrospection->getExactName( rApproximateName ); if (!aRet.getLength() && _xENNameAccess.is()) aRet = _xENNameAccess->getExactName( rApproximateName ); return aRet; } //-------------------------------------------------------------------------------------------------- Reference Invocation_Impl::getIntrospection(void) throw( RuntimeException ) { if( _xDirect.is() ) return _xDirect->getIntrospection(); else return _xIntrospectionAccess; } //-------------------------------------------------------------------------------------------------- sal_Bool Invocation_Impl::hasMethod( const OUString& Name ) throw( RuntimeException ) { if (_xDirect.is()) return _xDirect->hasMethod( Name ); if( _xIntrospectionAccess.is() ) return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); return sal_False; } //-------------------------------------------------------------------------------------------------- sal_Bool Invocation_Impl::hasProperty( const OUString& Name ) throw( RuntimeException ) { if (_xDirect.is()) return _xDirect->hasProperty( Name ); // PropertySet if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) return sal_True; // NameAccess if( _xNameAccess.is() ) return _xNameAccess->hasByName( Name ); return sal_False; } //-------------------------------------------------------------------------------------------------- Any Invocation_Impl::getValue( const OUString& PropertyName ) throw( UnknownPropertyException, RuntimeException ) { if (_xDirect.is()) return _xDirect->getValue( PropertyName ); try { // PropertySet if( _xIntrospectionAccess.is() && _xPropertySet.is() && _xIntrospectionAccess->hasProperty ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) { return _xPropertySet->getPropertyValue( PropertyName ); } // NameAccess if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) ) return _xNameAccess->getByName( PropertyName ); } catch (UnknownPropertyException &) { throw; } catch (RuntimeException &) { throw; } catch (Exception &) { } throw UnknownPropertyException( OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get value ") ) + PropertyName, Reference< XInterface >() ); } //-------------------------------------------------------------------------------------------------- void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value ) throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ) { if (_xDirect.is()) _xDirect->setValue( PropertyName, Value ); else { try { // Properties if( _xIntrospectionAccess.is() && _xPropertySet.is() && _xIntrospectionAccess->hasProperty( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) { Property aProp = _xIntrospectionAccess->getProperty( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ); Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection ); if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) ) _xPropertySet->setPropertyValue( PropertyName, Value ); else if( xTypeConverter.is() ) _xPropertySet->setPropertyValue( PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) ); else throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no type converter service!") ), Reference< XInterface >() ); } // NameContainer else if( _xNameContainer.is() ) { Any aConv; Reference < XIdlClass > r = TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection ); if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) ) aConv = Value; else if( xTypeConverter.is() ) aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() ); else throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no type converter service!") ), Reference< XInterface >() ); // bei Vorhandensein ersetzen, ansonsten einfuegen if (_xNameContainer->hasByName( PropertyName )) _xNameContainer->replaceByName( PropertyName, aConv ); else _xNameContainer->insertByName( PropertyName, aConv ); } else throw UnknownPropertyException( OUString( RTL_CONSTASCII_USTRINGPARAM("no introspection nor name container!") ), Reference< XInterface >() ); } catch (UnknownPropertyException &) { throw; } catch (CannotConvertException &) { throw; } catch (InvocationTargetException &) { throw; } catch (RuntimeException &) { throw; } catch (Exception & exc) { throw InvocationTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM("exception occurred in setValue(): ") ) + exc.Message, Reference< XInterface >(), makeAny( exc /* though sliced */ ) ); } } } //-------------------------------------------------------------------------------------------------- Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence& InParams, Sequence& OutIndizes, Sequence& OutParams ) throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ) { if (_xDirect.is()) return _xDirect->invoke( FunctionName, InParams, OutIndizes, OutParams ); if (_xIntrospectionAccess.is()) { // throw NoSuchMethodException if not exist Reference xMethod = _xIntrospectionAccess->getMethod( FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); // ParameterInfos Sequence aFParams = xMethod->getParameterInfos(); const ParamInfo* pFParams = aFParams.getConstArray(); sal_Int32 nFParamsLen = aFParams.getLength(); if (nFParamsLen != InParams.getLength()) { throw IllegalArgumentException( OUString( RTL_CONSTASCII_USTRINGPARAM("incorrect number of parameters passed invoking function ") ) + FunctionName, (OWeakObject *) this, (sal_Int16) 1 ); } // IN Parameter const Any* pInParams = InParams.getConstArray(); // Introspection Invoke Parameter Sequence aInvokeParams( nFParamsLen ); Any* pInvokeParams = aInvokeParams.getArray(); // OUT Indizes OutIndizes.realloc( nFParamsLen ); sal_Int16* pOutIndizes = OutIndizes.getArray(); sal_uInt32 nOutIndex = 0; for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos ) { try { const ParamInfo& rFParam = pFParams[nPos]; const Reference& rDestType = rFParam.aType; // is IN/INOUT parameter? if (rFParam.aMode != ParamMode_OUT) { if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) )) { pInvokeParams[nPos] = pInParams[nPos]; } else if (xTypeConverter.is()) { Type aDestType( rDestType->getTypeClass(), rDestType->getName() ); pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType ); } else { CannotConvertException aExc; aExc.Context = *this; aExc.Message = OUString( RTL_CONSTASCII_USTRINGPARAM("invocation type mismatch!") ); throw aExc; } } // is OUT/INOUT parameter? if (rFParam.aMode != ParamMode_IN) { pOutIndizes[nOutIndex] = (sal_Int16)nPos; if (rFParam.aMode == ParamMode_OUT) rDestType->createObject( pInvokeParams[nPos] ); // default init ++nOutIndex; } } catch( CannotConvertException& rExc ) { rExc.ArgumentIndex = nPos; // optionalen Parameter Index hinzufuegen throw rExc; } } // execute Method Any aRet = xMethod->invoke( _aMaterial, aInvokeParams ); // OUT Params OutIndizes.realloc( nOutIndex ); pOutIndizes = OutIndizes.getArray(); OutParams.realloc( nOutIndex ); Any* pOutParams = OutParams.getArray(); while (nOutIndex--) { pOutParams[nOutIndex] = pInvokeParams[ pOutIndizes[nOutIndex] ]; } return aRet; } RuntimeException aExc; aExc.Context = *this; aExc.Message = OUString( RTL_CONSTASCII_USTRINGPARAM("invocation lacking of introspection access!") ); throw aExc; } //-------------------------------------------------------------------------------------------------- // Struct to optimize sorting struct MemberItem { OUString aName; // Defines where the member comes from enum Mode { NAMEACCESS, PROPERTYSET, METHOD } eMode; // Index to respective sequence // (Index to NameAccess sequence for eMode==NAMEACCESS etc.) sal_Int32 nIndex; }; // Implementation of getting name or info // String sequence will be filled when pStringSeq != NULL // Info sequence will be filled when pInfoSeq != NULL void Invocation_Impl::getInfoSequenceImpl ( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq ) { //Sequence< OUString > aStrSeq; //if( !pStringSeq ) //pStringSeq = &aStrSeq; // Get all needed sequences Sequence aNameAccessNames; Sequence aPropertySeq; Sequence< Reference< XIdlMethod > > aMethodSeq; if( _xNameAccess.is() ) { aNameAccessNames = _xNameAccess->getElementNames(); } if( _xIntrospectionAccess.is() ) { aPropertySeq = _xIntrospectionAccess->getProperties ( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); aMethodSeq = _xIntrospectionAccess->getMethods ( MethodConcept::ALL - MethodConcept::DANGEROUS ); } sal_Int32 nNameAccessCount = aNameAccessNames.getLength(); sal_Int32 nPropertyCount = aPropertySeq.getLength(); sal_Int32 nMethodCount = aMethodSeq.getLength(); sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount; // Create and fill array of MemberItems boost::scoped_array< MemberItem > pItems( new MemberItem[ nTotalCount ] ); const OUString* pStrings = aNameAccessNames.getConstArray(); const Property* pProps = aPropertySeq.getConstArray(); const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); // Fill array of MemberItems sal_Int32 i, iTotal = 0; // Name Access for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ ) { MemberItem& rItem = pItems[ iTotal ]; rItem.aName = pStrings[ i ]; rItem.eMode = MemberItem::NAMEACCESS; rItem.nIndex = i; } // Property set for( i = 0 ; i < nPropertyCount ; i++, iTotal++ ) { MemberItem& rItem = pItems[ iTotal ]; rItem.aName = pProps[ i ].Name; rItem.eMode = MemberItem::PROPERTYSET; rItem.nIndex = i; } // Methods for( i = 0 ; i < nMethodCount ; i++, iTotal++ ) { MemberItem& rItem = pItems[ iTotal ]; Reference< XIdlMethod > xMethod = pMethods[ i ]; rItem.aName = xMethod->getName(); rItem.eMode = MemberItem::METHOD; rItem.nIndex = i; } // Setting up result sequences OUString* pRetStrings = NULL; if( pStringSeq ) { pStringSeq->realloc( nTotalCount ); pRetStrings = pStringSeq->getArray(); } InvocationInfo* pRetInfos = NULL; if( pInfoSeq ) { pInfoSeq->realloc( nTotalCount ); pRetInfos = pInfoSeq->getArray(); } // Fill result sequences in the correct order of members for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ ) { MemberItem& rItem = pItems[ iTotal ]; if( pRetStrings ) { pRetStrings[ iTotal ] = rItem.aName; } if( pRetInfos ) { if( rItem.eMode == MemberItem::NAMEACCESS ) { fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName ); } else if( rItem.eMode == MemberItem::PROPERTYSET ) { fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] ); } else if( rItem.eMode == MemberItem::METHOD ) { fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] ); } } } } // XInvocation2 Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( ) throw( RuntimeException ) { if( _xDirect2.is() ) { return _xDirect2->getMemberNames(); } Sequence< OUString > aRetSeq; getInfoSequenceImpl( &aRetSeq, NULL ); return aRetSeq; } Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( ) throw( RuntimeException ) { if( _xDirect2.is() ) { return _xDirect2->getInfo(); } Sequence< InvocationInfo > aRetSeq; getInfoSequenceImpl( NULL, &aRetSeq ); return aRetSeq; } InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact ) throw( IllegalArgumentException, RuntimeException ) { if( _xDirect2.is() ) { return _xDirect2->getInfoForName( aName, bExact ); } sal_Bool bFound = sal_False; OUString aExactName = aName; InvocationInfo aRetInfo; if( bExact ) aExactName = getExactName( aName ); if( aExactName.getLength() > 0 ) { if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) ) { Reference xMethod = _xIntrospectionAccess->getMethod ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); fillInfoForMethod( aRetInfo, xMethod ); bFound = sal_True; } else { if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) { Property aProp = _xIntrospectionAccess->getProperty ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ); fillInfoForProperty( aRetInfo, aProp ); bFound = sal_True; } // NameAccess else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) ) { fillInfoForNameAccess( aRetInfo, aExactName ); bFound = sal_True; } } } if( !bFound ) { throw IllegalArgumentException( OUString( RTL_CONSTASCII_USTRINGPARAM("Unknown name, getExactName() failed!") ), (XWeak *)(OWeakObject *)this, 0 ); } return aRetInfo; } // Helper functions to fill InvocationInfo for XNameAccess void Invocation_Impl::fillInfoForNameAccess ( InvocationInfo& rInfo, const OUString& aName ) { rInfo.aName = aName; rInfo.eMemberType = MemberType_PROPERTY; rInfo.PropertyAttribute = 0; if( !_xNameContainer.is() ) { rInfo.PropertyAttribute = PropertyAttribute::READONLY; } rInfo.aType = _xNameAccess->getElementType(); } void Invocation_Impl::fillInfoForProperty ( InvocationInfo& rInfo, const Property& rProp ) { rInfo.aName = rProp.Name; rInfo.eMemberType = MemberType_PROPERTY; rInfo.PropertyAttribute = rProp.Attributes; rInfo.aType = rProp.Type; } void Invocation_Impl::fillInfoForMethod ( InvocationInfo& rInfo, const Reference< XIdlMethod > xMethod ) { rInfo.aName = xMethod->getName(); rInfo.eMemberType = MemberType_METHOD; Reference< XIdlClass > xReturnClass = xMethod->getReturnType(); Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() ); rInfo.aType = aReturnType; Sequence aParamInfos = xMethod->getParameterInfos(); sal_Int32 nParamCount = aParamInfos.getLength(); if( nParamCount > 0 ) { const ParamInfo* pInfos = aParamInfos.getConstArray(); rInfo.aParamTypes.realloc( nParamCount ); Type* pParamTypes = rInfo.aParamTypes.getArray(); rInfo.aParamModes.realloc( nParamCount ); ParamMode* pParamModes = rInfo.aParamModes.getArray(); for( sal_Int32 i = 0 ; i < nParamCount ; i++ ) { Reference< XIdlClass > xParamClass = pInfos[i].aType; Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() ); pParamTypes[ i ] = aParamType; pParamModes[ i ] = pInfos[i].aMode; } } } // XTypeProvider Sequence< Type > SAL_CALL Invocation_Impl::getTypes(void) throw( RuntimeException ) { static Sequence< Type > const * s_pTypes = 0; if (! s_pTypes) { Sequence< Type > types( 4 +8 ); Type * pTypes = types.getArray(); sal_Int32 n = 0; pTypes[ n++ ] = ::getCppuType( (Reference< XTypeProvider > const *)0 ); pTypes[ n++ ] = ::getCppuType( (Reference< XWeak > const *)0 ); pTypes[ n++ ] = ::getCppuType( (Reference< XInvocation > const *)0 ); pTypes[ n++ ] = ::getCppuType( (Reference< XMaterialHolder > const *)0 ); // Ivocation does not support XExactName, if direct object supports // XInvocation, but not XExactName. if ((_xDirect.is() && _xENDirect.is()) || (!_xDirect.is() && (_xENIntrospection.is() || _xENNameAccess.is()))) { pTypes[ n++ ] = ::getCppuType( (Reference< XExactName > const *)0 ); } if( _xNameContainer.is() ) { pTypes[ n++ ] = ::getCppuType( (Reference< XNameContainer > const *)0 ); } if( _xNameAccess.is() ) { pTypes[ n++ ] = ::getCppuType( (Reference< XNameAccess > const *)0 ); } if (_xIndexContainer.is()) { pTypes[ n++ ] = ::getCppuType( (Reference< XIndexContainer > const *)0 ); } if (_xIndexAccess.is()) { pTypes[ n++ ] = ::getCppuType( (Reference< XIndexAccess > const *)0 ); } if (_xEnumerationAccess.is()) { pTypes[ n++ ] = ::getCppuType( (Reference< XEnumerationAccess > const *)0 ); } if (_xElementAccess.is()) { pTypes[ n++ ] = ::getCppuType( (Reference< XElementAccess > const *)0 ); } // Invocation does not support XInvocation2, if direct object supports // XInvocation, but not XInvocation2. if ( ( _xDirect.is() && _xDirect2.is()) || (!_xDirect.is() && _xIntrospectionAccess.is() ) ) { pTypes[ n++ ] = ::getCppuType( (Reference< XInvocation2 > const *)0 ); } types.realloc( n ); // store types MutexGuard guard( Mutex::getGlobalMutex() ); if (! s_pTypes) { static Sequence< Type > s_types( types ); s_pTypes = &s_types; } } return *s_pTypes; } Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( ) throw( RuntimeException) { static OImplementationId *pId = 0; if( ! pId ) { MutexGuard guard( Mutex::getGlobalMutex() ); if( ! pId ) { static OImplementationId id( sal_False ); pId = &id; } } return pId->getImplementationId(); } //================================================================================================== //================================================================================================== //================================================================================================== class InvocationService : public WeakImplHelper2< XSingleServiceFactory, XServiceInfo > { public: InvocationService( const Reference & xCtx ); virtual ~InvocationService(); // XServiceInfo OUString SAL_CALL getImplementationName() throw( RuntimeException ); sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( RuntimeException ); Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( RuntimeException ); // XSingleServiceFactory Reference SAL_CALL createInstance(void) throw( Exception, RuntimeException ); Reference SAL_CALL createInstanceWithArguments( const Sequence& rArguments ) throw( Exception, RuntimeException ); private: Reference mxCtx; Reference mxSMgr; Reference xTypeConverter; Reference xIntrospection; Reference xCoreReflection; }; InvocationService::InvocationService( const Reference & xCtx ) : mxCtx( xCtx ) , mxSMgr( xCtx->getServiceManager() ) { g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); xTypeConverter = Reference( mxSMgr->createInstanceWithContext( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")), xCtx ), UNO_QUERY ); xIntrospection = Reference( mxSMgr->createInstanceWithContext( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.Introspection")), xCtx), UNO_QUERY); mxCtx->getValueByName( OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection")) ) >>= xCoreReflection; OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessible!?" ); if (! xCoreReflection.is()) { throw DeploymentException( OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible") ), Reference< XInterface >() ); } // xCoreReflection = Reference( // mxSMgr->createInstanceWithContext( // OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")), // xCtx), // UNO_QUERY); } InvocationService::~InvocationService() { g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); } // XServiceInfo OUString InvocationService::getImplementationName() throw( RuntimeException ) { return inv_getImplementationName(); } // XServiceInfo sal_Bool InvocationService::supportsService(const OUString& ServiceName) throw( RuntimeException ) { Sequence< OUString > aSNL = getSupportedServiceNames(); const OUString * pArray = aSNL.getConstArray(); for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) if( pArray[i] == ServiceName ) return sal_True; return sal_False; } // XServiceInfo Sequence< OUString > InvocationService::getSupportedServiceNames(void) throw( RuntimeException ) { return inv_getSupportedServiceNames(); } //-------------------------------------------------------------------------------------------------- Reference InvocationService::createInstance(void) throw( Exception, RuntimeException ) { //TODO:throw( Exception(OUString( RTL_CONSTASCII_USTRINGPARAM("no default construction of invocation adapter possible!")), *this) ); return Reference(); // dummy } //-------------------------------------------------------------------------------------------------- Reference InvocationService::createInstanceWithArguments( const Sequence& rArguments ) throw( Exception, RuntimeException ) { if (rArguments.getLength() == 1) { return Reference< XInterface > ( *new Invocation_Impl( *rArguments.getConstArray(), xTypeConverter, xIntrospection, xCoreReflection ) ); } else { //TODO:throw( Exception(OUString( RTL_CONSTASCII_USTRINGPARAM("no default construction of invocation adapter possible!")), *this) ); return Reference(); } } //************************************************************************* Reference SAL_CALL InvocationService_CreateInstance( const Reference & xCtx ) throw( RuntimeException ) { Reference xService = Reference< XInterface > ( *new InvocationService( xCtx ) ); return xService; } } using namespace stoc_inv; static struct ImplementationEntry g_entries[] = { { InvocationService_CreateInstance, inv_getImplementationName, inv_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 ); } }