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 = ustring2PyString( 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 *>(&PyClass_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 ustring2PyString(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 183 PyObject_SetAttrString( 184 ret.get(), const_cast< char * >("__pyunostruct__"), 185 ustring2PyString(name).get() ); 186 PyObject_SetAttrString( 187 ret.get(), const_cast< char * >("typeName"), 188 ustring2PyString(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 } 202 return ret; 203 } 204 205 bool isInstanceOfStructOrException( PyObject *obj) 206 { 207 PyRef attr( 208 PyObject_GetAttrString(obj, const_cast< char * >("__class__")), 209 SAL_NO_ACQUIRE ); 210 return PyObject_HasAttrString( 211 attr.get(), const_cast< char * >("__pyunostruct__")); 212 } 213 214 sal_Bool isInterfaceClass( const Runtime &runtime, PyObject * obj ) 215 { 216 const ClassSet & set = runtime.getImpl()->cargo->interfaceSet; 217 return set.find( obj ) != set.end(); 218 } 219 220 PyRef getClass( const OUString & name , const Runtime &runtime) 221 { 222 PyRef ret; 223 224 RuntimeCargo *cargo =runtime.getImpl()->cargo; 225 ExceptionClassMap::iterator ii = cargo->exceptionMap.find( name ); 226 if( ii == cargo->exceptionMap.end() ) 227 { 228 ret = createClass( name, runtime ); 229 cargo->exceptionMap[name] = ret; 230 if( PyObject_HasAttrString( 231 ret.get(), const_cast< char * >("__pyunointerface__") ) ) 232 cargo->interfaceSet.insert( ret ); 233 234 PyObject_SetAttrString( 235 ret.get(), const_cast< char * >("__pyunointerface__"), 236 ustring2PyString(name).get() ); 237 } 238 else 239 { 240 ret = ii->second; 241 } 242 243 return ret; 244 } 245 246 247 } 248