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