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