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