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( PyUnicode_GetSize( value.get() ) < 1 )
154 {
155 throw RuntimeException(
156 USTR_ASCII( "uno.Char contains an empty unicode string" ),
157 Reference< XInterface > () );
158 }
159 #if PY_VERSION_HEX >= 0x03030000
160 sal_Unicode c = (sal_Unicode)PyUnicode_ReadChar( value.get(), 0 );
161 #else
162 sal_Unicode c = (sal_Unicode)PyUnicode_AsUnicode( value.get() )[0];
163 #endif
164 return c;
165 }
166
PyEnum2Enum(PyObject * obj)167 Any PyEnum2Enum( PyObject *obj ) throw ( RuntimeException )
168 {
169 Any ret;
170 PyRef typeName( PyObject_GetAttrString( obj,const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
171 PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE);
172 if( !PYSTR_CHECK( typeName.get() ) || ! PYSTR_CHECK( value.get() ) )
173 {
174 throw RuntimeException(
175 USTR_ASCII( "attributes typeName and/or value of uno.Enum are not strings" ),
176 Reference< XInterface > () );
177 }
178
179 OUString strTypeName( pyString2ustring( typeName.get() ) );
180 OUString strValue( pyString2ustring( value.get() ) );
181
182 TypeDescription desc( strTypeName );
183 if( desc.is() )
184 {
185 if(desc.get()->eTypeClass != typelib_TypeClass_ENUM )
186 {
187 OUStringBuffer buf;
188 buf.appendAscii( "pyuno.checkEnum: " ).append( strTypeName ).appendAscii( " is a " );
189 buf.appendAscii(
190 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
191 buf.appendAscii( ", expected ENUM" );
192 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
193 }
194
195 desc.makeComplete();
196
197 typelib_EnumTypeDescription *pEnumDesc = (typelib_EnumTypeDescription*) desc.get();
198 int i = 0;
199 for( i = 0; i < pEnumDesc->nEnumValues ; i ++ )
200 {
201 if( (*((OUString *)&pEnumDesc->ppEnumNames[i])).compareTo( strValue ) == 0 )
202 {
203 break;
204 }
205 }
206 if( i == pEnumDesc->nEnumValues )
207 {
208 OUStringBuffer buf;
209 buf.appendAscii( "value " ).append( strValue ).appendAscii( " is unknown in enum " );
210 buf.append( strTypeName );
211 throw RuntimeException( buf.makeStringAndClear(), Reference<XInterface> () );
212 }
213 ret = Any( &pEnumDesc->pEnumValues[i], desc.get()->pWeakRef );
214 }
215 else
216 {
217 OUStringBuffer buf;
218 buf.appendAscii( "enum " ).append( strTypeName ).appendAscii( " is unknown" );
219 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
220 }
221 return ret;
222 }
223
224
PyType2Type(PyObject * o)225 Type PyType2Type( PyObject * o ) throw(RuntimeException )
226 {
227 PyRef pyName( PyObject_GetAttrString( o, const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
228 if( !PYSTR_CHECK( pyName.get() ) )
229 {
230 throw RuntimeException(
231 USTR_ASCII( "type object does not have typeName property" ),
232 Reference< XInterface > () );
233 }
234
235 PyRef pyTC( PyObject_GetAttrString( o, const_cast< char * >("typeClass") ), SAL_NO_ACQUIRE );
236 Any enumValue = PyEnum2Enum( pyTC.get() );
237
238 OUString name( pyString2ustring( pyName.get() ) );
239 TypeDescription desc( name );
240 if( ! desc.is() )
241 {
242 OUStringBuffer buf;
243 buf.appendAscii( "type " ).append(name).appendAscii( " is unknown" );
244 throw RuntimeException(
245 buf.makeStringAndClear(), Reference< XInterface > () );
246 }
247 if( desc.get()->eTypeClass != (typelib_TypeClass) *(sal_Int32*)enumValue.getValue() )
248 {
249 OUStringBuffer buf;
250 buf.appendAscii( "pyuno.checkType: " ).append(name).appendAscii( " is a " );
251 buf.appendAscii( typeClassToString( (TypeClass) desc.get()->eTypeClass) );
252 buf.appendAscii( ", but type got construct with typeclass " );
253 buf.appendAscii( typeClassToString( (TypeClass) *(sal_Int32*)enumValue.getValue() ) );
254 throw RuntimeException(
255 buf.makeStringAndClear(), Reference< XInterface > () );
256 }
257 return desc.get()->pWeakRef;
258 }
259
importToGlobal(PyObject * str,PyObject * dict,PyObject * target)260 PyObject *importToGlobal(PyObject *str, PyObject *dict, PyObject *target)
261 {
262 // maybe a constant ?
263 PyObject *ret = 0;
264 OUString name = pyString2ustring(str);
265 try
266 {
267 Runtime runtime;
268 TypeDescription desc(name );
269 desc.makeComplete();
270 if( desc.is() )
271 {
272 com::sun::star::uno::TypeClass tc =
273 (com::sun::star::uno::TypeClass)desc.get()->eTypeClass;
274
275 PyRef typesModule( PyDict_GetItemString( dict, "unotypes" ) );
276 if( ! typesModule.is() || ! PyModule_Check( typesModule.get() ))
277 {
278 typesModule = PyRef( PyModule_New( const_cast< char * >("unotypes") ), SAL_NO_ACQUIRE );
279 Py_INCREF( typesModule.get() );
280 PyDict_SetItemString( dict, "unotypes" , typesModule.get() );
281 }
282 #if PY_VERSION_HEX >= 0x03030000
283 const char *targetName = PyUnicode_AsUTF8( target );
284 const char *typeName = PyUnicode_AsUTF8( str );
285 #elif PY_MAJOR_VERSION > 3
286 PyRef pUtf8( PyUnicode_AsUTF8String( target ), SAL_NO_ACQUIRE );
287 const char *targetName = PyBytes_AsString( pUtf8.get() );
288 PyRef pTypeName( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
289 const char *typeName = PyBytes_AsString( pTypeName.get() );
290 #else
291 /*const*/ char *targetName = PyBytes_AsString( target );
292 const char *typeName = PyBytes_AsString( str );
293 #endif
294 PyModule_AddObject(
295 typesModule.get(),
296 targetName,
297 PyUNO_Type_new( typeName, tc, runtime ) );
298
299 if( com::sun::star::uno::TypeClass_EXCEPTION == tc ||
300 com::sun::star::uno::TypeClass_STRUCT == tc )
301 {
302 PyRef exc = getClass( name, runtime );
303 PyDict_SetItem( dict, target, exc.getAcquired() );
304 }
305 else if( com::sun::star::uno::TypeClass_ENUM == tc )
306 {
307 // introduce all enums into the dictionary !
308 typelib_EnumTypeDescription *pDesc =
309 (typelib_EnumTypeDescription *) desc.get();
310 for( int i = 0 ; i < pDesc->nEnumValues; i ++ )
311 {
312 OString enumElementName(
313 OUStringToOString( pDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US) );
314 #if PY_VERSION_HEX >= 0x03030000
315 const char *name = PyUnicode_AsUTF8(str);
316 #elif PY_MAJOR_VERSION > 3
317 PyRef *pUtf8( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
318 const char *name = PyBytes_AsString( pUtf8.get() );
319 #else
320 const char *name = PyBytes_AsString(str);
321 #endif
322 PyDict_SetItemString(
323 dict, (char*)enumElementName.getStr(),
324 PyUNO_Enum_new(name, enumElementName.getStr(), runtime ) );
325 }
326 }
327 Py_INCREF( Py_None );
328 ret = Py_None;
329 }
330 else
331 {
332 Any a = runtime.getImpl()->cargo->xTdMgr->getByHierarchicalName(name);
333 if(a.hasValue())
334 {
335 PyRef constant = runtime.any2PyObject( a );
336 if( constant.is() )
337 {
338 Py_INCREF( constant.get() );
339 PyDict_SetItem( dict, target , constant.get());
340 ret = constant.get();
341 }
342 else
343 {
344 OUStringBuffer buf;
345 buf.appendAscii( "constant " ).append(pyString2ustring(str)).appendAscii( " unknown" );
346 PyErr_SetString(
347 PyExc_RuntimeError,
348 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr() );
349 }
350 }
351 else
352 {
353 OUStringBuffer buf;
354 buf.appendAscii( "pyuno.imp unknown type " );
355 buf.append( name );
356 PyErr_SetString(
357 PyExc_RuntimeError,
358 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
359 }
360 }
361 }
362 catch( com::sun::star::container::NoSuchElementException & )
363 {
364 OUStringBuffer buf;
365 buf.appendAscii( "pyuno.imp unknown type " );
366 buf.append( name );
367 PyErr_SetString(
368 PyExc_RuntimeError,
369 OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
370 }
371 catch( com::sun::star::script::CannotConvertException & e )
372 {
373 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
374 }
375 catch( com::sun::star::lang::IllegalArgumentException & e )
376 {
377 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
378 }
379 catch( RuntimeException &e )
380 {
381 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ));
382 }
383 return ret;
384 }
385
callCtor(const Runtime & r,const char * clazz,const PyRef & args)386 static PyObject* callCtor( const Runtime &r , const char * clazz, const PyRef & args )
387 {
388 PyRef code( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*)clazz ) );
389 if( ! code.is() )
390 {
391 OStringBuffer buf;
392 buf.append( "couldn't access uno." );
393 buf.append( clazz );
394 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
395 return NULL;
396 }
397 PyRef instance( PyObject_CallObject( code.get(), args.get() ), SAL_NO_ACQUIRE);
398 Py_XINCREF( instance.get() );
399 return instance.get();
400
401 }
402
403
PyUNO_Enum_new(const char * enumBase,const char * enumValue,const Runtime & r)404 PyObject *PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r )
405 {
406 PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
407 PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( enumBase ) );
408 PyTuple_SetItem( args.get() , 1 , PYSTR_FROMSTR( enumValue ) );
409
410 return callCtor( r, "Enum" , args );
411 }
412
413
PyUNO_Type_new(const char * typeName,TypeClass t,const Runtime & r)414 PyObject* PyUNO_Type_new (const char *typeName , TypeClass t , const Runtime &r )
415 {
416 // retrieve type object
417 PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
418
419 PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( typeName ) );
420 PyObject *typeClass = PyUNO_Enum_new( "com.sun.star.uno.TypeClass" , typeClassToString(t), r );
421 if( ! typeClass )
422 return NULL;
423 PyTuple_SetItem( args.get() , 1 , typeClass);
424
425 return callCtor( r, "Type" , args );
426 }
427
PyUNO_char_new(sal_Unicode val,const Runtime & r)428 PyObject* PyUNO_char_new ( sal_Unicode val , const Runtime &r )
429 {
430 // retrieve type object
431 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
432
433 #if PY_VERSION_HEX >= 0x03030000
434 Py_UCS2 u[1];
435 u[0] = val;
436 PyTuple_SetItem( args.get(), 0, PyUnicode_FromKindAndData( PyUnicode_2BYTE_KIND, u, 1 ) );
437 #else
438 Py_UNICODE u[2];
439 u[0] = val;
440 u[1] = 0;
441 PyTuple_SetItem( args.get() , 0 , PyUnicode_FromUnicode( u ,1) );
442 #endif
443
444 return callCtor( r, "Char" , args );
445 }
446
PyUNO_ByteSequence_new(const com::sun::star::uno::Sequence<sal_Int8> & byteSequence,const Runtime & r)447 PyObject *PyUNO_ByteSequence_new(
448 const com::sun::star::uno::Sequence< sal_Int8 > &byteSequence, const Runtime &r )
449 {
450 PyRef str(
451 PyBytes_FromStringAndSize( (char*)byteSequence.getConstArray(), byteSequence.getLength()),
452 SAL_NO_ACQUIRE );
453 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
454 PyTuple_SetItem( args.get() , 0 , str.getAcquired() );
455 return callCtor( r, "ByteSequence" , args );
456
457 }
458 }
459