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 #include "pyuno_impl.hxx"
25 
26 #include <osl/thread.h>
27 #include <osl/module.h>
28 #include <osl/process.h>
29 #include <rtl/strbuf.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include <rtl/bootstrap.hxx>
32 #include <locale.h>
33 
34 #include <typelib/typedescription.hxx>
35 
36 #include <com/sun/star/beans/XMaterialHolder.hpp>
37 
38 #include <vector>
39 
40 using rtl::OUString;
41 using rtl::OUStringToOString;
42 using rtl::OUStringBuffer;
43 using rtl::OStringBuffer;
44 using rtl::OString;
45 
46 using com::sun::star::uno::Reference;
47 using com::sun::star::uno::XInterface;
48 using com::sun::star::uno::Any;
49 using com::sun::star::uno::TypeDescription;
50 using com::sun::star::uno::Sequence;
51 using com::sun::star::uno::Type;
52 using com::sun::star::uno::UNO_QUERY;
53 using com::sun::star::uno::RuntimeException;
54 using com::sun::star::uno::XComponentContext;
55 using com::sun::star::lang::XSingleServiceFactory;
56 using com::sun::star::lang::XUnoTunnel;
57 using com::sun::star::reflection::XIdlReflection;
58 using com::sun::star::script::XTypeConverter;
59 using com::sun::star::script::XInvocationAdapterFactory2;
60 using com::sun::star::script::XInvocation;
61 using com::sun::star::beans::XMaterialHolder;
62 using com::sun::star::beans::XIntrospection;
63 
64 namespace pyuno
65 {
66 #define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
67 
68 static PyTypeObject RuntimeImpl_Type =
69 {
70     PyVarObject_HEAD_INIT(&PyType_Type, 0)
71     const_cast< char * >("pyuno_runtime"),
72     sizeof (RuntimeImpl),
73     0,
74     (destructor) RuntimeImpl::del,
75     (printfunc) 0,
76     (getattrfunc) 0,
77     (setattrfunc) 0,
78 #if PY_MAJOR_VERSION >= 3
79     0,
80 #else
81     (cmpfunc) 0,
82 #endif
83     (reprfunc) 0,
84     0,
85     0,
86     0,
87     (hashfunc) 0,
88     (ternaryfunc) 0,
89     (reprfunc) 0,
90     (getattrofunc)0,
91     (setattrofunc)0,
92     NULL,
93     0,
94     NULL,
95     (traverseproc)0,
96     (inquiry)0,
97     (richcmpfunc)0,
98     0,
99     (getiterfunc)0,
100     (iternextfunc)0,
101     NULL,
102     NULL,
103     NULL,
104     NULL,
105     NULL,
106     (descrgetfunc)0,
107     (descrsetfunc)0,
108     0,
109     (initproc)0,
110     (allocfunc)0,
111     (newfunc)0,
112     (freefunc)0,
113     (inquiry)0,
114     NULL,
115     NULL,
116     NULL,
117     NULL,
118     NULL,
119     (destructor)0
120 #if PY_VERSION_HEX >= 0x02060000
121     , 0
122 #endif
123 };
124 
125 /*----------------------------------------------------------------------
126   Runtime implementation
127  -----------------------------------------------------------------------*/
getRuntimeImpl(PyRef & globalDict,PyRef & runtimeImpl)128 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
129     throw ( com::sun::star::uno::RuntimeException )
130 {
131     PyThreadState * state = PyThreadState_Get();
132     if( ! state )
133     {
134         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
135             "python global interpreter must be held (thread must be attached)" )),
136                                 Reference< XInterface > () );
137     }
138 
139     globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
140 
141     if( ! globalDict.is() ) // FATAL !
142     {
143         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
144             "can't find __main__ module" )), Reference< XInterface > ());
145     }
146     runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
147 }
148 
importUnoModule()149 static PyRef importUnoModule( ) throw ( RuntimeException )
150 {
151     PyRef globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
152     // import the uno module
153     PyRef module( PyImport_ImportModule( const_cast< char * >("uno") ), SAL_NO_ACQUIRE );
154     if( PyErr_Occurred() )
155     {
156         PyRef excType, excValue, excTraceback;
157         PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
158         PyRef str( PyObject_Repr( excTraceback.get() ), SAL_NO_ACQUIRE );
159 
160         OUStringBuffer buf;
161         buf.appendAscii( "python object raised an unknown exception (" );
162         PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
163 
164         buf.append( pyString2ustring( valueRep.get() ) ).appendAscii( ", traceback follows\n" );
165         buf.append( pyString2ustring( str.get() ) );
166         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
167     }
168     PyRef dict( PyModule_GetDict( module.get() ) );
169     return dict;
170 }
171 
readLoggingConfig(sal_Int32 * pLevel,FILE ** ppFile)172 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
173 {
174     *pLevel = LogLevel::NONE;
175     *ppFile = 0;
176     OUString fileName;
177     osl_getModuleURLFromFunctionAddress(
178         reinterpret_cast< oslGenericFunction >(readLoggingConfig),
179         (rtl_uString **) &fileName );
180     fileName = OUString( fileName.getStr(), fileName.lastIndexOf( '/' )+1 );
181     fileName += OUString::createFromAscii(  SAL_CONFIGFILE("pyuno") );
182     rtl::Bootstrap bootstrapHandle( fileName );
183 
184     OUString str;
185     if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGLEVEL" ), str ) )
186     {
187         if( str.equalsAscii( "NONE" ) )
188             *pLevel = LogLevel::NONE;
189         else if( str.equalsAscii( "CALL" ) )
190             *pLevel = LogLevel::CALL;
191         else if( str.equalsAscii( "ARGS" ) )
192             *pLevel = LogLevel::ARGS;
193         else
194         {
195             fprintf( stderr, "unknown loglevel %s\n",
196                      OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
197         }
198     }
199     if( *pLevel > LogLevel::NONE )
200     {
201         *ppFile = stdout;
202         if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGTARGET" ), str ) )
203         {
204             if( str.equalsAscii( "stdout" ) )
205                 *ppFile = stdout;
206             else if( str.equalsAscii( "stderr" ) )
207                 *ppFile = stderr;
208             else
209             {
210                 oslProcessInfo data;
211                 data.Size = sizeof( data );
212                 osl_getProcessInfo(
213                     0 , osl_Process_IDENTIFIER , &data );
214                 osl_getSystemPathFromFileURL( str.pData, &str.pData);
215                 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
216                 o += ".";
217                 o += OString::valueOf( (sal_Int32)data.Ident );
218 
219                 *ppFile = fopen( o.getStr() , "w" );
220                 if ( *ppFile )
221                 {
222                     // do not buffer (useful if e.g. analyzing a crash)
223                     setvbuf( *ppFile, 0, _IONBF, 0 );
224                 }
225                 else
226                 {
227                     fprintf( stderr, "couldn't create file %s\n",
228                              OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
229 
230                 }
231             }
232         }
233     }
234 }
235 
236 /*-------------------------------------------------------------------
237  RuntimeImpl implementations
238  *-------------------------------------------------------------------*/
create(const Reference<XComponentContext> & ctx)239 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
240     throw( com::sun::star::uno::RuntimeException )
241 {
242     RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
243     if( ! me )
244         throw RuntimeException(
245             OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot instantiate pyuno::RuntimeImpl" ) ),
246             Reference< XInterface > () );
247     me->cargo = 0;
248     // must use a different struct here, as the PyObject_New
249     // makes C++ unusable
250     RuntimeCargo *c = new RuntimeCargo();
251     readLoggingConfig( &(c->logLevel) , &(c->logFile) );
252     log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
253 
254     c->valid = 1;
255     c->xContext = ctx;
256     c->xInvocation = Reference< XSingleServiceFactory > (
257         ctx->getServiceManager()->createInstanceWithContext(
258             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Invocation" ) ),
259             ctx ),
260         UNO_QUERY );
261     if( ! c->xInvocation.is() )
262         throw RuntimeException(
263             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation service" ) ),
264             Reference< XInterface > () );
265 
266     c->xTypeConverter = Reference< XTypeConverter > (
267         ctx->getServiceManager()->createInstanceWithContext(
268             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" ) ),
269             ctx ),
270         UNO_QUERY );
271     if( ! c->xTypeConverter.is() )
272         throw RuntimeException(
273             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate typeconverter service" )),
274             Reference< XInterface > () );
275 
276     c->xCoreReflection = Reference< XIdlReflection > (
277         ctx->getServiceManager()->createInstanceWithContext(
278             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ) ),
279             ctx ),
280         UNO_QUERY );
281     if( ! c->xCoreReflection.is() )
282         throw RuntimeException(
283             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate corereflection service" )),
284             Reference< XInterface > () );
285 
286     c->xAdapterFactory = Reference< XInvocationAdapterFactory2 > (
287         ctx->getServiceManager()->createInstanceWithContext(
288             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.InvocationAdapterFactory" ) ),
289             ctx ),
290         UNO_QUERY );
291     if( ! c->xAdapterFactory.is() )
292         throw RuntimeException(
293             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation adapter factory service" )),
294             Reference< XInterface > () );
295 
296     c->xIntrospection = Reference< XIntrospection > (
297         ctx->getServiceManager()->createInstanceWithContext(
298             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ),
299             ctx ),
300         UNO_QUERY );
301     if( ! c->xIntrospection.is() )
302         throw RuntimeException(
303             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate introspection service" )),
304             Reference< XInterface > () );
305 
306     Any a = ctx->getValueByName(OUString(
307         RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager" )) );
308     a >>= c->xTdMgr;
309     if( ! c->xTdMgr.is() )
310         throw RuntimeException(
311             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't retrieve typedescriptionmanager" )),
312             Reference< XInterface > () );
313 
314     me->cargo =c;
315     return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
316 }
317 
del(PyObject * self)318 void  stRuntimeImpl::del(PyObject* self)
319 {
320     RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
321     if( me->cargo->logFile )
322         fclose( me->cargo->logFile );
323     delete me->cargo;
324     PyObject_Del (self);
325 }
326 
327 
initialize(const Reference<XComponentContext> & ctx)328 void Runtime::initialize( const Reference< XComponentContext > & ctx )
329     throw ( RuntimeException )
330 {
331     PyRef globalDict, runtime;
332     getRuntimeImpl( globalDict , runtime );
333     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
334 
335     if( runtime.is() && impl->cargo->valid )
336     {
337         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
338             "pyuno runtime has already been initialized before" ) ),
339                                 Reference< XInterface > () );
340     }
341     PyRef keep( RuntimeImpl::create( ctx ) );
342     PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
343     Py_XINCREF( keep.get() );
344 }
345 
346 
isInitialized()347 bool Runtime::isInitialized() throw ( RuntimeException )
348 {
349     PyRef globalDict, runtime;
350     getRuntimeImpl( globalDict , runtime );
351     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
352     return runtime.is() && impl->cargo->valid;
353 }
354 
finalize()355 void Runtime::finalize() throw (RuntimeException)
356 {
357     PyRef globalDict, runtime;
358     getRuntimeImpl( globalDict , runtime );
359     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
360     if( !runtime.is() || ! impl->cargo->valid )
361     {
362         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
363             "pyuno bridge must have been initialized before finalizing" )),
364                                 Reference< XInterface > () );
365     }
366     impl->cargo->valid = false;
367     impl->cargo->xInvocation.clear();
368     impl->cargo->xContext.clear();
369     impl->cargo->xTypeConverter.clear();
370 }
371 
Runtime()372 Runtime::Runtime() throw(  RuntimeException )
373     : impl( 0 )
374 {
375     PyRef globalDict, runtime;
376     getRuntimeImpl( globalDict , runtime );
377     if( ! runtime.is() )
378     {
379         throw RuntimeException(
380             OUString( RTL_CONSTASCII_USTRINGPARAM("pyuno runtime is not initialized, "
381                                                   "(the pyuno.bootstrap needs to be called before using any uno classes)")),
382             Reference< XInterface > () );
383     }
384     impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
385     Py_XINCREF( runtime.get() );
386 }
387 
Runtime(const Runtime & r)388 Runtime::Runtime( const Runtime & r )
389 {
390     impl = r.impl;
391     Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
392 }
393 
~Runtime()394 Runtime::~Runtime()
395 {
396     Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
397 }
398 
operator =(const Runtime & r)399 Runtime & Runtime::operator = ( const Runtime & r )
400 {
401     PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
402     Py_XINCREF( temp.get() );
403     Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
404     impl = r.impl;
405     return *this;
406 }
407 
any2PyObject(const Any & a) const408 PyRef Runtime::any2PyObject (const Any &a ) const
409     throw ( com::sun::star::script::CannotConvertException,
410             com::sun::star::lang::IllegalArgumentException,
411             RuntimeException)
412 {
413     if( ! impl->cargo->valid )
414     {
415         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
416             "pyuno runtime must be initialized before calling any2PyObject" )),
417                                 Reference< XInterface > () );
418     }
419 
420     switch (a.getValueTypeClass ())
421     {
422     case typelib_TypeClass_VOID:
423 	{
424         Py_INCREF (Py_None);
425         return PyRef(Py_None);
426 	}
427     case typelib_TypeClass_CHAR:
428 	{
429         sal_Unicode c = *(sal_Unicode*)a.getValue();
430         return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
431 	}
432     case typelib_TypeClass_BOOLEAN:
433 	{
434         sal_Bool b = sal_Bool();
435         if ((a >>= b) && b)
436             return Py_True;
437         else
438             return Py_False;
439 	}
440     case typelib_TypeClass_BYTE:
441     case typelib_TypeClass_SHORT:
442     case typelib_TypeClass_UNSIGNED_SHORT:
443     case typelib_TypeClass_LONG:
444 	{
445         sal_Int32 l = 0;
446         a >>= l;
447 #if PY_MAJOR_VERSION >= 3
448         return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
449 #else
450         return PyRef( PyInt_FromLong (l), SAL_NO_ACQUIRE );
451 #endif
452 	}
453     case typelib_TypeClass_UNSIGNED_LONG:
454 	{
455         sal_uInt32 l = 0;
456         a >>= l;
457         return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
458 	}
459     case typelib_TypeClass_HYPER:
460 	{
461         sal_Int64 l = 0;
462         a >>= l;
463         return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
464 	}
465     case typelib_TypeClass_UNSIGNED_HYPER:
466 	{
467         sal_uInt64 l = 0;
468         a >>= l;
469         return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
470 	}
471     case typelib_TypeClass_FLOAT:
472 	{
473         float f = 0.0;
474         a >>= f;
475         return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
476 	}
477     case typelib_TypeClass_DOUBLE:
478 	{
479         double d = 0.0;
480         a >>= d;
481         return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
482 	}
483     case typelib_TypeClass_STRING:
484 	{
485         OUString tmp_ostr;
486         a >>= tmp_ostr;
487         return ustring2PyUnicode( tmp_ostr );
488 	}
489     case typelib_TypeClass_TYPE:
490 	{
491         Type t;
492         a >>= t;
493         OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
494         return PyRef(
495             PyUNO_Type_new (
496                 o.getStr(),  (com::sun::star::uno::TypeClass)t.getTypeClass(), *this),
497             SAL_NO_ACQUIRE);
498 	}
499     case typelib_TypeClass_ANY:
500 	{
501         //I don't think this can happen.
502         Py_INCREF (Py_None);
503         return Py_None;
504 	}
505     case typelib_TypeClass_ENUM:
506 	{
507         sal_Int32 l = *(sal_Int32 *) a.getValue();
508         TypeDescription desc( a.getValueType() );
509         if( desc.is() )
510         {
511             desc.makeComplete();
512             typelib_EnumTypeDescription *pEnumDesc =
513                 (typelib_EnumTypeDescription *) desc.get();
514             for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
515             {
516                 if( pEnumDesc->pEnumValues[i] == l )
517                 {
518                     OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
519                     OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
520                     return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
521                 }
522             }
523         }
524         OUStringBuffer buf;
525         buf.appendAscii( "Any carries enum " );
526         buf.append( a.getValueType().getTypeName());
527         buf.appendAscii( " with invalid value " ).append( l );
528         throw RuntimeException( buf.makeStringAndClear() , Reference< XInterface > ()  );
529 	}
530     case typelib_TypeClass_EXCEPTION:
531     case typelib_TypeClass_STRUCT:
532     {
533         PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
534         PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE);
535         PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE );
536         PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
537         PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
538         if( ! ret.is() )
539         {
540             OUStringBuffer buf;
541             buf.appendAscii( "Couldn't instantiate python representation of structered UNO type " );
542             buf.append( a.getValueType().getTypeName() );
543             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
544         }
545 
546         if( com::sun::star::uno::TypeClass_EXCEPTION == a.getValueTypeClass() )
547         {
548             // add the message in a standard python way !
549             PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
550 
551             // assuming that the Message is always the first member, wuuuu
552             void *pData = (void*)a.getValue();
553             OUString message = *(OUString * )pData;
554             PyRef pymsg = USTR_TO_PYSTR( message );
555             PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
556             // the exception base functions want to have an "args" tuple,
557             // which contains the message
558             PyObject_SetAttrString( ret.get(), const_cast< char * >("args"), args.get() );
559         }
560         return ret;
561     }
562     case typelib_TypeClass_SEQUENCE:
563 	{
564         Sequence<Any> s;
565 
566         Sequence< sal_Int8 > byteSequence;
567         if( a >>= byteSequence )
568         {
569             // byte sequence is treated in a special way because of peformance reasons
570             // @since 0.9.2
571             return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
572         }
573         else
574         {
575             Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
576             Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
577             tc->convertTo (a, ::getCppuType (&s)) >>= s;
578             PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE);
579             int i=0;
580             OUString errMsg;
581             try
582             {
583                 for ( i = 0; i < s.getLength (); i++)
584                 {
585                     PyRef element;
586                     element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
587                     OSL_ASSERT( element.is() );
588                     PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
589                 }
590             }
591             catch( com::sun::star::uno::Exception & )
592             {
593                 for( ; i < s.getLength() ; i ++ )
594                 {
595                     Py_INCREF( Py_None );
596                     PyTuple_SetItem( tuple.get(), i,  Py_None );
597                 }
598                 throw;
599             }
600             return tuple;
601 	    }
602 	}
603     case typelib_TypeClass_INTERFACE:
604 	{
605         Reference< XUnoTunnel > tunnel;
606         a >>= tunnel;
607         if( tunnel.is() )
608         {
609             sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
610             if( that )
611                 return ((Adapter*)sal::static_int_cast< sal_IntPtr >(that))->getWrappedObject();
612         }
613         //This is just like the struct case:
614         return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE );
615 	}
616     default:
617 	{
618         OUStringBuffer buf;
619         buf.appendAscii( "Unknonwn UNO type class " );
620         buf.append( (sal_Int32 ) a.getValueTypeClass() );
621         throw RuntimeException(buf.makeStringAndClear( ), Reference< XInterface > () );
622 	}
623     }
624     //We shouldn't be here...
625     Py_INCREF( Py_None );
626     return Py_None;
627 }
628 
invokeGetTypes(const Runtime & r,PyObject * o)629 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
630 {
631     Sequence< Type > ret;
632 
633     PyRef method( PyObject_GetAttrString( o , const_cast< char * >("getTypes") ), SAL_NO_ACQUIRE );
634     raiseInvocationTargetExceptionWhenNeeded( r );
635     if( method.is() && PyCallable_Check( method.get() ) )
636     {
637         PyRef types( PyObject_CallObject( method.get(), 0 ) , SAL_NO_ACQUIRE );
638         raiseInvocationTargetExceptionWhenNeeded( r );
639         if( types.is() && PyTuple_Check( types.get() ) )
640         {
641             int size = PyTuple_Size( types.get() );
642 
643             // add the XUnoTunnel interface  for uno object identity concept (hack)
644             ret.realloc( size + 1 );
645             for( int i = 0 ; i < size ; i ++ )
646             {
647                 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
648                 a >>= ret[i];
649             }
650             ret[size] = getCppuType( (Reference< com::sun::star::lang::XUnoTunnel> *) 0 );
651         }
652     }
653     return ret;
654 }
655 
pyObject2Any(const PyRef & source,enum ConversionMode mode) const656 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
657     throw ( com::sun::star::uno::RuntimeException )
658 {
659     if( ! impl->cargo->valid )
660     {
661         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
662             "pyuno runtime must be initialized before calling any2PyObject" )),
663                                 Reference< XInterface > () );
664     }
665 
666     Any a;
667     PyObject *o = source.get();
668     if( Py_None == o )
669     {
670 
671     }
672 #if PY_MAJOR_VERSION >= 3	// Python 3 has no PyInt
673     else if (PyBool_Check(o))
674     {
675         if( o == Py_True )
676         {
677             sal_Bool b = sal_True;
678             a = Any( &b, getBooleanCppuType() );
679         }
680         else
681         {
682             sal_Bool b = sal_False;
683             a = Any( &b, getBooleanCppuType() );
684         }
685     }
686 #else
687     else if (PyInt_Check (o))
688     {
689         if( o == Py_True )
690         {
691             sal_Bool b = sal_True;
692             a = Any( &b, getBooleanCppuType() );
693         }
694         else if ( o == Py_False )
695         {
696             sal_Bool b = sal_False;
697             a = Any( &b, getBooleanCppuType() );
698         }
699         else
700         {
701             sal_Int32 l = (sal_Int32) PyInt_AsLong( o );
702             if( l < 128 && l >= -128 )
703             {
704                 sal_Int8 b = (sal_Int8 ) l;
705                 a <<= b;
706             }
707             else if( l <= 0x7fff && l >= -0x8000 )
708             {
709                 sal_Int16 s = (sal_Int16) l;
710                 a <<= s;
711             }
712             else
713             {
714                 a <<= l;
715             }
716         }
717     }
718 #endif				// Python 3 has no PyInt
719     else if (PyLong_Check (o))
720     {
721         sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
722         if( l < 128 && l >= -128 )
723         {
724             sal_Int8 b = (sal_Int8 ) l;
725             a <<= b;
726         }
727         else if( l <= 0x7fff && l >= -0x8000 )
728         {
729             sal_Int16 s = (sal_Int16) l;
730             a <<= s;
731         }
732         else if( l <= SAL_CONST_INT64(0x7fffffff) &&
733                  l >= -SAL_CONST_INT64(0x80000000) )
734         {
735             sal_Int32 l32 = (sal_Int32) l;
736             a <<= l32;
737         }
738         else
739         {
740             a <<= l;
741         }
742     }
743     else if (PyFloat_Check (o))
744     {
745         double d = PyFloat_AsDouble (o);
746         a <<= d;
747     }
748 #if PY_MAJOR_VERSION < 3
749     else if (PyBytes_Check (o))
750 	a <<= pyString2ustring(o);
751 #endif
752     else if( PyUnicode_Check( o ) )
753 	a <<= pyString2ustring(o);
754     else if (PyTuple_Check (o))
755     {
756         Sequence<Any> s (PyTuple_Size (o));
757         for (int i = 0; i < PyTuple_Size (o); i++)
758         {
759             s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
760         }
761         a <<= s;
762     }
763     else
764     {
765         Runtime runtime;
766         // should be removed, in case ByteSequence gets derived from String
767         if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
768         {
769             PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
770             Sequence< sal_Int8 > seq;
771             if( PyBytes_Check( str.get() ) )
772             {
773                 seq = Sequence<sal_Int8 > (
774                     (sal_Int8*) PyBytes_AsString(str.get()), PyBytes_Size(str.get()));
775             }
776 #if PY_MAJOR_VERSION >= 3
777             else if ( PyByteArray_Check( str.get() ) )
778             {
779                 seq = Sequence< sal_Int8 >(
780                     (sal_Int8 *) PyByteArray_AS_STRING(str.get()), PyByteArray_GET_SIZE(str.get()));
781             }
782 #endif
783             a <<= seq;
784         }
785         else
786         if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
787         {
788             Type t = PyType2Type( o );
789             a <<= t;
790         }
791         else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
792         {
793             a = PyEnum2Enum( o );
794         }
795         else if( isInstanceOfStructOrException( o ) )
796         {
797             PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
798             PyUNO * obj = (PyUNO*)struc.get();
799             Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
800             if( holder.is( ) )
801                 a = holder->getMaterial();
802             else
803             {
804                 throw RuntimeException(
805                     USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ),
806                     Reference< XInterface > () );
807             }
808         }
809         else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
810         {
811             PyUNO* o_pi;
812             o_pi = (PyUNO*) o;
813             if (o_pi->members->wrappedObject.getValueTypeClass () ==
814                 com::sun::star::uno::TypeClass_STRUCT ||
815                 o_pi->members->wrappedObject.getValueTypeClass () ==
816                 com::sun::star::uno::TypeClass_EXCEPTION)
817             {
818                 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
819 
820                 if (!my_mh.is ())
821                 {
822                     throw RuntimeException(
823                         USTR_ASCII( "struct wrapper does not support XMaterialHolder" ),
824                         Reference< XInterface > () );
825                 }
826                 else
827                     a = my_mh->getMaterial ();
828             }
829             else
830             {
831                 a = o_pi->members->wrappedObject;
832             }
833         }
834         else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
835         {
836             sal_Unicode c = PyChar2Unicode( o );
837             a.setValue( &c, getCharCppuType( ));
838         }
839         else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
840         {
841             if( ACCEPT_UNO_ANY == mode )
842             {
843                 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) );
844                 Type t;
845                 pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t;
846 
847                 try
848                 {
849                     a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
850                 }
851                 catch( com::sun::star::uno::Exception & e )
852                 {
853                     throw RuntimeException( e.Message, e.Context );
854                 }
855             }
856             else
857             {
858                 throw RuntimeException(
859                     OUString( RTL_CONSTASCII_USTRINGPARAM(
860                                   "uno.Any instance not accepted during method call, "
861                                   "use uno.invoke instead" ) ),
862                     Reference< XInterface > () );
863             }
864         }
865         else
866         {
867             Reference< XInterface > mappedObject;
868             Reference< XInvocation > adapterObject;
869 
870             // instance already mapped out to the world ?
871             PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
872             if( ii != impl->cargo->mappedObjects.end() )
873             {
874                 adapterObject = ii->second;
875             }
876 
877             if( adapterObject.is() )
878             {
879                 // object got already bridged !
880                 Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
881 
882                 Adapter *pAdapter = ( Adapter * )
883                     sal::static_int_cast< sal_IntPtr >(
884                         tunnel->getSomething(
885                             ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
886 
887                 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
888                     adapterObject, pAdapter->getWrappedTypes() );
889             }
890             else
891             {
892                 Sequence< Type > interfaces = invokeGetTypes( *this, o );
893                 if( interfaces.getLength() )
894                 {
895                     Adapter *pAdapter = new Adapter( o, interfaces );
896                     mappedObject =
897                         getImpl()->cargo->xAdapterFactory->createAdapter(
898                             pAdapter, interfaces );
899 
900                     // keep a list of exported objects to ensure object identity !
901                     impl->cargo->mappedObjects[ PyRef(o) ] =
902                         com::sun::star::uno::WeakReference< XInvocation > ( pAdapter );
903                 }
904             }
905             if( mappedObject.is() )
906             {
907                 a = com::sun::star::uno::makeAny( mappedObject );
908             }
909             else
910             {
911                 OUStringBuffer buf;
912                 buf.appendAscii( "Couldn't convert " );
913                 PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE );
914                 buf.append( pyString2ustring( reprString.get() ) );
915                 buf.appendAscii( " to a UNO type" );
916                 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
917             }
918         }
919     }
920     return a;
921 }
922 
extractUnoException(const PyRef & excType,const PyRef & excValue,const PyRef & excTraceback) const923 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
924 {
925     PyRef str;
926     Any ret;
927     if( excTraceback.is() )
928     {
929         PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 );
930         if( unoModule.is() )
931         {
932             PyRef extractTraceback(
933                 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
934 
935             if( extractTraceback.is() )
936             {
937                 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE );
938                 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
939                 str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
940             }
941             else
942             {
943                 str = PyRef(
944                     PyBytes_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ),
945                     SAL_NO_ACQUIRE );
946             }
947         }
948         else
949         {
950             str = PyRef(
951                 PyBytes_FromString( "Couldn't find uno.py, no stacktrace available" ),
952                 SAL_NO_ACQUIRE );
953         }
954 
955     }
956     else
957     {
958         // it may occur, that no traceback is given (e.g. only native code below)
959         str = PyRef( PyBytes_FromString( "no traceback available" ), SAL_NO_ACQUIRE);
960     }
961 
962     if( isInstanceOfStructOrException( excValue.get() ) )
963     {
964         ret = pyObject2Any( excValue );
965     }
966     else
967     {
968         OUStringBuffer buf;
969         PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
970         if( typeName.is() )
971         {
972             buf.append( pyString2ustring( typeName.get() ) );
973         }
974         else
975         {
976             buf.appendAscii( "no typename available" );
977         }
978         buf.appendAscii( ": " );
979         PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
980         if( valueRep.is() )
981         {
982             buf.append( pyString2ustring( valueRep.get()));
983         }
984         else
985         {
986             buf.appendAscii( "Couldn't convert exception value to a string" );
987         }
988         buf.appendAscii( ", traceback follows\n" );
989         if( str.is() )
990         {
991             buf.append( pyString2ustring( str.get() ) );
992         }
993         else
994         {
995             buf.appendAscii( ", no traceback available\n" );
996         }
997         RuntimeException e;
998         e.Message = buf.makeStringAndClear();
999         ret = com::sun::star::uno::makeAny( e );
1000     }
1001     return ret;
1002 }
1003 
1004 
1005 static const char * g_NUMERICID = "pyuno.lcNumeric";
1006 static ::std::vector< rtl::OString > g_localeList;
1007 
ensureUnlimitedLifetime(const char * str)1008 static const char *ensureUnlimitedLifetime( const char *str )
1009 {
1010     int size = g_localeList.size();
1011     int i;
1012     for( i = 0 ; i < size ; i ++ )
1013     {
1014         if( 0 == strcmp( g_localeList[i].getStr(), str ) )
1015             break;
1016     }
1017     if( i == size )
1018     {
1019         g_localeList.push_back( str );
1020     }
1021     return g_localeList[i].getStr();
1022 }
1023 
1024 
PyThreadAttach(PyInterpreterState * interp)1025 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
1026     throw ( com::sun::star::uno::RuntimeException )
1027 {
1028     tstate = PyThreadState_New( interp );
1029     if( !tstate  )
1030         throw RuntimeException(
1031             OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ),
1032             Reference< XInterface > () );
1033     PyEval_AcquireThread( tstate);
1034     // set LC_NUMERIC to "C"
1035     const char * oldLocale =
1036         ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 )  );
1037     setlocale( LC_NUMERIC, "C" );
1038     PyRef locale( // python requires C locale
1039         PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE);
1040     PyDict_SetItemString(
1041         PyThreadState_GetDict(), g_NUMERICID, locale.get() );
1042 }
1043 
~PyThreadAttach()1044 PyThreadAttach::~PyThreadAttach()
1045 {
1046     PyObject *value =
1047         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1048     if( value )
1049         setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1050     PyThreadState_Clear( tstate );
1051     PyEval_ReleaseThread( tstate );
1052     PyThreadState_Delete( tstate );
1053 
1054 }
1055 
PyThreadDetach()1056 PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException )
1057 {
1058     tstate = PyThreadState_Get();
1059     PyObject *value =
1060         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1061     if( value )
1062         setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1063     PyEval_ReleaseThread( tstate );
1064 }
1065 
1066     /** Acquires the global interpreter lock again
1067 
1068     */
~PyThreadDetach()1069 PyThreadDetach::~PyThreadDetach()
1070 {
1071     PyEval_AcquireThread( tstate );
1072 //     PyObject *value =
1073 //         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1074 
1075     // python requires C LC_NUMERIC locale,
1076     // always set even when it is already "C"
1077     setlocale( LC_NUMERIC, "C" );
1078 }
1079 
1080 
getUnoModule()1081 PyRef RuntimeCargo::getUnoModule()
1082 {
1083     if( ! dictUnoModule.is() )
1084     {
1085         dictUnoModule = importUnoModule();
1086     }
1087     return dictUnoModule;
1088 }
1089 }
1090