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