1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pyuno_module.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "pyuno_impl.hxx"
33 #include <osl/module.hxx>
34 #include <osl/thread.h>
35 #include <osl/file.hxx>
37 #include <typelib/typedescription.hxx>
39 #include <rtl/strbuf.hxx>
40 #include <rtl/ustrbuf.hxx>
42 #include <rtl/bootstrap.hxx>
44 #include <uno/current_context.hxx>
45 #include <cppuhelper/bootstrap.hxx>
47 #include <com/sun/star/reflection/XIdlReflection.hpp>
48 #include <com/sun/star/reflection/XIdlClass.hpp>
49 #include <com/sun/star/registry/InvalidRegistryException.hpp>
55 using rtl::OUStringToOString
;
56 using rtl::OUStringBuffer
;
57 using rtl::OStringBuffer
;
59 using com::sun::star::uno::Sequence
;
60 using com::sun::star::uno::Reference
;
61 using com::sun::star::uno::XInterface
;
62 using com::sun::star::uno::Any
;
63 using com::sun::star::uno::makeAny
;
64 using com::sun::star::uno::UNO_QUERY
;
65 using com::sun::star::uno::RuntimeException
;
66 using com::sun::star::uno::TypeDescription
;
67 using com::sun::star::uno::XComponentContext
;
68 using com::sun::star::container::NoSuchElementException
;
69 using com::sun::star::reflection::XIdlReflection
;
70 using com::sun::star::reflection::XIdlClass
;
71 using com::sun::star::script::XInvocation2
;
73 using namespace pyuno
;
78 @ index of the next to be used member in the initializer list !
80 sal_Int32
fillStructWithInitializer(
81 const Reference
< XInvocation2
> &inv
,
82 typelib_CompoundTypeDescription
*pCompType
,
83 PyObject
*initializer
,
84 const Runtime
&runtime
) throw ( RuntimeException
)
87 if( pCompType
->pBaseTypeDescription
)
88 nIndex
= fillStructWithInitializer(
89 inv
, pCompType
->pBaseTypeDescription
, initializer
, runtime
);
91 sal_Int32 nTupleSize
= PyTuple_Size(initializer
);
93 for( i
= 0 ; i
< pCompType
->nMembers
; i
++ )
95 if( i
+ nIndex
>= nTupleSize
)
98 buf
.appendAscii( "pyuno._createUnoStructHelper: too few elements in the initializer tuple,");
99 buf
.appendAscii( "expected at least " ).append( nIndex
+ pCompType
->nMembers
);
100 buf
.appendAscii( ", got " ).append( nTupleSize
);
101 throw RuntimeException(buf
.makeStringAndClear(), Reference
< XInterface
> ());
103 PyObject
*element
= PyTuple_GetItem( initializer
, i
+ nIndex
);
104 Any a
= runtime
.pyObject2Any( element
, ACCEPT_UNO_ANY
);
105 inv
->setValue( pCompType
->ppMemberNames
[i
], a
);
112 static OUString
*pLibDir
;
115 osl::MutexGuard
guard( osl::Mutex::getGlobalMutex() );
118 static OUString libDir
;
120 // workarounds the $(ORIGIN) until it is available
121 if( Module::getUrlFromAddress(
122 reinterpret_cast< oslGenericFunction
>(getLibDir
), libDir
) )
124 libDir
= OUString( libDir
.getStr(), libDir
.lastIndexOf('/' ) );
125 OUString
name ( RTL_CONSTASCII_USTRINGPARAM( "PYUNOLIBDIR" ) );
126 rtl_bootstrap_set( name
.pData
, libDir
.pData
);
134 void raisePySystemException( const char * exceptionType
, const OUString
& message
)
137 buf
.append( "Error during bootstrapping uno (");
138 buf
.append( exceptionType
);
140 buf
.append( OUStringToOString( message
, osl_getThreadTextEncoding() ) );
141 PyErr_SetString( PyExc_SystemError
, buf
.makeStringAndClear().getStr() );
146 static PyObject
* getComponentContext (PyObject
*, PyObject
*)
151 Reference
<XComponentContext
> ctx
;
153 // getLibDir() must be called in order to set bootstrap variables correctly !
154 OUString
path( getLibDir());
155 if( Runtime::isInitialized() )
158 ctx
= runtime
.getImpl()->cargo
->xContext
;
163 if( !path
.getLength() )
166 PyExc_RuntimeError
, "osl_getUrlFromAddress fails, that's why I cannot find ini "
167 "file for bootstrapping python uno bridge\n" );
171 OUStringBuffer iniFileName
;
172 iniFileName
.append( path
);
173 iniFileName
.appendAscii( "/" );
174 iniFileName
.appendAscii( SAL_CONFIGFILE( "pyuno" ) );
175 iniFile
= iniFileName
.makeStringAndClear();
176 osl::DirectoryItem item
;
177 if( osl::DirectoryItem::get( iniFile
, item
) == item
.E_None
)
179 // in case pyuno.ini exists, use this file for bootstrapping
180 PyThreadDetach antiguard
;
181 ctx
= cppu::defaultBootstrap_InitialComponentContext (iniFile
);
185 // defaulting to the standard bootstrapping
186 PyThreadDetach antiguard
;
187 ctx
= cppu::defaultBootstrap_InitialComponentContext ();
192 if( ! Runtime::isInitialized() )
194 Runtime::initialize( ctx
);
197 ret
= runtime
.any2PyObject( makeAny( ctx
) );
199 catch (com::sun::star::registry::InvalidRegistryException
&e
)
201 // can't use raisePyExceptionWithAny() here, because the function
202 // does any conversions, which will not work with a
203 // wrongly bootstrapped pyuno!
204 raisePySystemException( "InvalidRegistryException", e
.Message
);
206 catch( com::sun::star::lang::IllegalArgumentException
& e
)
208 raisePySystemException( "IllegalArgumentException", e
.Message
);
210 catch( com::sun::star::script::CannotConvertException
& e
)
212 raisePySystemException( "CannotConvertException", e
.Message
);
214 catch (com::sun::star::uno::RuntimeException
& e
)
216 raisePySystemException( "RuntimeException", e
.Message
);
218 catch (com::sun::star::uno::Exception
& e
)
220 raisePySystemException( "uno::Exception", e
.Message
);
222 return ret
.getAcquired();
225 PyObject
* extractOneStringArg( PyObject
*args
, char const *funcName
)
227 if( !PyTuple_Check( args
) || PyTuple_Size( args
) != 1 )
230 buf
.append( funcName
).append( ": expecting one string argument" );
231 PyErr_SetString( PyExc_RuntimeError
, buf
.getStr() );
234 PyObject
*obj
= PyTuple_GetItem( args
, 0 );
235 if( !PyString_Check( obj
) && ! PyUnicode_Check(obj
))
238 buf
.append( funcName
).append( ": expecting one string argument" );
239 PyErr_SetString( PyExc_TypeError
, buf
.getStr());
245 static PyObject
*createUnoStructHelper(PyObject
*, PyObject
* args
)
253 if( PyTuple_Size( args
) == 2 )
255 PyObject
*structName
= PyTuple_GetItem( args
,0 );
256 PyObject
*initializer
= PyTuple_GetItem( args
,1 );
258 if( PyString_Check( structName
) )
260 if( PyTuple_Check( initializer
) )
262 OUString
typeName( OUString::createFromAscii(PyString_AsString(structName
)));
263 RuntimeCargo
*c
= runtime
.getImpl()->cargo
;
264 Reference
<XIdlClass
> idl_class ( c
->xCoreReflection
->forName (typeName
),UNO_QUERY
);
267 idl_class
->createObject (IdlStruct
);
268 PyUNO
*me
= (PyUNO
*)PyUNO_new_UNCHECKED( IdlStruct
, c
->xInvocation
);
269 PyRef
returnCandidate( (PyObject
*)me
, SAL_NO_ACQUIRE
);
270 if( PyTuple_Size( initializer
) > 0 )
272 TypeDescription
desc( typeName
);
273 OSL_ASSERT( desc
.is() ); // could already instantiate an XInvocation2 !
275 typelib_CompoundTypeDescription
*pCompType
=
276 ( typelib_CompoundTypeDescription
* ) desc
.get();
277 sal_Int32 n
= fillStructWithInitializer(
278 me
->members
->xInvocation
, pCompType
, initializer
, runtime
);
279 if( n
!= PyTuple_Size(initializer
) )
282 buf
.appendAscii( "pyuno._createUnoStructHelper: wrong number of ");
283 buf
.appendAscii( "elements in the initializer list, expected " );
285 buf
.appendAscii( ", got " );
286 buf
.append( (sal_Int32
) PyTuple_Size(initializer
) );
287 throw RuntimeException(
288 buf
.makeStringAndClear(), Reference
< XInterface
> ());
291 ret
= returnCandidate
;
296 buf
.append( "UNO struct " );
297 buf
.append( PyString_AsString(structName
) );
298 buf
.append( " is unkown" );
299 PyErr_SetString (PyExc_RuntimeError
, buf
.getStr());
306 "pyuno._createUnoStructHelper: 2nd argument (initializer sequence) is no tuple" );
311 PyErr_SetString (PyExc_AttributeError
, "createUnoStruct: first argument wasn't a string");
316 PyErr_SetString (PyExc_AttributeError
, "1 Arguments: Structure Name");
319 catch( com::sun::star::uno::RuntimeException
& e
)
321 raisePyExceptionWithAny( makeAny( e
) );
323 catch( com::sun::star::script::CannotConvertException
& e
)
325 raisePyExceptionWithAny( makeAny( e
) );
327 catch( com::sun::star::uno::Exception
& e
)
329 raisePyExceptionWithAny( makeAny( e
) );
331 return ret
.getAcquired();
334 static PyObject
*getTypeByName( PyObject
*, PyObject
*args
)
336 PyObject
* ret
= NULL
;
342 if (PyArg_ParseTuple (args
, const_cast< char * >("s"), &name
))
344 OUString
typeName ( OUString::createFromAscii( name
) );
345 TypeDescription
typeDesc( typeName
);
349 ret
= PyUNO_Type_new(
350 name
, (com::sun::star::uno::TypeClass
)typeDesc
.get()->eTypeClass
, runtime
);
355 buf
.append( "Type " ).append(name
).append( " is unknown" );
356 PyErr_SetString( PyExc_RuntimeError
, buf
.getStr() );
360 catch ( RuntimeException
& e
)
362 raisePyExceptionWithAny( makeAny( e
) );
367 static PyObject
*getConstantByName( PyObject
*, PyObject
*args
)
374 if (PyArg_ParseTuple (args
, const_cast< char * >("s"), &name
))
376 OUString
typeName ( OUString::createFromAscii( name
) );
378 Any a
= runtime
.getImpl()->cargo
->xTdMgr
->getByHierarchicalName(typeName
);
379 if( a
.getValueType().getTypeClass() ==
380 com::sun::star::uno::TypeClass_INTERFACE
)
382 // a idl constant cannot be an instance of an uno-object, thus
383 // this cannot be a constant
385 buf
.appendAscii( "pyuno.getConstantByName: " ).append( typeName
);
386 buf
.appendAscii( "is not a constant" );
387 throw RuntimeException(buf
.makeStringAndClear(), Reference
< XInterface
> () );
389 PyRef constant
= runtime
.any2PyObject( a
);
390 ret
= constant
.getAcquired();
393 catch( NoSuchElementException
& e
)
395 // to the python programmer, this is a runtime exception,
396 // do not support tweakings with the type system
397 RuntimeException
runExc( e
.Message
, Reference
< XInterface
> () );
398 raisePyExceptionWithAny( makeAny( runExc
) );
400 catch( com::sun::star::script::CannotConvertException
& e
)
402 raisePyExceptionWithAny( makeAny( e
) );
404 catch( com::sun::star::lang::IllegalArgumentException
& e
)
406 raisePyExceptionWithAny( makeAny( e
) );
408 catch( RuntimeException
& e
)
410 raisePyExceptionWithAny( makeAny(e
) );
415 static PyObject
*checkType( PyObject
*, PyObject
*args
)
417 if( !PyTuple_Check( args
) || PyTuple_Size( args
) != 1 )
420 buf
.append( "pyuno.checkType : expecting one uno.Type argument" );
421 PyErr_SetString( PyExc_RuntimeError
, buf
.getStr() );
424 PyObject
*obj
= PyTuple_GetItem( args
, 0 );
430 catch( RuntimeException
& e
)
432 raisePyExceptionWithAny( makeAny( e
) );
435 Py_INCREF( Py_None
);
439 static PyObject
*checkEnum( PyObject
*, PyObject
*args
)
441 if( !PyTuple_Check( args
) || PyTuple_Size( args
) != 1 )
444 buf
.append( "pyuno.checkType : expecting one uno.Type argument" );
445 PyErr_SetString( PyExc_RuntimeError
, buf
.getStr() );
448 PyObject
*obj
= PyTuple_GetItem( args
, 0 );
454 catch( RuntimeException
& e
)
456 raisePyExceptionWithAny( makeAny( e
) );
459 Py_INCREF( Py_None
);
463 static PyObject
*getClass( PyObject
*, PyObject
*args
)
465 PyObject
*obj
= extractOneStringArg( args
, "pyuno.getClass");
472 PyRef ret
= getClass(
473 OUString( PyString_AsString( obj
), strlen(PyString_AsString(obj
)),RTL_TEXTENCODING_ASCII_US
),
475 Py_XINCREF( ret
.get() );
478 catch( RuntimeException
& e
)
481 // gcc 3.2.3 crashes here in the regcomp test scenario
482 // only since migration to python 2.3.4 ???? strange thing
483 // optimization switched off for this module !
484 raisePyExceptionWithAny( makeAny(e
) );
489 static PyObject
*isInterface( PyObject
*, PyObject
*args
)
492 if( PyTuple_Check( args
) && PyTuple_Size( args
) == 1 )
494 PyObject
*obj
= PyTuple_GetItem( args
, 0 );
496 return PyInt_FromLong( isInterfaceClass( r
, obj
) );
498 return PyInt_FromLong( 0 );
501 static PyObject
* generateUuid( PyObject
*, PyObject
* )
503 Sequence
< sal_Int8
> seq( 16 );
504 rtl_createUuid( (sal_uInt8
*)seq
.getArray() , 0 , sal_False
);
509 ret
= runtime
.any2PyObject( makeAny( seq
) );
511 catch( RuntimeException
& e
)
513 raisePyExceptionWithAny( makeAny(e
) );
515 return ret
.getAcquired();
518 static PyObject
*systemPathToFileUrl( PyObject
*, PyObject
* args
)
520 PyObject
*obj
= extractOneStringArg( args
, "pyuno.systemPathToFileUrl" );
524 OUString sysPath
= pyString2ustring( obj
);
526 osl::FileBase::RC e
= osl::FileBase::getFileURLFromSystemPath( sysPath
, url
);
528 if( e
!= osl::FileBase::E_None
)
531 buf
.appendAscii( "Couldn't convert " );
532 buf
.append( sysPath
);
533 buf
.appendAscii( " to a file url for reason (" );
534 buf
.append( (sal_Int32
) e
);
535 buf
.appendAscii( ")" );
536 raisePyExceptionWithAny(
537 makeAny( RuntimeException( buf
.makeStringAndClear(), Reference
< XInterface
> () )));
540 return ustring2PyUnicode( url
).getAcquired();
543 static PyObject
* fileUrlToSystemPath( PyObject
*, PyObject
* args
)
545 PyObject
*obj
= extractOneStringArg( args
, "pyuno.fileUrlToSystemPath" );
549 OUString url
= pyString2ustring( obj
);
551 osl::FileBase::RC e
= osl::FileBase::getSystemPathFromFileURL( url
, sysPath
);
553 if( e
!= osl::FileBase::E_None
)
556 buf
.appendAscii( "Couldn't convert file url " );
557 buf
.append( sysPath
);
558 buf
.appendAscii( " to a system path for reason (" );
559 buf
.append( (sal_Int32
) e
);
560 buf
.appendAscii( ")" );
561 raisePyExceptionWithAny(
562 makeAny( RuntimeException( buf
.makeStringAndClear(), Reference
< XInterface
> () )));
565 return ustring2PyUnicode( sysPath
).getAcquired();
568 static PyObject
* absolutize( PyObject
*, PyObject
* args
)
570 if( PyTuple_Check( args
) && PyTuple_Size( args
) == 2 )
572 OUString ouPath
= pyString2ustring( PyTuple_GetItem( args
, 0 ) );
573 OUString ouRel
= pyString2ustring( PyTuple_GetItem( args
, 1 ) );
575 oslFileError e
= osl_getAbsoluteFileURL( ouPath
.pData
, ouRel
.pData
, &(ret
.pData
) );
576 if( e
!= osl_File_E_None
)
579 buf
.appendAscii( "Couldn't absolutize " );
581 buf
.appendAscii( " using root " );
582 buf
.append( ouPath
);
583 buf
.appendAscii( " for reason (" );
584 buf
.append( (sal_Int32
) e
);
585 buf
.appendAscii( ")" );
589 OUStringToOString(buf
.makeStringAndClear(),osl_getThreadTextEncoding()));
592 return ustring2PyUnicode( ret
).getAcquired();
597 static PyObject
* invoke ( PyObject
*, PyObject
* args
)
600 if( PyTuple_Check( args
) && PyTuple_Size( args
) == 3 )
602 PyObject
*object
= PyTuple_GetItem( args
, 0 );
604 if( PyString_Check( PyTuple_GetItem( args
, 1 ) ) )
606 const char *name
= PyString_AsString( PyTuple_GetItem( args
, 1 ) );
607 if( PyTuple_Check( PyTuple_GetItem( args
, 2 )))
609 ret
= PyUNO_invoke( object
, name
, PyTuple_GetItem( args
, 2 ) );
614 buf
.append( "uno.invoke expects a tuple as 3rd argument, got " );
615 buf
.append( PyString_AsString( PyObject_Str( PyTuple_GetItem( args
, 2) ) ) );
616 PyErr_SetString( PyExc_RuntimeError
, buf
.makeStringAndClear() );
622 buf
.append( "uno.invoke expected a string as 2nd argument, got " );
623 buf
.append( PyString_AsString( PyObject_Str( PyTuple_GetItem( args
, 1) ) ) );
624 PyErr_SetString( PyExc_RuntimeError
, buf
.makeStringAndClear() );
630 buf
.append( "uno.invoke expects object, name, (arg1, arg2, ... )\n" );
631 PyErr_SetString( PyExc_RuntimeError
, buf
.makeStringAndClear() );
636 static PyObject
*getCurrentContext( PyObject
*, PyObject
* )
642 ret
= runtime
.any2PyObject(
643 makeAny( com::sun::star::uno::getCurrentContext() ) );
645 catch( com::sun::star::uno::Exception
& e
)
647 raisePyExceptionWithAny( makeAny( e
) );
649 return ret
.getAcquired();
652 static PyObject
*setCurrentContext( PyObject
*, PyObject
* args
)
657 if( PyTuple_Check( args
) && PyTuple_Size( args
) == 1 )
661 Any a
= runtime
.pyObject2Any( PyTuple_GetItem( args
, 0 ) );
663 Reference
< com::sun::star::uno::XCurrentContext
> context
;
665 if( (a
.hasValue() && (a
>>= context
)) || ! a
.hasValue() )
667 ret
= com::sun::star::uno::setCurrentContext( context
) ? Py_True
: Py_False
;
672 buf
.append( "uno.setCurrentContext expects an XComponentContext implementation, got " );
673 buf
.append( PyString_AsString( PyObject_Str( PyTuple_GetItem( args
, 0) ) ) );
674 PyErr_SetString( PyExc_RuntimeError
, buf
.makeStringAndClear() );
680 buf
.append( "uno.setCurrentContext expects exactly one argument (the current Context)\n" );
681 PyErr_SetString( PyExc_RuntimeError
, buf
.makeStringAndClear() );
684 catch( com::sun::star::uno::Exception
& e
)
686 raisePyExceptionWithAny( makeAny( e
) );
688 return ret
.getAcquired();
693 struct PyMethodDef PyUNOModule_methods
[] =
695 {const_cast< char * >("getComponentContext"), getComponentContext
, 1, NULL
},
696 {const_cast< char * >("_createUnoStructHelper"), createUnoStructHelper
, 2, NULL
},
697 {const_cast< char * >("getTypeByName"), getTypeByName
, 1, NULL
},
698 {const_cast< char * >("getConstantByName"), getConstantByName
,1, NULL
},
699 {const_cast< char * >("getClass"), getClass
,1, NULL
},
700 {const_cast< char * >("checkEnum"), checkEnum
, 1, NULL
},
701 {const_cast< char * >("checkType"), checkType
, 1, NULL
},
702 {const_cast< char * >("generateUuid"), generateUuid
,0, NULL
},
703 {const_cast< char * >("systemPathToFileUrl"),systemPathToFileUrl
,1, NULL
},
704 {const_cast< char * >("fileUrlToSystemPath"),fileUrlToSystemPath
,1, NULL
},
705 {const_cast< char * >("absolutize"),absolutize
,2, NULL
},
706 {const_cast< char * >("isInterface"),isInterface
,1, NULL
},
707 {const_cast< char * >("invoke"),invoke
, 2, NULL
},
708 {const_cast< char * >("setCurrentContext"),setCurrentContext
,1, NULL
},
709 {const_cast< char * >("getCurrentContext"),getCurrentContext
,1, NULL
},
710 {NULL
, NULL
, 0, NULL
}
715 extern "C" PY_DLLEXPORT
void initpyuno()
717 // noop when called already, otherwise needed to allow multiple threads
718 PyEval_InitThreads();
719 Py_InitModule (const_cast< char * >("pyuno"), PyUNOModule_methods
);