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 { 114 // TODO: throw CannotConvertException 115 // TODO: check length of aOutParamIndex, aOutParam 116 117 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 118 119 Any aReturn; 120 121 if ( m_xMethod ) 122 { 123 // check if compiled 124 SbModule* pModule = static_cast< SbModule* >( m_xMethod->GetParent() ); 125 if ( pModule && !pModule->IsCompiled() ) 126 pModule->Compile(); 127 128 // check number of parameters 129 sal_Int32 nParamsCount = aParams.getLength(); 130 SbxInfo* pInfo = m_xMethod->GetInfo(); 131 if ( pInfo ) 132 { 133 sal_Int32 nSbxOptional = 0; 134 sal_uInt16 n = 1; 135 for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) ) 136 { 137 if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 ) 138 ++nSbxOptional; 139 else 140 nSbxOptional = 0; 141 } 142 sal_Int32 nSbxCount = n - 1; 143 if ( nParamsCount < nSbxCount - nSbxOptional ) 144 { 145 throw provider::ScriptFrameworkErrorException( 146 ::rtl::OUString( 147 RTL_CONSTASCII_USTRINGPARAM( 148 "wrong number of parameters!" ) ), 149 Reference< XInterface >(), 150 m_funcName, 151 ::rtl::OUString( 152 RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ), 153 provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); 154 } 155 } 156 157 // set parameters 158 SbxArrayRef xSbxParams; 159 if ( nParamsCount > 0 ) 160 { 161 xSbxParams = new SbxArray; 162 const Any* pParams = aParams.getConstArray(); 163 for ( sal_Int32 i = 0; i < nParamsCount; ++i ) 164 { 165 SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); 166 unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] ); 167 xSbxParams->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 ); 168 169 // Enable passing by ref 170 if ( xSbxVar->GetType() != SbxVARIANT ) 171 xSbxVar->SetFlag( SBX_FIXED ); 172 } 173 } 174 if ( xSbxParams.Is() ) 175 m_xMethod->SetParameters( xSbxParams ); 176 177 // call method 178 SbxVariableRef xReturn = new SbxVariable; 179 ErrCode nErr = SbxERR_OK; 180 { 181 // if it's a document-based script, temporarily reset ThisComponent to the script invocation context 182 Any aOldThisComponent; 183 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 184 aOldThisComponent = m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( m_xDocumentScriptContext ) ); 185 186 nErr = m_xMethod->Call( xReturn ); 187 188 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 189 m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); 190 } 191 if ( nErr != SbxERR_OK ) 192 { 193 // TODO: throw InvocationTargetException ? 194 } 195 196 // get output parameters 197 if ( xSbxParams.Is() ) 198 { 199 SbxInfo* pInfo_ = m_xMethod->GetInfo(); 200 if ( pInfo_ ) 201 { 202 OutParamMap aOutParamMap; 203 for ( sal_uInt16 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n ) 204 { 205 const SbxParamInfo* pParamInfo = pInfo_->GetParam( n ); 206 if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 ) 207 { 208 SbxVariable* pVar = xSbxParams->Get( n ); 209 if ( pVar ) 210 { 211 SbxVariableRef xVar = pVar; 212 aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) ); 213 } 214 } 215 } 216 sal_Int32 nOutParamCount = aOutParamMap.size(); 217 aOutParamIndex.realloc( nOutParamCount ); 218 aOutParam.realloc( nOutParamCount ); 219 sal_Int16* pOutParamIndex = aOutParamIndex.getArray(); 220 Any* pOutParam = aOutParam.getArray(); 221 for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam ) 222 { 223 *pOutParamIndex = aIt->first; 224 *pOutParam = aIt->second; 225 } 226 } 227 } 228 229 // get return value 230 aReturn = sbxToUnoValue( xReturn ); 231 232 // reset parameters 233 m_xMethod->SetParameters( NULL ); 234 } 235 236 return aReturn; 237 } 238 239 // ----------------------------------------------------------------------------- 240 241 //......................................................................... 242 } // namespace basprov 243 //......................................................................... 244