1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23 #include "pyuno_impl.hxx"
24
25 #include <rtl/ustrbuf.hxx>
26 #include <rtl/strbuf.hxx>
27
28 #include <typelib/typedescription.hxx>
29
30 using rtl::OString;
31 using rtl::OUString;
32 using rtl::OUStringBuffer;
33 using rtl::OUStringToOString;
34 using rtl::OStringBuffer;
35
36 using com::sun::star::uno::TypeClass;
37 using com::sun::star::uno::Type;
38 using com::sun::star::uno::RuntimeException;
39 using com::sun::star::uno::Any;
40 using com::sun::star::uno::XInterface;
41 using com::sun::star::uno::Reference;
42 using com::sun::star::uno::TypeDescription;
43
44 #define USTR_ASCII(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
45 namespace pyuno
46 {
typeClassToString(TypeClass t)47 const char *typeClassToString( TypeClass t )
48 {
49 const char * ret = 0;
50 switch (t)
51 {
52 case com::sun::star::uno::TypeClass_VOID:
53 ret = "VOID"; break;
54 case com::sun::star::uno::TypeClass_CHAR:
55 ret = "CHAR"; break;
56 case com::sun::star::uno::TypeClass_BOOLEAN:
57 ret = "BOOLEAN"; break;
58 case com::sun::star::uno::TypeClass_BYTE:
59 ret = "BYTE"; break;
60 case com::sun::star::uno::TypeClass_SHORT:
61 ret = "SHORT"; break;
62 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
63 ret = "UNSIGNED_SHORT"; break;
64 case com::sun::star::uno::TypeClass_LONG:
65 ret = "LONG"; break;
66 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
67 ret = "UNSIGNED_LONG"; break;
68 case com::sun::star::uno::TypeClass_HYPER:
69 ret = "HYPER"; break;
70 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
71 ret = "UNSIGNED_HYPER"; break;
72 case com::sun::star::uno::TypeClass_FLOAT:
73 ret = "FLOAT"; break;
74 case com::sun::star::uno::TypeClass_DOUBLE:
75 ret = "DOUBLE"; break;
76 case com::sun::star::uno::TypeClass_STRING:
77 ret = "STRING"; break;
78 case com::sun::star::uno::TypeClass_TYPE:
79 ret = "TYPE"; break;
80 case com::sun::star::uno::TypeClass_ANY:
81 ret = "ANY";break;
82 case com::sun::star::uno::TypeClass_ENUM:
83 ret = "ENUM";break;
84 case com::sun::star::uno::TypeClass_STRUCT:
85 ret = "STRUCT"; break;
86 case com::sun::star::uno::TypeClass_EXCEPTION:
87 ret = "EXCEPTION"; break;
88 case com::sun::star::uno::TypeClass_SEQUENCE:
89 ret = "SEQUENCE"; break;
90 case com::sun::star::uno::TypeClass_INTERFACE:
91 ret = "INTERFACE"; break;
92 case com::sun::star::uno::TypeClass_TYPEDEF:
93 ret = "TYPEDEF"; break;
94 case com::sun::star::uno::TypeClass_UNION:
95 ret = "UNION"; break;
96 case com::sun::star::uno::TypeClass_ARRAY:
97 ret = "ARRAY"; break;
98 case com::sun::star::uno::TypeClass_SERVICE:
99 ret = "SERVICE"; break;
100 case com::sun::star::uno::TypeClass_MODULE:
101 ret = "MODULE"; break;
102 case com::sun::star::uno::TypeClass_INTERFACE_METHOD:
103 ret = "INTERFACE_METHOD"; break;
104 case com::sun::star::uno::TypeClass_INTERFACE_ATTRIBUTE:
105 ret = "INTERFACE_ATTRIBUTE"; break;
106 default:
107 ret = "UNKNOWN"; break;
108 }
109 return ret;
110 }
111
getClass(const Runtime & r,const char * name)112 static PyRef getClass( const Runtime & r , const char * name)
113 {
114 return PyRef( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*) name ) );
115 }
116
getTypeClass(const Runtime & r)117 PyRef getTypeClass( const Runtime & r )
118 {
119 return getClass( r , "Type" );
120 }
121
getEnumClass(const Runtime & r)122 PyRef getEnumClass( const Runtime & r )
123 {
124 return getClass( r , "Enum" );
125 }
126
getCharClass(const Runtime & r)127 PyRef getCharClass( const Runtime & r )
128 {
129 return getClass( r , "Char" );
130 }
131
getByteSequenceClass(const Runtime & r)132 PyRef getByteSequenceClass( const Runtime & r )
133 {
134 return getClass( r , "ByteSequence" );
135 }
136
getAnyClass(const Runtime & r)137 PyRef getAnyClass( const Runtime & r )
138 {
139 return getClass( r , "Any" );
140 }
141
142
PyChar2Unicode(PyObject * obj)143 sal_Unicode PyChar2Unicode( PyObject *obj ) throw ( RuntimeException )
144 {
145 PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE );
146 if( ! PyUnicode_Check( value.get() ) )
147 {
148 throw RuntimeException(
149 USTR_ASCII( "attribute value of uno.Char is not a unicode string" ),
150 Reference< XInterface > () );
151 }
152
153 #if PY_VERSION_HEX >= 0x030C0000
154 if( PyUnicode_GetLength( value.get() ) < 1 )
155 #else
156 if( PyUnicode_GetSize( value.get() ) < 1 )
157 #endif
158 {
159 throw RuntimeException(
160 USTR_ASCII( "uno.Char contains an empty unicode string" ),
161 Reference< XInterface > () );
162 }
163 #if PY_VERSION_HEX >= 0x03030000
164 sal_Unicode c = (sal_Unicode)PyUnicode_ReadChar( value.get(), 0 );
165 #else
166 sal_Unicode c = (sal_Unicode)PyUnicode_AsUnicode( value.get() )[0];
167 #endif
168 return c;
169 }
170
PyEnum2Enum(PyObject * obj)171 Any PyEnum2Enum( PyObject *obj ) throw ( RuntimeException )
172 {
173 Any ret;
174 PyRef typeName( PyObject_GetAttrString( obj,const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
175 PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE);
176 if( !PYSTR_CHECK( typeName.get() ) || ! PYSTR_CHECK( value.get() ) )
177 {
178 throw RuntimeException(
179 USTR_ASCII( "attributes typeName and/or value of uno.Enum are not strings" ),
180 Reference< XInterface > () );
181 }
182
183 OUString strTypeName( pyString2ustring( typeName.get() ) );
184 OUString strValue( pyString2ustring( value.get() ) );
185
186 TypeDescription desc( strTypeName );
187 if( desc.is() )
188 {
189 if(desc.get()->eTypeClass != typelib_TypeClass_ENUM )
190 {
191 OUStringBuffer buf;
192 buf.appendAscii( "pyuno.checkEnum: " ).append( strTypeName ).appendAscii( " is a " );
193 buf.appendAscii(
194 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
195 buf.appendAscii( ", expected ENUM" );
196 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
197 }
198
199 desc.makeComplete();
200
201 typelib_EnumTypeDescription *pEnumDesc = (typelib_EnumTypeDescription*) desc.get();
202 int i = 0;
203 for( i = 0; i < pEnumDesc->nEnumValues ; i ++ )
204 {
205 if( (*((OUString *)&pEnumDesc->ppEnumNames[i])).compareTo( strValue ) == 0 )
206 {
207 break;
208 }
209 }
210 if( i == pEnumDesc->nEnumValues )
211 {
212 OUStringBuffer buf;
213 buf.appendAscii( "value " ).append( strValue ).appendAscii( " is unknown in enum " );
214 buf.append( strTypeName );
215 throw RuntimeException( buf.makeStringAndClear(), Reference<XInterface> () );
216 }
217 ret = Any( &pEnumDesc->pEnumValues[i], desc.get()->pWeakRef );
218 }
219 else
220 {
221 OUStringBuffer buf;
222 buf.appendAscii( "enum " ).append( strTypeName ).appendAscii( " is unknown" );
223 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
224 }
225 return ret;
226 }
227
228
PyType2Type(PyObject * o)229 Type PyType2Type( PyObject * o ) throw(RuntimeException )
230 {
231 PyRef pyName( PyObject_GetAttrString( o, const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
232 if( !PYSTR_CHECK( pyName.get() ) )
233 {
234 throw RuntimeException(
235 USTR_ASCII( "type object does not have typeName property" ),
236 Reference< XInterface > () );
237 }
238
239 PyRef pyTC( PyObject_GetAttrString( o, const_cast< char * >("typeClass") ), SAL_NO_ACQUIRE );
240 Any enumValue = PyEnum2Enum( pyTC.get() );
241
242 OUString name( pyString2ustring( pyName.get() ) );
243 TypeDescription desc( name );
244 if( ! desc.is() )
245 {
246 OUStringBuffer buf;
247 buf.appendAscii( "type " ).append(name).appendAscii( " is unknown" );
248 throw RuntimeException(
249 buf.makeStringAndClear(), Reference< XInterface > () );
250 }
251 if( desc.get()->eTypeClass != (typelib_TypeClass) *(sal_Int32*)enumValue.getValue() )
252 {
253 OUStringBuffer buf;
254 buf.appendAscii( "pyuno.checkType: " ).append(name).appendAscii( " is a " );
255 buf.appendAscii( typeClassToString( (TypeClass) desc.get()->eTypeClass) );
256 buf.appendAscii( ", but type got construct with typeclass " );
257 buf.appendAscii( typeClassToString( (TypeClass) *(sal_Int32*)enumValue.getValue() ) );
258 throw RuntimeException(
259 buf.makeStringAndClear(), Reference< XInterface > () );
260 }
261 return desc.get()->pWeakRef;
262 }
263
importToGlobal(PyObject * str,PyObject * dict,PyObject * target)264 PyObject *importToGlobal(PyObject *str, PyObject *dict, PyObject *target)
265 {
266 // maybe a constant ?
267 PyObject *ret = 0;
268 OUString name = pyString2ustring(str);
269 try
270 {
271 Runtime runtime;
272 TypeDescription desc(name );
273 desc.makeComplete();
274 if( desc.is() )
275 {
276 com::sun::star::uno::TypeClass tc =
277 (com::sun::star::uno::TypeClass)desc.get()->eTypeClass;
278
279 PyRef typesModule( PyDict_GetItemString( dict, "unotypes" ) );
280 if( ! typesModule.is() || ! PyModule_Check( typesModule.get() ))
281 {
282 typesModule = PyRef( PyModule_New( const_cast< char * >("unotypes") ), SAL_NO_ACQUIRE );
283 Py_INCREF( typesModule.get() );
284 PyDict_SetItemString( dict, "unotypes" , typesModule.get() );
285 }
286 #if PY_VERSION_HEX >= 0x03030000
287 const char *targetName = PyUnicode_AsUTF8( target );
288 const char *typeName = PyUnicode_AsUTF8( str );
289 #elif PY_MAJOR_VERSION > 3
290 PyRef pUtf8( PyUnicode_AsUTF8String( target ), SAL_NO_ACQUIRE );
291 const char *targetName = PyBytes_AsString( pUtf8.get() );
292 PyRef pTypeName( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
293 const char *typeName = PyBytes_AsString( pTypeName.get() );
294 #else
295 /*const*/ char *targetName = PyBytes_AsString( target );
296 const char *typeName = PyBytes_AsString( str );
297 #endif
298 PyModule_AddObject(
299 typesModule.get(),
300 targetName,
301 PyUNO_Type_new( typeName, tc, runtime ) );
302
303 if( com::sun::star::uno::TypeClass_EXCEPTION == tc ||
304 com::sun::star::uno::TypeClass_STRUCT == tc )
305 {
306 PyRef exc = getClass( name, runtime );
307 PyDict_SetItem( dict, target, exc.getAcquired() );
308 }
309 else if( com::sun::star::uno::TypeClass_ENUM == tc )
310 {
311 // introduce all enums into the dictionary !
312 typelib_EnumTypeDescription *pDesc =
313 (typelib_EnumTypeDescription *) desc.get();
314 for( int i = 0 ; i < pDesc->nEnumValues; i ++ )
315 {
316 OString enumElementName(
317 OUStringToOString( pDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US) );
318 #if PY_VERSION_HEX >= 0x03030000
319 const char *name = PyUnicode_AsUTF8(str);
320 #elif PY_MAJOR_VERSION > 3
321 PyRef *pUtf8( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
322 const char *name = PyBytes_AsString( pUtf8.get() );
323 #else
324 const char *name = PyBytes_AsString(str);
325 #endif
326 PyDict_SetItemString(
327 dict, (char*)enumElementName.getStr(),
328 PyUNO_Enum_new(name, enumElementName.getStr(), runtime ) );
329 }
330 }
331 Py_INCREF( Py_None );
332 ret = Py_None;
333 }
334 else
335 {
336 Any a = runtime.getImpl()->cargo->xTdMgr->getByHierarchicalName(name);
337 if(a.hasValue())
338 {
339 PyRef constant = runtime.any2PyObject( a );
340 if( constant.is() )
341 {
342 Py_INCREF( constant.get() );
343 PyDict_SetItem( dict, target , constant.get());
344 ret = constant.get();
345 }
346 else
347 {
348 OUStringBuffer buf;
349 buf.appendAscii( "constant " ).append(pyString2ustring(str)).appendAscii( " unknown" );
350 PyErr_SetString(
351 PyExc_RuntimeError,
352 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr() );
353 }
354 }
355 else
356 {
357 OUStringBuffer buf;
358 buf.appendAscii( "pyuno.imp unknown type " );
359 buf.append( name );
360 PyErr_SetString(
361 PyExc_RuntimeError,
362 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
363 }
364 }
365 }
366 catch( com::sun::star::container::NoSuchElementException & )
367 {
368 OUStringBuffer buf;
369 buf.appendAscii( "pyuno.imp unknown type " );
370 buf.append( name );
371 PyErr_SetString(
372 PyExc_RuntimeError,
373 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
374 }
375 catch( com::sun::star::script::CannotConvertException & e )
376 {
377 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
378 }
379 catch( com::sun::star::lang::IllegalArgumentException & e )
380 {
381 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
382 }
383 catch( RuntimeException &e )
384 {
385 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ));
386 }
387 return ret;
388 }
389
callCtor(const Runtime & r,const char * clazz,const PyRef & args)390 static PyObject* callCtor( const Runtime &r , const char * clazz, const PyRef & args )
391 {
392 PyRef code( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*)clazz ) );
393 if( ! code.is() )
394 {
395 OStringBuffer buf;
396 buf.append( "couldn't access uno." );
397 buf.append( clazz );
398 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
399 return NULL;
400 }
401 PyRef instance( PyObject_CallObject( code.get(), args.get() ), SAL_NO_ACQUIRE);
402 Py_XINCREF( instance.get() );
403 return instance.get();
404
405 }
406
407
PyUNO_Enum_new(const char * enumBase,const char * enumValue,const Runtime & r)408 PyObject *PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r )
409 {
410 PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
411 PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( enumBase ) );
412 PyTuple_SetItem( args.get() , 1 , PYSTR_FROMSTR( enumValue ) );
413
414 return callCtor( r, "Enum" , args );
415 }
416
417
PyUNO_Type_new(const char * typeName,TypeClass t,const Runtime & r)418 PyObject* PyUNO_Type_new (const char *typeName , TypeClass t , const Runtime &r )
419 {
420 // retrieve type object
421 PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
422
423 PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( typeName ) );
424 PyObject *typeClass = PyUNO_Enum_new( "com.sun.star.uno.TypeClass" , typeClassToString(t), r );
425 if( ! typeClass )
426 return NULL;
427 PyTuple_SetItem( args.get() , 1 , typeClass);
428
429 return callCtor( r, "Type" , args );
430 }
431
PyUNO_char_new(sal_Unicode val,const Runtime & r)432 PyObject* PyUNO_char_new ( sal_Unicode val , const Runtime &r )
433 {
434 // retrieve type object
435 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
436
437 #if PY_VERSION_HEX >= 0x03030000
438 Py_UCS2 u[1];
439 u[0] = val;
440 PyTuple_SetItem( args.get(), 0, PyUnicode_FromKindAndData( PyUnicode_2BYTE_KIND, u, 1 ) );
441 #else
442 Py_UNICODE u[2];
443 u[0] = val;
444 u[1] = 0;
445 PyTuple_SetItem( args.get() , 0 , PyUnicode_FromUnicode( u ,1) );
446 #endif
447
448 return callCtor( r, "Char" , args );
449 }
450
PyUNO_ByteSequence_new(const com::sun::star::uno::Sequence<sal_Int8> & byteSequence,const Runtime & r)451 PyObject *PyUNO_ByteSequence_new(
452 const com::sun::star::uno::Sequence< sal_Int8 > &byteSequence, const Runtime &r )
453 {
454 PyRef str(
455 PyBytes_FromStringAndSize( (char*)byteSequence.getConstArray(), byteSequence.getLength()),
456 SAL_NO_ACQUIRE );
457 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
458 PyTuple_SetItem( args.get() , 0 , str.getAcquired() );
459 return callCtor( r, "ByteSequence" , args );
460
461 }
462 }
463