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