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