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