1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #if ! defined INCLUDED_JNI_INFO_H 25 #define INCLUDED_JNI_INFO_H 26 27 #include <hash_map> 28 29 #include "jni_base.h" 30 31 #include "osl/mutex.hxx" 32 #include "rtl/ref.hxx" 33 #include "rtl/ustring.hxx" 34 #include "rtl/strbuf.hxx" 35 36 #include "uno/environment.h" 37 #include "typelib/typedescription.hxx" 38 39 #include "com/sun/star/uno/Type.hxx" 40 41 namespace jvmaccess { class UnoVirtualMachine; } 42 43 namespace jni_uno 44 { 45 46 //------------------------------------------------------------------------------ 47 inline bool type_equals( 48 typelib_TypeDescriptionReference * type1, 49 typelib_TypeDescriptionReference * type2 ) 50 { 51 if (type1 == type2) 52 return true; 53 ::rtl::OUString const & name1 = 54 ::rtl::OUString::unacquired( &type1->pTypeName ); 55 ::rtl::OUString const & name2 = 56 ::rtl::OUString::unacquired( &type2->pTypeName ); 57 return ((type1->eTypeClass == type2->eTypeClass) && name1.equals( name2 )); 58 } 59 60 //------------------------------------------------------------------------------ 61 inline bool is_XInterface( typelib_TypeDescriptionReference * type ) 62 { 63 return ((typelib_TypeClass_INTERFACE == type->eTypeClass) && 64 ::rtl::OUString::unacquired( &type->pTypeName ).equalsAsciiL( 65 RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )); 66 } 67 68 //============================================================================== 69 struct JNI_type_info 70 { 71 ::com::sun::star::uno::TypeDescription m_td; 72 jclass m_class; 73 74 virtual void destroy( JNIEnv * jni_env ) = 0; 75 protected: 76 inline void destruct( JNIEnv * jni_env ) 77 { jni_env->DeleteGlobalRef( m_class ); } 78 virtual inline ~JNI_type_info() {} 79 explicit JNI_type_info( 80 JNI_context const & jni, typelib_TypeDescription * td ); 81 }; 82 83 //============================================================================== 84 struct JNI_interface_type_info : public JNI_type_info 85 { 86 jobject m_proxy_ctor; // proxy ctor 87 jobject m_type; 88 // sorted via typelib function index 89 jmethodID * m_methods; 90 91 virtual void destroy( JNIEnv * jni_env ); 92 explicit JNI_interface_type_info( 93 JNI_context const & jni, typelib_TypeDescription * td ); 94 }; 95 96 //============================================================================== 97 struct JNI_compound_type_info : public JNI_type_info 98 { 99 JNI_type_info const * m_base; 100 // ctor( msg ) for exceptions 101 jmethodID m_exc_ctor; 102 // sorted via typelib member index 103 jfieldID * m_fields; 104 105 virtual void destroy( JNIEnv * jni_env ); 106 explicit JNI_compound_type_info( 107 JNI_context const & jni, typelib_TypeDescription * td ); 108 }; 109 110 //============================================================================== 111 struct JNI_type_info_holder 112 { 113 JNI_type_info * m_info; 114 inline JNI_type_info_holder() 115 : m_info( 0 ) 116 {} 117 }; 118 119 typedef ::std::hash_map< 120 ::rtl::OUString, JNI_type_info_holder, ::rtl::OUStringHash > t_str2type; 121 122 //============================================================================== 123 class JNI_info 124 { 125 mutable ::osl::Mutex m_mutex; 126 mutable t_str2type m_type_map; 127 128 public: 129 // These two are needed very early by find_class from within the ctor: 130 jclass m_class_Class; 131 jmethodID m_method_Class_forName; 132 133 // 134 jobject m_object_java_env; 135 jobject m_object_Any_VOID; 136 jobject m_object_Type_UNSIGNED_SHORT; 137 jobject m_object_Type_UNSIGNED_LONG; 138 jobject m_object_Type_UNSIGNED_HYPER; 139 140 // 141 jclass m_class_Object; 142 jclass m_class_Character; 143 jclass m_class_Boolean; 144 jclass m_class_Byte; 145 jclass m_class_Short; 146 jclass m_class_Integer; 147 jclass m_class_Long; 148 jclass m_class_Float; 149 jclass m_class_Double; 150 jclass m_class_String; 151 152 jclass m_class_UnoRuntime; 153 jclass m_class_RuntimeException; 154 jclass m_class_Any; 155 jclass m_class_Type; 156 jclass m_class_TypeClass; 157 jclass m_class_JNI_proxy; 158 159 // 160 jmethodID m_method_Object_toString; 161 jmethodID m_method_Class_getName; 162 jmethodID m_method_Throwable_getMessage; 163 jmethodID m_ctor_Character_with_char; 164 jmethodID m_ctor_Boolean_with_boolean; 165 jmethodID m_ctor_Byte_with_byte; 166 jmethodID m_ctor_Short_with_short; 167 jmethodID m_ctor_Integer_with_int; 168 jmethodID m_ctor_Long_with_long; 169 jmethodID m_ctor_Float_with_float; 170 jmethodID m_ctor_Double_with_double; 171 jmethodID m_method_Boolean_booleanValue; 172 jmethodID m_method_Byte_byteValue; 173 jmethodID m_method_Character_charValue; 174 jmethodID m_method_Double_doubleValue; 175 jmethodID m_method_Float_floatValue; 176 jmethodID m_method_Integer_intValue; 177 jmethodID m_method_Long_longValue; 178 jmethodID m_method_Short_shortValue; 179 180 // 181 jmethodID m_method_IEnvironment_getRegisteredInterface; 182 jmethodID m_method_IEnvironment_registerInterface; 183 jmethodID m_method_UnoRuntime_generateOid; 184 jmethodID m_method_UnoRuntime_queryInterface; 185 jmethodID m_ctor_Any_with_Type_Object; 186 jfieldID m_field_Any__type; 187 jfieldID m_field_Any__object; 188 jmethodID m_ctor_Type_with_Class; 189 jmethodID m_ctor_Type_with_Name_TypeClass; 190 jfieldID m_field_Type__typeName; 191 jmethodID m_method_TypeClass_fromInt; 192 jfieldID m_field_Enum_m_value; 193 194 // 195 jmethodID m_method_JNI_proxy_get_proxy_ctor; 196 jmethodID m_method_JNI_proxy_create; 197 jfieldID m_field_JNI_proxy_m_receiver_handle; 198 jfieldID m_field_JNI_proxy_m_td_handle; 199 jfieldID m_field_JNI_proxy_m_type; 200 jfieldID m_field_JNI_proxy_m_oid; 201 202 // 203 ::com::sun::star::uno::TypeDescription m_XInterface_queryInterface_td; 204 ::com::sun::star::uno::Type const & m_Exception_type; 205 ::com::sun::star::uno::Type const & m_RuntimeException_type; 206 ::com::sun::star::uno::Type const & m_void_type; 207 // 208 JNI_interface_type_info const * m_XInterface_type_info; 209 210 // 211 JNI_type_info const * get_type_info( 212 JNI_context const & jni, 213 typelib_TypeDescription * type ) const; 214 JNI_type_info const * get_type_info( 215 JNI_context const & jni, 216 typelib_TypeDescriptionReference * type ) const; 217 JNI_type_info const * get_type_info( 218 JNI_context const & jni, 219 ::rtl::OUString const & uno_name ) const; 220 // 221 inline static void append_sig( 222 ::rtl::OStringBuffer * buf, typelib_TypeDescriptionReference * type, 223 bool use_Object_for_type_XInterface = true, bool use_slashes = true ); 224 225 // get this 226 static JNI_info const * get_jni_info( 227 rtl::Reference< jvmaccess::UnoVirtualMachine > const & uno_vm ); 228 inline void destroy( JNIEnv * jni_env ); 229 230 private: 231 JNI_type_info const * create_type_info( 232 JNI_context const & jni, typelib_TypeDescription * td ) const; 233 234 void destruct( JNIEnv * jni_env ); 235 236 JNI_info( JNIEnv * jni_env, jobject class_loader, 237 jclass classClass, jmethodID methodForName ); 238 inline ~JNI_info() {} 239 }; 240 241 //______________________________________________________________________________ 242 inline void JNI_info::destroy( JNIEnv * jni_env ) 243 { 244 destruct( jni_env ); 245 delete this; 246 } 247 248 //______________________________________________________________________________ 249 inline void JNI_info::append_sig( 250 ::rtl::OStringBuffer * buf, typelib_TypeDescriptionReference * type, 251 bool use_Object_for_type_XInterface, bool use_slashes ) 252 { 253 switch (type->eTypeClass) 254 { 255 case typelib_TypeClass_VOID: 256 buf->append( 'V' ); 257 break; 258 case typelib_TypeClass_CHAR: 259 buf->append( 'C' ); 260 break; 261 case typelib_TypeClass_BOOLEAN: 262 buf->append( 'Z' ); 263 break; 264 case typelib_TypeClass_BYTE: 265 buf->append( 'B' ); 266 break; 267 case typelib_TypeClass_SHORT: 268 case typelib_TypeClass_UNSIGNED_SHORT: 269 buf->append( 'S' ); 270 break; 271 case typelib_TypeClass_LONG: 272 case typelib_TypeClass_UNSIGNED_LONG: 273 buf->append( 'I' ); 274 break; 275 case typelib_TypeClass_HYPER: 276 case typelib_TypeClass_UNSIGNED_HYPER: 277 buf->append( 'J' ); 278 break; 279 case typelib_TypeClass_FLOAT: 280 buf->append( 'F' ); 281 break; 282 case typelib_TypeClass_DOUBLE: 283 buf->append( 'D' ); 284 break; 285 case typelib_TypeClass_STRING: 286 if ( use_slashes ) { 287 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;") ); 288 } else { 289 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.String;") ); 290 } 291 break; 292 case typelib_TypeClass_TYPE: 293 if ( use_slashes ) { 294 buf->append( 295 RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;") ); 296 } else { 297 buf->append( 298 RTL_CONSTASCII_STRINGPARAM("Lcom.sun.star.uno.Type;") ); 299 } 300 break; 301 case typelib_TypeClass_ANY: 302 if ( use_slashes ) { 303 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;") ); 304 } else { 305 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.Object;") ); 306 } 307 break; 308 case typelib_TypeClass_ENUM: 309 case typelib_TypeClass_STRUCT: 310 case typelib_TypeClass_EXCEPTION: 311 { 312 ::rtl::OUString const & uno_name = 313 ::rtl::OUString::unacquired( &type->pTypeName ); 314 buf->append( 'L' ); 315 // Erase type arguments of instantiated polymorphic struct types: 316 sal_Int32 i = uno_name.indexOf( '<' ); 317 if ( i < 0 ) { 318 buf->append( 319 ::rtl::OUStringToOString( 320 use_slashes ? uno_name.replace( '.', '/' ) : uno_name, 321 RTL_TEXTENCODING_JAVA_UTF8 ) ); 322 } else { 323 rtl::OUString s( uno_name.copy( 0, i ) ); 324 buf->append( 325 ::rtl::OUStringToOString( 326 use_slashes ? s.replace( '.', '/' ) : s, 327 RTL_TEXTENCODING_JAVA_UTF8 ) ); 328 } 329 buf->append( ';' ); 330 break; 331 } 332 case typelib_TypeClass_SEQUENCE: 333 { 334 buf->append( '[' ); 335 TypeDescr td( type ); 336 append_sig( 337 buf, ((typelib_IndirectTypeDescription *)td.get())->pType, 338 use_Object_for_type_XInterface, use_slashes ); 339 break; 340 } 341 case typelib_TypeClass_INTERFACE: 342 if (use_Object_for_type_XInterface && is_XInterface( type )) 343 { 344 if ( use_slashes ) { 345 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;") ); 346 } else { 347 buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.Object;") ); 348 } 349 } 350 else 351 { 352 ::rtl::OUString const & uno_name = 353 ::rtl::OUString::unacquired( &type->pTypeName ); 354 buf->append( 'L' ); 355 buf->append( 356 ::rtl::OUStringToOString( 357 use_slashes ? uno_name.replace( '.', '/' ) : uno_name, 358 RTL_TEXTENCODING_JAVA_UTF8 ) ); 359 buf->append( ';' ); 360 } 361 break; 362 default: 363 throw BridgeRuntimeError( 364 OUSTR("unsupported type: ") + 365 ::rtl::OUString::unacquired( &type->pTypeName ) ); 366 } 367 } 368 369 } 370 371 #endif 372