Update ooo320-m1
[ooovba.git] / pyuno / source / module / pyuno_module.cxx
blob2ed8dedfbb2415370dc7b6e6d32e1752a80dd348
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pyuno_module.cxx,v $
10 * $Revision: 1.14 $
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>
41 #include <rtl/uuid.h>
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>
51 using osl::Module;
53 using rtl::OString;
54 using rtl::OUString;
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;
75 namespace {
77 /**
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 )
86 sal_Int32 nIndex = 0;
87 if( pCompType->pBaseTypeDescription )
88 nIndex = fillStructWithInitializer(
89 inv, pCompType->pBaseTypeDescription, initializer, runtime );
91 sal_Int32 nTupleSize = PyTuple_Size(initializer);
92 int i;
93 for( i = 0 ; i < pCompType->nMembers ; i ++ )
95 if( i + nIndex >= nTupleSize )
97 OUStringBuffer buf;
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 );
107 return i+nIndex;
110 OUString getLibDir()
112 static OUString *pLibDir;
113 if( !pLibDir )
115 osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
116 if( ! pLibDir )
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 );
128 pLibDir = &libDir;
131 return *pLibDir;
134 void raisePySystemException( const char * exceptionType, const OUString & message )
136 OStringBuffer buf;
137 buf.append( "Error during bootstrapping uno (");
138 buf.append( exceptionType );
139 buf.append( "):" );
140 buf.append( OUStringToOString( message, osl_getThreadTextEncoding() ) );
141 PyErr_SetString( PyExc_SystemError, buf.makeStringAndClear().getStr() );
144 extern "C" {
146 static PyObject* getComponentContext (PyObject*, PyObject*)
148 PyRef ret;
151 Reference<XComponentContext> ctx;
153 // getLibDir() must be called in order to set bootstrap variables correctly !
154 OUString path( getLibDir());
155 if( Runtime::isInitialized() )
157 Runtime runtime;
158 ctx = runtime.getImpl()->cargo->xContext;
160 else
162 OUString iniFile;
163 if( !path.getLength() )
165 PyErr_SetString(
166 PyExc_RuntimeError, "osl_getUrlFromAddress fails, that's why I cannot find ini "
167 "file for bootstrapping python uno bridge\n" );
168 return NULL;
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);
183 else
185 // defaulting to the standard bootstrapping
186 PyThreadDetach antiguard;
187 ctx = cppu::defaultBootstrap_InitialComponentContext ();
192 if( ! Runtime::isInitialized() )
194 Runtime::initialize( ctx );
196 Runtime runtime;
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 )
229 OStringBuffer buf;
230 buf.append( funcName ).append( ": expecting one string argument" );
231 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
232 return NULL;
234 PyObject *obj = PyTuple_GetItem( args, 0 );
235 if( !PyString_Check( obj ) && ! PyUnicode_Check(obj))
237 OStringBuffer buf;
238 buf.append( funcName ).append( ": expecting one string argument" );
239 PyErr_SetString( PyExc_TypeError, buf.getStr());
240 return NULL;
242 return obj;
245 static PyObject *createUnoStructHelper(PyObject *, PyObject* args )
247 Any IdlStruct;
248 PyRef ret;
252 Runtime runtime;
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);
265 if (idl_class.is ())
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) )
281 OUStringBuffer buf;
282 buf.appendAscii( "pyuno._createUnoStructHelper: wrong number of ");
283 buf.appendAscii( "elements in the initializer list, expected " );
284 buf.append( n );
285 buf.appendAscii( ", got " );
286 buf.append( (sal_Int32) PyTuple_Size(initializer) );
287 throw RuntimeException(
288 buf.makeStringAndClear(), Reference< XInterface > ());
291 ret = returnCandidate;
293 else
295 OStringBuffer buf;
296 buf.append( "UNO struct " );
297 buf.append( PyString_AsString(structName) );
298 buf.append( " is unkown" );
299 PyErr_SetString (PyExc_RuntimeError, buf.getStr());
302 else
304 PyErr_SetString(
305 PyExc_RuntimeError,
306 "pyuno._createUnoStructHelper: 2nd argument (initializer sequence) is no tuple" );
309 else
311 PyErr_SetString (PyExc_AttributeError, "createUnoStruct: first argument wasn't a string");
314 else
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;
340 char *name;
342 if (PyArg_ParseTuple (args, const_cast< char * >("s"), &name))
344 OUString typeName ( OUString::createFromAscii( name ) );
345 TypeDescription typeDesc( typeName );
346 if( typeDesc.is() )
348 Runtime runtime;
349 ret = PyUNO_Type_new(
350 name, (com::sun::star::uno::TypeClass)typeDesc.get()->eTypeClass, runtime );
352 else
354 OStringBuffer buf;
355 buf.append( "Type " ).append(name).append( " is unknown" );
356 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
360 catch ( RuntimeException & e )
362 raisePyExceptionWithAny( makeAny( e ) );
364 return ret;
367 static PyObject *getConstantByName( PyObject *, PyObject *args )
369 PyObject *ret = 0;
372 char *name;
374 if (PyArg_ParseTuple (args, const_cast< char * >("s"), &name))
376 OUString typeName ( OUString::createFromAscii( name ) );
377 Runtime runtime;
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
384 OUStringBuffer buf;
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) );
412 return ret;
415 static PyObject *checkType( PyObject *, PyObject *args )
417 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
419 OStringBuffer buf;
420 buf.append( "pyuno.checkType : expecting one uno.Type argument" );
421 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
422 return NULL;
424 PyObject *obj = PyTuple_GetItem( args, 0 );
428 PyType2Type( obj );
430 catch( RuntimeException & e)
432 raisePyExceptionWithAny( makeAny( e ) );
433 return NULL;
435 Py_INCREF( Py_None );
436 return Py_None;
439 static PyObject *checkEnum( PyObject *, PyObject *args )
441 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
443 OStringBuffer buf;
444 buf.append( "pyuno.checkType : expecting one uno.Type argument" );
445 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
446 return NULL;
448 PyObject *obj = PyTuple_GetItem( args, 0 );
452 PyEnum2Enum( obj );
454 catch( RuntimeException & e)
456 raisePyExceptionWithAny( makeAny( e) );
457 return NULL;
459 Py_INCREF( Py_None );
460 return Py_None;
463 static PyObject *getClass( PyObject *, PyObject *args )
465 PyObject *obj = extractOneStringArg( args, "pyuno.getClass");
466 if( ! obj )
467 return NULL;
471 Runtime runtime;
472 PyRef ret = getClass(
473 OUString( PyString_AsString( obj), strlen(PyString_AsString(obj)),RTL_TEXTENCODING_ASCII_US),
474 runtime );
475 Py_XINCREF( ret.get() );
476 return ret.get();
478 catch( RuntimeException & e)
480 // NOOPT !!!
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) );
486 return NULL;
489 static PyObject *isInterface( PyObject *, PyObject *args )
492 if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
494 PyObject *obj = PyTuple_GetItem( args, 0 );
495 Runtime r;
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 );
505 PyRef ret;
508 Runtime runtime;
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" );
521 if( ! obj )
522 return NULL;
524 OUString sysPath = pyString2ustring( obj );
525 OUString url;
526 osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath( sysPath, url );
528 if( e != osl::FileBase::E_None )
530 OUStringBuffer buf;
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 > () )));
538 return NULL;
540 return ustring2PyUnicode( url ).getAcquired();
543 static PyObject * fileUrlToSystemPath( PyObject *, PyObject * args )
545 PyObject *obj = extractOneStringArg( args, "pyuno.fileUrlToSystemPath" );
546 if( ! obj )
547 return NULL;
549 OUString url = pyString2ustring( obj );
550 OUString sysPath;
551 osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( url, sysPath );
553 if( e != osl::FileBase::E_None )
555 OUStringBuffer buf;
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 > () )));
563 return NULL;
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 ) );
574 OUString ret;
575 oslFileError e = osl_getAbsoluteFileURL( ouPath.pData, ouRel.pData, &(ret.pData) );
576 if( e != osl_File_E_None )
578 OUStringBuffer buf;
579 buf.appendAscii( "Couldn't absolutize " );
580 buf.append( ouRel );
581 buf.appendAscii( " using root " );
582 buf.append( ouPath );
583 buf.appendAscii( " for reason (" );
584 buf.append( (sal_Int32) e );
585 buf.appendAscii( ")" );
587 PyErr_SetString(
588 PyExc_OSError,
589 OUStringToOString(buf.makeStringAndClear(),osl_getThreadTextEncoding()));
590 return 0;
592 return ustring2PyUnicode( ret ).getAcquired();
594 return 0;
597 static PyObject * invoke ( PyObject *, PyObject * args )
599 PyObject *ret = 0;
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 ) );
611 else
613 OStringBuffer buf;
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() );
619 else
621 OStringBuffer buf;
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() );
627 else
629 OStringBuffer buf;
630 buf.append( "uno.invoke expects object, name, (arg1, arg2, ... )\n" );
631 PyErr_SetString( PyExc_RuntimeError, buf.makeStringAndClear() );
633 return ret;
636 static PyObject *getCurrentContext( PyObject *, PyObject * )
638 PyRef ret;
641 Runtime runtime;
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 )
654 PyRef ret;
657 if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
660 Runtime runtime;
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;
669 else
671 OStringBuffer buf;
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() );
677 else
679 OStringBuffer buf;
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);