1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_scripting.hxx" 30 #include "basscript.hxx" 31 #include <vos/mutex.hxx> 32 #include <vcl/svapp.hxx> 33 #include <basic/sbx.hxx> 34 #include <basic/sbstar.hxx> 35 #include <basic/sbmod.hxx> 36 #include <basic/sbmeth.hxx> 37 #include <basic/basmgr.hxx> 38 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp> 39 40 #include <map> 41 42 43 using namespace ::com::sun::star; 44 using namespace ::com::sun::star::lang; 45 using namespace ::com::sun::star::uno; 46 using namespace ::com::sun::star::script; 47 using namespace ::com::sun::star::document; 48 49 extern ::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar ); 50 extern void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue ); 51 52 53 //......................................................................... 54 namespace basprov 55 { 56 //......................................................................... 57 58 typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap; 59 60 // ============================================================================= 61 // BasicScriptImpl 62 // ============================================================================= 63 64 // ----------------------------------------------------------------------------- 65 66 BasicScriptImpl::BasicScriptImpl( const ::rtl::OUString& funcName, SbMethodRef xMethod ) 67 :m_xMethod( xMethod ) 68 ,m_funcName( funcName ) 69 ,m_documentBasicManager( NULL ) 70 ,m_xDocumentScriptContext() 71 { 72 } 73 74 // ----------------------------------------------------------------------------- 75 76 BasicScriptImpl::BasicScriptImpl( const ::rtl::OUString& funcName, SbMethodRef xMethod, 77 BasicManager& documentBasicManager, const Reference< XScriptInvocationContext >& documentScriptContext ) 78 :m_xMethod( xMethod ) 79 ,m_funcName( funcName ) 80 ,m_documentBasicManager( &documentBasicManager ) 81 ,m_xDocumentScriptContext( documentScriptContext ) 82 { 83 StartListening( *m_documentBasicManager ); 84 } 85 86 // ----------------------------------------------------------------------------- 87 BasicScriptImpl::~BasicScriptImpl() 88 { 89 if ( m_documentBasicManager ) 90 EndListening( *m_documentBasicManager ); 91 } 92 93 // ----------------------------------------------------------------------------- 94 // SfxListener 95 // ----------------------------------------------------------------------------- 96 void BasicScriptImpl::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 97 { 98 if ( &rBC != m_documentBasicManager ) 99 { 100 OSL_ENSURE( false, "BasicScriptImpl::Notify: where does this come from?" ); 101 // not interested in 102 return; 103 } 104 const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint ); 105 if ( pSimpleHint && ( pSimpleHint->GetId() == SFX_HINT_DYING ) ) 106 { 107 m_documentBasicManager = NULL; 108 EndListening( rBC ); // prevent multiple notifications 109 } 110 } 111 112 // ----------------------------------------------------------------------------- 113 // XScript 114 // ----------------------------------------------------------------------------- 115 116 Any BasicScriptImpl::invoke( const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) 117 throw ( provider::ScriptFrameworkErrorException, reflection::InvocationTargetException, uno::RuntimeException) 118 { 119 // TODO: throw CannotConvertException 120 // TODO: check length of aOutParamIndex, aOutParam 121 122 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 123 124 Any aReturn; 125 126 if ( m_xMethod ) 127 { 128 // check if compiled 129 SbModule* pModule = static_cast< SbModule* >( m_xMethod->GetParent() ); 130 if ( pModule && !pModule->IsCompiled() ) 131 pModule->Compile(); 132 133 // check number of parameters 134 sal_Int32 nParamsCount = aParams.getLength(); 135 SbxInfo* pInfo = m_xMethod->GetInfo(); 136 if ( pInfo ) 137 { 138 sal_Int32 nSbxOptional = 0; 139 sal_uInt16 n = 1; 140 for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) ) 141 { 142 if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 ) 143 ++nSbxOptional; 144 else 145 nSbxOptional = 0; 146 } 147 sal_Int32 nSbxCount = n - 1; 148 if ( nParamsCount < nSbxCount - nSbxOptional ) 149 { 150 throw provider::ScriptFrameworkErrorException( 151 ::rtl::OUString( 152 RTL_CONSTASCII_USTRINGPARAM( 153 "wrong number of parameters!" ) ), 154 Reference< XInterface >(), 155 m_funcName, 156 ::rtl::OUString( 157 RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ), 158 provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); 159 } 160 } 161 162 // set parameters 163 SbxArrayRef xSbxParams; 164 if ( nParamsCount > 0 ) 165 { 166 xSbxParams = new SbxArray; 167 const Any* pParams = aParams.getConstArray(); 168 for ( sal_Int32 i = 0; i < nParamsCount; ++i ) 169 { 170 SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); 171 unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] ); 172 xSbxParams->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 ); 173 174 // Enable passing by ref 175 if ( xSbxVar->GetType() != SbxVARIANT ) 176 xSbxVar->SetFlag( SBX_FIXED ); 177 } 178 } 179 if ( xSbxParams.Is() ) 180 m_xMethod->SetParameters( xSbxParams ); 181 182 // call method 183 SbxVariableRef xReturn = new SbxVariable; 184 ErrCode nErr = SbxERR_OK; 185 { 186 // if it's a document-based script, temporarily reset ThisComponent to the script invocation context 187 Any aOldThisComponent; 188 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 189 aOldThisComponent = m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( m_xDocumentScriptContext ) ); 190 191 nErr = m_xMethod->Call( xReturn ); 192 193 if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) 194 m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); 195 } 196 if ( nErr != SbxERR_OK ) 197 { 198 // TODO: throw InvocationTargetException ? 199 } 200 201 // get output parameters 202 if ( xSbxParams.Is() ) 203 { 204 SbxInfo* pInfo_ = m_xMethod->GetInfo(); 205 if ( pInfo_ ) 206 { 207 OutParamMap aOutParamMap; 208 for ( sal_uInt16 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n ) 209 { 210 const SbxParamInfo* pParamInfo = pInfo_->GetParam( n ); 211 if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 ) 212 { 213 SbxVariable* pVar = xSbxParams->Get( n ); 214 if ( pVar ) 215 { 216 SbxVariableRef xVar = pVar; 217 aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) ); 218 } 219 } 220 } 221 sal_Int32 nOutParamCount = aOutParamMap.size(); 222 aOutParamIndex.realloc( nOutParamCount ); 223 aOutParam.realloc( nOutParamCount ); 224 sal_Int16* pOutParamIndex = aOutParamIndex.getArray(); 225 Any* pOutParam = aOutParam.getArray(); 226 for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam ) 227 { 228 *pOutParamIndex = aIt->first; 229 *pOutParam = aIt->second; 230 } 231 } 232 } 233 234 // get return value 235 aReturn = sbxToUnoValue( xReturn ); 236 237 // reset parameters 238 m_xMethod->SetParameters( NULL ); 239 } 240 241 return aReturn; 242 } 243 244 // ----------------------------------------------------------------------------- 245 246 //......................................................................... 247 } // namespace basprov 248 //......................................................................... 249