1*61dff127SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*61dff127SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*61dff127SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*61dff127SAndrew Rist  * distributed with this work for additional information
6*61dff127SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*61dff127SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*61dff127SAndrew Rist  * "License"); you may not use this file except in compliance
9*61dff127SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*61dff127SAndrew Rist  *
11*61dff127SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*61dff127SAndrew Rist  *
13*61dff127SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*61dff127SAndrew Rist  * software distributed under the License is distributed on an
15*61dff127SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*61dff127SAndrew Rist  * KIND, either express or implied.  See the License for the
17*61dff127SAndrew Rist  * specific language governing permissions and limitations
18*61dff127SAndrew Rist  * under the License.
19*61dff127SAndrew Rist  *
20*61dff127SAndrew Rist  *************************************************************/
21*61dff127SAndrew Rist 
22*61dff127SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_bridges.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <sal/alloca.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "jni_bridge.h"
30cdf0e10cSrcweir //#include "jni_finalizer.h"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <algorithm>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir 
37cdf0e10cSrcweir using namespace ::rtl;
38cdf0e10cSrcweir 
39cdf0e10cSrcweir namespace jni_uno
40cdf0e10cSrcweir {
41cdf0e10cSrcweir 
42cdf0e10cSrcweir //______________________________________________________________________________
map_to_java(JNI_context const & jni,uno_Interface * pUnoI,JNI_interface_type_info const * info) const43cdf0e10cSrcweir jobject Bridge::map_to_java(
44cdf0e10cSrcweir     JNI_context const & jni,
45cdf0e10cSrcweir     uno_Interface * pUnoI, JNI_interface_type_info const * info ) const
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     // get oid
48cdf0e10cSrcweir     rtl_uString * pOid = 0;
49cdf0e10cSrcweir     (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
50cdf0e10cSrcweir     OSL_ASSERT( 0 != pOid );
51cdf0e10cSrcweir     OUString oid( pOid, SAL_NO_ACQUIRE );
52cdf0e10cSrcweir 
53cdf0e10cSrcweir     // opt getRegisteredInterface()
54cdf0e10cSrcweir     JLocalAutoRef jo_oid( jni, ustring_to_jstring( jni, oid.pData ) );
55cdf0e10cSrcweir     jvalue args[ 2 ];
56cdf0e10cSrcweir     args[ 0 ].l = jo_oid.get();
57cdf0e10cSrcweir     args[ 1 ].l = info->m_type;
58cdf0e10cSrcweir     jobject jo_iface = jni->CallObjectMethodA(
59cdf0e10cSrcweir         m_jni_info->m_object_java_env,
60cdf0e10cSrcweir         m_jni_info->m_method_IEnvironment_getRegisteredInterface, args );
61cdf0e10cSrcweir     jni.ensure_no_exception();
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     if (0 == jo_iface) // no registered iface
64cdf0e10cSrcweir     {
65cdf0e10cSrcweir         // register uno interface
66cdf0e10cSrcweir         (*m_uno_env->registerInterface)(
67cdf0e10cSrcweir             m_uno_env, reinterpret_cast< void ** >( &pUnoI ),
68cdf0e10cSrcweir             oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
69cdf0e10cSrcweir 
70cdf0e10cSrcweir         // create java and register java proxy
71cdf0e10cSrcweir         jvalue args2[ 7 ];
72cdf0e10cSrcweir         acquire();
73cdf0e10cSrcweir         args2[ 0 ].j = reinterpret_cast< sal_Int64 >( this );
74cdf0e10cSrcweir         (*pUnoI->acquire)( pUnoI );
75cdf0e10cSrcweir         args2[ 1 ].l = m_jni_info->m_object_java_env;
76cdf0e10cSrcweir         args2[ 2 ].j = reinterpret_cast< sal_Int64 >( pUnoI );
77cdf0e10cSrcweir         typelib_typedescription_acquire( info->m_td.get() );
78cdf0e10cSrcweir         args2[ 3 ].j = reinterpret_cast< sal_Int64 >( info->m_td.get() );
79cdf0e10cSrcweir         args2[ 4 ].l = info->m_type;
80cdf0e10cSrcweir         args2[ 5 ].l = jo_oid.get();
81cdf0e10cSrcweir         args2[ 6 ].l = info->m_proxy_ctor;
82cdf0e10cSrcweir         jo_iface = jni->CallStaticObjectMethodA(
83cdf0e10cSrcweir             m_jni_info->m_class_JNI_proxy,
84cdf0e10cSrcweir             m_jni_info->m_method_JNI_proxy_create, args2 );
85cdf0e10cSrcweir         jni.ensure_no_exception();
86cdf0e10cSrcweir     }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     OSL_ASSERT( 0 != jo_iface );
89cdf0e10cSrcweir     return jo_iface;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 
93cdf0e10cSrcweir //______________________________________________________________________________
handle_uno_exc(JNI_context const & jni,uno_Any * uno_exc) const94cdf0e10cSrcweir void Bridge::handle_uno_exc( JNI_context const & jni, uno_Any * uno_exc ) const
95cdf0e10cSrcweir {
96cdf0e10cSrcweir     if (typelib_TypeClass_EXCEPTION == uno_exc->pType->eTypeClass)
97cdf0e10cSrcweir     {
98cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
99cdf0e10cSrcweir         // append java stack trace to Message member
100cdf0e10cSrcweir         reinterpret_cast< ::com::sun::star::uno::Exception * >(
101cdf0e10cSrcweir             uno_exc->pData )->Message += jni.get_stack_trace();
102cdf0e10cSrcweir #endif
103cdf0e10cSrcweir 
104cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
105cdf0e10cSrcweir         {
106cdf0e10cSrcweir         OUStringBuffer buf( 128 );
107cdf0e10cSrcweir         buf.appendAscii(
108cdf0e10cSrcweir             RTL_CONSTASCII_STRINGPARAM("exception occured java->uno: [") );
109cdf0e10cSrcweir         buf.append( OUString::unacquired( &uno_exc->pType->pTypeName ) );
110cdf0e10cSrcweir         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
111cdf0e10cSrcweir         buf.append(
112cdf0e10cSrcweir             reinterpret_cast< ::com::sun::star::uno::Exception const * >(
113cdf0e10cSrcweir                 uno_exc->pData )->Message );
114cdf0e10cSrcweir         OString cstr_msg(
115cdf0e10cSrcweir             OUStringToOString(
116cdf0e10cSrcweir                 buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
117cdf0e10cSrcweir         OSL_TRACE( cstr_msg.getStr() );
118cdf0e10cSrcweir         }
119cdf0e10cSrcweir #endif
120cdf0e10cSrcweir         // signal exception
121cdf0e10cSrcweir         jvalue java_exc;
122cdf0e10cSrcweir         try
123cdf0e10cSrcweir         {
124cdf0e10cSrcweir             map_to_java(
125cdf0e10cSrcweir                 jni, &java_exc, uno_exc->pData, uno_exc->pType, 0,
126cdf0e10cSrcweir                 true /* in */, false /* no out */ );
127cdf0e10cSrcweir         }
128cdf0e10cSrcweir         catch (...)
129cdf0e10cSrcweir         {
130cdf0e10cSrcweir             uno_any_destruct( uno_exc, 0 );
131cdf0e10cSrcweir             throw;
132cdf0e10cSrcweir         }
133cdf0e10cSrcweir         uno_any_destruct( uno_exc, 0 );
134cdf0e10cSrcweir 
135cdf0e10cSrcweir         JLocalAutoRef jo_exc( jni, java_exc.l );
136cdf0e10cSrcweir         jint res = jni->Throw( (jthrowable) jo_exc.get() );
137cdf0e10cSrcweir         if (0 != res)
138cdf0e10cSrcweir         {
139cdf0e10cSrcweir             // call toString()
140cdf0e10cSrcweir             JLocalAutoRef jo_descr(
141cdf0e10cSrcweir                 jni, jni->CallObjectMethodA(
142cdf0e10cSrcweir                     jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) );
143cdf0e10cSrcweir             jni.ensure_no_exception();
144cdf0e10cSrcweir             OUStringBuffer buf( 128 );
145cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
146cdf0e10cSrcweir                                  "throwing java exception failed: ") );
147cdf0e10cSrcweir             buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
148cdf0e10cSrcweir             buf.append( jni.get_stack_trace() );
149cdf0e10cSrcweir             throw BridgeRuntimeError( buf.makeStringAndClear() );
150cdf0e10cSrcweir         }
151cdf0e10cSrcweir     }
152cdf0e10cSrcweir     else
153cdf0e10cSrcweir     {
154cdf0e10cSrcweir         OUString message(
155cdf0e10cSrcweir             OUSTR("thrown exception is no uno exception: ") +
156cdf0e10cSrcweir             OUString::unacquired( &uno_exc->pType->pTypeName ) +
157cdf0e10cSrcweir             jni.get_stack_trace() );
158cdf0e10cSrcweir         uno_any_destruct( uno_exc, 0 );
159cdf0e10cSrcweir         throw BridgeRuntimeError( message );
160cdf0e10cSrcweir     }
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir union largest
164cdf0e10cSrcweir {
165cdf0e10cSrcweir     sal_Int64 n;
166cdf0e10cSrcweir     double d;
167cdf0e10cSrcweir     void * p;
168cdf0e10cSrcweir     uno_Any a;
169cdf0e10cSrcweir };
170cdf0e10cSrcweir 
171cdf0e10cSrcweir //______________________________________________________________________________
call_uno(JNI_context const & jni,uno_Interface * pUnoI,typelib_TypeDescription * member_td,typelib_TypeDescriptionReference * return_type,sal_Int32 nParams,typelib_MethodParameter const * pParams,jobjectArray jo_args) const172cdf0e10cSrcweir jobject Bridge::call_uno(
173cdf0e10cSrcweir     JNI_context const & jni,
174cdf0e10cSrcweir     uno_Interface * pUnoI, typelib_TypeDescription * member_td,
175cdf0e10cSrcweir     typelib_TypeDescriptionReference * return_type,
176cdf0e10cSrcweir     sal_Int32 nParams, typelib_MethodParameter const * pParams,
177cdf0e10cSrcweir     jobjectArray jo_args /* may be 0 */ ) const
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     // return mem
180cdf0e10cSrcweir     sal_Int32 return_size;
181cdf0e10cSrcweir     switch (return_type->eTypeClass) {
182cdf0e10cSrcweir     case typelib_TypeClass_VOID:
183cdf0e10cSrcweir         return_size = 0;
184cdf0e10cSrcweir         break;
185cdf0e10cSrcweir 
186cdf0e10cSrcweir     case typelib_TypeClass_STRUCT:
187cdf0e10cSrcweir     case typelib_TypeClass_EXCEPTION:
188cdf0e10cSrcweir         return_size = std::max(
189cdf0e10cSrcweir             TypeDescr(return_type).get()->nSize,
190cdf0e10cSrcweir             static_cast< sal_Int32 >(sizeof (largest)));
191cdf0e10cSrcweir         break;
192cdf0e10cSrcweir 
193cdf0e10cSrcweir     default:
194cdf0e10cSrcweir         return_size = sizeof (largest);
195cdf0e10cSrcweir         break;
196cdf0e10cSrcweir     }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
199cdf0e10cSrcweir     char * mem = (char *) malloc(
200cdf0e10cSrcweir #else
201cdf0e10cSrcweir     char * mem = (char *) alloca(
202cdf0e10cSrcweir #endif
203cdf0e10cSrcweir         (nParams * sizeof (void *)) +
204cdf0e10cSrcweir         return_size + (nParams * sizeof (largest)) );
205cdf0e10cSrcweir     void ** uno_args = (void **) mem;
206cdf0e10cSrcweir     void * uno_ret = return_size == 0 ? 0 : (mem + (nParams * sizeof (void *)));
207cdf0e10cSrcweir     largest * uno_args_mem = (largest *)
208cdf0e10cSrcweir         (mem + (nParams * sizeof (void *)) + return_size);
209cdf0e10cSrcweir 
210cdf0e10cSrcweir     OSL_ASSERT( (0 == nParams) || (nParams == jni->GetArrayLength( jo_args )) );
211cdf0e10cSrcweir     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
212cdf0e10cSrcweir     {
213cdf0e10cSrcweir         typelib_MethodParameter const & param = pParams[ nPos ];
214cdf0e10cSrcweir         typelib_TypeDescriptionReference * type = param.pTypeRef;
215cdf0e10cSrcweir 
216cdf0e10cSrcweir         uno_args[ nPos ] = &uno_args_mem[ nPos ];
217cdf0e10cSrcweir         if (typelib_TypeClass_STRUCT == type->eTypeClass ||
218cdf0e10cSrcweir             typelib_TypeClass_EXCEPTION == type->eTypeClass)
219cdf0e10cSrcweir         {
220cdf0e10cSrcweir             TypeDescr td( type );
221cdf0e10cSrcweir             if (sal::static_int_cast< sal_uInt32 >(td.get()->nSize)
222cdf0e10cSrcweir                 > sizeof (largest))
223cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
224cdf0e10cSrcweir                 uno_args[ nPos ] = malloc( td.get()->nSize );
225cdf0e10cSrcweir #else
226cdf0e10cSrcweir                 uno_args[ nPos ] = alloca( td.get()->nSize );
227cdf0e10cSrcweir #endif
228cdf0e10cSrcweir         }
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         if (param.bIn)
231cdf0e10cSrcweir         {
232cdf0e10cSrcweir             try
233cdf0e10cSrcweir             {
234cdf0e10cSrcweir                 JLocalAutoRef jo_arg(
235cdf0e10cSrcweir                     jni, jni->GetObjectArrayElement( jo_args, nPos ) );
236cdf0e10cSrcweir                 jni.ensure_no_exception();
237cdf0e10cSrcweir                 jvalue java_arg;
238cdf0e10cSrcweir                 java_arg.l = jo_arg.get();
239cdf0e10cSrcweir                 map_to_uno(
240cdf0e10cSrcweir                     jni, uno_args[ nPos ], java_arg, type, 0,
241cdf0e10cSrcweir                     false /* no assign */, sal_False != param.bOut,
242cdf0e10cSrcweir                     true /* special wrapped integral types */ );
243cdf0e10cSrcweir             }
244cdf0e10cSrcweir             catch (...)
245cdf0e10cSrcweir             {
246cdf0e10cSrcweir                 // cleanup uno in args
247cdf0e10cSrcweir                 for ( sal_Int32 n = 0; n < nPos; ++n )
248cdf0e10cSrcweir                 {
249cdf0e10cSrcweir                     typelib_MethodParameter const & p = pParams[ n ];
250cdf0e10cSrcweir                     if (p.bIn)
251cdf0e10cSrcweir                     {
252cdf0e10cSrcweir                         uno_type_destructData(
253cdf0e10cSrcweir                             uno_args[ n ], p.pTypeRef, 0 );
254cdf0e10cSrcweir                     }
255cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
256cdf0e10cSrcweir 		    if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ])
257cdf0e10cSrcweir 			free( uno_args[ nPos ] );
258cdf0e10cSrcweir #endif
259cdf0e10cSrcweir                 }
260cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
261cdf0e10cSrcweir 		free( mem );
262cdf0e10cSrcweir #endif
263cdf0e10cSrcweir                 throw;
264cdf0e10cSrcweir             }
265cdf0e10cSrcweir         }
266cdf0e10cSrcweir     }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir     uno_Any uno_exc_holder;
269cdf0e10cSrcweir     uno_Any * uno_exc = &uno_exc_holder;
270cdf0e10cSrcweir     // call binary uno
271cdf0e10cSrcweir     (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     if (0 == uno_exc)
274cdf0e10cSrcweir     {
275cdf0e10cSrcweir         // convert out args; destruct uno args
276cdf0e10cSrcweir         for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
277cdf0e10cSrcweir         {
278cdf0e10cSrcweir             typelib_MethodParameter const & param = pParams[ nPos ];
279cdf0e10cSrcweir             typelib_TypeDescriptionReference * type = param.pTypeRef;
280cdf0e10cSrcweir             if (param.bOut)
281cdf0e10cSrcweir             {
282cdf0e10cSrcweir                 try
283cdf0e10cSrcweir                 {
284cdf0e10cSrcweir                     // get out holder array[ 1 ]
285cdf0e10cSrcweir                     JLocalAutoRef jo_out_holder(
286cdf0e10cSrcweir                         jni, jni->GetObjectArrayElement( jo_args, nPos ) );
287cdf0e10cSrcweir                     jni.ensure_no_exception();
288cdf0e10cSrcweir                     jvalue java_arg;
289cdf0e10cSrcweir                     java_arg.l = jo_out_holder.get();
290cdf0e10cSrcweir                     map_to_java(
291cdf0e10cSrcweir                         jni, &java_arg, uno_args[ nPos ], type, 0,
292cdf0e10cSrcweir                         true /* in */, true /* out holder */ );
293cdf0e10cSrcweir                 }
294cdf0e10cSrcweir                 catch (...)
295cdf0e10cSrcweir                 {
296cdf0e10cSrcweir                     // cleanup further uno args
297cdf0e10cSrcweir                     for ( sal_Int32 n = nPos; n < nParams; ++n )
298cdf0e10cSrcweir                     {
299cdf0e10cSrcweir                         uno_type_destructData(
300cdf0e10cSrcweir                             uno_args[ n ], pParams[ n ].pTypeRef, 0 );
301cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
302cdf0e10cSrcweir 			if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ])
303cdf0e10cSrcweir 			    free( uno_args[ nPos ] );
304cdf0e10cSrcweir #endif
305cdf0e10cSrcweir                     }
306cdf0e10cSrcweir                     // cleanup uno return value
307cdf0e10cSrcweir                     uno_type_destructData( uno_ret, return_type, 0 );
308cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
309cdf0e10cSrcweir 		    free( mem );
310cdf0e10cSrcweir #endif
311cdf0e10cSrcweir                     throw;
312cdf0e10cSrcweir                 }
313cdf0e10cSrcweir             }
314cdf0e10cSrcweir             if (typelib_TypeClass_DOUBLE < type->eTypeClass &&
315cdf0e10cSrcweir                 typelib_TypeClass_ENUM != type->eTypeClass) // opt
316cdf0e10cSrcweir             {
317cdf0e10cSrcweir                 uno_type_destructData( uno_args[ nPos ], type, 0 );
318cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
319cdf0e10cSrcweir 		if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ])
320cdf0e10cSrcweir 		    free( uno_args[ nPos ] );
321cdf0e10cSrcweir #endif
322cdf0e10cSrcweir             }
323cdf0e10cSrcweir         }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir         if (typelib_TypeClass_VOID != return_type->eTypeClass)
326cdf0e10cSrcweir         {
327cdf0e10cSrcweir             // convert uno return value
328cdf0e10cSrcweir             jvalue java_ret;
329cdf0e10cSrcweir             try
330cdf0e10cSrcweir             {
331cdf0e10cSrcweir                 map_to_java(
332cdf0e10cSrcweir                     jni, &java_ret, uno_ret, return_type, 0,
333cdf0e10cSrcweir                     true /* in */, false /* no out */,
334cdf0e10cSrcweir                     true /* special_wrapped_integral_types */ );
335cdf0e10cSrcweir             }
336cdf0e10cSrcweir             catch (...)
337cdf0e10cSrcweir             {
338cdf0e10cSrcweir                 uno_type_destructData( uno_ret, return_type, 0 );
339cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
340cdf0e10cSrcweir 		free( mem );
341cdf0e10cSrcweir #endif
342cdf0e10cSrcweir                 throw;
343cdf0e10cSrcweir             }
344cdf0e10cSrcweir             if (typelib_TypeClass_DOUBLE < return_type->eTypeClass &&
345cdf0e10cSrcweir                 typelib_TypeClass_ENUM != return_type->eTypeClass) // opt
346cdf0e10cSrcweir             {
347cdf0e10cSrcweir                 uno_type_destructData( uno_ret, return_type, 0 );
348cdf0e10cSrcweir             }
349cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
350cdf0e10cSrcweir 	    free( mem );
351cdf0e10cSrcweir #endif
352cdf0e10cSrcweir             return java_ret.l;
353cdf0e10cSrcweir         }
354cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
355cdf0e10cSrcweir 	free( mem );
356cdf0e10cSrcweir #endif
357cdf0e10cSrcweir         return 0; // void return
358cdf0e10cSrcweir     }
359cdf0e10cSrcweir     else // exception occured
360cdf0e10cSrcweir     {
361cdf0e10cSrcweir         // destruct uno in args
362cdf0e10cSrcweir         for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
363cdf0e10cSrcweir         {
364cdf0e10cSrcweir             typelib_MethodParameter const & param = pParams[ nPos ];
365cdf0e10cSrcweir             if (param.bIn)
366cdf0e10cSrcweir                 uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 );
367cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
368cdf0e10cSrcweir 		if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ])
369cdf0e10cSrcweir 		    free( uno_args[ nPos ] );
370cdf0e10cSrcweir #endif
371cdf0e10cSrcweir         }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         handle_uno_exc( jni, uno_exc );
374cdf0e10cSrcweir #ifdef BROKEN_ALLOCA
375cdf0e10cSrcweir 	free( mem );
376cdf0e10cSrcweir #endif
377cdf0e10cSrcweir         return 0;
378cdf0e10cSrcweir     }
379cdf0e10cSrcweir }
380cdf0e10cSrcweir 
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir using namespace ::jni_uno;
384cdf0e10cSrcweir 
385cdf0e10cSrcweir extern "C"
386cdf0e10cSrcweir {
387cdf0e10cSrcweir 
388cdf0e10cSrcweir //------------------------------------------------------------------------------
389cdf0e10cSrcweir JNIEXPORT jobject
Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call(JNIEnv * jni_env,jobject jo_proxy,jlong bridge_handle,jstring,jstring jo_method,jobjectArray jo_args)390cdf0e10cSrcweir JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call(
391cdf0e10cSrcweir     JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle, jstring,
392cdf0e10cSrcweir     jstring jo_method, jobjectArray jo_args /* may be 0 */ )
393cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
394cdf0e10cSrcweir {
395cdf0e10cSrcweir     Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle );
396cdf0e10cSrcweir     JNI_info const * jni_info = bridge->m_jni_info;
397cdf0e10cSrcweir     JNI_context jni(
398cdf0e10cSrcweir         jni_info, jni_env,
399cdf0e10cSrcweir         static_cast< jobject >(
400cdf0e10cSrcweir             reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
401cdf0e10cSrcweir                 bridge->m_java_env->pContext )->getClassLoader() ) );
402cdf0e10cSrcweir 
403cdf0e10cSrcweir     OUString method_name;
404cdf0e10cSrcweir 
405cdf0e10cSrcweir     try
406cdf0e10cSrcweir     {
407cdf0e10cSrcweir         method_name = jstring_to_oustring( jni, jo_method );
408cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
409cdf0e10cSrcweir         {
410cdf0e10cSrcweir         OUStringBuffer trace_buf( 64 );
411cdf0e10cSrcweir         trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("java->uno call: ") );
412cdf0e10cSrcweir         trace_buf.append( method_name );
413cdf0e10cSrcweir         trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") );
414cdf0e10cSrcweir         JLocalAutoRef jo_oid(
415cdf0e10cSrcweir             jni, jni->GetObjectField(
416cdf0e10cSrcweir                 jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) );
417cdf0e10cSrcweir         trace_buf.append( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
418cdf0e10cSrcweir         OString cstr_msg(
419cdf0e10cSrcweir             OUStringToOString(
420cdf0e10cSrcweir                 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
421cdf0e10cSrcweir         OSL_TRACE( cstr_msg.getStr() );
422cdf0e10cSrcweir         }
423cdf0e10cSrcweir #endif
424cdf0e10cSrcweir 
425cdf0e10cSrcweir         // special IQueryInterface.queryInterface()
426cdf0e10cSrcweir         if (method_name.equalsAsciiL(
427cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM("queryInterface") ))
428cdf0e10cSrcweir         {
429cdf0e10cSrcweir             // oid
430cdf0e10cSrcweir             JLocalAutoRef jo_oid(
431cdf0e10cSrcweir                 jni, jni->GetObjectField(
432cdf0e10cSrcweir                     jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) );
433cdf0e10cSrcweir             // type
434cdf0e10cSrcweir             JLocalAutoRef jo_type(
435cdf0e10cSrcweir                 jni, jni->GetObjectArrayElement( jo_args, 0 ) );
436cdf0e10cSrcweir             jni.ensure_no_exception();
437cdf0e10cSrcweir 
438cdf0e10cSrcweir             JLocalAutoRef jo_type_name(
439cdf0e10cSrcweir                 jni, jni->GetObjectField(
440cdf0e10cSrcweir                     jo_type.get(), jni_info->m_field_Type__typeName ) );
441cdf0e10cSrcweir             if (! jo_type_name.is())
442cdf0e10cSrcweir             {
443cdf0e10cSrcweir                 throw BridgeRuntimeError(
444cdf0e10cSrcweir                     OUSTR("incomplete type object: no type name!") +
445cdf0e10cSrcweir                     jni.get_stack_trace() );
446cdf0e10cSrcweir             }
447cdf0e10cSrcweir             OUString type_name(
448cdf0e10cSrcweir                 jstring_to_oustring( jni, (jstring) jo_type_name.get() ) );
449cdf0e10cSrcweir             JNI_type_info const * info =
450cdf0e10cSrcweir                 jni_info->get_type_info( jni, type_name );
451cdf0e10cSrcweir             if (typelib_TypeClass_INTERFACE != info->m_td.get()->eTypeClass)
452cdf0e10cSrcweir             {
453cdf0e10cSrcweir                 throw BridgeRuntimeError(
454cdf0e10cSrcweir                     OUSTR("queryInterface() call demands an INTERFACE type!") );
455cdf0e10cSrcweir             }
456cdf0e10cSrcweir             JNI_interface_type_info const * iface_info =
457cdf0e10cSrcweir                 static_cast< JNI_interface_type_info const * >( info );
458cdf0e10cSrcweir 
459cdf0e10cSrcweir             // getRegisteredInterface() already tested in JNI_proxy:
460cdf0e10cSrcweir             // perform queryInterface call on binary uno interface
461cdf0e10cSrcweir             uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(
462cdf0e10cSrcweir                 jni->GetLongField(
463cdf0e10cSrcweir                     jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) );
464cdf0e10cSrcweir 
465cdf0e10cSrcweir             uno_Any uno_ret;
466cdf0e10cSrcweir             void * uno_args[] = { &iface_info->m_td.get()->pWeakRef };
467cdf0e10cSrcweir             uno_Any uno_exc_holder;
468cdf0e10cSrcweir             uno_Any * uno_exc = &uno_exc_holder;
469cdf0e10cSrcweir             // call binary uno
470cdf0e10cSrcweir             (*pUnoI->pDispatcher)(
471cdf0e10cSrcweir                 pUnoI, jni_info->m_XInterface_queryInterface_td.get(),
472cdf0e10cSrcweir                 &uno_ret, uno_args, &uno_exc );
473cdf0e10cSrcweir             if (0 == uno_exc)
474cdf0e10cSrcweir             {
475cdf0e10cSrcweir                 jobject jo_ret = 0;
476cdf0e10cSrcweir                 if (typelib_TypeClass_INTERFACE == uno_ret.pType->eTypeClass)
477cdf0e10cSrcweir                 {
478cdf0e10cSrcweir                     uno_Interface * pUnoRet =
479cdf0e10cSrcweir                         (uno_Interface *) uno_ret.pReserved;
480cdf0e10cSrcweir                     if (0 != pUnoRet)
481cdf0e10cSrcweir                     {
482cdf0e10cSrcweir                         try
483cdf0e10cSrcweir                         {
484cdf0e10cSrcweir                             jo_ret =
485cdf0e10cSrcweir                                 bridge->map_to_java( jni, pUnoRet, iface_info );
486cdf0e10cSrcweir                         }
487cdf0e10cSrcweir                         catch (...)
488cdf0e10cSrcweir                         {
489cdf0e10cSrcweir                             uno_any_destruct( &uno_ret, 0 );
490cdf0e10cSrcweir                             throw;
491cdf0e10cSrcweir                         }
492cdf0e10cSrcweir                     }
493cdf0e10cSrcweir                 }
494cdf0e10cSrcweir                 uno_any_destruct( &uno_ret, 0 );
495cdf0e10cSrcweir                 return jo_ret;
496cdf0e10cSrcweir             }
497cdf0e10cSrcweir             else
498cdf0e10cSrcweir             {
499cdf0e10cSrcweir                 bridge->handle_uno_exc( jni, uno_exc );
500cdf0e10cSrcweir                 return 0;
501cdf0e10cSrcweir             }
502cdf0e10cSrcweir         }
503cdf0e10cSrcweir 
504cdf0e10cSrcweir         typelib_InterfaceTypeDescription * td =
505cdf0e10cSrcweir             reinterpret_cast< typelib_InterfaceTypeDescription * >(
506cdf0e10cSrcweir                 jni->GetLongField(
507cdf0e10cSrcweir                     jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) );
508cdf0e10cSrcweir         uno_Interface * pUnoI =
509cdf0e10cSrcweir             reinterpret_cast< uno_Interface * >(
510cdf0e10cSrcweir                 jni->GetLongField(
511cdf0e10cSrcweir                     jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) );
512cdf0e10cSrcweir 
513cdf0e10cSrcweir         typelib_TypeDescriptionReference ** ppAllMembers = td->ppAllMembers;
514cdf0e10cSrcweir         for ( sal_Int32 nPos = td->nAllMembers; nPos--; )
515cdf0e10cSrcweir         {
516cdf0e10cSrcweir             // try to avoid getting typedescription as long as possible,
517cdf0e10cSrcweir             // because of a Mutex.acquire() in
518cdf0e10cSrcweir             // typelib_typedescriptionreference_getDescription()
519cdf0e10cSrcweir             typelib_TypeDescriptionReference * member_type =
520cdf0e10cSrcweir                 ppAllMembers[ nPos ];
521cdf0e10cSrcweir 
522cdf0e10cSrcweir             // check method_name against fully qualified type_name
523cdf0e10cSrcweir             // of member_type; type_name is of the form
524cdf0e10cSrcweir             //  <name> "::" <method_name> *(":@" <idx> "," <idx> ":" <name>)
525cdf0e10cSrcweir             OUString const & type_name =
526cdf0e10cSrcweir                 OUString::unacquired( &member_type->pTypeName );
527cdf0e10cSrcweir             sal_Int32 offset = type_name.indexOf( ':' ) + 2;
528cdf0e10cSrcweir             OSL_ASSERT(
529cdf0e10cSrcweir                 offset >= 2 && offset < type_name.getLength()
530cdf0e10cSrcweir                 && type_name[offset - 1] == ':' );
531cdf0e10cSrcweir             sal_Int32 remainder = type_name.getLength() - offset;
532cdf0e10cSrcweir             if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass)
533cdf0e10cSrcweir             {
534cdf0e10cSrcweir                 if ((method_name.getLength() == remainder
535cdf0e10cSrcweir                      || (method_name.getLength() < remainder
536cdf0e10cSrcweir                          && type_name[offset + method_name.getLength()] == ':'))
537cdf0e10cSrcweir                     && type_name.match(method_name, offset))
538cdf0e10cSrcweir                 {
539cdf0e10cSrcweir                     TypeDescr member_td( member_type );
540cdf0e10cSrcweir                     typelib_InterfaceMethodTypeDescription * method_td =
541cdf0e10cSrcweir                         reinterpret_cast<
542cdf0e10cSrcweir                           typelib_InterfaceMethodTypeDescription * >(
543cdf0e10cSrcweir                               member_td.get() );
544cdf0e10cSrcweir                     return bridge->call_uno(
545cdf0e10cSrcweir                         jni, pUnoI, member_td.get(),
546cdf0e10cSrcweir                         method_td->pReturnTypeRef,
547cdf0e10cSrcweir                         method_td->nParams, method_td->pParams,
548cdf0e10cSrcweir                         jo_args );
549cdf0e10cSrcweir                 }
550cdf0e10cSrcweir             }
551cdf0e10cSrcweir             else // attribute
552cdf0e10cSrcweir             {
553cdf0e10cSrcweir                 OSL_ASSERT(
554cdf0e10cSrcweir                     typelib_TypeClass_INTERFACE_ATTRIBUTE ==
555cdf0e10cSrcweir                       member_type->eTypeClass );
556cdf0e10cSrcweir 
557cdf0e10cSrcweir                 if (method_name.getLength() >= 3
558cdf0e10cSrcweir                     && (method_name.getLength() - 3 == remainder
559cdf0e10cSrcweir                         || (method_name.getLength() - 3 < remainder
560cdf0e10cSrcweir                             && type_name[
561cdf0e10cSrcweir                                 offset + (method_name.getLength() - 3)] == ':'))
562cdf0e10cSrcweir                     && method_name[1] == 'e' && method_name[2] == 't'
563cdf0e10cSrcweir                     && rtl_ustr_compare_WithLength(
564cdf0e10cSrcweir                         type_name.getStr() + offset,
565cdf0e10cSrcweir                         method_name.getLength() - 3,
566cdf0e10cSrcweir                         method_name.getStr() + 3,
567cdf0e10cSrcweir                         method_name.getLength() - 3) == 0)
568cdf0e10cSrcweir                 {
569cdf0e10cSrcweir                     if ('g' == method_name[ 0 ])
570cdf0e10cSrcweir                     {
571cdf0e10cSrcweir                         TypeDescr member_td( member_type );
572cdf0e10cSrcweir                         typelib_InterfaceAttributeTypeDescription * attr_td =
573cdf0e10cSrcweir                             reinterpret_cast<
574cdf0e10cSrcweir                               typelib_InterfaceAttributeTypeDescription * >(
575cdf0e10cSrcweir                                   member_td.get() );
576cdf0e10cSrcweir                         return bridge->call_uno(
577cdf0e10cSrcweir                             jni, pUnoI, member_td.get(),
578cdf0e10cSrcweir                             attr_td->pAttributeTypeRef,
579cdf0e10cSrcweir                             0, 0,
580cdf0e10cSrcweir                             jo_args );
581cdf0e10cSrcweir                     }
582cdf0e10cSrcweir                     else if ('s' == method_name[ 0 ])
583cdf0e10cSrcweir                     {
584cdf0e10cSrcweir                         TypeDescr member_td( member_type );
585cdf0e10cSrcweir                         typelib_InterfaceAttributeTypeDescription * attr_td =
586cdf0e10cSrcweir                             reinterpret_cast<
587cdf0e10cSrcweir                               typelib_InterfaceAttributeTypeDescription * >(
588cdf0e10cSrcweir                                   member_td.get() );
589cdf0e10cSrcweir                         if (! attr_td->bReadOnly)
590cdf0e10cSrcweir                         {
591cdf0e10cSrcweir                             typelib_MethodParameter param;
592cdf0e10cSrcweir                             param.pTypeRef = attr_td->pAttributeTypeRef;
593cdf0e10cSrcweir                             param.bIn = sal_True;
594cdf0e10cSrcweir                             param.bOut = sal_False;
595cdf0e10cSrcweir                             return bridge->call_uno(
596cdf0e10cSrcweir                                 jni, pUnoI, member_td.get(),
597cdf0e10cSrcweir                                 jni_info->m_void_type.getTypeLibType(),
598cdf0e10cSrcweir                                 1, &param,
599cdf0e10cSrcweir                                 jo_args );
600cdf0e10cSrcweir                         }
601cdf0e10cSrcweir                     }
602cdf0e10cSrcweir                 }
603cdf0e10cSrcweir             }
604cdf0e10cSrcweir         }
605cdf0e10cSrcweir         // the thing that should not be... no method info found!
606cdf0e10cSrcweir         OUStringBuffer buf( 64 );
607cdf0e10cSrcweir         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
608cdf0e10cSrcweir             "calling undeclared function on interface ") );
609cdf0e10cSrcweir         buf.append( OUString::unacquired(
610cdf0e10cSrcweir                         &((typelib_TypeDescription *)td)->pTypeName ) );
611cdf0e10cSrcweir         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
612cdf0e10cSrcweir         buf.append( method_name );
613cdf0e10cSrcweir         buf.append( jni.get_stack_trace() );
614cdf0e10cSrcweir         throw BridgeRuntimeError( buf.makeStringAndClear() );
615cdf0e10cSrcweir     }
616cdf0e10cSrcweir     catch (BridgeRuntimeError & err)
617cdf0e10cSrcweir     {
618cdf0e10cSrcweir         OUStringBuffer buf( 128 );
619cdf0e10cSrcweir         buf.appendAscii(
620cdf0e10cSrcweir             RTL_CONSTASCII_STRINGPARAM("[jni_uno bridge error] "
621cdf0e10cSrcweir                                        "Java calling UNO method ") );
622cdf0e10cSrcweir         buf.append( method_name );
623cdf0e10cSrcweir         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
624cdf0e10cSrcweir         buf.append( err.m_message );
625cdf0e10cSrcweir         // notify RuntimeException
626cdf0e10cSrcweir         OString cstr_msg(
627cdf0e10cSrcweir             OUStringToOString(
628cdf0e10cSrcweir                 buf.makeStringAndClear(), RTL_TEXTENCODING_JAVA_UTF8 ) );
629cdf0e10cSrcweir         OSL_ENSURE( 0, cstr_msg.getStr() );
630cdf0e10cSrcweir         if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr())
631cdf0e10cSrcweir             != 0)
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             OSL_ASSERT( false );
634cdf0e10cSrcweir         }
635cdf0e10cSrcweir         return 0;
636cdf0e10cSrcweir     }
637cdf0e10cSrcweir     catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
638cdf0e10cSrcweir     {
639cdf0e10cSrcweir         OString cstr_msg(
640cdf0e10cSrcweir             OString( RTL_CONSTASCII_STRINGPARAM(
641cdf0e10cSrcweir                 "[jni_uno bridge error] "
642cdf0e10cSrcweir                 "attaching current thread to java failed!") ) +
643cdf0e10cSrcweir             OUStringToOString(
644cdf0e10cSrcweir                 jni.get_stack_trace(), RTL_TEXTENCODING_JAVA_UTF8 ) );
645cdf0e10cSrcweir         OSL_ENSURE( 0, cstr_msg.getStr() );
646cdf0e10cSrcweir         if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr())
647cdf0e10cSrcweir             != 0)
648cdf0e10cSrcweir         {
649cdf0e10cSrcweir             OSL_ASSERT( false );
650cdf0e10cSrcweir         }
651cdf0e10cSrcweir         return 0;
652cdf0e10cSrcweir     }
653cdf0e10cSrcweir }
654cdf0e10cSrcweir 
655cdf0e10cSrcweir //------------------------------------------------------------------------------
656cdf0e10cSrcweir JNIEXPORT void
Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J(JNIEnv * jni_env,jobject jo_proxy,jlong bridge_handle)657cdf0e10cSrcweir JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J(
658cdf0e10cSrcweir     JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle )
659cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
660cdf0e10cSrcweir {
661cdf0e10cSrcweir     Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle );
662cdf0e10cSrcweir     JNI_info const * jni_info = bridge->m_jni_info;
663cdf0e10cSrcweir     JNI_context jni(
664cdf0e10cSrcweir         jni_info, jni_env,
665cdf0e10cSrcweir         static_cast< jobject >(
666cdf0e10cSrcweir             reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
667cdf0e10cSrcweir                 bridge->m_java_env->pContext )->getClassLoader() ) );
668cdf0e10cSrcweir 
669cdf0e10cSrcweir     uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(
670cdf0e10cSrcweir         jni->GetLongField(
671cdf0e10cSrcweir             jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) );
672cdf0e10cSrcweir     typelib_TypeDescription * td =
673cdf0e10cSrcweir         reinterpret_cast< typelib_TypeDescription * >(
674cdf0e10cSrcweir             jni->GetLongField(
675cdf0e10cSrcweir                 jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) );
676cdf0e10cSrcweir 
677cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
678cdf0e10cSrcweir     {
679cdf0e10cSrcweir     JLocalAutoRef jo_oid(
680cdf0e10cSrcweir         jni, jni->GetObjectField(
681cdf0e10cSrcweir             jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) );
682cdf0e10cSrcweir     OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
683cdf0e10cSrcweir     OString cstr_msg(
684cdf0e10cSrcweir         OUStringToOString(
685cdf0e10cSrcweir             OUSTR("freeing java uno proxy: ") + oid,
686cdf0e10cSrcweir             RTL_TEXTENCODING_ASCII_US ) );
687cdf0e10cSrcweir     OSL_TRACE( cstr_msg.getStr() );
688cdf0e10cSrcweir     }
689cdf0e10cSrcweir #endif
690cdf0e10cSrcweir     // revoke from uno env; has already been revoked from java env
691cdf0e10cSrcweir     (*bridge->m_uno_env->revokeInterface)( bridge->m_uno_env, pUnoI );
692cdf0e10cSrcweir     // release receiver
693cdf0e10cSrcweir 	(*pUnoI->release)( pUnoI );
694cdf0e10cSrcweir     // release typedescription handle
695cdf0e10cSrcweir     typelib_typedescription_release( td );
696cdf0e10cSrcweir     // release bridge handle
697cdf0e10cSrcweir     bridge->release();
698cdf0e10cSrcweir }
699cdf0e10cSrcweir 
700cdf0e10cSrcweir }
701