mib17: #111144# Enable calls to module function via Sheet object

This commit is contained in:
Andreas Bregas 2010-07-01 16:23:26 +02:00
parent 5db01bbf8f
commit 7e018ced84
6 changed files with 404 additions and 6 deletions

View file

@ -28,6 +28,7 @@
#ifndef _SB_SBMOD_HXX
#define _SB_SBMOD_HXX
#include <com/sun/star/script/XInvocation.hpp>
#include <basic/sbdef.hxx>
#include <basic/sbxobj.hxx>
#include <basic/sbxdef.hxx>
@ -57,6 +58,7 @@ class SbModule : public SbxObject
SbModuleImpl* mpSbModuleImpl; // Impl data
protected:
com::sun::star::uno::Reference< com::sun::star::script::XInvocation > mxWrapper;
::rtl::OUString aOUSource;
String aComment;
SbiImage* pImage; // the Image
@ -131,6 +133,7 @@ public:
INT32 GetModuleType() { return mnType; }
void SetModuleType( INT32 nType ) { mnType = nType; }
bool GetIsProxyModule() { return bIsProxyModule; }
::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation > GetUnoModule();
bool createCOMWrapperForIface( ::com::sun::star::uno::Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject );
};

View file

@ -76,7 +76,20 @@ using namespace com::sun::star;
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <map>
#include <com/sun/star/reflection/XProxyFactory.hpp>
#include <cppuhelper/implbase1.hxx>
#include <basic/sbobjmod.hxx>
#include <com/sun/star/uno/XAggregation.hpp>
#include <map>
#include <com/sun/star/script/XInvocation.hpp>
using namespace ::com::sun::star;
using namespace com::sun::star::lang;
using namespace com::sun::star::reflection;
using namespace com::sun::star::beans;
using namespace com::sun::star::script;
#include <com/sun/star/script/XLibraryContainer.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
@ -85,6 +98,340 @@ using namespace com::sun::star;
#include <com/sun/star/awt/XControl.hpp>
#include <cppuhelper/implbase1.hxx>
#include <comphelper/anytostring.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
typedef ::cppu::WeakImplHelper1< XInvocation > DocObjectWrapper_BASE;
typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap;
::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar );
void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue );
class DocObjectWrapper : public DocObjectWrapper_BASE
{
Reference< XAggregation > m_xAggProxy;
Reference< XInvocation > m_xAggInv;
Reference< XTypeProvider > m_xAggregateTypeProv;
Sequence< Type > m_Types;
SbModule* m_pMod;
SbMethodRef getMethod( const rtl::OUString& aName ) throw (RuntimeException);
SbPropertyRef getProperty( const rtl::OUString& aName ) throw (RuntimeException);
String mName; // for debugging
public:
DocObjectWrapper( SbModule* pMod );
~DocObjectWrapper();
virtual void SAL_CALL acquire() throw();
virtual void SAL_CALL release() throw();
virtual Sequence< sal_Int8 > SAL_CALL getImplementationId()
throw ( com::sun::star::uno::RuntimeException )
{
return m_xAggregateTypeProv->getImplementationId();
}
virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection( ) throw (RuntimeException);
virtual Any SAL_CALL invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException);
virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException);
virtual Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException);
virtual ::sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException);
virtual ::sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException);
virtual Any SAL_CALL queryInterface( const Type& aType ) throw ( RuntimeException );
virtual Sequence< Type > SAL_CALL getTypes() throw ( RuntimeException );
};
DocObjectWrapper::DocObjectWrapper( SbModule* pVar ) : m_pMod( pVar ), mName( pVar->GetName() )
{
SbObjModule* pMod = PTR_CAST(SbObjModule,pVar);
if ( pMod )
{
sal_Int16 nType = pMod->GetModuleType();
if ( pMod->GetModuleType() == ModuleType::DOCUMENT )
{
Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
// Use proxy factory service to create aggregatable proxy.
SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pMod->GetObject() );
Reference< XInterface > xIf;
if ( pUnoObj )
{
Any aObj = pUnoObj->getUnoAny();
aObj >>= xIf;
if ( xIf.is() )
{
m_xAggregateTypeProv.set( xIf, UNO_QUERY );
m_xAggInv.set( xIf, UNO_QUERY );
}
}
if ( xIf.is() )
{
try
{
Reference< XMultiComponentFactory > xMFac( xFactory, UNO_QUERY_THROW );
Reference< XPropertySet> xPSMPropertySet( xMFac, UNO_QUERY_THROW );
Reference< XComponentContext > xCtx;
xPSMPropertySet->getPropertyValue(
String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xCtx;
Reference< XProxyFactory > xProxyFac( xMFac->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ), xCtx ), UNO_QUERY_THROW );
m_xAggProxy = xProxyFac->createProxy( xIf );
}
catch( Exception& )
{
OSL_ENSURE( false, "DocObjectWrapper::DocObjectWrapper: Caught exception!" );
}
}
if ( m_xAggProxy.is() )
{
osl_incrementInterlockedCount( &m_refCount );
/* i35609 - Fix crash on Solaris. The setDelegator call needs
to be in its own block to ensure that all temporary Reference
instances that are acquired during the call are released
before m_refCount is decremented again */
{
m_xAggProxy->setDelegator( static_cast< cppu::OWeakObject * >( this ) );
}
osl_decrementInterlockedCount( &m_refCount );
}
}
}
}
void SAL_CALL
DocObjectWrapper::acquire() throw ()
{
osl_incrementInterlockedCount( &m_refCount );
OSL_TRACE("DocObjectWrapper::acquire(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
}
void SAL_CALL
DocObjectWrapper::release() throw ()
{
if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
{
OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
delete this;
}
else
OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
}
DocObjectWrapper::~DocObjectWrapper()
{
}
Sequence< Type > SAL_CALL DocObjectWrapper::getTypes()
throw ( RuntimeException )
{
if ( m_Types.getLength() == 0 )
{
Sequence< Type > sTypes;
if ( m_xAggregateTypeProv.is() )
sTypes = m_xAggregateTypeProv->getTypes();
m_Types.realloc( sTypes.getLength() + 1 );
Type* pPtr = m_Types.getArray();
for ( int i=0; i<m_Types.getLength(); ++i, ++pPtr )
{
if ( i == 0 )
*pPtr = XInvocation::static_type( NULL );
else
*pPtr = sTypes[ i - 1 ];
}
}
return m_Types;
}
Reference< XIntrospectionAccess > SAL_CALL
DocObjectWrapper::getIntrospection( ) throw (RuntimeException)
{
return NULL;
}
Any SAL_CALL
DocObjectWrapper::invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException)
{
if ( m_xAggInv.is() && m_xAggInv->hasMethod( aFunctionName ) )
return m_xAggInv->invoke( aFunctionName, aParams, aOutParamIndex, aOutParam );
SbMethodRef pMethod = getMethod( aFunctionName );
if ( !pMethod )
throw RuntimeException();
// check number of parameters
sal_Int32 nParamsCount = aParams.getLength();
SbxInfo* pInfo = pMethod->GetInfo();
if ( pInfo )
{
sal_Int32 nSbxOptional = 0;
USHORT n = 1;
for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) )
{
if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 )
++nSbxOptional;
else
nSbxOptional = 0;
}
sal_Int32 nSbxCount = n - 1;
if ( nParamsCount < nSbxCount - nSbxOptional )
{
throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "wrong number of parameters!" ) ), Reference< XInterface >() );
}
}
// set parameters
SbxArrayRef xSbxParams;
if ( nParamsCount > 0 )
{
xSbxParams = new SbxArray;
const Any* pParams = aParams.getConstArray();
for ( sal_Int32 i = 0; i < nParamsCount; ++i )
{
SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] );
xSbxParams->Put( xSbxVar, static_cast< USHORT >( i ) + 1 );
// Enable passing by ref
if ( xSbxVar->GetType() != SbxVARIANT )
xSbxVar->SetFlag( SBX_FIXED );
}
}
if ( xSbxParams.Is() )
pMethod->SetParameters( xSbxParams );
// call method
SbxVariableRef xReturn = new SbxVariable;
ErrCode nErr = SbxERR_OK;
nErr = pMethod->Call( xReturn );
Any aReturn;
// get output parameters
if ( xSbxParams.Is() )
{
SbxInfo* pInfo_ = pMethod->GetInfo();
if ( pInfo_ )
{
OutParamMap aOutParamMap;
for ( USHORT n = 1, nCount = xSbxParams->Count(); n < nCount; ++n )
{
const SbxParamInfo* pParamInfo = pInfo_->GetParam( n );
if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 )
{
SbxVariable* pVar = xSbxParams->Get( n );
if ( pVar )
{
SbxVariableRef xVar = pVar;
aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) );
}
}
}
sal_Int32 nOutParamCount = aOutParamMap.size();
aOutParamIndex.realloc( nOutParamCount );
aOutParam.realloc( nOutParamCount );
sal_Int16* pOutParamIndex = aOutParamIndex.getArray();
Any* pOutParam = aOutParam.getArray();
for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam )
{
*pOutParamIndex = aIt->first;
*pOutParam = aIt->second;
}
}
}
// get return value
aReturn = sbxToUnoValue( xReturn );
pMethod->SetParameters( NULL );
return aReturn;
}
void SAL_CALL
DocObjectWrapper::setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException)
{
if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) )
return m_xAggInv->setValue( aPropertyName, aValue );
SbPropertyRef pProperty = getProperty( aPropertyName );
if ( !pProperty.Is() )
throw UnknownPropertyException();
unoToSbxValue( (SbxVariable*) pProperty, aValue );
}
Any SAL_CALL
DocObjectWrapper::getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException)
{
if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) )
return m_xAggInv->getValue( aPropertyName );
SbPropertyRef pProperty = getProperty( aPropertyName );
if ( !pProperty.Is() )
throw UnknownPropertyException();
SbxVariable* pProp = ( SbxVariable* ) pProperty;
if ( pProp->GetType() == SbxEMPTY )
pProperty->Broadcast( SBX_HINT_DATAWANTED );
Any aRet = sbxToUnoValue( pProp );
return aRet;
}
::sal_Bool SAL_CALL
DocObjectWrapper::hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException)
{
if ( m_xAggInv.is() && m_xAggInv->hasMethod( aName ) )
return sal_True;
return getMethod( aName ).Is();
}
::sal_Bool SAL_CALL
DocObjectWrapper::hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException)
{
sal_Bool bRes = sal_False;
if ( m_xAggInv.is() && m_xAggInv->hasProperty( aName ) )
bRes = sal_True;
else bRes = getProperty( aName ).Is();
return bRes;
}
Any SAL_CALL DocObjectWrapper::queryInterface( const Type& aType )
throw ( RuntimeException )
{
Any aRet = DocObjectWrapper_BASE::queryInterface( aType );
if ( aRet.hasValue() )
return aRet;
else if ( m_xAggProxy.is() )
aRet = m_xAggProxy->queryAggregation( aType );
return aRet;
}
SbMethodRef DocObjectWrapper::getMethod( const rtl::OUString& aName ) throw (RuntimeException)
{
SbMethodRef pMethod = NULL;
if ( m_pMod )
{
USHORT nSaveFlgs = m_pMod->GetFlags();
// Limit search to this module
m_pMod->ResetFlag( SBX_GBLSEARCH );
pMethod = (SbMethod*) m_pMod->SbModule::Find( aName, SbxCLASS_METHOD );
m_pMod->SetFlags( nSaveFlgs );
}
return pMethod;
}
SbPropertyRef DocObjectWrapper::getProperty( const rtl::OUString& aName ) throw (RuntimeException)
{
SbPropertyRef pProperty = NULL;
if ( m_pMod )
{
USHORT nSaveFlgs = m_pMod->GetFlags();
// Limit search to this module.
m_pMod->ResetFlag( SBX_GBLSEARCH );
pProperty = (SbProperty*)m_pMod->SbModule::Find( aName, SbxCLASS_PROPERTY );
m_pMod->SetFlag( nSaveFlgs );
}
return pProperty;
}
TYPEINIT1(SbModule,SbxObject)
TYPEINIT1(SbMethod,SbxMethod)
@ -199,12 +546,24 @@ SbModule::SbModule( const String& rName, BOOL bVBACompat )
SbModule::~SbModule()
{
OSL_TRACE("Module named %s is destructing", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
if( pImage )
delete pImage;
if( pBreaks )
delete pBreaks;
if( pClassData )
delete pClassData;
mxWrapper = NULL;
}
uno::Reference< script::XInvocation >
SbModule::GetUnoModule()
{
if ( !mxWrapper.is() )
mxWrapper = new DocObjectWrapper( this );
OSL_TRACE("Module named %s returning wrapper mxWrapper (0x%x)", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mxWrapper.get() );
return mxWrapper;
}
BOOL SbModule::IsCompiled() const

View file

@ -133,11 +133,12 @@ protected:
class VBAHELPER_DLLPUBLIC EnumerationHelperImpl : public EnumerationHelper_BASE
{
protected:
css::uno::WeakReference< ov::XHelperInterface > m_xParent;
css::uno::Reference< css::uno::XComponentContext > m_xContext;
css::uno::Reference< css::container::XEnumeration > m_xEnumeration;
public:
EnumerationHelperImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XEnumeration >& xEnumeration ) throw ( css::uno::RuntimeException ) : m_xContext( xContext ), m_xEnumeration( xEnumeration ) { }
EnumerationHelperImpl( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XEnumeration >& xEnumeration ) throw ( css::uno::RuntimeException ) : m_xParent( xParent ), m_xContext( xContext ), m_xEnumeration( xEnumeration ) { }
virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (css::uno::RuntimeException) { return m_xEnumeration->hasMoreElements(); }
};

View file

@ -63,6 +63,7 @@ namespace ooo
throw css::lang::IllegalArgumentException();
return aSomething;
}
VBAHELPER_DLLPUBLIC css::uno::Reference< css::uno::XInterface > getUnoDocModule( const String& aModName, SfxObjectShell* pShell );
VBAHELPER_DLLPUBLIC SfxObjectShell* getSfxObjShell( const css::uno::Reference< css::frame::XModel >& xModel ) throw ( css::uno::RuntimeException);
VBAHELPER_DLLPUBLIC css::uno::Reference< css::uno::XInterface > createVBAUnoAPIService( SfxObjectShell* pShell, const sal_Char* _pAsciiName ) throw (css::uno::RuntimeException);

View file

@ -35,6 +35,9 @@ using namespace ooo::vba;
rtl::OUString sApplication( RTL_CONSTASCII_USTRINGPARAM("Application") );
// special key to return the Application
rtl::OUString sAppService( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.Application") );
VbaGlobalsBase::VbaGlobalsBase(
const uno::Reference< ov::XHelperInterface >& xParent,
const uno::Reference< uno::XComponentContext >& xContext, const rtl::OUString& sDocCtxName )
@ -74,19 +77,30 @@ uno::Reference< uno::XInterface > SAL_CALL
VbaGlobalsBase::createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (uno::Exception, uno::RuntimeException)
{
uno::Reference< uno::XInterface > xReturn;
if ( hasServiceName( aServiceSpecifier ) )
if ( aServiceSpecifier.equals( sAppService ) )
{
// try to extract the Application from the context
uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY );
xNameContainer->getByName( sApplication ) >>= xReturn;
}
else if ( hasServiceName( aServiceSpecifier ) )
xReturn = mxContext->getServiceManager()->createInstanceWithContext( aServiceSpecifier, mxContext );
return xReturn;
}
uno::Reference< uno::XInterface > SAL_CALL
VbaGlobalsBase::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments ) throw (uno::Exception, uno::RuntimeException)
VbaGlobalsBase::createInstanceWithArguments( const ::rtl::OUString& aServiceSpecifier, const uno::Sequence< uno::Any >& Arguments ) throw (uno::Exception, uno::RuntimeException)
{
uno::Reference< uno::XInterface > xReturn;
if ( hasServiceName( ServiceSpecifier ) )
xReturn = mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( ServiceSpecifier, Arguments, mxContext );
if ( aServiceSpecifier.equals( sAppService ) )
{
// try to extract the Application from the context
uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY );
xNameContainer->getByName( sApplication ) >>= xReturn;
}
else if ( hasServiceName( aServiceSpecifier ) )
xReturn = mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( aServiceSpecifier, Arguments, mxContext );
return xReturn;
}

View file

@ -1404,6 +1404,26 @@ void UserFormGeometryHelper::setHeight( double nHeight )
return points;
}
uno::Reference< uno::XInterface > getUnoDocModule( const String& aModName, SfxObjectShell* pShell )
{
uno::Reference< uno::XInterface > xIf;
if ( pShell )
{
rtl::OUString sProj( RTL_CONSTASCII_USTRINGPARAM("Standard") );
BasicManager* pBasMgr = pShell->GetBasicManager();
if ( pBasMgr && pBasMgr->GetName().Len() )
sProj = pShell->GetBasicManager()->GetName();
StarBASIC* pBasic = pShell->GetBasicManager()->GetLib( sProj );
if ( pBasic )
{
SbModule* pMod = pBasic->FindModule( aModName );
if ( pMod )
xIf = pMod->GetUnoModule();
}
}
return xIf;
}
SfxObjectShell* getSfxObjShell( const uno::Reference< frame::XModel >& xModel ) throw (uno::RuntimeException)
{
SfxObjectShell* pFoundShell = NULL;