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 : ¶m, 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: */
|