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_bridge.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 "jni_bridge.h"
36 #include "jvmaccess/unovirtualmachine.hxx"
37 #include "rtl/ref.hxx"
38 #include "rtl/unload.h"
39 #include "rtl/strbuf.hxx"
40 #include "uno/lbnames.h"
43 using namespace ::std
;
44 using namespace ::rtl
;
45 using namespace ::osl
;
46 using namespace ::jni_uno
;
53 //------------------------------------------------------------------------------
54 void SAL_CALL
Mapping_acquire( uno_Mapping
* mapping
)
57 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
58 that
->m_bridge
->acquire();
61 //------------------------------------------------------------------------------
62 void SAL_CALL
Mapping_release( uno_Mapping
* mapping
)
65 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
66 that
->m_bridge
->release();
69 //------------------------------------------------------------------------------
70 void SAL_CALL
Mapping_map_to_uno(
71 uno_Mapping
* mapping
, void ** ppOut
,
72 void * pIn
, typelib_InterfaceTypeDescription
* td
)
75 uno_Interface
** ppUnoI
= (uno_Interface
**)ppOut
;
76 jobject javaI
= (jobject
) pIn
;
78 OSL_ASSERT( sizeof (void *) == sizeof (jobject
) );
79 OSL_ENSURE( ppUnoI
&& td
, "### null ptr!" );
85 uno_Interface
* p
= *(uno_Interface
**)ppUnoI
;
94 Bridge
const * bridge
=
95 static_cast< Mapping
const * >( mapping
)->m_bridge
;
96 JNI_guarded_context
jni(
98 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
99 bridge
->m_java_env
->pContext
) );
101 JNI_interface_type_info
const * info
=
102 static_cast< JNI_interface_type_info
const * >(
103 bridge
->m_jni_info
->get_type_info(
104 jni
, (typelib_TypeDescription
*)td
) );
105 uno_Interface
* pUnoI
= bridge
->map_to_uno( jni
, javaI
, info
);
108 uno_Interface
* p
= *(uno_Interface
**)ppUnoI
;
113 catch (BridgeRuntimeError
& err
)
115 #if OSL_DEBUG_LEVEL > 0
118 OUSTR("[jni_uno bridge error] ") + err
.m_message
,
119 RTL_TEXTENCODING_ASCII_US
) );
120 OSL_ENSURE( 0, cstr_msg
.getStr() );
122 (void) err
; // unused
125 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException
&)
129 "[jni_uno bridge error] attaching current thread "
135 //------------------------------------------------------------------------------
136 void SAL_CALL
Mapping_map_to_java(
137 uno_Mapping
* mapping
, void ** ppOut
,
138 void * pIn
, typelib_InterfaceTypeDescription
* td
)
141 jobject
* ppJavaI
= (jobject
*) ppOut
;
142 uno_Interface
* pUnoI
= (uno_Interface
*)pIn
;
144 OSL_ASSERT( sizeof (void *) == sizeof (jobject
) );
145 OSL_ENSURE( ppJavaI
&& td
, "### null ptr!" );
153 Bridge
const * bridge
=
154 static_cast< Mapping
const * >( mapping
)->m_bridge
;
155 JNI_guarded_context
jni(
157 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
158 bridge
->m_java_env
->pContext
) );
159 jni
->DeleteGlobalRef( *ppJavaI
);
165 Bridge
const * bridge
=
166 static_cast< Mapping
const * >( mapping
)->m_bridge
;
167 JNI_guarded_context
jni(
169 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
170 bridge
->m_java_env
->pContext
) );
172 JNI_interface_type_info
const * info
=
173 static_cast< JNI_interface_type_info
const * >(
174 bridge
->m_jni_info
->get_type_info(
175 jni
, (typelib_TypeDescription
*)td
) );
176 jobject jlocal
= bridge
->map_to_java( jni
, pUnoI
, info
);
178 jni
->DeleteGlobalRef( *ppJavaI
);
179 *ppJavaI
= jni
->NewGlobalRef( jlocal
);
180 jni
->DeleteLocalRef( jlocal
);
183 catch (BridgeRuntimeError
& err
)
185 #if OSL_DEBUG_LEVEL > 0
188 OUSTR("[jni_uno bridge error] ") + err
.m_message
,
189 RTL_TEXTENCODING_ASCII_US
) );
190 OSL_ENSURE( 0, cstr_msg
.getStr() );
192 (void) err
; // unused
195 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException
&)
199 "[jni_uno bridge error] attaching current thread to java failed!" );
203 //______________________________________________________________________________
204 void SAL_CALL
Bridge_free( uno_Mapping
* mapping
)
207 Mapping
* that
= static_cast< Mapping
* >( mapping
);
208 delete that
->m_bridge
;
213 rtl_StandardModuleCount g_moduleCount
= MODULE_COUNT_INIT
;
220 //______________________________________________________________________________
221 void Bridge::acquire() const SAL_THROW( () )
223 if (1 == osl_incrementInterlockedCount( &m_ref
))
225 if (m_registered_java2uno
)
227 uno_Mapping
* mapping
= const_cast< Mapping
* >( &m_java2uno
);
229 &mapping
, Bridge_free
,
230 m_java_env
, (uno_Environment
*)m_uno_env
, 0 );
234 uno_Mapping
* mapping
= const_cast< Mapping
* >( &m_uno2java
);
236 &mapping
, Bridge_free
,
237 (uno_Environment
*)m_uno_env
, m_java_env
, 0 );
242 //______________________________________________________________________________
243 void Bridge::release() const SAL_THROW( () )
245 if (! osl_decrementInterlockedCount( &m_ref
))
248 m_registered_java2uno
249 ? const_cast< Mapping
* >( &m_java2uno
)
250 : const_cast< Mapping
* >( &m_uno2java
) );
254 //______________________________________________________________________________
256 uno_Environment
* java_env
, uno_ExtEnvironment
* uno_env
,
257 bool registered_java2uno
)
259 m_uno_env( uno_env
),
260 m_java_env( java_env
),
261 m_registered_java2uno( registered_java2uno
)
263 // bootstrapping bridge jni_info
264 m_jni_info
= JNI_info::get_jni_info(
265 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
266 m_java_env
->pContext
) );
268 OSL_ASSERT( 0 != m_java_env
&& 0 != m_uno_env
);
269 (*((uno_Environment
*)m_uno_env
)->acquire
)( (uno_Environment
*)m_uno_env
);
270 (*m_java_env
->acquire
)( m_java_env
);
273 m_java2uno
.acquire
= Mapping_acquire
;
274 m_java2uno
.release
= Mapping_release
;
275 m_java2uno
.mapInterface
= Mapping_map_to_uno
;
276 m_java2uno
.m_bridge
= this;
278 m_uno2java
.acquire
= Mapping_acquire
;
279 m_uno2java
.release
= Mapping_release
;
280 m_uno2java
.mapInterface
= Mapping_map_to_java
;
281 m_uno2java
.m_bridge
= this;
283 (*g_moduleCount
.modCnt
.acquire
)( &g_moduleCount
.modCnt
);
286 //______________________________________________________________________________
287 Bridge::~Bridge() SAL_THROW( () )
289 (*m_java_env
->release
)( m_java_env
);
290 (*((uno_Environment
*)m_uno_env
)->release
)( (uno_Environment
*)m_uno_env
);
292 (*g_moduleCount
.modCnt
.release
)( &g_moduleCount
.modCnt
);
296 //______________________________________________________________________________
297 void JNI_context::java_exc_occured() const
299 // !don't rely on JNI_info!
301 JLocalAutoRef
jo_exc( *this, m_env
->ExceptionOccurred() );
302 m_env
->ExceptionClear();
303 OSL_ASSERT( jo_exc
.is() );
306 throw BridgeRuntimeError(
307 OUSTR("java exception occured, but not available!?") +
311 // call toString(); don't rely on m_jni_info
312 jclass jo_class
= m_env
->FindClass( "java/lang/Object" );
313 if (JNI_FALSE
!= m_env
->ExceptionCheck())
315 m_env
->ExceptionClear();
316 throw BridgeRuntimeError(
317 OUSTR("cannot get class java.lang.Object!") + get_stack_trace() );
319 JLocalAutoRef
jo_Object( *this, jo_class
);
320 // method Object.toString()
321 jmethodID method_Object_toString
= m_env
->GetMethodID(
322 (jclass
) jo_Object
.get(), "toString", "()Ljava/lang/String;" );
323 if (JNI_FALSE
!= m_env
->ExceptionCheck())
325 m_env
->ExceptionClear();
326 throw BridgeRuntimeError(
327 OUSTR("cannot get method id of java.lang.Object.toString()!") +
330 OSL_ASSERT( 0 != method_Object_toString
);
332 JLocalAutoRef
jo_descr(
333 *this, m_env
->CallObjectMethodA(
334 jo_exc
.get(), method_Object_toString
, 0 ) );
335 if (m_env
->ExceptionCheck()) // no chance at all
337 m_env
->ExceptionClear();
338 throw BridgeRuntimeError(
339 OUSTR("error examining java exception object!") +
343 jsize len
= m_env
->GetStringLength( (jstring
) jo_descr
.get() );
344 auto_ptr
< rtl_mem
> ustr_mem(
346 sizeof (rtl_uString
) + (len
* sizeof (sal_Unicode
)) ) );
347 rtl_uString
* ustr
= (rtl_uString
*)ustr_mem
.get();
348 m_env
->GetStringRegion( (jstring
) jo_descr
.get(), 0, len
, ustr
->buffer
);
349 if (m_env
->ExceptionCheck())
351 m_env
->ExceptionClear();
352 throw BridgeRuntimeError(
353 OUSTR("invalid java string object!") + get_stack_trace() );
357 ustr
->buffer
[ len
] = '\0';
358 OUString
message( (rtl_uString
*)ustr_mem
.release(), SAL_NO_ACQUIRE
);
360 throw BridgeRuntimeError( message
+ get_stack_trace( jo_exc
.get() ) );
363 //______________________________________________________________________________
364 void JNI_context::getClassForName(
365 jclass
* classClass
, jmethodID
* methodForName
) const
367 jclass c
= m_env
->FindClass("java/lang/Class");
369 *methodForName
= m_env
->GetStaticMethodID(
371 "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
376 //______________________________________________________________________________
377 jclass
JNI_context::findClass(
378 char const * name
, jclass classClass
, jmethodID methodForName
,
379 bool inException
) const
382 JLocalAutoRef
s(*this, m_env
->NewStringUTF(name
));
387 a
[2].l
= m_class_loader
;
388 c
= static_cast< jclass
>(
389 m_env
->CallStaticObjectMethodA(classClass
, methodForName
, a
));
392 ensure_no_exception();
397 //______________________________________________________________________________
398 OUString
JNI_context::get_stack_trace( jobject jo_exc
) const
400 JLocalAutoRef
jo_JNI_proxy(
402 find_class( *this, "com.sun.star.bridges.jni_uno.JNI_proxy", true ) );
403 if (assert_no_exception())
405 // static method JNI_proxy.get_stack_trace()
406 jmethodID method
= m_env
->GetStaticMethodID(
407 (jclass
) jo_JNI_proxy
.get(), "get_stack_trace",
408 "(Ljava/lang/Throwable;)Ljava/lang/String;" );
409 if (assert_no_exception() && (0 != method
))
413 JLocalAutoRef
jo_stack_trace(
414 *this, m_env
->CallStaticObjectMethodA(
415 (jclass
) jo_JNI_proxy
.get(), method
, &arg
) );
416 if (assert_no_exception())
419 m_env
->GetStringLength( (jstring
) jo_stack_trace
.get() );
420 auto_ptr
< rtl_mem
> ustr_mem(
422 sizeof (rtl_uString
) + (len
* sizeof (sal_Unicode
)) ) );
423 rtl_uString
* ustr
= (rtl_uString
*)ustr_mem
.get();
424 m_env
->GetStringRegion(
425 (jstring
) jo_stack_trace
.get(), 0, len
, ustr
->buffer
);
426 if (assert_no_exception())
430 ustr
->buffer
[ len
] = '\0';
432 (rtl_uString
*)ustr_mem
.release(), SAL_NO_ACQUIRE
);
442 using namespace ::jni_uno
;
449 //------------------------------------------------------------------------------
450 void SAL_CALL
java_env_disposing( uno_Environment
* java_env
)
453 ::jvmaccess::UnoVirtualMachine
* machine
=
454 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
455 java_env
->pContext
);
456 java_env
->pContext
= 0;
461 //------------------------------------------------------------------------------
462 void SAL_CALL
uno_initEnvironment( uno_Environment
* java_env
)
465 java_env
->environmentDisposing
= java_env_disposing
;
466 java_env
->pExtEnv
= 0; // no extended support
467 OSL_ASSERT( 0 != java_env
->pContext
);
469 ::jvmaccess::UnoVirtualMachine
* machine
=
470 reinterpret_cast< ::jvmaccess::UnoVirtualMachine
* >(
471 java_env
->pContext
);
475 //------------------------------------------------------------------------------
476 void SAL_CALL
uno_ext_getMapping(
477 uno_Mapping
** ppMapping
, uno_Environment
* pFrom
, uno_Environment
* pTo
)
480 OSL_ASSERT( 0 != ppMapping
&& 0 != pFrom
&& 0 != pTo
);
483 (*(*ppMapping
)->release
)( *ppMapping
);
487 OSL_ASSERT( JNI_FALSE
== sal_False
);
488 OSL_ASSERT( JNI_TRUE
== sal_True
);
489 OSL_ASSERT( sizeof (jboolean
) == sizeof (sal_Bool
) );
490 OSL_ASSERT( sizeof (jchar
) == sizeof (sal_Unicode
) );
491 OSL_ASSERT( sizeof (jdouble
) == sizeof (double) );
492 OSL_ASSERT( sizeof (jfloat
) == sizeof (float) );
493 OSL_ASSERT( sizeof (jbyte
) == sizeof (sal_Int8
) );
494 OSL_ASSERT( sizeof (jshort
) == sizeof (sal_Int16
) );
495 OSL_ASSERT( sizeof (jint
) == sizeof (sal_Int32
) );
496 OSL_ASSERT( sizeof (jlong
) == sizeof (sal_Int64
) );
497 if ((JNI_FALSE
== sal_False
) &&
498 (JNI_TRUE
== sal_True
) &&
499 (sizeof (jboolean
) == sizeof (sal_Bool
)) &&
500 (sizeof (jchar
) == sizeof (sal_Unicode
)) &&
501 (sizeof (jdouble
) == sizeof (double)) &&
502 (sizeof (jfloat
) == sizeof (float)) &&
503 (sizeof (jbyte
) == sizeof (sal_Int8
)) &&
504 (sizeof (jshort
) == sizeof (sal_Int16
)) &&
505 (sizeof (jint
) == sizeof (sal_Int32
)) &&
506 (sizeof (jlong
) == sizeof (sal_Int64
)))
508 OUString
const & from_env_typename
=
509 OUString::unacquired( &pFrom
->pTypeName
);
510 OUString
const & to_env_typename
=
511 OUString::unacquired( &pTo
->pTypeName
);
513 uno_Mapping
* mapping
= 0;
517 if (from_env_typename
.equalsAsciiL(
518 RTL_CONSTASCII_STRINGPARAM(UNO_LB_JAVA
) ) &&
519 to_env_typename
.equalsAsciiL(
520 RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO
) ))
523 new Bridge( pFrom
, pTo
->pExtEnv
, true ); // ref count = 1
524 mapping
= &bridge
->m_java2uno
;
526 &mapping
, Bridge_free
,
527 pFrom
, (uno_Environment
*)pTo
->pExtEnv
, 0 );
529 else if (from_env_typename
.equalsAsciiL(
530 RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO
) ) &&
531 to_env_typename
.equalsAsciiL(
532 RTL_CONSTASCII_STRINGPARAM(UNO_LB_JAVA
) ))
535 new Bridge( pTo
, pFrom
->pExtEnv
, false ); // ref count = 1
536 mapping
= &bridge
->m_uno2java
;
538 &mapping
, Bridge_free
,
539 (uno_Environment
*)pFrom
->pExtEnv
, pTo
, 0 );
542 catch (BridgeRuntimeError
& err
)
544 #if OSL_DEBUG_LEVEL > 0
547 OUSTR("[jni_uno bridge error] ") + err
.m_message
,
548 RTL_TEXTENCODING_ASCII_US
) );
549 OSL_ENSURE( 0, cstr_msg
.getStr() );
551 (void) err
; // unused
554 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException
&)
558 "[jni_uno bridge error] attaching current thread "
562 *ppMapping
= mapping
;
566 //------------------------------------------------------------------------------
567 sal_Bool SAL_CALL
component_canUnload( TimeValue
* pTime
)
570 return (*g_moduleCount
.canUnload
)( &g_moduleCount
, pTime
);