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