LCOV - code coverage report
Current view: top level - bridges/source/jni_uno - jni_uno2java.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 128 256 50.0 %
Date: 2014-11-03 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10