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
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26
27 #include <sal/alloca.h>
28
29 #include "com/sun/star/uno/RuntimeException.hpp"
30
31 #include "rtl/ustrbuf.hxx"
32
33 #include "jni_bridge.h"
34
35
36 using namespace ::std;
37 using namespace ::rtl;
38
39 namespace
40 {
41 extern "C"
42 {
43
44 //------------------------------------------------------------------------------
45 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
46 SAL_THROW_EXTERN_C();
47
48 //------------------------------------------------------------------------------
49 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
50 SAL_THROW_EXTERN_C();
51
52 //------------------------------------------------------------------------------
53 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
54 SAL_THROW_EXTERN_C();
55
56 //------------------------------------------------------------------------------
57 void SAL_CALL UNO_proxy_dispatch(
58 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
59 void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
60 SAL_THROW_EXTERN_C();
61 }
62 }
63
64 namespace jni_uno
65 {
66
67 //______________________________________________________________________________
handle_java_exc(JNI_context const & jni,JLocalAutoRef const & jo_exc,uno_Any * uno_exc) const68 void Bridge::handle_java_exc(
69 JNI_context const & jni,
70 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const
71 {
72 OSL_ASSERT( jo_exc.is() );
73 if (! jo_exc.is())
74 {
75 throw BridgeRuntimeError(
76 OUSTR("java exception occured, but no java exception available!?") +
77 jni.get_stack_trace() );
78 }
79
80 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) );
81 JLocalAutoRef jo_class_name(
82 jni, jni->CallObjectMethodA(
83 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) );
84 jni.ensure_no_exception();
85 OUString exc_name(
86 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) );
87
88 ::com::sun::star::uno::TypeDescription td( exc_name.pData );
89 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass))
90 {
91 // call toString()
92 JLocalAutoRef jo_descr(
93 jni, jni->CallObjectMethodA(
94 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) );
95 jni.ensure_no_exception();
96 OUStringBuffer buf( 128 );
97 buf.appendAscii(
98 RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") );
99 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
100 buf.append( jni.get_stack_trace( jo_exc.get() ) );
101 throw BridgeRuntimeError( buf.makeStringAndClear() );
102 }
103
104 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) );
105 jvalue val;
106 val.l = jo_exc.get();
107 map_to_uno(
108 jni, uno_data.get(), val, td.get()->pWeakRef, 0,
109 false /* no assign */, false /* no out param */ );
110
111 #if OSL_DEBUG_LEVEL > 0
112 // patch Message, append stack trace
113 reinterpret_cast< ::com::sun::star::uno::Exception * >(
114 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() );
115 #endif
116
117 typelib_typedescriptionreference_acquire( td.get()->pWeakRef );
118 uno_exc->pType = td.get()->pWeakRef;
119 uno_exc->pData = uno_data.release();
120
121 #if OSL_DEBUG_LEVEL > 1
122 OUStringBuffer trace_buf( 128 );
123 trace_buf.appendAscii(
124 RTL_CONSTASCII_STRINGPARAM("exception occured uno->java: [") );
125 trace_buf.append( exc_name );
126 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
127 trace_buf.append(
128 reinterpret_cast< ::com::sun::star::uno::Exception const * >(
129 uno_exc->pData )->Message );
130 OString cstr_trace(
131 OUStringToOString(
132 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
133 OSL_TRACE( cstr_trace.getStr() );
134 #endif
135 }
136
137 //______________________________________________________________________________
call_java(jobject javaI,typelib_InterfaceTypeDescription * iface_td,sal_Int32 local_member_index,sal_Int32 function_pos_offset,typelib_TypeDescriptionReference * return_type,typelib_MethodParameter * params,sal_Int32 nParams,void * uno_ret,void * uno_args[],uno_Any ** uno_exc) const138 void Bridge::call_java(
139 jobject javaI, typelib_InterfaceTypeDescription * iface_td,
140 sal_Int32 local_member_index, sal_Int32 function_pos_offset,
141 typelib_TypeDescriptionReference * return_type,
142 typelib_MethodParameter * params, sal_Int32 nParams,
143 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
144 {
145 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 );
146
147 JNI_guarded_context jni(
148 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
149 m_java_env->pContext ) );
150
151 // assure fully initialized iface_td:
152 ::com::sun::star::uno::TypeDescription iface_holder;
153 if (! iface_td->aBase.bComplete) {
154 iface_holder = ::com::sun::star::uno::TypeDescription(
155 reinterpret_cast<typelib_TypeDescription *>(iface_td) );
156 iface_holder.makeComplete();
157 if (! iface_holder.get()->bComplete) {
158 OUStringBuffer buf;
159 buf.appendAscii(
160 RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") );
161 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) );
162 buf.append( jni.get_stack_trace() );
163 throw BridgeRuntimeError( buf.makeStringAndClear() );
164 }
165 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>(
166 iface_holder.get() );
167 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE );
168 }
169
170 // prepare java args, save param td
171 #ifdef BROKEN_ALLOCA
172 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams );
173 #else
174 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams );
175 #endif
176
177 sal_Int32 nPos;
178 for ( nPos = 0; nPos < nParams; ++nPos )
179 {
180 try
181 {
182 typelib_MethodParameter const & param = params[ nPos ];
183 java_args[ nPos ].l = 0; // if out: build up array[ 1 ]
184 map_to_java(
185 jni, &java_args[ nPos ],
186 uno_args[ nPos ],
187 param.pTypeRef, 0,
188 sal_False != param.bIn /* convert uno value */,
189 sal_False != param.bOut /* build up array[ 1 ] */ );
190 }
191 catch (...)
192 {
193 // cleanup
194 for ( sal_Int32 n = 0; n < nPos; ++n )
195 {
196 typelib_MethodParameter const & param = params[ n ];
197 if (param.bOut ||
198 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
199 {
200 jni->DeleteLocalRef( java_args[ n ].l );
201 }
202 }
203 #ifdef BROKEN_ALLOCA
204 free( java_args );
205 #endif
206 throw;
207 }
208 }
209
210 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers;
211 OSL_ASSERT( base_members < iface_td->nAllMembers );
212 sal_Int32 base_members_function_pos =
213 iface_td->pMapMemberIndexToFunctionIndex[ base_members ];
214 sal_Int32 member_pos = base_members + local_member_index;
215 OSL_ENSURE(
216 member_pos < iface_td->nAllMembers, "### member pos out of range!" );
217 sal_Int32 function_pos =
218 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ]
219 + function_pos_offset;
220 OSL_ENSURE(
221 function_pos >= base_members_function_pos
222 && function_pos < iface_td->nMapFunctionIndexToMemberIndex,
223 "### illegal function index!" );
224 function_pos -= base_members_function_pos;
225
226 JNI_interface_type_info const * info =
227 static_cast< JNI_interface_type_info const * >(
228 m_jni_info->get_type_info( jni, &iface_td->aBase ) );
229 jmethodID method_id = info->m_methods[ function_pos ];
230
231 #if OSL_DEBUG_LEVEL > 1
232 OUStringBuffer trace_buf( 128 );
233 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") );
234 JLocalAutoRef jo_method(
235 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) );
236 jni.ensure_no_exception();
237 JLocalAutoRef jo_descr(
238 jni, jni->CallObjectMethodA(
239 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) );
240 jni.ensure_no_exception();
241 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
242 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") );
243 jo_descr.reset(
244 jni->CallObjectMethodA(
245 javaI, m_jni_info->m_method_Object_toString, 0 ) );
246 jni.ensure_no_exception();
247 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
248 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") );
249 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) );
250 jo_descr.reset(
251 jni->CallObjectMethodA(
252 jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) );
253 jni.ensure_no_exception();
254 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
255 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
256 OString cstr_trace(
257 OUStringToOString(
258 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
259 OSL_TRACE( cstr_trace.getStr() );
260 #endif
261
262 // complex return value
263 JLocalAutoRef java_ret( jni );
264
265 switch (return_type->eTypeClass)
266 {
267 case typelib_TypeClass_VOID:
268 jni->CallVoidMethodA( javaI, method_id, java_args );
269 break;
270 case typelib_TypeClass_CHAR:
271 *(sal_Unicode *)uno_ret =
272 jni->CallCharMethodA( javaI, method_id, java_args );
273 break;
274 case typelib_TypeClass_BOOLEAN:
275 *(sal_Bool *)uno_ret =
276 jni->CallBooleanMethodA( javaI, method_id, java_args );
277 break;
278 case typelib_TypeClass_BYTE:
279 *(sal_Int8 *)uno_ret =
280 jni->CallByteMethodA( javaI, method_id, java_args );
281 break;
282 case typelib_TypeClass_SHORT:
283 case typelib_TypeClass_UNSIGNED_SHORT:
284 *(sal_Int16 *)uno_ret =
285 jni->CallShortMethodA( javaI, method_id, java_args );
286 break;
287 case typelib_TypeClass_LONG:
288 case typelib_TypeClass_UNSIGNED_LONG:
289 *(sal_Int32 *)uno_ret =
290 jni->CallIntMethodA( javaI, method_id, java_args );
291 break;
292 case typelib_TypeClass_HYPER:
293 case typelib_TypeClass_UNSIGNED_HYPER:
294 *(sal_Int64 *)uno_ret =
295 jni->CallLongMethodA( javaI, method_id, java_args );
296 break;
297 case typelib_TypeClass_FLOAT:
298 *(float *)uno_ret =
299 jni->CallFloatMethodA( javaI, method_id, java_args );
300 break;
301 case typelib_TypeClass_DOUBLE:
302 *(double *)uno_ret =
303 jni->CallDoubleMethodA( javaI, method_id, java_args );
304 break;
305 default:
306 java_ret.reset(
307 jni->CallObjectMethodA( javaI, method_id, java_args ) );
308 break;
309 }
310
311 if (jni->ExceptionCheck())
312 {
313 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
314 jni->ExceptionClear();
315
316 // release temp java local refs
317 for ( nPos = 0; nPos < nParams; ++nPos )
318 {
319 typelib_MethodParameter const & param = params[ nPos ];
320 if (param.bOut ||
321 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
322 {
323 jni->DeleteLocalRef( java_args[ nPos ].l );
324 }
325 }
326
327 handle_java_exc( jni, jo_exc, *uno_exc );
328 }
329 else // no exception
330 {
331 for ( nPos = 0; nPos < nParams; ++nPos )
332 {
333 typelib_MethodParameter const & param = params[ nPos ];
334 if (param.bOut)
335 {
336 try
337 {
338 map_to_uno(
339 jni, uno_args[ nPos ],
340 java_args[ nPos ], param.pTypeRef, 0,
341 sal_False != param.bIn /* assign if inout */,
342 true /* out param */ );
343 }
344 catch (...)
345 {
346 // cleanup uno pure out
347 for ( sal_Int32 n = 0; n < nPos; ++n )
348 {
349 typelib_MethodParameter const & p = params[ n ];
350 if (! p.bIn)
351 {
352 uno_type_destructData(
353 uno_args[ n ], p.pTypeRef, 0 );
354 }
355 }
356 // cleanup java temp local refs
357 for ( ; nPos < nParams; ++nPos )
358 {
359 typelib_MethodParameter const & p = params[ nPos ];
360 if (p.bOut ||
361 typelib_TypeClass_DOUBLE <
362 p.pTypeRef->eTypeClass)
363 {
364 jni->DeleteLocalRef( java_args[ nPos ].l );
365 }
366 }
367 #ifdef BROKEN_ALLOCA
368 free( java_args );
369 #endif
370 throw;
371 }
372 jni->DeleteLocalRef( java_args[ nPos ].l );
373 }
374 else // pure temp in param
375 {
376 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
377 jni->DeleteLocalRef( java_args[ nPos ].l );
378 }
379 }
380
381 // return value
382 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass)
383 {
384 try
385 {
386 jvalue val;
387 val.l = java_ret.get();
388 map_to_uno(
389 jni, uno_ret, val, return_type, 0,
390 false /* no assign */, false /* no out param */ );
391 }
392 catch (...)
393 {
394 // cleanup uno pure out
395 for ( sal_Int32 i = 0; i < nParams; ++i )
396 {
397 typelib_MethodParameter const & param = params[ i ];
398 if (! param.bIn)
399 {
400 uno_type_destructData(
401 uno_args[ i ], param.pTypeRef, 0 );
402 }
403 }
404 #ifdef BROKEN_ALLOCA
405 free( java_args );
406 #endif
407 throw;
408 }
409 } // else: already set integral uno return value
410
411 // no exception occured
412 *uno_exc = 0;
413 }
414 #ifdef BROKEN_ALLOCA
415 free( java_args );
416 #endif
417 }
418
419 //==== a uno proxy wrapping a java interface ===================================
420 struct UNO_proxy : public uno_Interface
421 {
422 mutable oslInterlockedCount m_ref;
423 Bridge const * m_bridge;
424
425 // mapping information
426 jobject m_javaI;
427 jstring m_jo_oid;
428 OUString m_oid;
429 JNI_interface_type_info const * m_type_info;
430
431 inline void acquire() const;
432 inline void release() const;
433
434 // ctor
435 inline UNO_proxy(
436 JNI_context const & jni, Bridge const * bridge,
437 jobject javaI, jstring jo_oid, OUString const & oid,
438 JNI_interface_type_info const * info );
439 };
440
441 //______________________________________________________________________________
UNO_proxy(JNI_context const & jni,Bridge const * bridge,jobject javaI,jstring jo_oid,OUString const & oid,JNI_interface_type_info const * info)442 inline UNO_proxy::UNO_proxy(
443 JNI_context const & jni, Bridge const * bridge,
444 jobject javaI, jstring jo_oid, OUString const & oid,
445 JNI_interface_type_info const * info )
446 : m_ref( 1 ),
447 m_oid( oid ),
448 m_type_info( info )
449 {
450 JNI_info const * jni_info = bridge->m_jni_info;
451 JLocalAutoRef jo_string_array(
452 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) );
453 jni.ensure_no_exception();
454 jvalue args[ 3 ];
455 args[ 0 ].l = javaI;
456 args[ 1 ].l = jo_string_array.get();
457 args[ 2 ].l = info->m_type;
458 jobject jo_iface = jni->CallObjectMethodA(
459 jni_info->m_object_java_env,
460 jni_info->m_method_IEnvironment_registerInterface, args );
461 jni.ensure_no_exception();
462
463 m_javaI = jni->NewGlobalRef( jo_iface );
464 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid );
465 bridge->acquire();
466 m_bridge = bridge;
467
468 // uno_Interface
469 uno_Interface::acquire = UNO_proxy_acquire;
470 uno_Interface::release = UNO_proxy_release;
471 uno_Interface::pDispatcher = UNO_proxy_dispatch;
472 }
473
474 //______________________________________________________________________________
acquire() const475 inline void UNO_proxy::acquire() const
476 {
477 if (1 == osl_incrementInterlockedCount( &m_ref ))
478 {
479 // rebirth of proxy zombie
480 void * that = const_cast< UNO_proxy * >( this );
481 // register at uno env
482 (*m_bridge->m_uno_env->registerProxyInterface)(
483 m_bridge->m_uno_env, &that,
484 UNO_proxy_free, m_oid.pData,
485 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() );
486 #if OSL_DEBUG_LEVEL > 1
487 OSL_ASSERT( this == (void const * const)that );
488 #endif
489 }
490 }
491
492 //______________________________________________________________________________
release() const493 inline void UNO_proxy::release() const
494 {
495 if (0 == osl_decrementInterlockedCount( &m_ref ))
496 {
497 // revoke from uno env on last release
498 (*m_bridge->m_uno_env->revokeInterface)(
499 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) );
500 }
501 }
502
503
504 //______________________________________________________________________________
map_to_uno(JNI_context const & jni,jobject javaI,JNI_interface_type_info const * info) const505 uno_Interface * Bridge::map_to_uno(
506 JNI_context const & jni,
507 jobject javaI, JNI_interface_type_info const * info ) const
508 {
509 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) );
510 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
511
512 uno_Interface * pUnoI = 0;
513 (*m_uno_env->getRegisteredInterface)(
514 m_uno_env, (void **)&pUnoI,
515 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
516
517 if (0 == pUnoI) // no existing interface, register new proxy
518 {
519 // refcount initially 1
520 pUnoI = new UNO_proxy(
521 jni, const_cast< Bridge * >( this ),
522 javaI, (jstring) jo_oid.get(), oid, info );
523
524 (*m_uno_env->registerProxyInterface)(
525 m_uno_env, (void **)&pUnoI,
526 UNO_proxy_free,
527 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
528 }
529 return pUnoI;
530 }
531
532 }
533
534 using namespace ::jni_uno;
535
536 namespace
537 {
538 extern "C"
539 {
540
541 //------------------------------------------------------------------------------
UNO_proxy_free(uno_ExtEnvironment * env,void * proxy)542 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
543 SAL_THROW_EXTERN_C()
544 {
545 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy );
546 Bridge const * bridge = that->m_bridge;
547
548 if ( env != bridge->m_uno_env ) {
549 OSL_ASSERT(false);
550 }
551 #if OSL_DEBUG_LEVEL > 1
552 OString cstr_msg(
553 OUStringToOString(
554 OUSTR("freeing binary uno proxy: ") + that->m_oid,
555 RTL_TEXTENCODING_ASCII_US ) );
556 OSL_TRACE( cstr_msg.getStr() );
557 #endif
558
559 try
560 {
561 JNI_guarded_context jni(
562 bridge->m_jni_info,
563 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
564 bridge->m_java_env->pContext ) );
565
566 jni->DeleteGlobalRef( that->m_javaI );
567 jni->DeleteGlobalRef( that->m_jo_oid );
568 }
569 catch (BridgeRuntimeError & err)
570 {
571 #if OSL_DEBUG_LEVEL > 0
572 OString cstr_msg2(
573 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) );
574 OSL_ENSURE( 0, cstr_msg2.getStr() );
575 #else
576 (void) err; // unused
577 #endif
578 }
579 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
580 {
581 OSL_ENSURE(
582 0,
583 "[jni_uno bridge error] attaching current thread to java failed!" );
584 }
585
586 bridge->release();
587 #if OSL_DEBUG_LEVEL > 1
588 *(int *)that = 0xdeadcafe;
589 #endif
590 delete that;
591 }
592
593 //------------------------------------------------------------------------------
UNO_proxy_acquire(uno_Interface * pUnoI)594 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
595 SAL_THROW_EXTERN_C()
596 {
597 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
598 that->acquire();
599 }
600
601 //------------------------------------------------------------------------------
UNO_proxy_release(uno_Interface * pUnoI)602 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
603 SAL_THROW_EXTERN_C()
604 {
605 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
606 that->release();
607 }
608
609 //------------------------------------------------------------------------------
UNO_proxy_dispatch(uno_Interface * pUnoI,typelib_TypeDescription const * member_td,void * uno_ret,void * uno_args[],uno_Any ** uno_exc)610 void SAL_CALL UNO_proxy_dispatch(
611 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
612 void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
613 SAL_THROW_EXTERN_C()
614 {
615 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
616 Bridge const * bridge = that->m_bridge;
617
618 #if OSL_DEBUG_LEVEL > 1
619 OUStringBuffer trace_buf( 64 );
620 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") );
621 trace_buf.append( OUString::unacquired( &member_td->pTypeName ) );
622 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") );
623 trace_buf.append( that->m_oid );
624 OString cstr_msg(
625 OUStringToOString(
626 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
627 OSL_TRACE( cstr_msg.getStr() );
628 #endif
629
630 try
631 {
632 switch (member_td->eTypeClass)
633 {
634 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
635 {
636 typelib_InterfaceAttributeTypeDescription const * attrib_td =
637 reinterpret_cast<
638 typelib_InterfaceAttributeTypeDescription const * >(
639 member_td );
640 com::sun::star::uno::TypeDescription attrib_holder;
641 while ( attrib_td->pBaseRef != 0 ) {
642 attrib_holder = com::sun::star::uno::TypeDescription(
643 attrib_td->pBaseRef );
644 OSL_ASSERT(
645 attrib_holder.get()->eTypeClass
646 == typelib_TypeClass_INTERFACE_ATTRIBUTE );
647 attrib_td = reinterpret_cast<
648 typelib_InterfaceAttributeTypeDescription * >(
649 attrib_holder.get() );
650 }
651 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface;
652
653 if (0 == uno_ret) // is setter method
654 {
655 typelib_MethodParameter param;
656 param.pTypeRef = attrib_td->pAttributeTypeRef;
657 param.bIn = sal_True;
658 param.bOut = sal_False;
659
660 bridge->call_java(
661 that->m_javaI, iface_td,
662 attrib_td->nIndex, 1, // get, then set method
663 bridge->m_jni_info->m_void_type.getTypeLibType(),
664 ¶m, 1,
665 0, uno_args, uno_exc );
666 }
667 else // is getter method
668 {
669 bridge->call_java(
670 that->m_javaI, iface_td, attrib_td->nIndex, 0,
671 attrib_td->pAttributeTypeRef,
672 0, 0, // no params
673 uno_ret, 0, uno_exc );
674 }
675 break;
676 }
677 case typelib_TypeClass_INTERFACE_METHOD:
678 {
679 typelib_InterfaceMethodTypeDescription const * method_td =
680 reinterpret_cast<
681 typelib_InterfaceMethodTypeDescription const * >(
682 member_td );
683 com::sun::star::uno::TypeDescription method_holder;
684 while ( method_td->pBaseRef != 0 ) {
685 method_holder = com::sun::star::uno::TypeDescription(
686 method_td->pBaseRef );
687 OSL_ASSERT(
688 method_holder.get()->eTypeClass
689 == typelib_TypeClass_INTERFACE_METHOD );
690 method_td = reinterpret_cast<
691 typelib_InterfaceMethodTypeDescription * >(
692 method_holder.get() );
693 }
694 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface;
695
696 switch ( method_td->aBase.nPosition )
697 {
698 case 0: // queryInterface()
699 {
700 TypeDescr demanded_td(
701 *reinterpret_cast< typelib_TypeDescriptionReference ** >(
702 uno_args[ 0 ] ) );
703 if (typelib_TypeClass_INTERFACE !=
704 demanded_td.get()->eTypeClass)
705 {
706 throw BridgeRuntimeError(
707 OUSTR("queryInterface() call demands "
708 "an INTERFACE type!") );
709 }
710
711 uno_Interface * pInterface = 0;
712 (*bridge->m_uno_env->getRegisteredInterface)(
713 bridge->m_uno_env,
714 (void **) &pInterface, that->m_oid.pData,
715 (typelib_InterfaceTypeDescription *)demanded_td.get() );
716
717 if (0 == pInterface)
718 {
719 JNI_info const * jni_info = bridge->m_jni_info;
720 JNI_guarded_context jni(
721 jni_info,
722 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
723 bridge->m_java_env->pContext ) );
724
725 JNI_interface_type_info const * info =
726 static_cast< JNI_interface_type_info const * >(
727 jni_info->get_type_info( jni, demanded_td.get() ) );
728
729 jvalue args[ 2 ];
730 args[ 0 ].l = info->m_type;
731 args[ 1 ].l = that->m_javaI;
732
733 JLocalAutoRef jo_ret(
734 jni, jni->CallStaticObjectMethodA(
735 jni_info->m_class_UnoRuntime,
736 jni_info->m_method_UnoRuntime_queryInterface,
737 args ) );
738
739 if (jni->ExceptionCheck())
740 {
741 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
742 jni->ExceptionClear();
743 bridge->handle_java_exc( jni, jo_exc, *uno_exc );
744 }
745 else
746 {
747 if (jo_ret.is())
748 {
749 #if OSL_DEBUG_LEVEL > 0
750 JLocalAutoRef jo_oid(
751 jni, compute_oid( jni, jo_ret.get() ) );
752 OUString oid( jstring_to_oustring(
753 jni, (jstring) jo_oid.get() ) );
754 OSL_ENSURE(
755 oid.equals( that->m_oid ),
756 "### different oids!" );
757 #endif
758 // refcount initially 1
759 uno_Interface * pUnoI2 = new UNO_proxy(
760 jni, bridge, jo_ret.get(),
761 that->m_jo_oid, that->m_oid, info );
762
763 (*bridge->m_uno_env->registerProxyInterface)(
764 bridge->m_uno_env,
765 (void **) &pUnoI2,
766 UNO_proxy_free, that->m_oid.pData,
767 reinterpret_cast<
768 typelib_InterfaceTypeDescription * >(
769 info->m_td.get() ) );
770
771 uno_any_construct(
772 (uno_Any *)uno_ret, &pUnoI2,
773 demanded_td.get(), 0 );
774 (*pUnoI2->release)( pUnoI2 );
775 }
776 else // object does not support demanded interface
777 {
778 uno_any_construct(
779 reinterpret_cast< uno_Any * >( uno_ret ),
780 0, 0, 0 );
781 }
782 // no exception occured
783 *uno_exc = 0;
784 }
785 }
786 else
787 {
788 uno_any_construct(
789 reinterpret_cast< uno_Any * >( uno_ret ),
790 &pInterface, demanded_td.get(), 0 );
791 (*pInterface->release)( pInterface );
792 *uno_exc = 0;
793 }
794 break;
795 }
796 case 1: // acquire this proxy
797 that->acquire();
798 *uno_exc = 0;
799 break;
800 case 2: // release this proxy
801 that->release();
802 *uno_exc = 0;
803 break;
804 default: // arbitrary method call
805 bridge->call_java(
806 that->m_javaI, iface_td, method_td->nIndex, 0,
807 method_td->pReturnTypeRef,
808 method_td->pParams, method_td->nParams,
809 uno_ret, uno_args, uno_exc );
810 break;
811 }
812 break;
813 }
814 default:
815 {
816 throw BridgeRuntimeError(
817 OUSTR("illegal member type description!") );
818 }
819 }
820 }
821 catch (BridgeRuntimeError & err)
822 {
823 OUStringBuffer buf( 128 );
824 buf.appendAscii(
825 RTL_CONSTASCII_STRINGPARAM(
826 "[jni_uno bridge error] UNO calling Java method ") );
827 if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass ||
828 typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass)
829 {
830 buf.append( OUString::unacquired(
831 &reinterpret_cast<
832 typelib_InterfaceMemberTypeDescription const * >(
833 member_td )->pMemberName ) );
834 }
835 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
836 buf.append( err.m_message );
837 // binary identical struct
838 ::com::sun::star::uno::RuntimeException exc(
839 buf.makeStringAndClear(),
840 ::com::sun::star::uno::Reference<
841 ::com::sun::star::uno::XInterface >() );
842 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
843 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
844 #if OSL_DEBUG_LEVEL > 0
845 OString cstr_msg2(
846 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
847 OSL_TRACE( "%s", cstr_msg2.getStr() );
848 #endif
849 }
850 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
851 {
852 // binary identical struct
853 ::com::sun::star::uno::RuntimeException exc(
854 OUSTR("[jni_uno bridge error] attaching current thread "
855 "to java failed!"),
856 ::com::sun::star::uno::Reference<
857 ::com::sun::star::uno::XInterface >() );
858 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
859 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
860 #if OSL_DEBUG_LEVEL > 0
861 OString cstr_msg2(
862 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
863 OSL_ENSURE( 0, cstr_msg2.getStr() );
864 #endif
865 }
866 }
867
868 }
869 }
870