update dev300-m58
[ooovba.git] / bridges / source / jni_uno / jni_bridge.cxx
blob3e5fca15437bf1b2e360fb81b0ce5ccb5b0840b1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: jni_bridge.cxx,v $
10 * $Revision: 1.18 $
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;
48 namespace
50 extern "C"
53 //------------------------------------------------------------------------------
54 void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
55 SAL_THROW_EXTERN_C()
57 Mapping const * that = static_cast< Mapping const * >( mapping );
58 that->m_bridge->acquire();
61 //------------------------------------------------------------------------------
62 void SAL_CALL Mapping_release( uno_Mapping * mapping )
63 SAL_THROW_EXTERN_C()
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 )
73 SAL_THROW_EXTERN_C()
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!" );
81 if (0 == javaI)
83 if (0 != *ppUnoI)
85 uno_Interface * p = *(uno_Interface **)ppUnoI;
86 (*p->release)( p );
87 *ppUnoI = 0;
90 else
92 try
94 Bridge const * bridge =
95 static_cast< Mapping const * >( mapping )->m_bridge;
96 JNI_guarded_context jni(
97 bridge->m_jni_info,
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 );
106 if (0 != *ppUnoI)
108 uno_Interface * p = *(uno_Interface **)ppUnoI;
109 (*p->release)( p );
111 *ppUnoI = pUnoI;
113 catch (BridgeRuntimeError & err)
115 #if OSL_DEBUG_LEVEL > 0
116 OString cstr_msg(
117 OUStringToOString(
118 OUSTR("[jni_uno bridge error] ") + err.m_message,
119 RTL_TEXTENCODING_ASCII_US ) );
120 OSL_ENSURE( 0, cstr_msg.getStr() );
121 #else
122 (void) err; // unused
123 #endif
125 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
127 OSL_ENSURE(
129 "[jni_uno bridge error] attaching current thread "
130 "to java failed!" );
135 //------------------------------------------------------------------------------
136 void SAL_CALL Mapping_map_to_java(
137 uno_Mapping * mapping, void ** ppOut,
138 void * pIn, typelib_InterfaceTypeDescription * td )
139 SAL_THROW_EXTERN_C()
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!" );
149 if (0 == pUnoI)
151 if (0 != *ppJavaI)
153 Bridge const * bridge =
154 static_cast< Mapping const * >( mapping )->m_bridge;
155 JNI_guarded_context jni(
156 bridge->m_jni_info,
157 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
158 bridge->m_java_env->pContext ) );
159 jni->DeleteGlobalRef( *ppJavaI );
160 *ppJavaI = 0;
163 else
165 Bridge const * bridge =
166 static_cast< Mapping const * >( mapping )->m_bridge;
167 JNI_guarded_context jni(
168 bridge->m_jni_info,
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 );
177 if (0 != *ppJavaI)
178 jni->DeleteGlobalRef( *ppJavaI );
179 *ppJavaI = jni->NewGlobalRef( jlocal );
180 jni->DeleteLocalRef( jlocal );
183 catch (BridgeRuntimeError & err)
185 #if OSL_DEBUG_LEVEL > 0
186 OString cstr_msg(
187 OUStringToOString(
188 OUSTR("[jni_uno bridge error] ") + err.m_message,
189 RTL_TEXTENCODING_ASCII_US ) );
190 OSL_ENSURE( 0, cstr_msg.getStr() );
191 #else
192 (void) err; // unused
193 #endif
195 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
197 OSL_ENSURE(
199 "[jni_uno bridge error] attaching current thread to java failed!" );
203 //______________________________________________________________________________
204 void SAL_CALL Bridge_free( uno_Mapping * mapping )
205 SAL_THROW_EXTERN_C()
207 Mapping * that = static_cast< Mapping * >( mapping );
208 delete that->m_bridge;
213 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
217 namespace jni_uno
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 );
228 uno_registerMapping(
229 &mapping, Bridge_free,
230 m_java_env, (uno_Environment *)m_uno_env, 0 );
232 else
234 uno_Mapping * mapping = const_cast< Mapping * >( &m_uno2java );
235 uno_registerMapping(
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 ))
247 uno_revokeMapping(
248 m_registered_java2uno
249 ? const_cast< Mapping * >( &m_java2uno )
250 : const_cast< Mapping * >( &m_uno2java ) );
254 //______________________________________________________________________________
255 Bridge::Bridge(
256 uno_Environment * java_env, uno_ExtEnvironment * uno_env,
257 bool registered_java2uno )
258 : m_ref( 1 ),
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 );
272 // java2uno
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;
277 // uno2java
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() );
304 if (! jo_exc.is())
306 throw BridgeRuntimeError(
307 OUSTR("java exception occured, but not available!?") +
308 get_stack_trace() );
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()!") +
328 get_stack_trace() );
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!") +
340 get_stack_trace() );
343 jsize len = m_env->GetStringLength( (jstring) jo_descr.get() );
344 auto_ptr< rtl_mem > ustr_mem(
345 rtl_mem::allocate(
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() );
355 ustr->refCount = 1;
356 ustr->length = len;
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");
368 if (c != 0) {
369 *methodForName = m_env->GetStaticMethodID(
370 c, "forName",
371 "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
373 *classClass = c;
376 //______________________________________________________________________________
377 jclass JNI_context::findClass(
378 char const * name, jclass classClass, jmethodID methodForName,
379 bool inException) const
381 jclass c = 0;
382 JLocalAutoRef s(*this, m_env->NewStringUTF(name));
383 if (s.is()) {
384 jvalue a[3];
385 a[0].l = s.get();
386 a[1].z = JNI_FALSE;
387 a[2].l = m_class_loader;
388 c = static_cast< jclass >(
389 m_env->CallStaticObjectMethodA(classClass, methodForName, a));
391 if (!inException) {
392 ensure_no_exception();
394 return c;
397 //______________________________________________________________________________
398 OUString JNI_context::get_stack_trace( jobject jo_exc ) const
400 JLocalAutoRef jo_JNI_proxy(
401 *this,
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))
411 jvalue arg;
412 arg.l = jo_exc;
413 JLocalAutoRef jo_stack_trace(
414 *this, m_env->CallStaticObjectMethodA(
415 (jclass) jo_JNI_proxy.get(), method, &arg ) );
416 if (assert_no_exception())
418 jsize len =
419 m_env->GetStringLength( (jstring) jo_stack_trace.get() );
420 auto_ptr< rtl_mem > ustr_mem(
421 rtl_mem::allocate(
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())
428 ustr->refCount = 1;
429 ustr->length = len;
430 ustr->buffer[ len ] = '\0';
431 return OUString(
432 (rtl_uString *)ustr_mem.release(), SAL_NO_ACQUIRE );
437 return OUString();
442 using namespace ::jni_uno;
444 extern "C"
446 namespace
449 //------------------------------------------------------------------------------
450 void SAL_CALL java_env_disposing( uno_Environment * java_env )
451 SAL_THROW_EXTERN_C()
453 ::jvmaccess::UnoVirtualMachine * machine =
454 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
455 java_env->pContext );
456 java_env->pContext = 0;
457 machine->release();
461 //------------------------------------------------------------------------------
462 void SAL_CALL uno_initEnvironment( uno_Environment * java_env )
463 SAL_THROW_EXTERN_C()
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 );
472 machine->acquire();
475 //------------------------------------------------------------------------------
476 void SAL_CALL uno_ext_getMapping(
477 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
478 SAL_THROW_EXTERN_C()
480 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
481 if (0 != *ppMapping)
483 (*(*ppMapping)->release)( *ppMapping );
484 *ppMapping = 0;
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) ))
522 Bridge * bridge =
523 new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
524 mapping = &bridge->m_java2uno;
525 uno_registerMapping(
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) ))
534 Bridge * bridge =
535 new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
536 mapping = &bridge->m_uno2java;
537 uno_registerMapping(
538 &mapping, Bridge_free,
539 (uno_Environment *)pFrom->pExtEnv, pTo, 0 );
542 catch (BridgeRuntimeError & err)
544 #if OSL_DEBUG_LEVEL > 0
545 OString cstr_msg(
546 OUStringToOString(
547 OUSTR("[jni_uno bridge error] ") + err.m_message,
548 RTL_TEXTENCODING_ASCII_US ) );
549 OSL_ENSURE( 0, cstr_msg.getStr() );
550 #else
551 (void) err; // unused
552 #endif
554 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
556 OSL_ENSURE(
558 "[jni_uno bridge error] attaching current thread "
559 "to java failed!" );
562 *ppMapping = mapping;
566 //------------------------------------------------------------------------------
567 sal_Bool SAL_CALL component_canUnload( TimeValue * pTime )
568 SAL_THROW_EXTERN_C()
570 return (*g_moduleCount.canUnload)( &g_moduleCount, pTime );