diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /bridges/source/jni_uno/jni_data.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bridges/source/jni_uno/jni_data.cxx')
-rw-r--r-- | bridges/source/jni_uno/jni_data.cxx | 2476 |
1 files changed, 2476 insertions, 0 deletions
diff --git a/bridges/source/jni_uno/jni_data.cxx b/bridges/source/jni_uno/jni_data.cxx new file mode 100644 index 000000000..06e8467f7 --- /dev/null +++ b/bridges/source/jni_uno/jni_data.cxx @@ -0,0 +1,2476 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cassert> +#include <memory> + +#include "jni_bridge.h" + +#include <rtl/strbuf.hxx> +#include <uno/sequence2.h> + +namespace jni_uno +{ + + +static std::unique_ptr<rtl_mem> seq_allocate( + sal_Int32 nElements, sal_Int32 nSize ) +{ + std::unique_ptr< rtl_mem > seq( + rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) ); + uno_Sequence * p = reinterpret_cast<uno_Sequence *>(seq.get()); + p->nRefCount = 1; + p->nElements = nElements; + return seq; +} + + +namespace { + +void createDefaultUnoValue( + JNI_context const & jni, void * uno_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, bool assign) +{ + switch (type->eTypeClass) { + case typelib_TypeClass_BOOLEAN: + *static_cast< sal_Bool * >(uno_data) = false; + break; + + case typelib_TypeClass_BYTE: + *static_cast< sal_Int8 * >(uno_data) = 0; + break; + + case typelib_TypeClass_SHORT: + *static_cast< sal_Int16 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_SHORT: + *static_cast< sal_uInt16 * >(uno_data) = 0; + break; + + case typelib_TypeClass_LONG: + *static_cast< sal_Int32 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_LONG: + *static_cast< sal_uInt32 * >(uno_data) = 0; + break; + + case typelib_TypeClass_HYPER: + *static_cast< sal_Int64 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_HYPER: + *static_cast< sal_uInt64 * >(uno_data) = 0; + break; + + case typelib_TypeClass_FLOAT: + *static_cast< float * >(uno_data) = 0; + break; + + case typelib_TypeClass_DOUBLE: + *static_cast< double * >(uno_data) = 0; + break; + + case typelib_TypeClass_CHAR: + *static_cast< sal_Unicode * >(uno_data) = 0; + break; + + case typelib_TypeClass_STRING: + if (!assign) { + *static_cast< rtl_uString ** >(uno_data) = nullptr; + } + rtl_uString_new(static_cast< rtl_uString ** >(uno_data)); + break; + + case typelib_TypeClass_TYPE: + if (assign) { + typelib_typedescriptionreference_release( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data)); + } + *static_cast< typelib_TypeDescriptionReference ** >(uno_data) + = *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID); + assert( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data) != nullptr); + typelib_typedescriptionreference_acquire( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data)); + break; + + case typelib_TypeClass_ANY: + if (assign) { + uno_any_destruct(static_cast< uno_Any * >(uno_data), nullptr); + } + uno_any_construct( + static_cast< uno_Any * >(uno_data), nullptr, + jni.get_info()->m_XInterface_type_info->m_td.get(), nullptr); + break; + + case typelib_TypeClass_SEQUENCE: + { + std::unique_ptr< rtl_mem > seq(seq_allocate(0, 0)); + if (assign) { + uno_type_destructData(uno_data, type, nullptr); + } + *static_cast< uno_Sequence ** >(uno_data) + = reinterpret_cast< uno_Sequence * >(seq.release()); + break; + } + + case typelib_TypeClass_ENUM: + { + typelib_TypeDescription * td = nullptr; + TYPELIB_DANGER_GET(&td, type); + *static_cast< sal_Int32 * >(uno_data) + = (reinterpret_cast< typelib_EnumTypeDescription * >(td)-> + nDefaultEnumValue); + TYPELIB_DANGER_RELEASE(td); + break; + } + + case typelib_TypeClass_STRUCT: + { + if (info == nullptr) { + info = jni.get_info()->get_type_info(jni, type); + } + JNI_compound_type_info const * comp_info + = static_cast< JNI_compound_type_info const * >(info); + typelib_CompoundTypeDescription * comp_td + = reinterpret_cast< typelib_CompoundTypeDescription * >( + comp_info->m_td.get()); + sal_Int32 nPos = 0; + sal_Int32 nMembers = comp_td->nMembers; + try { + if (comp_td->pBaseTypeDescription != nullptr) { + createDefaultUnoValue( + jni, uno_data, + comp_td->pBaseTypeDescription->aBase.pWeakRef, + comp_info->m_base, assign); + } + for (; nPos < nMembers; ++nPos) { + createDefaultUnoValue( + jni, + (static_cast< char * >(uno_data) + + comp_td->pMemberOffsets[nPos]), + comp_td->ppTypeRefs[nPos], nullptr, assign); + } + } catch (...) { + if (!assign) { + for (sal_Int32 i = 0; i < nPos; ++i) { + uno_type_destructData( + (static_cast< char * >(uno_data) + + comp_td->pMemberOffsets[i]), + comp_td->ppTypeRefs[i], nullptr); + } + if (comp_td->pBaseTypeDescription != nullptr) { + uno_destructData( + uno_data, &comp_td->pBaseTypeDescription->aBase, nullptr); + } + } + throw; + } + } + break; + + case typelib_TypeClass_INTERFACE: + if (assign) { + uno_Interface * p = *static_cast< uno_Interface ** >(uno_data); + if (p != nullptr) { + (*p->release)(p); + } + } + *static_cast< uno_Interface ** >(uno_data) = nullptr; + break; + + default: + assert(false); + break; + } +} + +} + +void Bridge::map_to_uno( + JNI_context const & jni, + void * uno_data, jvalue java_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool assign, bool out_param, + bool special_wrapped_integral_types ) const +{ + assert( + !out_param || + (jni->GetArrayLength( static_cast<jarray>(java_data.l) ) == 1) ); + + switch (type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (out_param) + { + jni->GetCharArrayRegion( + static_cast<jcharArray>(java_data.l), 0, 1, static_cast<jchar *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jchar *>(uno_data) = jni->CallCharMethodA( + java_data.l, getJniInfo()->m_method_Character_charValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jchar *>(uno_data) = java_data.c; + } + break; + case typelib_TypeClass_BOOLEAN: + if (out_param) + { + jni->GetBooleanArrayRegion( + static_cast<jbooleanArray>(java_data.l), 0, 1, static_cast<jboolean *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jboolean *>(uno_data) = jni->CallBooleanMethodA( + java_data.l, getJniInfo()->m_method_Boolean_booleanValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jboolean *>(uno_data) = java_data.z; + } + break; + case typelib_TypeClass_BYTE: + if (out_param) + { + jni->GetByteArrayRegion( + static_cast<jbyteArray>(java_data.l), 0, 1, static_cast<jbyte *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jbyte *>(uno_data) = jni->CallByteMethodA( + java_data.l, getJniInfo()->m_method_Byte_byteValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jbyte *>(uno_data) = java_data.b; + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (out_param) + { + jni->GetShortArrayRegion( + static_cast<jshortArray>(java_data.l), 0, 1, static_cast<jshort *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jshort *>(uno_data) = jni->CallShortMethodA( + java_data.l, getJniInfo()->m_method_Short_shortValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jshort *>(uno_data) = java_data.s; + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (out_param) + { + jni->GetIntArrayRegion( + static_cast<jintArray>(java_data.l), 0, 1, static_cast<jint *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jint *>(uno_data) = jni->CallIntMethodA( + java_data.l, getJniInfo()->m_method_Integer_intValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jint *>(uno_data) = java_data.i; + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (out_param) + { + jni->GetLongArrayRegion( + static_cast<jlongArray>(java_data.l), 0, 1, static_cast<jlong *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jlong *>(uno_data) = jni->CallLongMethodA( + java_data.l, getJniInfo()->m_method_Long_longValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jlong *>(uno_data) = java_data.j; + } + break; + case typelib_TypeClass_FLOAT: + if (out_param) + { + jni->GetFloatArrayRegion( + static_cast<jfloatArray>(java_data.l), 0, 1, static_cast<jfloat *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jfloat *>(uno_data) = jni->CallFloatMethodA( + java_data.l, getJniInfo()->m_method_Float_floatValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jfloat *>(uno_data) = java_data.f; + } + break; + case typelib_TypeClass_DOUBLE: + if (out_param) + { + jni->GetDoubleArrayRegion( + static_cast<jdoubleArray>(java_data.l), 0, 1, static_cast<jdouble *>(uno_data) ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *static_cast<jdouble *>(uno_data) = jni->CallDoubleMethodA( + java_data.l, getJniInfo()->m_method_Double_doubleValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + *static_cast<jdouble *>(uno_data) = java_data.d; + } + break; + case typelib_TypeClass_STRING: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (java_data.l == nullptr) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] null-ref given!" + jni.get_stack_trace() ); + } + if (! assign) + *static_cast<rtl_uString **>(uno_data) = nullptr; + jstring_to_ustring( + jni, static_cast<rtl_uString **>(uno_data), static_cast<jstring>(java_data.l) ); + break; + } + case typelib_TypeClass_TYPE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (java_data.l == nullptr) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] null-ref given!" + jni.get_stack_trace() ); + } + + // type name + JLocalAutoRef jo_type_name( + jni, jni->GetObjectField( + java_data.l, getJniInfo()->m_field_Type_typeName ) ); + if (! jo_type_name.is()) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] incomplete type object: no type name!" + + jni.get_stack_trace() ); + } + OUString type_name( + jstring_to_oustring( jni, static_cast<jstring>(jo_type_name.get()) ) ); + ::com::sun::star::uno::TypeDescription td( type_name ); + if (! td.is()) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] UNO type not found: " + type_name + + jni.get_stack_trace() ); + } + typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); + if (assign) + { + typelib_typedescriptionreference_release( + *static_cast<typelib_TypeDescriptionReference **>(uno_data) ); + } + *static_cast<typelib_TypeDescriptionReference **>(uno_data) = td.get()->pWeakRef; + break; + } + case typelib_TypeClass_ANY: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + + uno_Any * pAny = static_cast<uno_Any *>(uno_data); + if (java_data.l == nullptr) // null-ref maps to XInterface null-ref + { + if (assign) + uno_any_destruct( pAny, nullptr ); + uno_any_construct( + pAny, nullptr, getJniInfo()->m_XInterface_type_info->m_td.get(), nullptr ); + break; + } + + JLocalAutoRef jo_type( jni ); + JLocalAutoRef jo_wrapped_holder( jni ); + + if (jni->IsInstanceOf( java_data.l, getJniInfo()->m_class_Any )) + { + // boxed any + jo_type.reset( jni->GetObjectField( + java_data.l, getJniInfo()->m_field_Any_type ) ); + if (! jo_type.is()) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] no type set at com.sun.star.uno.Any!" + + jni.get_stack_trace() ); + } + // wrapped value + jo_wrapped_holder.reset( + jni->GetObjectField( + java_data.l, getJniInfo()->m_field_Any_object ) ); + java_data.l = jo_wrapped_holder.get(); + } + else + { + // create type out of class + JLocalAutoRef jo_class( jni, jni->GetObjectClass( java_data.l ) ); + jo_type.reset( create_type( jni, static_cast<jclass>(jo_class.get()) ) ); + } + + // get type name + JLocalAutoRef jo_type_name( + jni, jni->GetObjectField( + jo_type.get(), getJniInfo()->m_field_Type_typeName ) ); + jni.ensure_no_exception(); + OUString type_name( + jstring_to_oustring( jni, static_cast<jstring>(jo_type_name.get()) ) ); + + ::com::sun::star::uno::TypeDescription value_td( type_name ); + if (! value_td.is()) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] UNO type not found: " + type_name + + jni.get_stack_trace() ); + } + typelib_TypeClass type_class = value_td.get()->eTypeClass; + + if (assign) + { + uno_any_destruct( pAny, nullptr ); + } + try + { + switch (type_class) + { + case typelib_TypeClass_VOID: + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_CHAR: + pAny->pData = &pAny->pReserved; + *static_cast<jchar *>(pAny->pData) = jni->CallCharMethodA( + java_data.l, getJniInfo()->m_method_Character_charValue, nullptr ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BOOLEAN: + pAny->pData = &pAny->pReserved; + *static_cast<jboolean *>(pAny->pData) = jni->CallBooleanMethodA( + java_data.l, getJniInfo()->m_method_Boolean_booleanValue, nullptr ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BYTE: + pAny->pData = &pAny->pReserved; + *static_cast<jbyte *>(pAny->pData) = jni->CallByteMethodA( + java_data.l, getJniInfo()->m_method_Byte_byteValue, nullptr ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pAny->pData = &pAny->pReserved; + *static_cast<jshort *>(pAny->pData) = jni->CallShortMethodA( + java_data.l, getJniInfo()->m_method_Short_shortValue, nullptr ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + pAny->pData = &pAny->pReserved; + *static_cast<jint *>(pAny->pData) = jni->CallIntMethodA( + java_data.l, getJniInfo()->m_method_Integer_intValue, nullptr ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof (sal_Int64) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *static_cast<jlong *>(pAny->pData) = jni->CallLongMethodA( + java_data.l, getJniInfo()->m_method_Long_longValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + std::unique_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (sal_Int64) ) ); + *reinterpret_cast<jlong *>(mem.get()) = jni->CallLongMethodA( + java_data.l, getJniInfo()->m_method_Long_longValue, nullptr ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof (float) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *static_cast<jfloat *>(pAny->pData) = jni->CallFloatMethodA( + java_data.l, getJniInfo()->m_method_Float_floatValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + std::unique_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (float) ) ); + *reinterpret_cast<jfloat *>(mem.get()) = jni->CallFloatMethodA( + java_data.l, getJniInfo()->m_method_Float_floatValue, nullptr ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof (double) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *static_cast<jdouble *>(pAny->pData) = + jni->CallDoubleMethodA( + java_data.l, + getJniInfo()->m_method_Double_doubleValue, nullptr ); + jni.ensure_no_exception(); + } + else + { + std::unique_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (double) ) ); + *reinterpret_cast<jdouble *>(mem.get()) = + jni->CallDoubleMethodA( + java_data.l, + getJniInfo()->m_method_Double_doubleValue, nullptr ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_STRING: + // opt: anies often contain strings; copy string directly + pAny->pReserved = nullptr; + pAny->pData = &pAny->pReserved; + jstring_to_ustring( + jni, static_cast<rtl_uString **>(pAny->pData), + static_cast<jstring>(java_data.l) ); + break; + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + pAny->pData = &pAny->pReserved; + map_to_uno( + jni, pAny->pData, java_data, + value_td.get()->pWeakRef, nullptr, + false /* no assign */, false /* no out param */ ); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + std::unique_ptr< rtl_mem > mem( + rtl_mem::allocate( value_td.get()->nSize ) ); + map_to_uno( + jni, mem.get(), java_data, value_td.get()->pWeakRef, nullptr, + false /* no assign */, false /* no out param */ ); + pAny->pData = mem.release(); + break; + } + default: + { + throw BridgeRuntimeError( + "[map_to_uno():" + type_name + + "] unsupported value type of any!" + + jni.get_stack_trace() ); + } + } + } + catch (...) + { + if (assign) + { + // restore to valid any + uno_any_construct( pAny, nullptr, nullptr, nullptr ); + } + throw; + } + typelib_typedescriptionreference_acquire( value_td.get()->pWeakRef ); + pAny->pType = value_td.get()->pWeakRef; + break; + } + case typelib_TypeClass_ENUM: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (java_data.l == nullptr) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] null-ref given!" + jni.get_stack_trace() ); + } + + *static_cast<jint *>(uno_data) = jni->GetIntField( + java_data.l, getJniInfo()->m_field_Enum_m_value ); + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (java_data.l == nullptr) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] null-ref given!" + jni.get_stack_trace() ); + } + + if (info == nullptr) + info = getJniInfo()->get_type_info( jni, type ); + JNI_compound_type_info const * comp_info = + static_cast< JNI_compound_type_info const * >( info ); + + typelib_CompoundTypeDescription * comp_td = + reinterpret_cast<typelib_CompoundTypeDescription *>(comp_info->m_td.get()); + bool polymorphic + = comp_td->aBase.eTypeClass == typelib_TypeClass_STRUCT + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes != nullptr; + + sal_Int32 nPos = 0; + sal_Int32 nMembers = comp_td->nMembers; + try + { + if (comp_td->pBaseTypeDescription != nullptr) + { + map_to_uno( + jni, uno_data, java_data, + comp_td->pBaseTypeDescription->aBase.pWeakRef, + comp_info->m_base, + assign, false /* no out param */ ); + } + + for ( ; nPos < nMembers; ++nPos ) + { + void * p = static_cast<char *>(uno_data) + comp_td->pMemberOffsets[ nPos ]; + typelib_TypeDescriptionReference * member_type = + comp_td->ppTypeRefs[ nPos ]; + jfieldID field_id = comp_info->m_fields[ nPos ]; + bool parameterizedType = polymorphic + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes[nPos]; + switch (member_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jchar *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jchar *>(p) = jni->GetCharField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jboolean *>(p) = false; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jboolean *>(p) = jni->GetBooleanField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_BYTE: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jbyte *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jbyte *>(p) = jni->GetByteField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jshort *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jshort *>(p) = jni->GetShortField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jint *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jint *>(p) = jni->GetIntField( java_data.l, field_id ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jlong *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jlong *>(p) = jni->GetLongField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_FLOAT: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jfloat *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jfloat *>(p) = jni->GetFloatField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_DOUBLE: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == nullptr ) { + *static_cast<jdouble *>(p) = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, nullptr, assign, false, + true ); + } + } else { + *static_cast<jdouble *>(p) = jni->GetDoubleField( + java_data.l, field_id ); + } + break; + default: + { + JLocalAutoRef jo_field( jni ); + bool checkNull; + if (field_id == nullptr) + { + // special for Message: call Throwable.getMessage() + assert( + type_equals( + type, + getJniInfo()->m_Exception_type.getTypeLibType() ) + || type_equals( + type, + getJniInfo()->m_RuntimeException_type. + getTypeLibType() ) ); + assert( nPos == 0 ); // first member + // call getMessage() + jo_field.reset( + jni->CallObjectMethodA( + java_data.l, + getJniInfo()->m_method_Throwable_getMessage, nullptr ) + ); + jni.ensure_no_exception(); + checkNull = true; + } + else + { + jo_field.reset( + jni->GetObjectField( java_data.l, field_id ) ); + checkNull = parameterizedType; + } + if (checkNull && !jo_field.is()) { + createDefaultUnoValue(jni, p, member_type, nullptr, assign); + } else { + jvalue val; + val.l = jo_field.get(); + map_to_uno( + jni, p, val, member_type, nullptr, + assign, false /* no out param */ ); + } + break; + } + } + } + } + catch (...) + { + if (! assign) + { + // cleanup + for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup ) + { + void * p = + static_cast<char *>(uno_data) + comp_td->pMemberOffsets[ nCleanup ]; + uno_type_destructData( + p, comp_td->ppTypeRefs[ nCleanup ], nullptr ); + } + if (comp_td->pBaseTypeDescription != nullptr) + { + uno_destructData( + uno_data, &comp_td->pBaseTypeDescription->aBase, nullptr ); + } + } + throw; + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (java_data.l == nullptr) + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] null-ref given!" + jni.get_stack_trace() ); + } + + TypeDescr td( type ); + typelib_TypeDescriptionReference * element_type = + reinterpret_cast<typelib_IndirectTypeDescription *>(td.get())->pType; + + std::unique_ptr< rtl_mem > seq; + sal_Int32 nElements = jni->GetArrayLength( static_cast<jarray>(java_data.l) ); + + switch (element_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + seq = seq_allocate( nElements, sizeof (sal_Unicode) ); + jni->GetCharArrayRegion( + static_cast<jcharArray>(java_data.l), 0, nElements, + reinterpret_cast<jchar *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BOOLEAN: + seq = seq_allocate( nElements, sizeof (sal_Bool) ); + jni->GetBooleanArrayRegion( + static_cast<jbooleanArray>(java_data.l), 0, nElements, + reinterpret_cast<jboolean *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BYTE: + seq = seq_allocate( nElements, sizeof (sal_Int8) ); + jni->GetByteArrayRegion( + static_cast<jbyteArray>(java_data.l), 0, nElements, + reinterpret_cast<jbyte *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + seq = seq_allocate( nElements, sizeof (sal_Int16) ); + jni->GetShortArrayRegion( + static_cast<jshortArray>(java_data.l), 0, nElements, + reinterpret_cast<jshort *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + seq = seq_allocate( nElements, sizeof (sal_Int32) ); + jni->GetIntArrayRegion( + static_cast<jintArray>(java_data.l), 0, nElements, + reinterpret_cast<jint *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + seq = seq_allocate( nElements, sizeof (sal_Int64) ); + jni->GetLongArrayRegion( + static_cast<jlongArray>(java_data.l), 0, nElements, + reinterpret_cast<jlong *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_FLOAT: + seq = seq_allocate( nElements, sizeof (float) ); + jni->GetFloatArrayRegion( + static_cast<jfloatArray>(java_data.l), 0, nElements, + reinterpret_cast<jfloat *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_DOUBLE: + seq = seq_allocate( nElements, sizeof (double) ); + jni->GetDoubleArrayRegion( + static_cast<jdoubleArray>(java_data.l), 0, nElements, + reinterpret_cast<jdouble *>(reinterpret_cast<uno_Sequence *>(seq.get())->elements) ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + { + TypeDescr element_td( element_type ); + seq = seq_allocate( nElements, element_td.get()->nSize ); + + JNI_type_info const * element_info; + if (element_type->eTypeClass == typelib_TypeClass_STRUCT || + element_type->eTypeClass == typelib_TypeClass_EXCEPTION || + element_type->eTypeClass == typelib_TypeClass_INTERFACE) + { + element_info = + getJniInfo()->get_type_info( jni, element_td.get() ); + } + else + { + element_info = nullptr; + } + + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + try + { + JLocalAutoRef jo( + jni, jni->GetObjectArrayElement( + static_cast<jobjectArray>(java_data.l), nPos ) ); + jni.ensure_no_exception(); + jvalue val; + val.l = jo.get(); + void * p = + reinterpret_cast<uno_Sequence *>(seq.get())->elements + + (nPos * element_td.get()->nSize); + map_to_uno( + jni, p, val, element_td.get()->pWeakRef, element_info, + false /* no assign */, false /* no out param */ ); + } + catch (...) + { + // cleanup + for ( sal_Int32 nCleanPos = 0; + nCleanPos < nPos; ++nCleanPos ) + { + void * p = + reinterpret_cast<uno_Sequence *>(seq.get())->elements + + (nCleanPos * element_td.get()->nSize); + uno_destructData( p, element_td.get(), nullptr ); + } + throw; + } + } + break; + } + default: + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] unsupported sequence element type: " + + OUString::unacquired( &element_type->pTypeName ) + + jni.get_stack_trace() ); + } + } + + if (assign) + uno_destructData( uno_data, td.get(), nullptr ); + *static_cast<uno_Sequence **>(uno_data) = reinterpret_cast<uno_Sequence *>(seq.release()); + break; + } + case typelib_TypeClass_INTERFACE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( static_cast<jobjectArray>(java_data.l), 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + + if (java_data.l == nullptr) // null-ref + { + if (assign) + { + uno_Interface * p = *static_cast<uno_Interface **>(uno_data); + if (p != nullptr) + (*p->release)( p ); + } + *static_cast<uno_Interface **>(uno_data) = nullptr; + } + else + { + if (info == nullptr) + info = getJniInfo()->get_type_info( jni, type ); + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( info ); + uno_Interface * pUnoI = map_to_uno( jni, java_data.l, iface_info ); + if (assign) + { + uno_Interface * p = *static_cast<uno_Interface **>(uno_data); + if (p != nullptr) + (*p->release)( p ); + } + *static_cast<uno_Interface **>(uno_data) = pUnoI; + } + break; + } + default: + { + throw BridgeRuntimeError( + "[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + + "] unsupported type!" + jni.get_stack_trace() ); + } + } +} + + +void Bridge::map_to_java( + JNI_context const & jni, + jvalue * java_data, void const * uno_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool in_param, bool out_param, + bool special_wrapped_integral_types ) const +{ + // 4th param of Set*ArrayRegion changed from pointer to non-const to pointer + // to const between <http://docs.oracle.com/javase/6/docs/technotes/guides/ + // jni/spec/functions.html#wp22933> and <http://docs.oracle.com/javase/7/ + // docs/technotes/guides/jni/spec/functions.html#wp22933>; work around that + // difference in a way that doesn't trigger loplugin:redundantcast: + void * data = const_cast<void *>(uno_data); + + switch (type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewCharArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetCharArrayRegion( + static_cast<jcharArray>(jo_ar.get()), 0, 1, static_cast<jchar *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetCharArrayRegion( + static_cast<jcharArray>(java_data->l), 0, 1, static_cast<jchar *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.c = *static_cast<jchar const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Character, + getJniInfo()->m_ctor_Character_with_char, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->c = *static_cast<jchar const *>(uno_data); + } + break; + case typelib_TypeClass_BOOLEAN: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewBooleanArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetBooleanArrayRegion( + static_cast<jbooleanArray>(jo_ar.get()), + 0, 1, static_cast<jboolean *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetBooleanArrayRegion( + static_cast<jbooleanArray>(java_data->l), + 0, 1, static_cast<jboolean *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.z = *static_cast<jboolean const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Boolean, + getJniInfo()->m_ctor_Boolean_with_boolean, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->z = *static_cast<jboolean const *>(uno_data); + } + break; + case typelib_TypeClass_BYTE: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewByteArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetByteArrayRegion( + static_cast<jbyteArray>(jo_ar.get()), 0, 1, static_cast<jbyte *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetByteArrayRegion( + static_cast<jbyteArray>(java_data->l), 0, 1, static_cast<jbyte *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.b = *static_cast<jbyte const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Byte, + getJniInfo()->m_ctor_Byte_with_byte, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->b = *static_cast<jbyte const *>(uno_data); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewShortArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetShortArrayRegion( + static_cast<jshortArray>(jo_ar.get()), 0, 1, static_cast<jshort *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetShortArrayRegion( + static_cast<jshortArray>(java_data->l), 0, 1, static_cast<jshort *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.s = *static_cast<jshort const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Short, + getJniInfo()->m_ctor_Short_with_short, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->s = *static_cast<jshort const *>(uno_data); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewIntArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetIntArrayRegion( + static_cast<jintArray>(jo_ar.get()), 0, 1, static_cast<jint *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetIntArrayRegion( + static_cast<jintArray>(java_data->l), 0, 1, static_cast<jint *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.i = *static_cast<jint const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Integer, + getJniInfo()->m_ctor_Integer_with_int, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->i = *static_cast<jint const *>(uno_data); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewLongArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetLongArrayRegion( + static_cast<jlongArray>(jo_ar.get()), 0, 1, static_cast<jlong *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetLongArrayRegion( + static_cast<jlongArray>(java_data->l), 0, 1, static_cast<jlong *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.j = *static_cast<jlong const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Long, + getJniInfo()->m_ctor_Long_with_long, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->j = *static_cast<jlong const *>(uno_data); + } + break; + case typelib_TypeClass_FLOAT: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewFloatArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetFloatArrayRegion( + static_cast<jfloatArray>(jo_ar.get()), 0, 1, static_cast<jfloat *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetFloatArrayRegion( + static_cast<jfloatArray>(java_data->l), 0, 1, static_cast<jfloat *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.f = *static_cast<jfloat const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Float, + getJniInfo()->m_ctor_Float_with_float, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->f = *static_cast<jfloat const *>(uno_data); + } + break; + case typelib_TypeClass_DOUBLE: + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_ar( jni, jni->NewDoubleArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetDoubleArrayRegion( + static_cast<jdoubleArray>(jo_ar.get()), + 0, 1, static_cast<jdouble *>(data) ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetDoubleArrayRegion( + static_cast<jdoubleArray>(java_data->l), + 0, 1, static_cast<jdouble *>(data) ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.d = *static_cast<double const *>(uno_data); + java_data->l = jni->NewObjectA( + getJniInfo()->m_class_Double, + getJniInfo()->m_ctor_Double_with_double, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->d = *static_cast<jdouble const *>(uno_data); + } + break; + case typelib_TypeClass_STRING: + { + if (out_param) + { + JLocalAutoRef jo_in( jni ); + if (in_param) + { + jo_in.reset( + ustring_to_jstring( + jni, *static_cast<rtl_uString * const *>(uno_data) ) ); + } + if (java_data->l == nullptr) + { + java_data->l = jni->NewObjectArray( + 1, getJniInfo()->m_class_String, jo_in.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_in.get() ); + jni.ensure_no_exception(); + } + } + else + { + assert( in_param ); + java_data->l = + ustring_to_jstring( jni, *static_cast<rtl_uString * const *>(uno_data) ); + } + break; + } + case typelib_TypeClass_TYPE: + { + if (out_param) + { + JLocalAutoRef jo_in( jni ); + if (in_param) + { + jo_in.reset( + create_type( + jni, + *static_cast<typelib_TypeDescriptionReference * const *>(uno_data) ) + ); + } + if (java_data->l == nullptr) + { + java_data->l = jni->NewObjectArray( + 1, getJniInfo()->m_class_Type, jo_in.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_in.get() ); + jni.ensure_no_exception(); + } + } + else + { + assert( in_param ); + java_data->l = + create_type( + jni, + *static_cast<typelib_TypeDescriptionReference * const *>(uno_data) ); + } + break; + } + case typelib_TypeClass_ANY: + { + JLocalAutoRef jo_any( jni ); + if (in_param) + { + uno_Any const * pAny = static_cast<uno_Any const *>(uno_data); + switch (pAny->pType->eTypeClass) + { + case typelib_TypeClass_VOID: + jo_any.reset( + jni->NewLocalRef( getJniInfo()->m_object_Any_VOID ) ); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + { + jvalue args[ 2 ]; + args[ 0 ].s = *static_cast<jshort const *>(pAny->pData); + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + getJniInfo()->m_class_Short, + getJniInfo()->m_ctor_Short_with_short, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = getJniInfo()->m_object_Type_UNSIGNED_SHORT; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_UNSIGNED_LONG: + { + jvalue args[ 2 ]; + args[ 0 ].i = *static_cast<jint const *>(pAny->pData); + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + getJniInfo()->m_class_Integer, + getJniInfo()->m_ctor_Integer_with_int, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = getJniInfo()->m_object_Type_UNSIGNED_LONG; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_UNSIGNED_HYPER: + { + jvalue args[ 2 ]; + args[ 0 ].j = *static_cast<jlong const *>(pAny->pData); + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + getJniInfo()->m_class_Long, + getJniInfo()->m_ctor_Long_with_long, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = getJniInfo()->m_object_Type_UNSIGNED_HYPER; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_STRING: // opt strings + jo_any.reset( ustring_to_jstring( + jni, static_cast<rtl_uString *>(pAny->pReserved) ) ); + break; + case typelib_TypeClass_SEQUENCE: + { + jvalue java_data2; + // prefetch sequence td + TypeDescr seq_td( pAny->pType ); + map_to_java( + jni, &java_data2, pAny->pData, seq_td.get()->pWeakRef, nullptr, + true /* in */, false /* no out */, + true /* create integral wrappers */ ); + jo_any.reset( java_data2.l ); + + // determine inner element type + ::com::sun::star::uno::Type element_type( + reinterpret_cast<typelib_IndirectTypeDescription *>(seq_td.get())->pType ); + while (element_type.getTypeLibType()->eTypeClass == + typelib_TypeClass_SEQUENCE) + { + TypeDescr element_td( element_type.getTypeLibType() ); + typelib_typedescriptionreference_assign( + reinterpret_cast< typelib_TypeDescriptionReference ** >( + &element_type ), + reinterpret_cast<typelib_IndirectTypeDescription *>(element_td.get()) + ->pType ); + } + // box up only if unsigned element type + switch (element_type.getTypeLibType()->eTypeClass) + { + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_UNSIGNED_HYPER: + { + jvalue args[ 2 ]; + JLocalAutoRef jo_type( + jni, create_type( jni, seq_td.get()->pWeakRef ) ); + args[ 0 ].l = jo_type.get(); + args[ 1 ].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + default: + break; + } + break; + } + case typelib_TypeClass_INTERFACE: + { + uno_Interface * pUnoI = static_cast<uno_Interface *>(pAny->pReserved); + if (is_XInterface( pAny->pType )) + { + if (pUnoI != nullptr) + { + jo_any.reset( + map_to_java( + jni, pUnoI, + getJniInfo()->m_XInterface_type_info ) ); + } + // else: empty XInterface ref maps to null-ref + } + else + { + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( + getJniInfo()->get_type_info( jni, pAny->pType ) ); + if (pUnoI != nullptr) + { + jo_any.reset( map_to_java( jni, pUnoI, iface_info ) ); + } + // box up in com.sun.star.uno.Any + jvalue args[ 2 ]; + args[ 0 ].l = iface_info->m_type; + args[ 1 ].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + } + break; + } + case typelib_TypeClass_STRUCT: + { + // Do not lose information about type arguments of instantiated + // polymorphic struct types: + OUString const & name = OUString::unacquired( + &pAny->pType->pTypeName); + assert(!name.isEmpty()); + if (name[name.getLength() - 1] == '>') + { + // Box up in com.sun.star.uno.Any: + JLocalAutoRef jo_type(jni, create_type(jni, pAny->pType)); + jvalue java_data2; + map_to_java( + jni, &java_data2, pAny->pData, pAny->pType, nullptr, true, + false); + jo_any.reset(java_data2.l); + jvalue args[2]; + args[0].l = jo_type.get(); + args[1].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + getJniInfo()->m_class_Any, + getJniInfo()->m_ctor_Any_with_Type_Object, args)); + jni.ensure_no_exception(); + break; + } + [[fallthrough]]; + } + default: + { + jvalue java_data2; + map_to_java( + jni, &java_data2, pAny->pData, pAny->pType, nullptr, + true /* in */, false /* no out */, + true /* create integral wrappers */ ); + jo_any.reset( java_data2.l ); + break; + } + } + } + + if (out_param) + { + if (java_data->l == nullptr) + { + java_data->l = jni->NewObjectArray( + 1, getJniInfo()->m_class_Object, jo_any.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_any.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_any.release(); + } + break; + } + case typelib_TypeClass_ENUM: + { + OUString const & type_name = OUString::unacquired( &type->pTypeName ); + OString class_name( + OUStringToOString( type_name, RTL_TEXTENCODING_JAVA_UTF8 ) ); + JLocalAutoRef jo_enum_class( + jni, find_class( jni, class_name.getStr() ) ); + + JLocalAutoRef jo_enum( jni ); + if (in_param) + { + // call static <enum_class>.fromInt( int ) + OString sig = "(I)L" + class_name.replace( '.', '/' ) + ";"; + jmethodID method_id = jni->GetStaticMethodID( + static_cast<jclass>(jo_enum_class.get()), "fromInt", sig.getStr() ); + jni.ensure_no_exception(); + assert( method_id != nullptr ); + + jvalue arg; + arg.i = *static_cast<jint const *>(uno_data); + jo_enum.reset( + jni->CallStaticObjectMethodA( + static_cast<jclass>(jo_enum_class.get()), method_id, &arg ) ); + jni.ensure_no_exception(); + } + if (out_param) + { + if (java_data->l == nullptr) + { + java_data->l = jni->NewObjectArray( + 1, static_cast<jclass>(jo_enum_class.get()), jo_enum.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_enum.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_enum.release(); + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + if (info == nullptr) + info = getJniInfo()->get_type_info( jni, type ); + JNI_compound_type_info const * comp_info = + static_cast< JNI_compound_type_info const * >( info ); + + JLocalAutoRef jo_comp( jni ); + if (in_param) + { + if (type->eTypeClass == typelib_TypeClass_EXCEPTION) + { + JLocalAutoRef jo_message( + jni, ustring_to_jstring( jni, *static_cast<rtl_uString * const *>(uno_data) ) ); + jvalue arg; + arg.l = jo_message.get(); + jo_comp.reset( + jni->NewObjectA( + comp_info->m_class, comp_info->m_exc_ctor, &arg ) ); + jni.ensure_no_exception(); + } + else + { + jo_comp.reset( jni->AllocObject( comp_info->m_class ) ); + jni.ensure_no_exception(); + } + + for ( JNI_compound_type_info const * linfo = comp_info; + linfo != nullptr; + linfo = static_cast< JNI_compound_type_info const * >( + linfo->m_base ) ) + { + typelib_CompoundTypeDescription * comp_td = + reinterpret_cast<typelib_CompoundTypeDescription *>(linfo->m_td.get()); + typelib_TypeDescriptionReference ** ppMemberTypeRefs = + comp_td->ppTypeRefs; + sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets; + bool polymorphic + = comp_td->aBase.eTypeClass == typelib_TypeClass_STRUCT + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes != nullptr; + for ( sal_Int32 nPos = comp_td->nMembers; nPos--; ) + { + jfieldID field_id = linfo->m_fields[ nPos ]; + if (field_id != nullptr) + { + void const * p = + static_cast<char const *>(uno_data) + pMemberOffsets[ nPos ]; + typelib_TypeDescriptionReference * member_type = + ppMemberTypeRefs[ nPos ]; + bool parameterizedType = polymorphic + && (reinterpret_cast< + typelib_StructTypeDescription * >(comp_td)-> + pParameterizedTypes[nPos]); + switch (member_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (parameterizedType) { + jvalue arg; + arg.c = *static_cast<jchar const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Character, + getJniInfo()->m_ctor_Character_with_char, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetCharField( + jo_comp.get(), + field_id, *static_cast<jchar const *>(p) ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (parameterizedType) { + jvalue arg; + arg.z = *static_cast<jboolean const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Boolean, + getJniInfo()->m_ctor_Boolean_with_boolean, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetBooleanField( + jo_comp.get(), + field_id, *static_cast<jboolean const *>(p) ); + } + break; + case typelib_TypeClass_BYTE: + if (parameterizedType) { + jvalue arg; + arg.b = *static_cast<jbyte const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Byte, + getJniInfo()->m_ctor_Byte_with_byte, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetByteField( + jo_comp.get(), + field_id, *static_cast<jbyte const *>(p) ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (parameterizedType) { + jvalue arg; + arg.s = *static_cast<jshort const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Short, + getJniInfo()->m_ctor_Short_with_short, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetShortField( + jo_comp.get(), + field_id, *static_cast<jshort const *>(p) ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (parameterizedType) { + jvalue arg; + arg.i = *static_cast<jint const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Integer, + getJniInfo()->m_ctor_Integer_with_int, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetIntField( + jo_comp.get(), + field_id, *static_cast<jint const *>(p) ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (parameterizedType) { + jvalue arg; + arg.j = *static_cast<jlong const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Long, + getJniInfo()->m_ctor_Long_with_long, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetLongField( + jo_comp.get(), + field_id, *static_cast<jlong const *>(p) ); + } + break; + case typelib_TypeClass_FLOAT: + if (parameterizedType) { + jvalue arg; + arg.f = *static_cast<jfloat const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Float, + getJniInfo()->m_ctor_Float_with_float, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetFloatField( + jo_comp.get(), + field_id, *static_cast<jfloat const *>(p) ); + } + break; + case typelib_TypeClass_DOUBLE: + if (parameterizedType) { + jvalue arg; + arg.d = *static_cast<jdouble const *>(p); + JLocalAutoRef jo( + jni, + jni->NewObjectA( + getJniInfo()->m_class_Double, + getJniInfo()->m_ctor_Double_with_double, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetDoubleField( + jo_comp.get(), + field_id, *static_cast<jdouble const *>(p) ); + } + break; + case typelib_TypeClass_STRING: // string opt here + { + JLocalAutoRef jo_string( + jni, ustring_to_jstring( + jni, *static_cast<rtl_uString * const *>(p) ) ); + jni->SetObjectField( + jo_comp.get(), field_id, jo_string.get() ); + break; + } + default: + { + jvalue java_data2; + map_to_java( + jni, &java_data2, p, member_type, nullptr, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_obj( jni, java_data2.l ); + jni->SetObjectField( + jo_comp.get(), field_id, jo_obj.get() ); + break; + } + } + } + } + } + } + if (out_param) + { + if (java_data->l == nullptr) + { + java_data->l = + jni->NewObjectArray( 1, comp_info->m_class, jo_comp.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_comp.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_comp.release(); + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + // xxx todo: possible opt for pure out sequences + JLocalAutoRef jo_ar( jni ); + + sal_Int32 nElements; + uno_Sequence * seq = nullptr; + if (in_param) + { + seq = *static_cast<uno_Sequence * const *>(uno_data); + nElements = seq->nElements; + } + else + { + nElements = 0; + } + + TypeDescr td( type ); + typelib_TypeDescriptionReference * element_type = + reinterpret_cast<typelib_IndirectTypeDescription *>(td.get())->pType; + + switch (element_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + jo_ar.reset( jni->NewCharArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetCharArrayRegion( + static_cast<jcharArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jchar *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_BOOLEAN: + jo_ar.reset( jni->NewBooleanArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetBooleanArrayRegion( + static_cast<jbooleanArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jboolean *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_BYTE: + jo_ar.reset( jni->NewByteArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetByteArrayRegion( + static_cast<jbyteArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jbyte *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + jo_ar.reset( jni->NewShortArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetShortArrayRegion( + static_cast<jshortArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jshort *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + jo_ar.reset( jni->NewIntArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetIntArrayRegion( + static_cast<jintArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jint *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + jo_ar.reset( jni->NewLongArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetLongArrayRegion( + static_cast<jlongArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jlong *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_FLOAT: + jo_ar.reset( jni->NewFloatArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetFloatArrayRegion( + static_cast<jfloatArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jfloat *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_DOUBLE: + jo_ar.reset( jni->NewDoubleArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetDoubleArrayRegion( + static_cast<jdoubleArray>(jo_ar.get()), + 0, nElements, reinterpret_cast<jdouble *>(seq->elements) ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_STRING: + jo_ar.reset( + jni->NewObjectArray( + nElements, getJniInfo()->m_class_String, nullptr ) ); + jni.ensure_no_exception(); + if (in_param) + { + rtl_uString * const * pp = + reinterpret_cast<rtl_uString * const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + JLocalAutoRef jo_string( + jni, ustring_to_jstring( jni, pp[ nPos ] ) ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_string.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_TYPE: + jo_ar.reset( + jni->NewObjectArray( nElements, getJniInfo()->m_class_Type, nullptr ) ); + jni.ensure_no_exception(); + if (in_param) + { + typelib_TypeDescriptionReference * const * pp = + reinterpret_cast<typelib_TypeDescriptionReference * const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, &pp[ nPos ], element_type, nullptr, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_ANY: + jo_ar.reset( + jni->NewObjectArray( + nElements, getJniInfo()->m_class_Object, nullptr ) ); + jni.ensure_no_exception(); + if (in_param) + { + uno_Any const * p = reinterpret_cast<uno_Any const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, &p[ nPos ], element_type, nullptr, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_ENUM: + { + OUString const & element_type_name = + OUString::unacquired( &element_type->pTypeName ); + OString class_name( + OUStringToOString( + element_type_name, RTL_TEXTENCODING_JAVA_UTF8 ) ); + JLocalAutoRef jo_enum_class( + jni, find_class( jni, class_name.getStr() ) ); + + jo_ar.reset( + jni->NewObjectArray( + nElements, static_cast<jclass>(jo_enum_class.get()), nullptr ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + // call static <enum_class>.fromInt( int ) + OString sig = "(I)L" + class_name.replace( '.', '/' ) + ";"; + jmethodID method_id = jni->GetStaticMethodID( + static_cast<jclass>(jo_enum_class.get()), "fromInt", sig.getStr() ); + jni.ensure_no_exception(); + assert( method_id != nullptr ); + + sal_Int32 const * p = reinterpret_cast<sal_Int32 const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue arg; + arg.i = p[ nPos ]; + JLocalAutoRef jo_enum( + jni, jni->CallStaticObjectMethodA( + static_cast<jclass>(jo_enum_class.get()), method_id, &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_enum.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + JNI_type_info const * element_info = + getJniInfo()->get_type_info( jni, element_type ); + + jo_ar.reset( + jni->NewObjectArray( nElements, element_info->m_class, nullptr ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + char * p = const_cast<char *>(seq->elements); + sal_Int32 nSize = element_info->m_td.get()->nSize; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, p + (nSize * nPos), + element_type, element_info, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + OStringBuffer buf( 64 ); + JNI_info::append_sig( + &buf, element_type, false /* use class XInterface */, + false /* '.' instead of '/' */ ); + OString class_name( buf.makeStringAndClear() ); + JLocalAutoRef jo_seq_class( + jni, find_class( jni, class_name.getStr() ) ); + + jo_ar.reset( + jni->NewObjectArray( + nElements, static_cast<jclass>(jo_seq_class.get()), nullptr ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + uno_Sequence * const * elements = reinterpret_cast<uno_Sequence * const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue java_data2; + map_to_java( + jni, &java_data2, elements + nPos, element_type, nullptr, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_seq( jni, java_data2.l ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), nPos, jo_seq.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_INTERFACE: + { + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( + getJniInfo()->get_type_info( jni, element_type ) ); + + jo_ar.reset( + jni->NewObjectArray( nElements, iface_info->m_class, nullptr ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + uno_Interface * const * pp = reinterpret_cast<uno_Interface * const *>(seq->elements); + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + uno_Interface * pUnoI = pp[ nPos ]; + if (pUnoI != nullptr) + { + JLocalAutoRef jo_element( + jni, map_to_java( jni, pUnoI, iface_info ) ); + jni->SetObjectArrayElement( + static_cast<jobjectArray>(jo_ar.get()), + nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + } + break; + } + default: + { + throw BridgeRuntimeError( + "[map_to_java():" + OUString::unacquired( &type->pTypeName ) + + "] unsupported element type: " + + OUString::unacquired( &element_type->pTypeName ) + + jni.get_stack_trace() ); + } + } + + if (out_param) + { + if (java_data->l == nullptr) + { + JLocalAutoRef jo_element_class( + jni, jni->GetObjectClass( jo_ar.get() ) ); + if (in_param) + { + java_data->l = jni->NewObjectArray( + 1, static_cast<jclass>(jo_element_class.get()), jo_ar.get() ); + } + else + { + java_data->l = jni->NewObjectArray( + 1, static_cast<jclass>(jo_element_class.get()), nullptr ); + } + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_ar.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_ar.release(); + } + break; + } + case typelib_TypeClass_INTERFACE: + { + JLocalAutoRef jo_iface( jni ); + if (in_param) + { + uno_Interface * pUnoI = *static_cast<uno_Interface * const *>(uno_data); + if (pUnoI != nullptr) + { + if (info == nullptr) + info = getJniInfo()->get_type_info( jni, type ); + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( info ); + jo_iface.reset( map_to_java( jni, pUnoI, iface_info ) ); + } + } + if (out_param) + { + if (java_data->l == nullptr) + { + if (info == nullptr) + info = getJniInfo()->get_type_info( jni, type ); + java_data->l = + jni->NewObjectArray( 1, info->m_class, jo_iface.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + static_cast<jobjectArray>(java_data->l), 0, jo_iface.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_iface.release(); + } + break; + } + default: + { + throw BridgeRuntimeError( + "[map_to_java():" + OUString::unacquired( &type->pTypeName ) + + "] unsupported type!" + jni.get_stack_trace() ); + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |