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_extensions.hxx" 26 #include <stdio.h> 27 #include <stardiv/uno/repos/implementationregistration.hxx> 28 #include <stardiv/uno/script/script.hxx> 29 #include <stardiv/uno/beans/exactname.hxx> 30 31 #include <rtl/ustring.hxx> 32 #include <vos/dynload.hxx> 33 #include <vos/diagnose.hxx> 34 #include <usr/services.hxx> 35 #include <vcl/svapp.hxx> 36 #include <usr/ustring.hxx> 37 #include <usr/weak.hxx> 38 #include <tools/string.hxx> 39 #include <vos/conditn.hxx> 40 41 using namespace rtl; 42 using namespace vos; 43 using namespace usr; 44 45 #define PCHAR_TO_USTRING(x) StringToOUString(String(x),CHARSET_SYSTEM) 46 #define USTRING_TO_PCHAR(x) OUStringToString(x , CHARSET_DONTKNOW ).GetCharStr() 47 48 49 50 51 52 /***** 53 * 54 * A Test root object ! 55 * 56 *****/ 57 class MyPythonRoot : 58 public XInvokation, 59 public OWeakObject 60 { 61 public: 62 MyPythonRoot() { m_iTestValue = 15; } 63 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); 64 void acquire() { OWeakObject::acquire(); } 65 void release() { OWeakObject::release(); } 66 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } 67 68 public: 69 XIntrospectionAccessRef getIntrospection(void) const THROWS( (UsrSystemException) ) 70 { return XIntrospectionAccessRef(); } 71 72 UsrAny invoke( const UString& FunctionName, 73 const Sequence< UsrAny >& Params, 74 Sequence< INT16 >& OutParamIndex, 75 Sequence< UsrAny >& OutParam) 76 THROWS( ( IllegalArgumentException, 77 CannotConvertException, 78 InvocationTargetException, 79 UsrSystemException) ); 80 void setValue(const UString& PropertyName, const UsrAny& Value) 81 THROWS( ( UnknownPropertyException, 82 CannotConvertException, 83 InvocationTargetException, 84 UsrSystemException) ); 85 86 UsrAny getValue(const UString& PropertyName) 87 THROWS( ( UnknownPropertyException, 88 UsrSystemException) ); 89 BOOL hasMethod(const UString& Name) const THROWS( (UsrSystemException) ); 90 BOOL hasProperty(const UString& Name) const THROWS( (UsrSystemException) ); 91 92 93 void getTestValueViaInout( int &inout ) 94 { inout = m_iTestValue; } 95 96 INT32 getTestValue() const 97 { return m_iTestValue; } 98 99 void setTestValue( INT32 i ) 100 { m_iTestValue = i; } 101 102 void printTestValue() 103 { fprintf( stderr, "TestValue : %d\n" , getTestValue() ); } 104 105 void addTestValue( INT32 i ) 106 { m_iTestValue += i; } 107 108 private: 109 110 INT32 m_iTestValue; 111 }; 112 113 BOOL MyPythonRoot::queryInterface( Uik aUik, XInterfaceRef &rOut ) 114 { 115 if( aUik == XInvokation::getSmartUik() ) { 116 rOut = ( XInvokation * ) this; 117 } 118 else { 119 return OWeakObject::queryInterface( aUik , rOut ); 120 } 121 return TRUE; 122 123 } 124 125 UsrAny MyPythonRoot::invoke( const UString& FunctionName, 126 const Sequence< UsrAny >& Params, 127 Sequence< INT16 >& OutParamIndex, 128 Sequence< UsrAny >& OutParam) 129 THROWS( ( IllegalArgumentException, 130 CannotConvertException, 131 InvocationTargetException, 132 UsrSystemException) ) 133 { 134 if( L"printTestValue" == FunctionName ) { 135 printTestValue(); 136 } 137 else if( L"addTestValue" == FunctionName ) { 138 addTestValue( Params.getConstArray()[0].getINT32() ); 139 } 140 else if( L"getTestValueViaInout" == FunctionName ) { 141 int i = Params.getConstArray()[0].getINT32(); 142 getTestValueViaInout( i ); 143 OutParam.getArray()[0].setINT32( i ); 144 } 145 else { 146 THROW( InvocationTargetException() ); 147 } 148 149 return UsrAny(); 150 } 151 152 void MyPythonRoot::setValue(const UString& PropertyName, const UsrAny& Value) 153 THROWS( ( UnknownPropertyException, 154 CannotConvertException, 155 InvocationTargetException, 156 UsrSystemException) ) 157 { 158 if( L"TestValue" == PropertyName ) { 159 setTestValue( Value.getINT32() ); 160 } 161 else { 162 THROW( UnknownPropertyException() ); 163 } 164 } 165 166 UsrAny MyPythonRoot::getValue(const UString& PropertyName) 167 THROWS( ( UnknownPropertyException, 168 UsrSystemException) ) 169 { 170 UsrAny aRet; 171 172 if( L"TestValue" == PropertyName ) { 173 aRet.setINT32( getTestValue() ); 174 } 175 else { 176 THROW( UnknownPropertyException() ); 177 } 178 179 return aRet; 180 } 181 182 183 BOOL MyPythonRoot::hasMethod(const UString& Name) const THROWS( (UsrSystemException) ) 184 { 185 if( L"printTestValue" == Name ) { 186 return TRUE; 187 } 188 else if( L"addTestValue" == Name ) { 189 return TRUE; 190 } 191 else if( L"getTestValueViaInout" == Name ) { 192 return TRUE; 193 } 194 return FALSE; 195 } 196 197 198 BOOL MyPythonRoot::hasProperty(const UString& Name) const THROWS( (UsrSystemException) ) 199 { 200 if( L"TestValue" == Name ) { 201 return TRUE; 202 } 203 204 return FALSE; 205 } 206 207 208 /***** 209 * 210 * A test engine listener to check the debug interface 211 * 212 *****/ 213 class TestListener : 214 public XEngineListener, 215 public OWeakObject 216 { 217 public: 218 219 TestListener() 220 { 221 m_pDebuggingRef = 0; 222 } 223 224 225 TestListener( XDebuggingRef *p ) 226 { 227 attach( p ); 228 } 229 230 ~TestListener() 231 { 232 if( m_pDebuggingRef ) { 233 detach(); 234 } 235 } 236 237 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); 238 void acquire() { OWeakObject::acquire(); } 239 void release() { OWeakObject::release(); } 240 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } 241 242 243 void attach( XDebuggingRef *p ) 244 { 245 m_pDebuggingRef = p; 246 } 247 248 void detach( ); 249 250 251 virtual void disposing( const EventObject &o ) 252 { 253 if( m_pDebuggingRef ) { 254 detach(); 255 } 256 } 257 virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) ) 258 { 259 } 260 261 virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) ) 262 { 263 (*m_pDebuggingRef)->stop(); 264 265 m_aDebugCondition.set(); 266 } 267 268 virtual void finished(const FinishEngineEvent& Evt) THROWS( (UsrSystemException) ) 269 { 270 m_aDebugCondition.set(); 271 } 272 273 274 void cmdLine(); 275 protected: 276 277 OCondition m_aDebugCondition; 278 XDebuggingRef *m_pDebuggingRef; 279 }; 280 281 282 283 void TestListener::cmdLine() 284 { 285 // Condition is set by running listener 286 m_aDebugCondition.wait(); 287 m_aDebugCondition.reset(); 288 (*m_pDebuggingRef)->doContinue(); 289 m_aDebugCondition.wait(); 290 } 291 292 void TestListener::detach() 293 { 294 OSL_ASSERT( m_pDebuggingRef ); 295 296 m_pDebuggingRef = 0; 297 } 298 299 BOOL TestListener::queryInterface( Uik aUik, XInterfaceRef & rOut ) 300 { 301 if( aUik == XEngineListener::getSmartUik() ) 302 rOut = (XEngineListener*)this; 303 else 304 return OWeakObject::queryInterface( aUik, rOut ); 305 return TRUE; 306 } 307 308 309 void checkInvokation( const XInvokationRef &xInvoke ) 310 { 311 UsrAny anyList; 312 313 // check exporting an object as an invokation 314 OSL_ASSERT( xInvoke->hasProperty( L"list" ) ); 315 anyList = xInvoke->getValue( L"list" ); 316 317 OSL_ASSERT( anyList.getReflection() == XInvokation_getReflection() ); 318 XInvokationRef *pRef = ( XInvokationRef * ) anyList.get(); 319 OSL_ASSERT( (*pRef).is() ); 320 321 OSL_ASSERT( (*pRef)->hasMethod( L"append" ) ); 322 OSL_ASSERT( (*pRef)->hasMethod( L"count" ) ); 323 324 Sequence<UsrAny> seq(1); 325 UsrAny any( (INT32) 1); 326 (seq.getArray())[0] = any; 327 328 any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() ); 329 int nOldSize = any.getINT32(); 330 331 any = (*pRef)->invoke( L"append" , seq , Sequence<INT16>(), Sequence<UsrAny>() ); 332 any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() ); 333 334 OSL_ASSERT( nOldSize + 1 == any.getINT32() ); 335 } 336 337 // just for testing ! 338 class PythonCodeLibrary : 339 public XLibraryAccess, 340 public OWeakObject 341 { 342 343 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); 344 void acquire() { OWeakObject::acquire(); } 345 void release() { OWeakObject::release(); } 346 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } 347 348 349 virtual BOOL isFunction(const UString& FunctionName) THROWS( (UsrSystemException) ) 350 { 351 return FALSE; 352 } 353 354 virtual BOOL isValidPath(const UString& PathName) THROWS( (UsrSystemException) ) 355 { 356 return FALSE; 357 } 358 359 virtual Sequence< UString > getModuleNames(void) THROWS( (UsrSystemException) ) 360 { 361 return Sequence<UString> (); 362 } 363 364 virtual UString getModuleSource(const UString& ModulName) THROWS( (UsrSystemException) ) 365 { 366 if( ModulName == L"testmodul" ) { 367 return UString( L"def testmethod():\n" 368 L" return 42\n"); 369 } 370 return UString(); 371 } 372 373 virtual Sequence< BYTE > getModuleCode(const UString& ModuleName) THROWS( (UsrSystemException) ) 374 { 375 return Sequence< BYTE > (); 376 } 377 378 virtual UString getFunctionSource(const UString& FunctionName) THROWS( (UsrSystemException) ) 379 { 380 return UString(); 381 } 382 virtual Sequence< BYTE > getFunctionCode(const UString& FunctionName) THROWS( (UsrSystemException) ) 383 { 384 return Sequence< BYTE > (); 385 } 386 }; 387 388 BOOL PythonCodeLibrary::queryInterface( Uik aUik, XInterfaceRef & rOut ) 389 { 390 if( XLibraryAccess::getSmartUik() == aUik ) { 391 rOut = (XLibraryAccess* ) this; 392 } 393 else { 394 return OWeakObject::queryInterface( aUik , rOut ); 395 } 396 397 return TRUE; 398 } 399 400 401 402 /* 403 * main. 404 */ 405 int __LOADONCALLAPI main (int argc, char **argv) 406 { 407 // necessary startup code 408 XMultiServiceFactoryRef xSMgr = createRegistryServiceManager(); 409 registerUsrServices( xSMgr ); 410 setProcessServiceManager( xSMgr ); 411 412 XInterfaceRef x = xSMgr->createInstance( L"stardiv.uno.repos.ImplementationRegistration" ); 413 XImplementationRegistrationRef xReg( x, USR_QUERY ); 414 sal_Char szBuf[1024]; 415 416 ORealDynamicLoader::computeModuleName( "pythonengine", szBuf, 1024 ); 417 UString aDllName( StringToOUString( szBuf, CHARSET_SYSTEM ) ); 418 xReg->registerImplementation( L"stardiv.loader.SharedLibrary", aDllName, XSimpleRegistryRef() ); 419 420 x = xSMgr->createInstance( L"stardiv.script.Python" ); 421 XEngineRef xEngine( x, USR_QUERY ); 422 XInvokationRef xInvoke( x, USR_QUERY ); 423 XDebuggingRef xDebug( x , USR_QUERY ); 424 425 XInterfaceRef rRoot( (XInvokation * )new MyPythonRoot , USR_QUERY ); 426 xEngine->setRoot( rRoot ); 427 428 429 // execute a simple script 430 xEngine->run( L"nIntTest = 5\n" 431 L"list = [2,3,4]\n" , XInterfaceRef(), Sequence<UsrAny> () ); 432 433 /**** 434 * 435 * Xinvokation - Test 436 * 437 *****/ 438 // get/set an int ! 439 { 440 OSL_ASSERT( xInvoke->hasProperty( L"nIntTest" ) ); 441 UsrAny any = xInvoke->getValue( L"nIntTest" ); 442 443 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG ); 444 OSL_ASSERT( any.getINT32() == 5 ); 445 446 // simple test: set an int ! 447 xInvoke->setValue( L"nIntTest" , UsrAny( (INT32) 10 ) ); 448 any = xInvoke->getValue( L"nIntTest" ); 449 450 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG ); 451 OSL_ASSERT( any.getINT32() == 10 ); 452 } 453 454 // call a python method ! 455 { 456 xEngine->run( L"def foo():\n" 457 L" return 'this is foo'\n" , XInterfaceRef() , Sequence<UsrAny> () ); 458 OSL_ASSERT( xInvoke->hasMethod( L"foo" ) ); 459 UsrAny any = xInvoke->invoke( L"foo" , 460 Sequence<UsrAny>(), 461 Sequence<INT16>() , 462 Sequence<UsrAny> () ); 463 OSL_ASSERT( any.getString() == L"this is foo" ); 464 } 465 466 467 // check exception handling ! 468 { 469 try { 470 xInvoke->invoke( L"foo" , Sequence<UsrAny>(1) , Sequence<INT16>(), Sequence<UsrAny> () ); 471 // wrong number of arguments 472 OSL_ASSERT( 0 ); 473 } 474 catch ( IllegalArgumentException& e ) { 475 } 476 catch ( InvocationTargetException& e ) { 477 } 478 catch ( CannotConvertException& e ) { 479 // empty any cannot be converted 480 } 481 } 482 483 // check InOut-Parameter 484 checkInvokation( xInvoke ); 485 486 /******* 487 * 488 * Check Introspection Access 489 * 490 *******/ 491 { 492 XIntrospectionAccessRef xIntrospection = xInvoke->getIntrospection(); 493 OSL_ASSERT( xIntrospection.is() ); 494 495 // no further test, simply call them 496 xIntrospection->getMethods(0); 497 xIntrospection->getProperties(0); 498 499 OSL_ASSERT( xIntrospection->getSuppliedMethodConcepts() == 0 ); 500 OSL_ASSERT( xIntrospection->getSuppliedPropertyConcepts() == 0 ); 501 502 Property prop = xIntrospection->getProperty( L"nIntTest" ,0 ); 503 OSL_ASSERT( prop.Name == L"nIntTest" ); 504 OSL_ASSERT( prop.Type->getTypeClass() == TypeClass_LONG ); 505 506 XIdlMethodRef method = xIntrospection->getMethod( L"foo" , 0 ); 507 OSL_ASSERT( method->getName() == L"foo" ); 508 } 509 510 511 /****** 512 * 513 * Multithreading test 514 * 515 *******/ 516 517 /****** 518 * 519 * XDebuggingTest 520 * 521 ******/ 522 // stop/doContinue + runAsync listener 523 { 524 // test hangs, if something is wrong 525 526 TestListener *pListener = new TestListener( &xDebug ); 527 XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY ); 528 529 // single listener check ! 530 xEngine->runAsync( L"pass\n" 531 , XInterfaceRef() , Sequence<UsrAny> () , ref ); 532 pListener->cmdLine(); 533 } 534 535 // ListenerAdministration check ! 536 { 537 // test hangs, if something is wrong 538 539 TestListener *pListener = new TestListener( &xDebug ); 540 XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY ); 541 542 // engine listener check ! 543 xEngine->addEngineListener( ref ); 544 xEngine->runAsync( L"pass\n" 545 , XInterfaceRef() , Sequence<UsrAny> () , XEngineListenerRef() ); 546 pListener->cmdLine(); 547 xEngine->removeEngineListener( ref); 548 549 } 550 551 // check the import mechanism 552 { 553 XLibraryAccessRef xLibrary( ( XLibraryAccess * ) new PythonCodeLibrary , USR_QUERY ); 554 xEngine->setLibraryAccess( xLibrary ); 555 556 xEngine->run( L"import testmodul\n" 557 L"x = testmodul.testmethod()\n" , XInterfaceRef() , Sequence<UsrAny>() ); 558 UsrAny any = xInvoke->getValue( L"x" ); 559 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG ); 560 OSL_ASSERT( any.getINT32() == 42 ); 561 } 562 563 // check other imports 564 { 565 // Check, if the libraries are available at run time 566 xEngine->run( L"import math\n" 567 L"dMathTest = math.exp(0)\n" , XInterfaceRef() , Sequence<UsrAny> () ); 568 569 OSL_ASSERT( xInvoke->hasProperty( L"dMathTest" ) ); 570 UsrAny any = xInvoke->getValue( L"dMathTest" ); 571 572 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_DOUBLE ); 573 OSL_ASSERT( any.getDouble() == 1. ); 574 } 575 576 // Test connection to root object ! 577 { 578 xEngine->run( L"x = stardiv.root.TestValue\n" 579 L"y = stardiv.inout(5)\n" 580 L"stardiv.root.getTestValueViaInout(y)\n" 581 L"z = y.value\n" , XInterfaceRef() , Sequence<UsrAny> () ); 582 583 UsrAny any = xInvoke->getValue( L"x" ); 584 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG ); 585 OSL_ASSERT( any.getINT32() == 15 ); 586 587 any = xInvoke->getValue( L"z" ); 588 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG ); 589 OSL_ASSERT( any.getINT32() == 15 ); 590 } 591 592 // Test exactName interface 593 { 594 UsrAny any = xInvoke->getValue( L"__builtins__" ); 595 OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_INTERFACE ); 596 597 XInvokationRef rInv( *((XInterfaceRef *) any.get() ), USR_QUERY ); 598 OSL_ASSERT( rInv.is() ); 599 600 XExactNameRef rName( *((XInterfaceRef*) any.get() ), USR_QUERY ); 601 OSL_ASSERT( rName.is() ); 602 603 UString str = rName->getExactName( L"SYNTAXERROR" ); 604 OSL_ASSERT( str.len() ); 605 } 606 607 608 // Test exactName interface of the engine itself 609 { 610 XExactNameRef rName( xInvoke , USR_QUERY ); 611 OSL_ASSERT( rName.is() ); 612 UString str = rName->getExactName( L"STARDIV" ); 613 OSL_ASSERT( str.len() ); 614 } 615 616 617 return 0; 618 } 619 620