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