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  OUStringBuffer trace_buf( 128 );
212  trace_buf.append( "calling " );
213  JLocalAutoRef jo_method(
214  jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) );
215  jni.ensure_no_exception();
216  JLocalAutoRef jo_descr(
217  jni, jni->CallObjectMethodA(
218  jo_method.get(), getJniInfo()->m_method_Object_toString, nullptr ) );
219  jni.ensure_no_exception();
220  trace_buf.append( jstring_to_oustring( jni, static_cast<jstring>(jo_descr.get()) ) );
221  trace_buf.append( " on " );
222  jo_descr.reset(
223  jni->CallObjectMethodA(
224  javaI, getJniInfo()->m_method_Object_toString, nullptr ) );
225  jni.ensure_no_exception();
226  trace_buf.append( jstring_to_oustring( jni, static_cast<jstring>(jo_descr.get()) ) );
227  trace_buf.append( " (" );
228  JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) );
229  jo_descr.reset(
230  jni->CallObjectMethodA(
231  jo_class.get(), getJniInfo()->m_method_Object_toString, nullptr ) );
232  jni.ensure_no_exception();
233  trace_buf.append( jstring_to_oustring( jni, static_cast<jstring>(jo_descr.get()) ) );
234  trace_buf.append( ")" );
235  SAL_INFO("bridges", trace_buf.makeStringAndClear());
236 #endif
237 
238  // complex return value
239  JLocalAutoRef java_ret( jni );
240 
241  switch (return_type->eTypeClass)
242  {
243  case typelib_TypeClass_VOID:
244  jni->CallVoidMethodA( javaI, method_id, java_args );
245  break;
246  case typelib_TypeClass_CHAR:
247  *static_cast<sal_Unicode *>(uno_ret) =
248  jni->CallCharMethodA( javaI, method_id, java_args );
249  break;
250  case typelib_TypeClass_BOOLEAN:
251  *static_cast<sal_Bool *>(uno_ret) =
252  jni->CallBooleanMethodA( javaI, method_id, java_args );
253  break;
254  case typelib_TypeClass_BYTE:
255  *static_cast<sal_Int8 *>(uno_ret) =
256  jni->CallByteMethodA( javaI, method_id, java_args );
257  break;
258  case typelib_TypeClass_SHORT:
259  case typelib_TypeClass_UNSIGNED_SHORT:
260  *static_cast<sal_Int16 *>(uno_ret) =
261  jni->CallShortMethodA( javaI, method_id, java_args );
262  break;
263  case typelib_TypeClass_LONG:
264  case typelib_TypeClass_UNSIGNED_LONG:
265  *static_cast<sal_Int32 *>(uno_ret) =
266  jni->CallIntMethodA( javaI, method_id, java_args );
267  break;
268  case typelib_TypeClass_HYPER:
269  case typelib_TypeClass_UNSIGNED_HYPER:
270  *static_cast<sal_Int64 *>(uno_ret) =
271  jni->CallLongMethodA( javaI, method_id, java_args );
272  break;
273  case typelib_TypeClass_FLOAT:
274  *static_cast<float *>(uno_ret) =
275  jni->CallFloatMethodA( javaI, method_id, java_args );
276  break;
277  case typelib_TypeClass_DOUBLE:
278  *static_cast<double *>(uno_ret) =
279  jni->CallDoubleMethodA( javaI, method_id, java_args );
280  break;
281  default:
282  java_ret.reset(
283  jni->CallObjectMethodA( javaI, method_id, java_args ) );
284  break;
285  }
286 
287  if (jni->ExceptionCheck())
288  {
289  JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
290  jni->ExceptionClear();
291 
292  // release temp java local refs
293  for ( nPos = 0; nPos < nParams; ++nPos )
294  {
295  typelib_MethodParameter const & param = params[ nPos ];
296  if (param.bOut ||
297  typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
298  {
299  jni->DeleteLocalRef( java_args[ nPos ].l );
300  }
301  }
302 
303  handle_java_exc( jni, jo_exc, *uno_exc );
304  }
305  else // no exception
306  {
307  for ( nPos = 0; nPos < nParams; ++nPos )
308  {
309  typelib_MethodParameter const & param = params[ nPos ];
310  if (param.bOut)
311  {
312  try
313  {
314  map_to_uno(
315  jni, uno_args[ nPos ],
316  java_args[ nPos ], param.pTypeRef, nullptr,
317  param.bIn /* assign if inout */,
318  true /* out param */ );
319  }
320  catch (...)
321  {
322  // cleanup uno pure out
323  for ( sal_Int32 n = 0; n < nPos; ++n )
324  {
325  typelib_MethodParameter const & p = params[ n ];
326  if (! p.bIn)
327  {
329  uno_args[ n ], p.pTypeRef, nullptr );
330  }
331  }
332  // cleanup java temp local refs
333  for ( ; nPos < nParams; ++nPos )
334  {
335  typelib_MethodParameter const & p = params[ nPos ];
336  if (p.bOut ||
337  typelib_TypeClass_DOUBLE <
338  p.pTypeRef->eTypeClass)
339  {
340  jni->DeleteLocalRef( java_args[ nPos ].l );
341  }
342  }
343  throw;
344  }
345  jni->DeleteLocalRef( java_args[ nPos ].l );
346  }
347  else // pure temp in param
348  {
349  if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
350  jni->DeleteLocalRef( java_args[ nPos ].l );
351  }
352  }
353 
354  // return value
355  if (typelib_TypeClass_DOUBLE < return_type->eTypeClass)
356  {
357  try
358  {
359  jvalue val;
360  val.l = java_ret.get();
361  map_to_uno(
362  jni, uno_ret, val, return_type, nullptr,
363  false /* no assign */, false /* no out param */ );
364  }
365  catch (...)
366  {
367  // cleanup uno pure out
368  for ( sal_Int32 i = 0; i < nParams; ++i )
369  {
370  typelib_MethodParameter const & param = params[ i ];
371  if (! param.bIn)
372  {
374  uno_args[ i ], param.pTypeRef, nullptr );
375  }
376  }
377  throw;
378  }
379  } // else: already set integral uno return value
380 
381  // no exception occurred
382  *uno_exc = nullptr;
383  }
384 }
385 
386 namespace {
387 
388 // a UNO proxy wrapping a Java interface
389 struct UNO_proxy : public uno_Interface
390 {
391  mutable std::atomic<std::size_t> m_ref;
392  Bridge const * m_bridge;
393 
394  // mapping information
395  jobject m_javaI;
396  jstring m_jo_oid;
397  OUString m_oid;
398  JNI_interface_type_info const * m_type_info;
399 
400  inline void acquire() const;
401  inline void release() const;
402 
403  // ctor
404  inline UNO_proxy(
405  JNI_context const & jni, Bridge const * bridge,
406  jobject javaI, jstring jo_oid, OUString const & oid,
407  JNI_interface_type_info const * info );
408 };
409 
410 }
411 
412 inline UNO_proxy::UNO_proxy(
413  JNI_context const & jni, Bridge const * bridge,
414  jobject javaI, jstring jo_oid, OUString const & oid,
415  JNI_interface_type_info const * info )
416  : m_ref( 1 ),
417  m_oid( oid ),
418  m_type_info( info )
419 {
420  JNI_info const * jni_info = bridge->getJniInfo();
421  JLocalAutoRef jo_string_array(
422  jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) );
423  jni.ensure_no_exception();
424  jvalue args[ 3 ];
425  args[ 0 ].l = javaI;
426  args[ 1 ].l = jo_string_array.get();
427  args[ 2 ].l = info->m_type;
428  jobject jo_iface = jni->CallObjectMethodA(
429  jni_info->m_object_java_env,
430  jni_info->m_method_IEnvironment_registerInterface, args );
431  jni.ensure_no_exception();
432 
433  m_javaI = jni->NewGlobalRef( jo_iface );
434  m_jo_oid = static_cast<jstring>(jni->NewGlobalRef( jo_oid ));
435  bridge->acquire();
436  m_bridge = bridge;
437 
438  // uno_Interface
439  uno_Interface::acquire = UNO_proxy_acquire;
440  uno_Interface::release = UNO_proxy_release;
441  uno_Interface::pDispatcher = UNO_proxy_dispatch;
442 }
443 
444 
445 inline void UNO_proxy::acquire() const
446 {
447  if (++m_ref == 1)
448  {
449  // rebirth of proxy zombie
450  void * that = const_cast< UNO_proxy * >( this );
451  // register at uno env
452  (*m_bridge->m_uno_env->registerProxyInterface)(
453  m_bridge->m_uno_env, &that,
454  UNO_proxy_free, m_oid.pData,
455  reinterpret_cast<typelib_InterfaceTypeDescription *>(m_type_info->m_td.get()) );
456  assert( this == that );
457  }
458 }
459 
460 
461 inline void UNO_proxy::release() const
462 {
463  if (--m_ref == 0)
464  {
465  // revoke from uno env on last release
466  (*m_bridge->m_uno_env->revokeInterface)(
467  m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) );
468  }
469 }
470 
471 
472 uno_Interface * Bridge::map_to_uno(
473  JNI_context const & jni,
474  jobject javaI, JNI_interface_type_info const * info ) const
475 {
476  JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) );
477  OUString oid( jstring_to_oustring( jni, static_cast<jstring>(jo_oid.get()) ) );
478 
479  uno_Interface * pUnoI = nullptr;
480  (*m_uno_env->getRegisteredInterface)(
481  m_uno_env, reinterpret_cast<void **>(&pUnoI),
482  oid.pData, reinterpret_cast<typelib_InterfaceTypeDescription *>(info->m_td.get()) );
483 
484  if (pUnoI == nullptr) // no existing interface, register new proxy
485  {
486  // refcount initially 1
487  pUnoI = new UNO_proxy(
488  jni, this,
489  javaI, static_cast<jstring>(jo_oid.get()), oid, info );
490 
491  (*m_uno_env->registerProxyInterface)(
492  m_uno_env, reinterpret_cast<void **>(&pUnoI),
493  UNO_proxy_free,
494  oid.pData, reinterpret_cast<typelib_InterfaceTypeDescription *>(info->m_td.get()) );
495  }
496  return pUnoI;
497 }
498 
499 }
500 
501 using namespace ::jni_uno;
502 
503 namespace
504 {
505 extern "C"
506 {
507 
508 
509 void UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
511 {
512  UNO_proxy * that = static_cast< UNO_proxy * >( proxy );
513  Bridge const * bridge = that->m_bridge;
514 
515  assert(env == bridge->m_uno_env); (void) env;
516  SAL_INFO("bridges", "freeing binary uno proxy: " << that->m_oid);
517 
518  try
519  {
520  JNI_guarded_context jni(
521  bridge->getJniInfo(),
522  (static_cast<JniUnoEnvironmentData *>(bridge->m_java_env->pContext)
523  ->machine));
524 
525  jni->DeleteGlobalRef( that->m_javaI );
526  jni->DeleteGlobalRef( that->m_jo_oid );
527  }
528  catch (BridgeRuntimeError & err)
529  {
530  SAL_WARN(
531  "bridges",
532  "ignoring BridgeRuntimeError \"" << err.m_message << "\"");
533  }
535  {
536  SAL_WARN("bridges", "attaching current thread to java failed");
537  }
538 
539  bridge->release();
540 #if OSL_DEBUG_LEVEL > 0
541  *reinterpret_cast<int *>(that) = 0xdeadcafe;
542 #endif
543  delete that;
544 }
545 
546 
547 void UNO_proxy_acquire( uno_Interface * pUnoI )
549 {
550  UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
551  that->acquire();
552 }
553 
554 
555 void UNO_proxy_release( uno_Interface * pUnoI )
557 {
558  UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
559  that->release();
560 }
561 
562 
563 void UNO_proxy_dispatch(
564  uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
565  void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
567 {
568  UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
569  Bridge const * bridge = that->m_bridge;
570 
571  SAL_INFO(
572  "bridges",
573  "uno->java call: " << OUString::unacquired(&member_td->pTypeName)
574  << " on oid " << that->m_oid);
575 
576  try
577  {
578  switch (member_td->eTypeClass)
579  {
580  case typelib_TypeClass_INTERFACE_ATTRIBUTE:
581  {
582  typelib_InterfaceAttributeTypeDescription const * attrib_td =
583  reinterpret_cast<
584  typelib_InterfaceAttributeTypeDescription const * >(
585  member_td );
586  com::sun::star::uno::TypeDescription attrib_holder;
587  while ( attrib_td->pBaseRef != nullptr ) {
588  attrib_holder = com::sun::star::uno::TypeDescription(
589  attrib_td->pBaseRef );
590  assert(
591  attrib_holder.get()->eTypeClass
592  == typelib_TypeClass_INTERFACE_ATTRIBUTE );
593  attrib_td = reinterpret_cast<
594  typelib_InterfaceAttributeTypeDescription * >(
595  attrib_holder.get() );
596  }
597  typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface;
598 
599  if (uno_ret == nullptr) // is setter method
600  {
601  typelib_MethodParameter param;
602  param.pTypeRef = attrib_td->pAttributeTypeRef;
603  param.bIn = true;
604  param.bOut = false;
605 
606  bridge->call_java(
607  that->m_javaI, iface_td,
608  attrib_td->nIndex, 1, // get, then set method
609  bridge->getJniInfo()->m_void_type.getTypeLibType(),
610  &param, 1,
611  nullptr, uno_args, uno_exc );
612  }
613  else // is getter method
614  {
615  bridge->call_java(
616  that->m_javaI, iface_td, attrib_td->nIndex, 0,
617  attrib_td->pAttributeTypeRef,
618  nullptr, 0, // no params
619  uno_ret, nullptr, uno_exc );
620  }
621  break;
622  }
623  case typelib_TypeClass_INTERFACE_METHOD:
624  {
625  typelib_InterfaceMethodTypeDescription const * method_td =
626  reinterpret_cast<
627  typelib_InterfaceMethodTypeDescription const * >(
628  member_td );
629  com::sun::star::uno::TypeDescription method_holder;
630  while ( method_td->pBaseRef != nullptr ) {
631  method_holder = com::sun::star::uno::TypeDescription(
632  method_td->pBaseRef );
633  assert(
634  method_holder.get()->eTypeClass
635  == typelib_TypeClass_INTERFACE_METHOD );
636  method_td = reinterpret_cast<
637  typelib_InterfaceMethodTypeDescription * >(
638  method_holder.get() );
639  }
640  typelib_InterfaceTypeDescription * iface_td = method_td->pInterface;
641 
642  switch ( method_td->aBase.nPosition )
643  {
644  case 0: // queryInterface()
645  {
646  TypeDescr demanded_td(
647  *static_cast< typelib_TypeDescriptionReference ** >(
648  uno_args[ 0 ] ) );
649  if (demanded_td.get()->eTypeClass !=
650  typelib_TypeClass_INTERFACE)
651  {
652  throw BridgeRuntimeError(
653  "queryInterface() call demands an INTERFACE type!" );
654  }
655 
656  uno_Interface * pInterface = nullptr;
657  (*bridge->m_uno_env->getRegisteredInterface)(
658  bridge->m_uno_env,
659  reinterpret_cast<void **>(&pInterface), that->m_oid.pData,
660  reinterpret_cast<typelib_InterfaceTypeDescription *>(demanded_td.get()) );
661 
662  if (pInterface == nullptr)
663  {
664  JNI_info const * jni_info = bridge->getJniInfo();
665  JNI_guarded_context jni(
666  jni_info,
667  (static_cast<JniUnoEnvironmentData *>(
668  bridge->m_java_env->pContext)
669  ->machine));
670 
671  JNI_interface_type_info const * info =
672  static_cast< JNI_interface_type_info const * >(
673  jni_info->get_type_info( jni, demanded_td.get() ) );
674 
675  jvalue args[ 2 ];
676  args[ 0 ].l = info->m_type;
677  args[ 1 ].l = that->m_javaI;
678 
679  JLocalAutoRef jo_ret(
680  jni, jni->CallStaticObjectMethodA(
681  jni_info->m_class_UnoRuntime,
682  jni_info->m_method_UnoRuntime_queryInterface,
683  args ) );
684 
685  if (jni->ExceptionCheck())
686  {
687  JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
688  jni->ExceptionClear();
689  bridge->handle_java_exc( jni, jo_exc, *uno_exc );
690  }
691  else
692  {
693  if (jo_ret.is())
694  {
695  SAL_WARN_IF(
697  jni,
698  static_cast<jstring>(
699  JLocalAutoRef(
700  jni, compute_oid(jni, jo_ret.get()))
701  .get()))
702  != that->m_oid),
703  "bridges", "different oids");
704  // refcount initially 1
705  uno_Interface * pUnoI2 = new UNO_proxy(
706  jni, bridge, jo_ret.get(),
707  that->m_jo_oid, that->m_oid, info );
708 
709  (*bridge->m_uno_env->registerProxyInterface)(
710  bridge->m_uno_env,
711  reinterpret_cast<void **>(&pUnoI2),
712  UNO_proxy_free, that->m_oid.pData,
713  reinterpret_cast<
714  typelib_InterfaceTypeDescription * >(
715  info->m_td.get() ) );
716 
718  static_cast<uno_Any *>(uno_ret), &pUnoI2,
719  demanded_td.get(), nullptr );
720  (*pUnoI2->release)( pUnoI2 );
721  }
722  else // object does not support demanded interface
723  {
725  static_cast< uno_Any * >( uno_ret ),
726  nullptr, nullptr, nullptr );
727  }
728  // no exception occurred
729  *uno_exc = nullptr;
730  }
731  }
732  else
733  {
735  static_cast< uno_Any * >( uno_ret ),
736  &pInterface, demanded_td.get(), nullptr );
737  (*pInterface->release)( pInterface );
738  *uno_exc = nullptr;
739  }
740  break;
741  }
742  case 1: // acquire this proxy
743  that->acquire();
744  *uno_exc = nullptr;
745  break;
746  case 2: // release this proxy
747  that->release();
748  *uno_exc = nullptr;
749  break;
750  default: // arbitrary method call
751  bridge->call_java(
752  that->m_javaI, iface_td, method_td->nIndex, 0,
753  method_td->pReturnTypeRef,
754  method_td->pParams, method_td->nParams,
755  uno_ret, uno_args, uno_exc );
756  break;
757  }
758  break;
759  }
760  default:
761  {
762  throw BridgeRuntimeError(
763  "illegal member type description!" );
764  }
765  }
766  }
767  catch (BridgeRuntimeError & err)
768  {
769  OUStringBuffer buf( 128 );
770  buf.append( "[jni_uno bridge error] UNO calling Java method " );
771  if (member_td->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ||
772  member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE)
773  {
774  buf.append( OUString::unacquired(
775  &reinterpret_cast<
776  typelib_InterfaceMemberTypeDescription const * >(
777  member_td )->pMemberName ) );
778  }
779  buf.append( ": " );
780  buf.append( err.m_message );
781  // binary identical struct
782  ::com::sun::star::uno::RuntimeException exc(
783  buf.makeStringAndClear(),
785  ::com::sun::star::uno::XInterface >() );
786  ::com::sun::star::uno::Type const & exc_type = cppu::UnoType<decltype(exc)>::get();
787  uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), nullptr );
788  SAL_INFO("bridges", exc.Message);
789  }
791  {
792  // binary identical struct
793  ::com::sun::star::uno::RuntimeException exc(
794  "[jni_uno bridge error] attaching current thread to java failed!",
796  ::com::sun::star::uno::XInterface >() );
797  ::com::sun::star::uno::Type const & exc_type = cppu::UnoType<decltype(exc)>::get();
798  uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), nullptr );
799  SAL_WARN("bridges", exc.Message);
800  }
801 }
802 
803 }
804 }
805 
806 /* 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
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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
void reset(jobject jo)
Definition: jni_base.h:184
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