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:
MyPythonRoot()62 	MyPythonRoot() { m_iTestValue = 15; }
63 	BOOL				queryInterface( Uik aUik, XInterfaceRef & rOut );
acquire()64 	void 				acquire() 						 { OWeakObject::acquire(); }
release()65 	void 				release() 						 { OWeakObject::release(); }
getImplementation(Reflection * p)66 	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
67 
68 public:
getIntrospection(void) const69     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 
getTestValueViaInout(int & inout)93 	void getTestValueViaInout( int &inout )
94 		{ inout = m_iTestValue; }
95 
getTestValue() const96 	INT32 getTestValue() const
97 		{ return m_iTestValue; }
98 
setTestValue(INT32 i)99 	void setTestValue( INT32 i )
100 		{ m_iTestValue = i; }
101 
printTestValue()102 	void printTestValue()
103 		{ fprintf( stderr, "TestValue : %d\n" , getTestValue() ); }
104 
addTestValue(INT32 i)105 	void addTestValue( INT32 i )
106 		{ m_iTestValue += i; }
107 
108 private:
109 
110 	INT32 m_iTestValue;
111 };
112 
queryInterface(Uik aUik,XInterfaceRef & rOut)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 
invoke(const UString & FunctionName,const Sequence<UsrAny> & Params,Sequence<INT16> & OutParamIndex,Sequence<UsrAny> & OutParam)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 
setValue(const UString & PropertyName,const UsrAny & Value)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 
getValue(const UString & PropertyName)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 
hasMethod(const UString & Name) const183 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 
hasProperty(const UString & Name) const198 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 
TestListener()219 	TestListener()
220 	{
221 		m_pDebuggingRef = 0;
222 	}
223 
224 
TestListener(XDebuggingRef * p)225 	TestListener( XDebuggingRef *p )
226 	{
227 		attach( p  );
228 	}
229 
~TestListener()230 	~TestListener()
231 	{
232 		if( m_pDebuggingRef ) {
233 			detach();
234 		}
235 	}
236 
237 	BOOL				queryInterface( Uik aUik, XInterfaceRef & rOut );
acquire()238 	void 				acquire() 						 { OWeakObject::acquire(); }
release()239 	void 				release() 						 { OWeakObject::release(); }
getImplementation(Reflection * p)240 	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
241 
242 
attach(XDebuggingRef * p)243 	void attach( XDebuggingRef *p )
244 	{
245 		m_pDebuggingRef = p;
246 	}
247 
248 	void detach( );
249 
250 
disposing(const EventObject & o)251 	virtual void disposing( const EventObject &o )
252 	{
253 		if( m_pDebuggingRef ) {
254 			detach();
255 		}
256 	}
interrupt(const InterruptEngineEvent & Evt)257     virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) )
258     {
259     }
260 
running(const EventObject & Evt)261     virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) )
262    	{
263 		(*m_pDebuggingRef)->stop();
264 
265    		m_aDebugCondition.set();
266     }
267 
finished(const FinishEngineEvent & Evt)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 
cmdLine()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 
detach()292 void TestListener::detach()
293 {
294 	OSL_ASSERT( m_pDebuggingRef );
295 
296    	m_pDebuggingRef = 0;
297 }
298 
queryInterface(Uik aUik,XInterfaceRef & rOut)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 
checkInvokation(const XInvokationRef & xInvoke)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 );
acquire()344 	void 				acquire() 						 { OWeakObject::acquire(); }
release()345 	void 				release() 						 { OWeakObject::release(); }
getImplementation(Reflection * p)346 	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
347 
348 
isFunction(const UString & FunctionName)349     virtual BOOL isFunction(const UString& FunctionName) 			THROWS( (UsrSystemException) )
350   	{
351   		return FALSE;
352   	}
353 
isValidPath(const UString & PathName)354     virtual BOOL isValidPath(const UString& PathName) 				THROWS( (UsrSystemException) )
355     {
356     	return FALSE;
357     }
358 
getModuleNames(void)359     virtual Sequence< UString > getModuleNames(void) 				THROWS( (UsrSystemException) )
360     {
361     	return Sequence<UString> ();
362     }
363 
getModuleSource(const UString & ModulName)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 
getModuleCode(const UString & ModuleName)373     virtual Sequence< BYTE > getModuleCode(const UString& ModuleName) THROWS( (UsrSystemException) )
374     {
375     	return Sequence< BYTE > ();
376     }
377 
getFunctionSource(const UString & FunctionName)378     virtual UString getFunctionSource(const UString& FunctionName) THROWS( (UsrSystemException) )
379     {
380     	return UString();
381     }
getFunctionCode(const UString & FunctionName)382     virtual Sequence< BYTE > getFunctionCode(const UString& FunctionName) THROWS( (UsrSystemException) )
383     {
384     	return Sequence< BYTE > ();
385     }
386 };
387 
queryInterface(Uik aUik,XInterfaceRef & rOut)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  */
main(int argc,char ** argv)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