xref: /trunk/main/pyuno/source/module/pyuno_except.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 
raisePyExceptionWithAny(const com::sun::star::uno::Any & anyExc)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 
createClass(const OUString & name,const Runtime & runtime)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 
isInstanceOfStructOrException(PyObject * obj)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 
isInterfaceClass(const Runtime & runtime,PyObject * obj)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 
getClass(const OUString & name,const Runtime & runtime)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