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