1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: jni_java2uno.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
34 #include <sal/alloca.h>
36 #include "jni_bridge.h"
37 //#include "jni_finalizer.h"
39 #include <rtl/ustrbuf.hxx>
44 using namespace ::rtl
;
49 //______________________________________________________________________________
50 jobject
Bridge::map_to_java(
51 JNI_context
const & jni
,
52 uno_Interface
* pUnoI
, JNI_interface_type_info
const * info
) const
55 rtl_uString
* pOid
= 0;
56 (*m_uno_env
->getObjectIdentifier
)( m_uno_env
, &pOid
, pUnoI
);
57 OSL_ASSERT( 0 != pOid
);
58 OUString
oid( pOid
, SAL_NO_ACQUIRE
);
60 // opt getRegisteredInterface()
61 JLocalAutoRef
jo_oid( jni
, ustring_to_jstring( jni
, oid
.pData
) );
63 args
[ 0 ].l
= jo_oid
.get();
64 args
[ 1 ].l
= info
->m_type
;
65 jobject jo_iface
= jni
->CallObjectMethodA(
66 m_jni_info
->m_object_java_env
,
67 m_jni_info
->m_method_IEnvironment_getRegisteredInterface
, args
);
68 jni
.ensure_no_exception();
70 if (0 == jo_iface
) // no registered iface
72 // register uno interface
73 (*m_uno_env
->registerInterface
)(
74 m_uno_env
, reinterpret_cast< void ** >( &pUnoI
),
75 oid
.pData
, (typelib_InterfaceTypeDescription
*)info
->m_td
.get() );
77 // create java and register java proxy
80 args2
[ 0 ].j
= reinterpret_cast< sal_Int64
>( this );
81 (*pUnoI
->acquire
)( pUnoI
);
82 args2
[ 1 ].l
= m_jni_info
->m_object_java_env
;
83 args2
[ 2 ].j
= reinterpret_cast< sal_Int64
>( pUnoI
);
84 typelib_typedescription_acquire( info
->m_td
.get() );
85 args2
[ 3 ].j
= reinterpret_cast< sal_Int64
>( info
->m_td
.get() );
86 args2
[ 4 ].l
= info
->m_type
;
87 args2
[ 5 ].l
= jo_oid
.get();
88 args2
[ 6 ].l
= info
->m_proxy_ctor
;
89 jo_iface
= jni
->CallStaticObjectMethodA(
90 m_jni_info
->m_class_JNI_proxy
,
91 m_jni_info
->m_method_JNI_proxy_create
, args2
);
92 jni
.ensure_no_exception();
95 OSL_ASSERT( 0 != jo_iface
);
100 //______________________________________________________________________________
101 void Bridge::handle_uno_exc( JNI_context
const & jni
, uno_Any
* uno_exc
) const
103 if (typelib_TypeClass_EXCEPTION
== uno_exc
->pType
->eTypeClass
)
105 #if OSL_DEBUG_LEVEL > 0
106 // append java stack trace to Message member
107 reinterpret_cast< ::com::sun::star::uno::Exception
* >(
108 uno_exc
->pData
)->Message
+= jni
.get_stack_trace();
111 #if OSL_DEBUG_LEVEL > 1
113 OUStringBuffer
buf( 128 );
115 RTL_CONSTASCII_STRINGPARAM("exception occured java->uno: [") );
116 buf
.append( OUString::unacquired( &uno_exc
->pType
->pTypeName
) );
117 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
119 reinterpret_cast< ::com::sun::star::uno::Exception
const * >(
120 uno_exc
->pData
)->Message
);
123 buf
.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US
) );
124 OSL_TRACE( cstr_msg
.getStr() );
132 jni
, &java_exc
, uno_exc
->pData
, uno_exc
->pType
, 0,
133 true /* in */, false /* no out */ );
137 uno_any_destruct( uno_exc
, 0 );
140 uno_any_destruct( uno_exc
, 0 );
142 JLocalAutoRef
jo_exc( jni
, java_exc
.l
);
143 jint res
= jni
->Throw( (jthrowable
) jo_exc
.get() );
147 JLocalAutoRef
jo_descr(
148 jni
, jni
->CallObjectMethodA(
149 jo_exc
.get(), m_jni_info
->m_method_Object_toString
, 0 ) );
150 jni
.ensure_no_exception();
151 OUStringBuffer
buf( 128 );
152 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
153 "throwing java exception failed: ") );
154 buf
.append( jstring_to_oustring( jni
, (jstring
) jo_descr
.get() ) );
155 buf
.append( jni
.get_stack_trace() );
156 throw BridgeRuntimeError( buf
.makeStringAndClear() );
162 OUSTR("thrown exception is no uno exception: ") +
163 OUString::unacquired( &uno_exc
->pType
->pTypeName
) +
164 jni
.get_stack_trace() );
165 uno_any_destruct( uno_exc
, 0 );
166 throw BridgeRuntimeError( message
);
178 //______________________________________________________________________________
179 jobject
Bridge::call_uno(
180 JNI_context
const & jni
,
181 uno_Interface
* pUnoI
, typelib_TypeDescription
* member_td
,
182 typelib_TypeDescriptionReference
* return_type
,
183 sal_Int32 nParams
, typelib_MethodParameter
const * pParams
,
184 jobjectArray jo_args
/* may be 0 */ ) const
187 sal_Int32 return_size
;
188 switch (return_type
->eTypeClass
) {
189 case typelib_TypeClass_VOID
:
193 case typelib_TypeClass_STRUCT
:
194 case typelib_TypeClass_EXCEPTION
:
195 return_size
= std::max(
196 TypeDescr(return_type
).get()->nSize
,
197 static_cast< sal_Int32
>(sizeof (largest
)));
201 return_size
= sizeof (largest
);
206 char * mem
= (char *) malloc(
208 char * mem
= (char *) alloca(
210 (nParams
* sizeof (void *)) +
211 return_size
+ (nParams
* sizeof (largest
)) );
212 void ** uno_args
= (void **) mem
;
213 void * uno_ret
= return_size
== 0 ? 0 : (mem
+ (nParams
* sizeof (void *)));
214 largest
* uno_args_mem
= (largest
*)
215 (mem
+ (nParams
* sizeof (void *)) + return_size
);
217 OSL_ASSERT( (0 == nParams
) || (nParams
== jni
->GetArrayLength( jo_args
)) );
218 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
220 typelib_MethodParameter
const & param
= pParams
[ nPos
];
221 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
223 uno_args
[ nPos
] = &uno_args_mem
[ nPos
];
224 if (typelib_TypeClass_STRUCT
== type
->eTypeClass
||
225 typelib_TypeClass_EXCEPTION
== type
->eTypeClass
)
227 TypeDescr
td( type
);
228 if (sal::static_int_cast
< sal_uInt32
>(td
.get()->nSize
)
231 uno_args
[ nPos
] = malloc( td
.get()->nSize
);
233 uno_args
[ nPos
] = alloca( td
.get()->nSize
);
241 JLocalAutoRef
jo_arg(
242 jni
, jni
->GetObjectArrayElement( jo_args
, nPos
) );
243 jni
.ensure_no_exception();
245 java_arg
.l
= jo_arg
.get();
247 jni
, uno_args
[ nPos
], java_arg
, type
, 0,
248 false /* no assign */, sal_False
!= param
.bOut
,
249 true /* special wrapped integral types */ );
253 // cleanup uno in args
254 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
256 typelib_MethodParameter
const & p
= pParams
[ n
];
259 uno_type_destructData(
260 uno_args
[ n
], p
.pTypeRef
, 0 );
263 if (uno_args
[ nPos
] && uno_args
[ nPos
] != &uno_args_mem
[ nPos
])
264 free( uno_args
[ nPos
] );
275 uno_Any uno_exc_holder
;
276 uno_Any
* uno_exc
= &uno_exc_holder
;
278 (*pUnoI
->pDispatcher
)( pUnoI
, member_td
, uno_ret
, uno_args
, &uno_exc
);
282 // convert out args; destruct uno args
283 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
285 typelib_MethodParameter
const & param
= pParams
[ nPos
];
286 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
291 // get out holder array[ 1 ]
292 JLocalAutoRef
jo_out_holder(
293 jni
, jni
->GetObjectArrayElement( jo_args
, nPos
) );
294 jni
.ensure_no_exception();
296 java_arg
.l
= jo_out_holder
.get();
298 jni
, &java_arg
, uno_args
[ nPos
], type
, 0,
299 true /* in */, true /* out holder */ );
303 // cleanup further uno args
304 for ( sal_Int32 n
= nPos
; n
< nParams
; ++n
)
306 uno_type_destructData(
307 uno_args
[ n
], pParams
[ n
].pTypeRef
, 0 );
309 if (uno_args
[ nPos
] && uno_args
[ nPos
] != &uno_args_mem
[ nPos
])
310 free( uno_args
[ nPos
] );
313 // cleanup uno return value
314 uno_type_destructData( uno_ret
, return_type
, 0 );
321 if (typelib_TypeClass_DOUBLE
< type
->eTypeClass
&&
322 typelib_TypeClass_ENUM
!= type
->eTypeClass
) // opt
324 uno_type_destructData( uno_args
[ nPos
], type
, 0 );
326 if (uno_args
[ nPos
] && uno_args
[ nPos
] != &uno_args_mem
[ nPos
])
327 free( uno_args
[ nPos
] );
332 if (typelib_TypeClass_VOID
!= return_type
->eTypeClass
)
334 // convert uno return value
339 jni
, &java_ret
, uno_ret
, return_type
, 0,
340 true /* in */, false /* no out */,
341 true /* special_wrapped_integral_types */ );
345 uno_type_destructData( uno_ret
, return_type
, 0 );
351 if (typelib_TypeClass_DOUBLE
< return_type
->eTypeClass
&&
352 typelib_TypeClass_ENUM
!= return_type
->eTypeClass
) // opt
354 uno_type_destructData( uno_ret
, return_type
, 0 );
364 return 0; // void return
366 else // exception occured
368 // destruct uno in args
369 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
371 typelib_MethodParameter
const & param
= pParams
[ nPos
];
373 uno_type_destructData( uno_args
[ nPos
], param
.pTypeRef
, 0 );
375 if (uno_args
[ nPos
] && uno_args
[ nPos
] != &uno_args_mem
[ nPos
])
376 free( uno_args
[ nPos
] );
380 handle_uno_exc( jni
, uno_exc
);
390 using namespace ::jni_uno
;
395 //------------------------------------------------------------------------------
397 JNICALL
Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call(
398 JNIEnv
* jni_env
, jobject jo_proxy
, jlong bridge_handle
, jstring
,
399 jstring jo_method
, jobjectArray jo_args
/* may be 0 */ )
402 Bridge
const * bridge
= reinterpret_cast< Bridge
const * >( bridge_handle
);
403 JNI_info
const * jni_info
= bridge
->m_jni_info
;
406 static_cast< jobject
>(
407 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
408 bridge
->m_java_env
->pContext
)->getClassLoader() ) );
410 OUString method_name
;
414 method_name
= jstring_to_oustring( jni
, jo_method
);
415 #if OSL_DEBUG_LEVEL > 1
417 OUStringBuffer
trace_buf( 64 );
418 trace_buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("java->uno call: ") );
419 trace_buf
.append( method_name
);
420 trace_buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") );
421 JLocalAutoRef
jo_oid(
422 jni
, jni
->GetObjectField(
423 jo_proxy
, jni_info
->m_field_JNI_proxy_m_oid
) );
424 trace_buf
.append( jstring_to_oustring( jni
, (jstring
) jo_oid
.get() ) );
427 trace_buf
.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US
) );
428 OSL_TRACE( cstr_msg
.getStr() );
432 // special IQueryInterface.queryInterface()
433 if (method_name
.equalsAsciiL(
434 RTL_CONSTASCII_STRINGPARAM("queryInterface") ))
437 JLocalAutoRef
jo_oid(
438 jni
, jni
->GetObjectField(
439 jo_proxy
, jni_info
->m_field_JNI_proxy_m_oid
) );
441 JLocalAutoRef
jo_type(
442 jni
, jni
->GetObjectArrayElement( jo_args
, 0 ) );
443 jni
.ensure_no_exception();
445 JLocalAutoRef
jo_type_name(
446 jni
, jni
->GetObjectField(
447 jo_type
.get(), jni_info
->m_field_Type__typeName
) );
448 if (! jo_type_name
.is())
450 throw BridgeRuntimeError(
451 OUSTR("incomplete type object: no type name!") +
452 jni
.get_stack_trace() );
455 jstring_to_oustring( jni
, (jstring
) jo_type_name
.get() ) );
456 JNI_type_info
const * info
=
457 jni_info
->get_type_info( jni
, type_name
);
458 if (typelib_TypeClass_INTERFACE
!= info
->m_td
.get()->eTypeClass
)
460 throw BridgeRuntimeError(
461 OUSTR("queryInterface() call demands an INTERFACE type!") );
463 JNI_interface_type_info
const * iface_info
=
464 static_cast< JNI_interface_type_info
const * >( info
);
466 // getRegisteredInterface() already tested in JNI_proxy:
467 // perform queryInterface call on binary uno interface
468 uno_Interface
* pUnoI
= reinterpret_cast< uno_Interface
* >(
470 jo_proxy
, jni_info
->m_field_JNI_proxy_m_receiver_handle
) );
473 void * uno_args
[] = { &iface_info
->m_td
.get()->pWeakRef
};
474 uno_Any uno_exc_holder
;
475 uno_Any
* uno_exc
= &uno_exc_holder
;
477 (*pUnoI
->pDispatcher
)(
478 pUnoI
, jni_info
->m_XInterface_queryInterface_td
.get(),
479 &uno_ret
, uno_args
, &uno_exc
);
483 if (typelib_TypeClass_INTERFACE
== uno_ret
.pType
->eTypeClass
)
485 uno_Interface
* pUnoRet
=
486 (uno_Interface
*) uno_ret
.pReserved
;
492 bridge
->map_to_java( jni
, pUnoRet
, iface_info
);
496 uno_any_destruct( &uno_ret
, 0 );
501 uno_any_destruct( &uno_ret
, 0 );
506 bridge
->handle_uno_exc( jni
, uno_exc
);
511 typelib_InterfaceTypeDescription
* td
=
512 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
514 jo_proxy
, jni_info
->m_field_JNI_proxy_m_td_handle
) );
515 uno_Interface
* pUnoI
=
516 reinterpret_cast< uno_Interface
* >(
518 jo_proxy
, jni_info
->m_field_JNI_proxy_m_receiver_handle
) );
520 typelib_TypeDescriptionReference
** ppAllMembers
= td
->ppAllMembers
;
521 for ( sal_Int32 nPos
= td
->nAllMembers
; nPos
--; )
523 // try to avoid getting typedescription as long as possible,
524 // because of a Mutex.acquire() in
525 // typelib_typedescriptionreference_getDescription()
526 typelib_TypeDescriptionReference
* member_type
=
527 ppAllMembers
[ nPos
];
529 // check method_name against fully qualified type_name
530 // of member_type; type_name is of the form
531 // <name> "::" <method_name> *(":@" <idx> "," <idx> ":" <name>)
532 OUString
const & type_name
=
533 OUString::unacquired( &member_type
->pTypeName
);
534 sal_Int32 offset
= type_name
.indexOf( ':' ) + 2;
536 offset
>= 2 && offset
< type_name
.getLength()
537 && type_name
[offset
- 1] == ':' );
538 sal_Int32 remainder
= type_name
.getLength() - offset
;
539 if (typelib_TypeClass_INTERFACE_METHOD
== member_type
->eTypeClass
)
541 if ((method_name
.getLength() == remainder
542 || (method_name
.getLength() < remainder
543 && type_name
[offset
+ method_name
.getLength()] == ':'))
544 && type_name
.match(method_name
, offset
))
546 TypeDescr
member_td( member_type
);
547 typelib_InterfaceMethodTypeDescription
* method_td
=
549 typelib_InterfaceMethodTypeDescription
* >(
551 return bridge
->call_uno(
552 jni
, pUnoI
, member_td
.get(),
553 method_td
->pReturnTypeRef
,
554 method_td
->nParams
, method_td
->pParams
,
561 typelib_TypeClass_INTERFACE_ATTRIBUTE
==
562 member_type
->eTypeClass
);
564 if (method_name
.getLength() >= 3
565 && (method_name
.getLength() - 3 == remainder
566 || (method_name
.getLength() - 3 < remainder
568 offset
+ (method_name
.getLength() - 3)] == ':'))
569 && method_name
[1] == 'e' && method_name
[2] == 't'
570 && rtl_ustr_compare_WithLength(
571 type_name
.getStr() + offset
,
572 method_name
.getLength() - 3,
573 method_name
.getStr() + 3,
574 method_name
.getLength() - 3) == 0)
576 if ('g' == method_name
[ 0 ])
578 TypeDescr
member_td( member_type
);
579 typelib_InterfaceAttributeTypeDescription
* attr_td
=
581 typelib_InterfaceAttributeTypeDescription
* >(
583 return bridge
->call_uno(
584 jni
, pUnoI
, member_td
.get(),
585 attr_td
->pAttributeTypeRef
,
589 else if ('s' == method_name
[ 0 ])
591 TypeDescr
member_td( member_type
);
592 typelib_InterfaceAttributeTypeDescription
* attr_td
=
594 typelib_InterfaceAttributeTypeDescription
* >(
596 if (! attr_td
->bReadOnly
)
598 typelib_MethodParameter param
;
599 param
.pTypeRef
= attr_td
->pAttributeTypeRef
;
600 param
.bIn
= sal_True
;
601 param
.bOut
= sal_False
;
602 return bridge
->call_uno(
603 jni
, pUnoI
, member_td
.get(),
604 jni_info
->m_void_type
.getTypeLibType(),
612 // the thing that should not be... no method info found!
613 OUStringBuffer
buf( 64 );
614 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
615 "calling undeclared function on interface ") );
616 buf
.append( OUString::unacquired(
617 &((typelib_TypeDescription
*)td
)->pTypeName
) );
618 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
619 buf
.append( method_name
);
620 buf
.append( jni
.get_stack_trace() );
621 throw BridgeRuntimeError( buf
.makeStringAndClear() );
623 catch (BridgeRuntimeError
& err
)
625 OUStringBuffer
buf( 128 );
627 RTL_CONSTASCII_STRINGPARAM("[jni_uno bridge error] "
628 "Java calling UNO method ") );
629 buf
.append( method_name
);
630 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
631 buf
.append( err
.m_message
);
632 // notify RuntimeException
635 buf
.makeStringAndClear(), RTL_TEXTENCODING_JAVA_UTF8
) );
636 OSL_ENSURE( 0, cstr_msg
.getStr() );
637 if (jni
->ThrowNew(jni_info
->m_class_RuntimeException
, cstr_msg
.getStr())
644 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException
&)
647 OString( RTL_CONSTASCII_STRINGPARAM(
648 "[jni_uno bridge error] "
649 "attaching current thread to java failed!") ) +
651 jni
.get_stack_trace(), RTL_TEXTENCODING_JAVA_UTF8
) );
652 OSL_ENSURE( 0, cstr_msg
.getStr() );
653 if (jni
->ThrowNew(jni_info
->m_class_RuntimeException
, cstr_msg
.getStr())
662 //------------------------------------------------------------------------------
664 JNICALL
Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J(
665 JNIEnv
* jni_env
, jobject jo_proxy
, jlong bridge_handle
)
668 Bridge
const * bridge
= reinterpret_cast< Bridge
const * >( bridge_handle
);
669 JNI_info
const * jni_info
= bridge
->m_jni_info
;
672 static_cast< jobject
>(
673 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
674 bridge
->m_java_env
->pContext
)->getClassLoader() ) );
676 uno_Interface
* pUnoI
= reinterpret_cast< uno_Interface
* >(
678 jo_proxy
, jni_info
->m_field_JNI_proxy_m_receiver_handle
) );
679 typelib_TypeDescription
* td
=
680 reinterpret_cast< typelib_TypeDescription
* >(
682 jo_proxy
, jni_info
->m_field_JNI_proxy_m_td_handle
) );
684 #if OSL_DEBUG_LEVEL > 1
686 JLocalAutoRef
jo_oid(
687 jni
, jni
->GetObjectField(
688 jo_proxy
, jni_info
->m_field_JNI_proxy_m_oid
) );
689 OUString
oid( jstring_to_oustring( jni
, (jstring
) jo_oid
.get() ) );
692 OUSTR("freeing java uno proxy: ") + oid
,
693 RTL_TEXTENCODING_ASCII_US
) );
694 OSL_TRACE( cstr_msg
.getStr() );
697 // revoke from uno env; has already been revoked from java env
698 (*bridge
->m_uno_env
->revokeInterface
)( bridge
->m_uno_env
, pUnoI
);
700 (*pUnoI
->release
)( pUnoI
);
701 // release typedescription handle
702 typelib_typedescription_release( td
);
703 // release bridge handle