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