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