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