1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include "pyuno_impl.hxx"
28 
29 #include <osl/thread.h>
30 #include <rtl/ustrbuf.hxx>
31 
32 using rtl::OUStringToOString;
33 using rtl::OUString;
34 using com::sun::star::uno::Sequence;
35 using com::sun::star::uno::Reference;
36 using com::sun::star::uno::XInterface;
37 using com::sun::star::uno::Any;
38 using com::sun::star::uno::Type;
39 using com::sun::star::uno::TypeClass;
40 using com::sun::star::uno::RuntimeException;
41 using com::sun::star::uno::XComponentContext;
42 using com::sun::star::lang::XSingleServiceFactory;
43 using com::sun::star::script::XTypeConverter;
44 using com::sun::star::script::XInvocation2;
45 
46 namespace pyuno
47 {
48 typedef struct
49 {
50     Reference<XInvocation2> xInvocation;
51     Reference<XSingleServiceFactory> xInvocationFactory;
52     Reference<XTypeConverter> xTypeConverter;
53     OUString methodName;
54     ConversionMode mode;
55 } PyUNO_callable_Internals;
56 
57 typedef struct
58 {
59     PyObject_HEAD
60     PyUNO_callable_Internals* members;
61 } PyUNO_callable;
62 
63 void PyUNO_callable_del (PyObject* self)
64 {
65     PyUNO_callable* me;
66 
67     me = (PyUNO_callable*) self;
68     delete me->members;
69     PyObject_Del (self);
70 
71     return;
72 }
73 
74 PyObject* PyUNO_callable_call (PyObject* self, PyObject* args, PyObject*)
75 {
76     PyUNO_callable* me;
77 
78     Sequence<short> aOutParamIndex;
79     Sequence<Any> aOutParam;
80     Sequence<Any> aParams;
81     Sequence<Type> aParamTypes;
82     Any any_params;
83     Any out_params;
84     Any ret_value;
85     RuntimeCargo *cargo = 0;
86     me = (PyUNO_callable*) self;
87 
88     PyRef ret;
89     try
90     {
91         Runtime runtime;
92         cargo = runtime.getImpl()->cargo;
93         any_params = runtime.pyObject2Any (args, me->members->mode);
94 
95         if (any_params.getValueTypeClass () == com::sun::star::uno::TypeClass_SEQUENCE)
96         {
97             any_params >>= aParams;
98         }
99         else
100         {
101             aParams.realloc (1);
102             aParams [0] <<= any_params;
103         }
104 
105         {
106             PyThreadDetach antiguard; //pyhton free zone
107 
108             // do some logging if desired ...
109             if( isLog( cargo, LogLevel::CALL ) )
110             {
111                 logCall( cargo, "try     py->uno[0x", me->members->xInvocation.get(),
112                          me->members->methodName, aParams );
113             }
114 
115             // do the call
116             ret_value = me->members->xInvocation->invoke (
117                 me->members->methodName, aParams, aOutParamIndex, aOutParam);
118 
119             // log the reply, if desired
120             if( isLog( cargo, LogLevel::CALL ) )
121             {
122                 logReply( cargo, "success py->uno[0x", me->members->xInvocation.get(),
123                           me->members->methodName, ret_value, aOutParam);
124             }
125         }
126 
127 
128         PyRef temp = runtime.any2PyObject (ret_value);
129         if( aOutParam.getLength() )
130         {
131             PyRef return_list( PyTuple_New (1+aOutParam.getLength()), SAL_NO_ACQUIRE );
132             PyTuple_SetItem (return_list.get(), 0, temp.getAcquired());
133 
134             // initialize with defaults in case of exceptions
135             int i;
136             for( i = 1 ; i < 1+aOutParam.getLength() ; i ++ )
137             {
138                 Py_INCREF( Py_None );
139                 PyTuple_SetItem( return_list.get() , i , Py_None );
140             }
141 
142             for( i = 0 ; i < aOutParam.getLength() ; i ++ )
143             {
144                 PyRef ref = runtime.any2PyObject( aOutParam[i] );
145                 PyTuple_SetItem (return_list.get(), 1+i, ref.getAcquired());
146             }
147             ret = return_list;
148         }
149         else
150         {
151             ret = temp;
152         }
153     }
154     catch( com::sun::star::reflection::InvocationTargetException & e )
155     {
156 
157         if( isLog( cargo, LogLevel::CALL ) )
158         {
159             logException( cargo, "except  py->uno[0x", me->members->xInvocation.get() ,
160                           me->members->methodName, e.TargetException.getValue(), e.TargetException.getValueTypeRef());
161         }
162         raisePyExceptionWithAny( e.TargetException );
163     }
164     catch( com::sun::star::script::CannotConvertException &e )
165     {
166         if( isLog( cargo, LogLevel::CALL ) )
167         {
168             logException( cargo, "error  py->uno[0x", me->members->xInvocation.get() ,
169                           me->members->methodName, &e, getCppuType(&e).getTypeLibType());
170         }
171         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
172     }
173     catch( com::sun::star::lang::IllegalArgumentException &e )
174     {
175         if( isLog( cargo, LogLevel::CALL ) )
176         {
177             logException( cargo, "error  py->uno[0x", me->members->xInvocation.get() ,
178                           me->members->methodName, &e, getCppuType(&e).getTypeLibType());
179         }
180         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
181     }
182     catch (::com::sun::star::uno::RuntimeException &e)
183     {
184         if( cargo && isLog( cargo, LogLevel::CALL ) )
185         {
186             logException( cargo, "error  py->uno[0x", me->members->xInvocation.get() ,
187                           me->members->methodName, &e, getCppuType(&e).getTypeLibType());
188         }
189         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
190     }
191 
192     return ret.getAcquired();
193 }
194 
195 
196 static PyTypeObject PyUNO_callable_Type =
197 {
198     PyObject_HEAD_INIT (&PyType_Type)
199     0,
200     const_cast< char * >("PyUNO_callable"),
201     sizeof (PyUNO_callable),
202     0,
203     (destructor) ::pyuno::PyUNO_callable_del,
204     (printfunc) 0,
205     (getattrfunc) 0,
206     (setattrfunc) 0,
207     (cmpfunc) 0,
208     (reprfunc) 0,
209     0,
210     0,
211     0,
212     (hashfunc) 0,
213     (ternaryfunc) ::pyuno::PyUNO_callable_call,
214     (reprfunc) 0,
215         (getattrofunc)0,
216     (setattrofunc)0,
217     NULL,
218     0,
219     NULL,
220     (traverseproc)0,
221     (inquiry)0,
222     (richcmpfunc)0,
223     0,
224     (getiterfunc)0,
225     (iternextfunc)0,
226     NULL,
227     NULL,
228     NULL,
229     NULL,
230     NULL,
231     (descrgetfunc)0,
232     (descrsetfunc)0,
233     0,
234     (initproc)0,
235     (allocfunc)0,
236     (newfunc)0,
237     (freefunc)0,
238     (inquiry)0,
239     NULL,
240     NULL,
241     NULL,
242     NULL,
243     NULL,
244     (destructor)0
245 #if PY_VERSION_HEX >= 0x02060000
246     , 0
247 #endif
248 };
249 
250 PyRef PyUNO_callable_new (
251     const Reference<XInvocation2> &my_inv,
252     const OUString & methodName,
253     const Reference<XSingleServiceFactory> &xInvocationFactory,
254     const Reference<XTypeConverter> &tc,
255     enum ConversionMode mode )
256 {
257     PyUNO_callable* self;
258 
259     self = PyObject_New (PyUNO_callable, &PyUNO_callable_Type);
260     if (self == NULL)
261         return NULL; //NULL == Error!
262 
263     self->members = new PyUNO_callable_Internals;
264     self->members->xInvocation = my_inv;
265     self->members->methodName = methodName;
266     self->members->xInvocationFactory = xInvocationFactory;
267     self->members->xTypeConverter = tc;
268     self->members->mode = mode;
269 
270     return PyRef( (PyObject*)self, SAL_NO_ACQUIRE );
271 }
272 
273 }
274