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 { 90 // assuming that this is never deleted ! 91 // note I don't have the knowledge how to initialize these type objects correctly ! 92 TypeDescription desc( name ); 93 if( ! desc.is() ) 94 { 95 OUStringBuffer buf; 96 buf.appendAscii( "pyuno.getClass: uno exception " ); 97 buf.append(name).appendAscii( " is unknown" ); 98 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 99 } 100 101 sal_Bool isStruct = desc.get()->eTypeClass == typelib_TypeClass_STRUCT; 102 sal_Bool isExc = desc.get()->eTypeClass == typelib_TypeClass_EXCEPTION; 103 sal_Bool isInterface = desc.get()->eTypeClass == typelib_TypeClass_INTERFACE; 104 if( !isStruct && !isExc && ! isInterface ) 105 { 106 OUStringBuffer buf; 107 buf.appendAscii( "pyuno.getClass: " ).append(name).appendAscii( "is a " ); 108 buf.appendAscii( 109 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass)); 110 buf.appendAscii( ", expected EXCEPTION, STRUCT or INTERFACE" ); 111 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>() ); 112 } 113 114 // retrieve base class 115 PyRef base; 116 if( isInterface ) 117 { 118 typelib_InterfaceTypeDescription *pDesc = (typelib_InterfaceTypeDescription * )desc.get(); 119 if( pDesc->pBaseTypeDescription ) 120 { 121 base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime ); 122 } 123 else 124 { 125 // must be XInterface ! 126 } 127 } 128 else 129 { 130 typelib_CompoundTypeDescription *pDesc = (typelib_CompoundTypeDescription*)desc.get(); 131 if( pDesc->pBaseTypeDescription ) 132 { 133 base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime ); 134 } 135 else 136 { 137 if( isExc ) 138 // we are currently creating the root UNO exception 139 base = PyRef(PyExc_Exception); 140 } 141 } 142 PyRef args( PyTuple_New( 3 ), SAL_NO_ACQUIRE ); 143 144 PyRef pyTypeName = USTR_TO_PYSTR( name /*.replace( '.', '_' )*/ ); 145 146 PyRef bases; 147 if( base.is() ) 148 { 149 { // for CC, keeping ref-count being 1 150 bases = PyRef( PyTuple_New( 1 ), SAL_NO_ACQUIRE ); 151 } 152 PyTuple_SetItem( bases.get(), 0 , base.getAcquired() ); 153 } 154 else 155 { 156 bases = PyRef( PyTuple_New( 0 ), SAL_NO_ACQUIRE ); 157 } 158 159 PyTuple_SetItem( args.get(), 0, pyTypeName.getAcquired()); 160 PyTuple_SetItem( args.get(), 1, bases.getAcquired() ); 161 PyTuple_SetItem( args.get(), 2, PyDict_New() ); 162 163 PyRef ret( 164 PyObject_CallObject(reinterpret_cast<PyObject *>(&PyType_Type) , args.get()), 165 SAL_NO_ACQUIRE ); 166 167 // now overwrite ctor and attrib functions 168 if( isInterface ) 169 { 170 PyObject_SetAttrString( 171 ret.get(), const_cast< char * >("__pyunointerface__"), 172 USTR_TO_PYSTR(name).get() ); 173 } 174 else 175 { 176 PyRef ctor = getObjectFromUnoModule( runtime,"_uno_struct__init__" ); 177 PyRef setter = getObjectFromUnoModule( runtime,"_uno_struct__setattr__" ); 178 PyRef getter = getObjectFromUnoModule( runtime,"_uno_struct__getattr__" ); 179 PyRef repr = getObjectFromUnoModule( runtime,"_uno_struct__repr__" ); 180 PyRef eq = getObjectFromUnoModule( runtime,"_uno_struct__eq__" ); 181 PyRef dir = getObjectFromUnoModule( runtime, "_uno_struct__dir__" ); 182 183 PyObject_SetAttrString( 184 ret.get(), const_cast< char * >("__pyunostruct__"), 185 USTR_TO_PYSTR(name).get() ); 186 PyObject_SetAttrString( 187 ret.get(), const_cast< char * >("typeName"), 188 USTR_TO_PYSTR(name).get() ); 189 PyObject_SetAttrString( 190 ret.get(), const_cast< char * >("__init__"), ctor.get() ); 191 PyObject_SetAttrString( 192 ret.get(), const_cast< char * >("__getattr__"), getter.get() ); 193 PyObject_SetAttrString( 194 ret.get(), const_cast< char * >("__setattr__"), setter.get() ); 195 PyObject_SetAttrString( 196 ret.get(), const_cast< char * >("__repr__"), repr.get() ); 197 PyObject_SetAttrString( 198 ret.get(), const_cast< char * >("__str__"), repr.get() ); 199 PyObject_SetAttrString( 200 ret.get(), const_cast< char * >("__eq__"), eq.get() ); 201 PyObject_SetAttrString( 202 ret.get(), const_cast< char * >("__dir__"), dir.get() ); 203 } 204 return ret; 205 } 206 207 bool isInstanceOfStructOrException( PyObject *obj) 208 { 209 PyRef attr( 210 PyObject_GetAttrString(obj, const_cast< char * >("__class__")), 211 SAL_NO_ACQUIRE ); 212 return PyObject_HasAttrString( 213 attr.get(), const_cast< char * >("__pyunostruct__")); 214 } 215 216 sal_Bool isInterfaceClass( const Runtime &runtime, PyObject * obj ) 217 { 218 const ClassSet & set = runtime.getImpl()->cargo->interfaceSet; 219 return set.find( obj ) != set.end(); 220 } 221 222 PyRef getClass( const OUString & name , const Runtime &runtime) 223 { 224 PyRef ret; 225 226 RuntimeCargo *cargo =runtime.getImpl()->cargo; 227 ExceptionClassMap::iterator ii = cargo->exceptionMap.find( name ); 228 if( ii == cargo->exceptionMap.end() ) 229 { 230 ret = createClass( name, runtime ); 231 cargo->exceptionMap[name] = ret; 232 if( PyObject_HasAttrString( 233 ret.get(), const_cast< char * >("__pyunointerface__") ) ) 234 cargo->interfaceSet.insert( ret ); 235 236 PyObject_SetAttrString( 237 ret.get(), const_cast< char * >("__pyunointerface__"), 238 USTR_TO_PYSTR(name).get() ); 239 } 240 else 241 { 242 ret = ii->second; 243 } 244 245 return ret; 246 } 247 248 249 } 250