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

Generated by: LCOV version 1.11