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 27 #include <typelib/typedescription.hxx> 28 29 using rtl::OUString; 30 using rtl::OUStringBuffer; 31 using rtl::OUStringToOString; 32 33 using com::sun::star::uno::RuntimeException; 34 using com::sun::star::uno::Sequence; 35 using com::sun::star::uno::Type; 36 using com::sun::star::uno::Reference; 37 using com::sun::star::uno::XInterface; 38 using com::sun::star::uno::TypeDescription; 39 40 namespace pyuno 41 { 42 43 void raisePyExceptionWithAny( const com::sun::star::uno::Any &anyExc ) 44 { 45 try 46 { 47 Runtime runtime; 48 PyRef exc = runtime.any2PyObject( anyExc ); 49 if( exc.is() ) 50 { 51 PyRef type( getClass( anyExc.getValueType().getTypeName(),runtime ) ); 52 PyErr_SetObject( type.get(), exc.get()); 53 } 54 else 55 { 56 com::sun::star::uno::Exception e; 57 anyExc >>= e; 58 59 OUStringBuffer buf; 60 buf.appendAscii( "Couldn't convert uno exception to a python exception (" ); 61 buf.append(anyExc.getValueType().getTypeName()); 62 buf.appendAscii( ": " ); 63 buf.append(e.Message ); 64 buf.appendAscii( ")" ); 65 PyErr_SetString( 66 PyExc_SystemError, 67 OUStringToOString(buf.makeStringAndClear(),RTL_TEXTENCODING_ASCII_US) ); 68 } 69 } 70 catch( com::sun::star::lang::IllegalArgumentException & e) 71 { 72 PyErr_SetString( PyExc_SystemError, 73 OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) ); 74 } 75 catch( com::sun::star::script::CannotConvertException & e) 76 { 77 PyErr_SetString( PyExc_SystemError, 78 OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) ); 79 } 80 catch( RuntimeException & e) 81 { 82 PyErr_SetString( PyExc_SystemError, 83 OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) ); 84 } 85 } 86 87 88 static PyRef createClass( const OUString & name, const Runtime &runtime ) 89 throw ( RuntimeException ) 90 { 91 // assuming that this is never deleted ! 92 // note I don't have the knowledge how to initialize these type objects correctly ! 93 TypeDescription desc( name ); 94 if( ! desc.is() ) 95 { 96 OUStringBuffer buf; 97 buf.appendAscii( "pyuno.getClass: uno exception " ); 98 buf.append(name).appendAscii( " is unknown" ); 99 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 100 } 101 102 sal_Bool isStruct = desc.get()->eTypeClass == typelib_TypeClass_STRUCT; 103 sal_Bool isExc = desc.get()->eTypeClass == typelib_TypeClass_EXCEPTION; 104 sal_Bool isInterface = desc.get()->eTypeClass == typelib_TypeClass_INTERFACE; 105 if( !isStruct && !isExc && ! isInterface ) 106 { 107 OUStringBuffer buf; 108 buf.appendAscii( "pyuno.getClass: " ).append(name).appendAscii( "is a " ); 109 buf.appendAscii( 110 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass)); 111 buf.appendAscii( ", expected EXCEPTION, STRUCT or INTERFACE" ); 112 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>() ); 113 } 114 115 // retrieve base class 116 PyRef base; 117 if( isInterface ) 118 { 119 typelib_InterfaceTypeDescription *pDesc = (typelib_InterfaceTypeDescription * )desc.get(); 120 if( pDesc->pBaseTypeDescription ) 121 { 122 base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime ); 123 } 124 else 125 { 126 // must be XInterface ! 127 } 128 } 129 else 130 { 131 typelib_CompoundTypeDescription *pDesc = (typelib_CompoundTypeDescription*)desc.get(); 132 if( pDesc->pBaseTypeDescription ) 133 { 134 base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime ); 135 } 136 else 137 { 138 if( isExc ) 139 // we are currently creating the root UNO exception 140 base = PyRef(PyExc_Exception); 141 } 142 } 143 PyRef args( PyTuple_New( 3 ), SAL_NO_ACQUIRE ); 144 145 PyRef pyTypeName = USTR_TO_PYSTR( name /*.replace( '.', '_' )*/ ); 146 147 PyRef bases; 148 if( base.is() ) 149 { 150 { // for CC, keeping ref-count being 1 151 bases = PyRef( PyTuple_New( 1 ), SAL_NO_ACQUIRE ); 152 } 153 PyTuple_SetItem( bases.get(), 0 , base.getAcquired() ); 154 } 155 else 156 { 157 bases = PyRef( PyTuple_New( 0 ), SAL_NO_ACQUIRE ); 158 } 159 160 PyTuple_SetItem( args.get(), 0, pyTypeName.getAcquired()); 161 PyTuple_SetItem( args.get(), 1, bases.getAcquired() ); 162 PyTuple_SetItem( args.get(), 2, PyDict_New() ); 163 164 PyRef ret( 165 PyObject_CallObject(reinterpret_cast<PyObject *>(&PyType_Type) , args.get()), 166 SAL_NO_ACQUIRE ); 167 168 // now overwrite ctor and attrib functions 169 if( isInterface ) 170 { 171 PyObject_SetAttrString( 172 ret.get(), const_cast< char * >("__pyunointerface__"), 173 USTR_TO_PYSTR(name).get() ); 174 } 175 else 176 { 177 PyRef ctor = getObjectFromUnoModule( runtime,"_uno_struct__init__" ); 178 PyRef setter = getObjectFromUnoModule( runtime,"_uno_struct__setattr__" ); 179 PyRef getter = getObjectFromUnoModule( runtime,"_uno_struct__getattr__" ); 180 PyRef repr = getObjectFromUnoModule( runtime,"_uno_struct__repr__" ); 181 PyRef eq = getObjectFromUnoModule( runtime,"_uno_struct__eq__" ); 182 #if PY_MAJOR_VERSION >= 3 183 PyRef dir = getObjectFromUnoModule( runtime, "_uno_struct__dir__" ); 184 #endif 185 186 PyObject_SetAttrString( 187 ret.get(), const_cast< char * >("__pyunostruct__"), 188 USTR_TO_PYSTR(name).get() ); 189 PyObject_SetAttrString( 190 ret.get(), const_cast< char * >("typeName"), 191 USTR_TO_PYSTR(name).get() ); 192 PyObject_SetAttrString( 193 ret.get(), const_cast< char * >("__init__"), ctor.get() ); 194 PyObject_SetAttrString( 195 ret.get(), const_cast< char * >("__getattr__"), getter.get() ); 196 PyObject_SetAttrString( 197 ret.get(), const_cast< char * >("__setattr__"), setter.get() ); 198 PyObject_SetAttrString( 199 ret.get(), const_cast< char * >("__repr__"), repr.get() ); 200 PyObject_SetAttrString( 201 ret.get(), const_cast< char * >("__str__"), repr.get() ); 202 PyObject_SetAttrString( 203 ret.get(), const_cast< char * >("__eq__"), eq.get() ); 204 #if PY_MAJOR_VERSION >= 3 205 PyObject_SetAttrString( 206 ret.get(), const_cast< char * >("__dir__"), dir.get() ); 207 #endif 208 } 209 return ret; 210 } 211 212 bool isInstanceOfStructOrException( PyObject *obj) 213 { 214 PyRef attr( 215 PyObject_GetAttrString(obj, const_cast< char * >("__class__")), 216 SAL_NO_ACQUIRE ); 217 return PyObject_HasAttrString( 218 attr.get(), const_cast< char * >("__pyunostruct__")); 219 } 220 221 sal_Bool isInterfaceClass( const Runtime &runtime, PyObject * obj ) 222 { 223 const ClassSet & set = runtime.getImpl()->cargo->interfaceSet; 224 return set.find( obj ) != set.end(); 225 } 226 227 PyRef getClass( const OUString & name , const Runtime &runtime) 228 { 229 PyRef ret; 230 231 RuntimeCargo *cargo =runtime.getImpl()->cargo; 232 ExceptionClassMap::iterator ii = cargo->exceptionMap.find( name ); 233 if( ii == cargo->exceptionMap.end() ) 234 { 235 ret = createClass( name, runtime ); 236 cargo->exceptionMap[name] = ret; 237 if( PyObject_HasAttrString( 238 ret.get(), const_cast< char * >("__pyunointerface__") ) ) 239 cargo->interfaceSet.insert( ret ); 240 241 PyObject_SetAttrString( 242 ret.get(), const_cast< char * >("__pyunointerface__"), 243 USTR_TO_PYSTR(name).get() ); 244 } 245 else 246 { 247 ret = ii->second; 248 } 249 250 return ret; 251 } 252 253 254 } 255