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_scripting.hxx" 26 #include "basscript.hxx" 27 #include <vos/mutex.hxx> 28 #include <vcl/svapp.hxx> 29 #include <basic/sbx.hxx> 30 #include <basic/sbstar.hxx> 31 #include <basic/sbmod.hxx> 32 #include <basic/sbmeth.hxx> 33 #include <basic/basmgr.hxx> 34 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp> 35 36 #include <map> 37 38 39 using namespace ::com::sun::star; 40 using namespace ::com::sun::star::lang; 41 using namespace ::com::sun::star::uno; 42 using namespace ::com::sun::star::script; 43 using namespace ::com::sun::star::document; 44 45 extern ::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar ); 46 extern void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue ); 47 48 49 //......................................................................... 50 namespace basprov 51 { 52 //......................................................................... 53 54 typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap; 55 56 // ============================================================================= 57 // BasicScriptImpl 58 // ============================================================================= 59 60 // ----------------------------------------------------------------------------- 61 BasicScriptImpl(const::rtl::OUString & funcName,SbMethodRef xMethod)62 BasicScriptImpl::BasicScriptImpl( const ::rtl::OUString& funcName, SbMethodRef xMethod ) 63 :m_xMethod( xMethod ) 64 ,m_funcName( funcName ) 65 ,m_documentBasicManager( NULL ) 66 ,m_xDocumentScriptContext() 67 { 68 } 69 70 // ----------------------------------------------------------------------------- 71 BasicScriptImpl(const::rtl::OUString & funcName,SbMethodRef xMethod,BasicManager & documentBasicManager,const Reference<XScriptInvocationContext> & documentScriptContext)72 BasicScriptImpl::BasicScriptImpl( const ::rtl::OUString& funcName, SbMethodRef xMethod, 73 BasicManager& documentBasicManager, const Reference< XScriptInvocationContext >& documentScriptContext ) 74 :m_xMethod( xMethod ) 75 ,m_funcName( funcName ) 76 ,m_documentBasicManager( &documentBasicManager ) 77 ,m_xDocumentScriptContext( documentScriptContext ) 78 { 79 StartListening( *m_documentBasicManager ); 80 } 81 82 // ----------------------------------------------------------------------------- ~BasicScriptImpl()83 BasicScriptImpl::~BasicScriptImpl() 84 { 85 if ( m_documentBasicManager ) 86 EndListening( *m_documentBasicManager ); 87 } 88 89 // ----------------------------------------------------------------------------- 90 // SfxListener 91 // ----------------------------------------------------------------------------- Notify(SfxBroadcaster & rBC,const SfxHint & rHint)92 void BasicScriptImpl::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 93 { 94 if ( &rBC != m_documentBasicManager ) 95 { 96 OSL_ENSURE( false, "BasicScriptImpl::Notify: where does this come from?" ); 97 // not interested in 98 return; 99 } 100 const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint ); 101 if ( pSimpleHint && ( pSimpleHint->GetId() == SFX_HINT_DYING ) ) 102 { 103 m_documentBasicManager = NULL; 104 EndListening( rBC ); // prevent multiple notifications 105 } 106 } 107 108 // ----------------------------------------------------------------------------- 109 // XScript 110 // ----------------------------------------------------------------------------- 111 invoke(const Sequence<Any> & aParams,Sequence<sal_Int16> & aOutParamIndex,Sequence<Any> & aOutParam)112 Any BasicScriptImpl::invoke( const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) 113 throw ( provider::ScriptFrameworkErrorException, reflection::InvocationTargetException, uno::RuntimeException) 114 { 115 // TODO: throw CannotConvertException 116 // TODO: check length of aOutParamIndex, aOutParam 117 118 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 119 120 Any aReturn; 121 122 if ( m_xMethod ) 123 { 124 // check if compiled 125 SbModule* pModule = static_cast< SbModule* >( m_xMethod->GetParent() ); 126 if ( pModule && !pModule->IsCompiled() ) 127 pModule->Compile(); 128 129 // check number of parameters 130 sal_Int32 nParamsCount = aParams.getLength(); 131 SbxInfo* pInfo = m_xMethod->GetInfo(); 132 if ( pInfo ) 133 { 134 sal_Int32 nSbxOptional = 0; 135 sal_uInt16 n = 1; 136 for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) ) 137 { 138 if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 ) 139 ++nSbxOptional; 140 else 141 nSbxOptional = 0; 142 } 143 sal_Int32 nSbxCount = n - 1; 144 if ( nParamsCount < nSbxCount - nSbxOptional ) 145 { 146 throw provider::ScriptFrameworkErrorException( 147 ::rtl::OUString( 148 RTL_CONSTASCII_USTRINGPARAM( 149 "wrong number of parameters!" ) ), 150 Reference< XInterface >(), 151 m_funcName, 152 ::rtl::OUString( 153 RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ), 154 provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); 155 } 156 } 157 158 // set parameters 159 SbxArrayRef xSbxParams; 160 if ( nParamsCount > 0 ) 161 { 162 xSbxParams = new SbxArray; 163 const Any* pParams = aParams.getConstArray(); 164 for ( sal_Int32 i = 0; i < nParamsCount; ++i ) 165 { 166 SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); 167 unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] ); 168 xSbxParams->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 ); 169 170 // Enable passing by ref 171 if ( xSbxVar->GetType() != SbxVARIANT ) 172 xSbxVar->SetFlag( SBX_FIXED ); 173 } 174 } 175 if ( xSbxParams.Is() ) 176 m_xMethod->SetParameters( xSbxParams ); 177 178 // call method 179 SbxVariableRef xReturn = new SbxVariable; 180 ErrCode nErr = SbxERR_OK; 181 { 182 // if it's a document-based script, temporarily reset ThisComponent to the script invocation context 183 Any aOldThisComponent; 184 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 185 aOldThisComponent = m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( m_xDocumentScriptContext ) ); 186 187 nErr = m_xMethod->Call( xReturn ); 188 189 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 190 m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); 191 } 192 if ( nErr != SbxERR_OK ) 193 { 194 // TODO: throw InvocationTargetException ? 195 } 196 197 // get output parameters 198 if ( xSbxParams.Is() ) 199 { 200 SbxInfo* pInfo_ = m_xMethod->GetInfo(); 201 if ( pInfo_ ) 202 { 203 OutParamMap aOutParamMap; 204 for ( sal_uInt16 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n ) 205 { 206 const SbxParamInfo* pParamInfo = pInfo_->GetParam( n ); 207 if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 ) 208 { 209 SbxVariable* pVar = xSbxParams->Get( n ); 210 if ( pVar ) 211 { 212 SbxVariableRef xVar = pVar; 213 aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) ); 214 } 215 } 216 } 217 sal_Int32 nOutParamCount = aOutParamMap.size(); 218 aOutParamIndex.realloc( nOutParamCount ); 219 aOutParam.realloc( nOutParamCount ); 220 sal_Int16* pOutParamIndex = aOutParamIndex.getArray(); 221 Any* pOutParam = aOutParam.getArray(); 222 for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam ) 223 { 224 *pOutParamIndex = aIt->first; 225 *pOutParam = aIt->second; 226 } 227 } 228 } 229 230 // get return value 231 aReturn = sbxToUnoValue( xReturn ); 232 233 // reset parameters 234 m_xMethod->SetParameters( NULL ); 235 } 236 237 return aReturn; 238 } 239 240 // ----------------------------------------------------------------------------- 241 242 //......................................................................... 243 } // namespace basprov 244 //......................................................................... 245