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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 #include "jni_bridge.h"
27 
28 #include "com/sun/star/uno/RuntimeException.hpp"
29 
30 #include "jvmaccess/unovirtualmachine.hxx"
31 #include "rtl/string.hxx"
32 #include "rtl/strbuf.hxx"
33 #include "rtl/ustrbuf.hxx"
34 
35 #include "uno/lbnames.h"
36 
37 
38 namespace css = ::com::sun::star;
39 using namespace ::std;
40 using namespace ::osl;
41 using namespace ::rtl;
42 
43 namespace jni_uno
44 {
45 
46 //______________________________________________________________________________
JNI_type_info(JNI_context const & jni,typelib_TypeDescription * td)47 JNI_type_info::JNI_type_info(
48     JNI_context const & jni, typelib_TypeDescription * td )
49     : m_td( td ),
50       m_class( 0 )
51 {
52     m_td.makeComplete();
53     if (! m_td.get()->bComplete)
54     {
55         OUStringBuffer buf( 128 );
56         buf.appendAscii(
57             RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") );
58         buf.append( OUString::unacquired( &m_td.get()->pTypeName ) );
59         buf.append( jni.get_stack_trace() );
60         throw BridgeRuntimeError( buf.makeStringAndClear() );
61     }
62 }
63 
64 
65 //______________________________________________________________________________
destroy(JNIEnv * jni_env)66 void JNI_interface_type_info::destroy( JNIEnv * jni_env )
67 {
68     JNI_type_info::destruct( jni_env );
69     jni_env->DeleteGlobalRef( m_proxy_ctor );
70     jni_env->DeleteGlobalRef( m_type );
71     delete [] m_methods;
72     delete this;
73 }
74 
75 //______________________________________________________________________________
JNI_interface_type_info(JNI_context const & jni,typelib_TypeDescription * td_)76 JNI_interface_type_info::JNI_interface_type_info(
77     JNI_context const & jni, typelib_TypeDescription * td_ )
78     : JNI_type_info( jni, td_ )
79 {
80     OSL_ASSERT( typelib_TypeClass_INTERFACE == m_td.get()->eTypeClass );
81 
82     OUString const & uno_name = OUString::unacquired( &m_td.get()->pTypeName );
83     JNI_info const * jni_info = jni.get_info();
84 
85     JLocalAutoRef jo_class(
86         jni,
87         find_class(
88             jni,
89             ( OUStringToOString( uno_name, RTL_TEXTENCODING_JAVA_UTF8 ).
90               getStr() ) ) );
91     JLocalAutoRef jo_type( jni, create_type( jni, (jclass) jo_class.get() ) );
92 
93     // get proxy ctor
94     jvalue arg;
95     arg.l = jo_class.get();
96     JLocalAutoRef jo_proxy_ctor(
97         jni, jni->CallStaticObjectMethodA(
98             jni_info->m_class_JNI_proxy,
99             jni_info->m_method_JNI_proxy_get_proxy_ctor, &arg ) );
100 
101     if (is_XInterface( m_td.get()->pWeakRef ))
102     {
103         m_methods = 0; // no methods
104     }
105     else
106     {
107         // retrieve method ids for all direct members
108         try
109         {
110             typelib_InterfaceTypeDescription * td =
111                 reinterpret_cast< typelib_InterfaceTypeDescription * >(
112                     m_td.get() );
113             m_methods = new jmethodID[ td->nMapFunctionIndexToMemberIndex ];
114             sal_Int32 nMethodIndex = 0;
115             typelib_TypeDescriptionReference ** ppMembers = td->ppMembers;
116             sal_Int32 nMembers = td->nMembers;
117 
118             for ( sal_Int32 nPos = 0; nPos < nMembers; ++nPos )
119             {
120                 TypeDescr member_td( ppMembers[ nPos ] );
121 
122                 OStringBuffer sig_buf( 64 );
123 
124                 if (typelib_TypeClass_INTERFACE_METHOD ==
125                       member_td.get()->eTypeClass) // method
126                 {
127                     typelib_InterfaceMethodTypeDescription * method_td =
128                         reinterpret_cast<
129                           typelib_InterfaceMethodTypeDescription * >(
130                               member_td.get() );
131 
132                     sig_buf.append( '(' );
133                     for ( sal_Int32 i = 0; i < method_td->nParams; ++i )
134                     {
135                         typelib_MethodParameter const & param =
136                             method_td->pParams[ i ];
137                         if (param.bOut)
138                             sig_buf.append( '[' );
139                         JNI_info::append_sig( &sig_buf, param.pTypeRef );
140                     }
141                     sig_buf.append( ')' );
142                     JNI_info::append_sig( &sig_buf, method_td->pReturnTypeRef );
143 
144                     OString method_signature( sig_buf.makeStringAndClear() );
145                     OString method_name(
146                         OUStringToOString( OUString::unacquired(
147                                                &method_td->aBase.pMemberName ),
148                                            RTL_TEXTENCODING_JAVA_UTF8 ) );
149 
150                     m_methods[ nMethodIndex ] = jni->GetMethodID(
151                         (jclass) jo_class.get(), method_name.getStr(),
152                         method_signature.getStr() );
153                     jni.ensure_no_exception();
154                     OSL_ASSERT( 0 != m_methods[ nMethodIndex ] );
155                     ++nMethodIndex;
156                 }
157                 else // attribute
158                 {
159                     OSL_ASSERT(
160                         typelib_TypeClass_INTERFACE_ATTRIBUTE ==
161                           member_td.get()->eTypeClass );
162                     typelib_InterfaceAttributeTypeDescription * attribute_td =
163                         reinterpret_cast<
164                           typelib_InterfaceAttributeTypeDescription * >(
165                               member_td.get() );
166 
167                     // type sig
168                     JNI_info::append_sig(
169                         &sig_buf, attribute_td->pAttributeTypeRef );
170                     OString type_sig( sig_buf.makeStringAndClear() );
171                     sig_buf.ensureCapacity( 64 );
172                     // member name
173                     OUString const & member_name =
174                         OUString::unacquired(
175                             &attribute_td->aBase.pMemberName );
176 
177                     // getter
178                     sig_buf.append( RTL_CONSTASCII_STRINGPARAM("()") );
179                     sig_buf.append( type_sig );
180                     OString method_signature( sig_buf.makeStringAndClear() );
181                     OUStringBuffer name_buf( 3 + member_name.getLength() );
182                     name_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("get") );
183                     name_buf.append( member_name );
184                     OString method_name(
185                         OUStringToOString(
186                             name_buf.makeStringAndClear(),
187                             RTL_TEXTENCODING_JAVA_UTF8 ) );
188                     m_methods[ nMethodIndex ] = jni->GetMethodID(
189                         (jclass) jo_class.get(), method_name.getStr(),
190                         method_signature.getStr() );
191                     jni.ensure_no_exception();
192                     OSL_ASSERT( 0 != m_methods[ nMethodIndex ] );
193                     ++nMethodIndex;
194                     if (! attribute_td->bReadOnly)
195                     {
196                         // setter
197                         sig_buf.ensureCapacity( 64 );
198                         sig_buf.append( '(' );
199                         sig_buf.append( type_sig );
200                         sig_buf.append( RTL_CONSTASCII_STRINGPARAM(")V") );
201                         method_signature = sig_buf.makeStringAndClear();
202                         name_buf.ensureCapacity( 3 + member_name.getLength() );
203                         name_buf.appendAscii(
204                             RTL_CONSTASCII_STRINGPARAM("set") );
205                         name_buf.append( member_name );
206                         method_name = OUStringToOString(
207                             name_buf.makeStringAndClear(),
208                             RTL_TEXTENCODING_JAVA_UTF8 );
209                         m_methods[ nMethodIndex ] = jni->GetMethodID(
210                             (jclass) jo_class.get(), method_name.getStr(),
211                             method_signature.getStr() );
212                         jni.ensure_no_exception();
213                         OSL_ASSERT( 0 != m_methods[ nMethodIndex ] );
214                         ++nMethodIndex;
215                     }
216                 }
217             }
218         }
219         catch (...)
220         {
221             delete [] m_methods;
222             throw;
223         }
224     }
225     m_class = (jclass) jni->NewGlobalRef( jo_class.get() );
226     m_type = jni->NewGlobalRef( jo_type.get() );
227     m_proxy_ctor = jni->NewGlobalRef( jo_proxy_ctor.get() );
228 }
229 
230 
231 //______________________________________________________________________________
destroy(JNIEnv * jni_env)232 void JNI_compound_type_info::destroy( JNIEnv * jni_env )
233 {
234     JNI_type_info::destruct( jni_env );
235     delete [] m_fields;
236     delete this;
237 }
238 
239 //______________________________________________________________________________
JNI_compound_type_info(JNI_context const & jni,typelib_TypeDescription * td_)240 JNI_compound_type_info::JNI_compound_type_info(
241     JNI_context const & jni, typelib_TypeDescription * td_ )
242     : JNI_type_info( jni, td_ ),
243       m_exc_ctor( 0 ),
244       m_fields( 0 )
245 {
246     OSL_ASSERT( typelib_TypeClass_STRUCT == m_td.get()->eTypeClass ||
247                 typelib_TypeClass_EXCEPTION == m_td.get()->eTypeClass );
248     typelib_CompoundTypeDescription * td =
249         reinterpret_cast< typelib_CompoundTypeDescription * >( m_td.get() );
250 
251     OUString const & uno_name =
252         OUString::unacquired( &((typelib_TypeDescription *)td)->pTypeName );
253 
254     // Erase type arguments of instantiated polymorphic struct types:
255     OUString nucleus;
256     sal_Int32 i = uno_name.indexOf( '<' );
257     if ( i < 0 ) {
258         nucleus = uno_name;
259     } else {
260         nucleus = uno_name.copy( 0, i );
261     }
262     JLocalAutoRef jo_class(
263         jni,
264         find_class(
265             jni,
266             OUStringToOString(
267                 nucleus, RTL_TEXTENCODING_JAVA_UTF8 ).getStr() ) );
268 
269     JNI_info const * jni_info = jni.get_info();
270 
271     if (typelib_TypeClass_EXCEPTION == m_td.get()->eTypeClass)
272     {
273         // retrieve exc ctor( msg )
274         m_exc_ctor = jni->GetMethodID(
275             (jclass) jo_class.get(), "<init>", "(Ljava/lang/String;)V" );
276         jni.ensure_no_exception();
277         OSL_ASSERT( 0 != m_exc_ctor );
278     }
279 
280     // retrieve info for base type
281     typelib_TypeDescription * base_td =
282         reinterpret_cast< typelib_TypeDescription * >(
283             td->pBaseTypeDescription );
284     m_base = (0 == base_td ? 0 : jni_info->get_type_info( jni, base_td ));
285 
286     try
287     {
288         if (type_equals(
289                 ((typelib_TypeDescription *)td)->pWeakRef,
290                 jni_info->m_Exception_type.getTypeLibType() ) ||
291             type_equals(
292                 ((typelib_TypeDescription *)td)->pWeakRef,
293                 jni_info->m_RuntimeException_type.getTypeLibType() ))
294         {
295             m_fields = new jfieldID[ 2 ];
296             m_fields[ 0 ] = 0; // special Throwable.getMessage()
297             // field Context
298             m_fields[ 1 ] = jni->GetFieldID(
299                 (jclass) jo_class.get(), "Context", "Ljava/lang/Object;" );
300             jni.ensure_no_exception();
301             OSL_ASSERT( 0 != m_fields[ 1 ] );
302         }
303         else
304         {
305             // retrieve field ids for all direct members
306             sal_Int32 nMembers = td->nMembers;
307             m_fields = new jfieldID[ nMembers ];
308 
309             for ( sal_Int32 nPos = 0; nPos < nMembers; ++nPos )
310             {
311                 OString sig;
312                 if (td->aBase.eTypeClass == typelib_TypeClass_STRUCT
313                     && reinterpret_cast< typelib_StructTypeDescription * >(
314                         td)->pParameterizedTypes != 0
315                     && reinterpret_cast< typelib_StructTypeDescription * >(
316                         td)->pParameterizedTypes[nPos])
317                 {
318                     sig = OString(
319                         RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"));
320                 } else {
321                     OStringBuffer sig_buf( 32 );
322                     JNI_info::append_sig( &sig_buf, td->ppTypeRefs[ nPos ] );
323                     sig = sig_buf.makeStringAndClear();
324                 }
325 
326                 OString member_name(
327                     OUStringToOString(
328                         OUString::unacquired( &td->ppMemberNames[ nPos ] ),
329                         RTL_TEXTENCODING_JAVA_UTF8 ) );
330 
331                 m_fields[ nPos ] = jni->GetFieldID(
332                     (jclass) jo_class.get(), member_name.getStr(),
333                     sig.getStr() );
334                 jni.ensure_no_exception();
335                 OSL_ASSERT( 0 != m_fields[ nPos ] );
336             }
337         }
338     }
339     catch (...)
340     {
341         delete [] m_fields;
342         throw;
343     }
344 
345     m_class = (jclass) jni->NewGlobalRef( jo_class.get() );
346 }
347 
348 
349 //______________________________________________________________________________
create_type_info(JNI_context const & jni,typelib_TypeDescription * td) const350 JNI_type_info const * JNI_info::create_type_info(
351     JNI_context const & jni, typelib_TypeDescription * td ) const
352 {
353     OUString const & uno_name = OUString::unacquired( &td->pTypeName );
354 
355     JNI_type_info * new_info;
356     switch (td->eTypeClass)
357     {
358     case typelib_TypeClass_STRUCT:
359     case typelib_TypeClass_EXCEPTION:
360     {
361         new_info = new JNI_compound_type_info( jni, td );
362         break;
363     }
364     case typelib_TypeClass_INTERFACE:
365     {
366         new_info = new JNI_interface_type_info( jni, td );
367         break;
368     }
369     default:
370     {
371         OUStringBuffer buf( 128 );
372         buf.appendAscii(
373             RTL_CONSTASCII_STRINGPARAM("type info not supported for ") );
374         buf.append( uno_name );
375         buf.append( jni.get_stack_trace() );
376         throw BridgeRuntimeError( buf.makeStringAndClear() );
377     }
378     }
379 
380     // look up
381     JNI_type_info * info;
382     ClearableMutexGuard guard( m_mutex );
383     JNI_type_info_holder & holder = m_type_map[ uno_name ];
384     if (0 == holder.m_info) // new insertion
385     {
386         holder.m_info = new_info;
387         guard.clear();
388         info = new_info;
389     }
390     else // inserted in the meantime
391     {
392         info = holder.m_info;
393         guard.clear();
394         new_info->destroy( jni.get_jni_env() );
395     }
396     return info;
397 }
398 
399 //______________________________________________________________________________
get_type_info(JNI_context const & jni,typelib_TypeDescription * td) const400 JNI_type_info const * JNI_info::get_type_info(
401     JNI_context const & jni, typelib_TypeDescription * td ) const
402 {
403     if (is_XInterface( td->pWeakRef ))
404     {
405         return m_XInterface_type_info;
406     }
407 
408     OUString const & uno_name = OUString::unacquired( &td->pTypeName );
409     JNI_type_info const * info;
410     ClearableMutexGuard guard( m_mutex );
411 
412     t_str2type::const_iterator iFind( m_type_map.find( uno_name ) );
413     if (iFind == m_type_map.end())
414     {
415         guard.clear();
416         info = create_type_info( jni, td );
417     }
418     else
419     {
420         info = iFind->second.m_info;
421     }
422 
423     return info;
424 }
425 
426 //______________________________________________________________________________
get_type_info(JNI_context const & jni,typelib_TypeDescriptionReference * type) const427 JNI_type_info const * JNI_info::get_type_info(
428     JNI_context const & jni, typelib_TypeDescriptionReference * type ) const
429 {
430     if (is_XInterface( type ))
431     {
432         return m_XInterface_type_info;
433     }
434 
435     OUString const & uno_name = OUString::unacquired( &type->pTypeName );
436     JNI_type_info const * info;
437     ClearableMutexGuard guard( m_mutex );
438     t_str2type::const_iterator iFind( m_type_map.find( uno_name ) );
439     if (iFind == m_type_map.end())
440     {
441         guard.clear();
442         TypeDescr td( type );
443         info = create_type_info( jni, td.get() );
444     }
445     else
446     {
447         info = iFind->second.m_info;
448     }
449 
450     return info;
451 }
452 
453 //______________________________________________________________________________
get_type_info(JNI_context const & jni,OUString const & uno_name) const454 JNI_type_info const * JNI_info::get_type_info(
455     JNI_context const & jni, OUString const & uno_name ) const
456 {
457     if (uno_name.equalsAsciiL(
458             RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ))
459     {
460         return m_XInterface_type_info;
461     }
462 
463     JNI_type_info const * info;
464     ClearableMutexGuard guard( m_mutex );
465     t_str2type::const_iterator iFind( m_type_map.find( uno_name ) );
466     if (iFind == m_type_map.end())
467     {
468         guard.clear();
469         css::uno::TypeDescription td( uno_name );
470         if (! td.is())
471         {
472             OUStringBuffer buf( 128 );
473             buf.appendAscii(
474                 RTL_CONSTASCII_STRINGPARAM("UNO type not found: ") );
475             buf.append( uno_name );
476             buf.append( jni.get_stack_trace() );
477             throw BridgeRuntimeError( buf.makeStringAndClear() );
478         }
479         info = create_type_info( jni, td.get() );
480     }
481     else
482     {
483         info = iFind->second.m_info;
484     }
485 
486     return info;
487 }
488 
489 //______________________________________________________________________________
JNI_info(JNIEnv * jni_env,jobject class_loader,jclass classClass,jmethodID methodForName)490 JNI_info::JNI_info(
491     JNIEnv * jni_env, jobject class_loader, jclass classClass,
492     jmethodID methodForName )
493     : m_class_Class( classClass ),
494       m_method_Class_forName( methodForName ),
495       m_class_JNI_proxy( 0 ),
496       m_XInterface_queryInterface_td(
497         (reinterpret_cast< typelib_InterfaceTypeDescription * >(
498             css::uno::TypeDescription(
499                 ::getCppuType(
500                     (css::uno::Reference< css::uno::XInterface > const *)0 ) )
501             .get())->ppMembers[ 0 ] ) ),
502       m_Exception_type( ::getCppuType( (css::uno::Exception const *)0 ) ),
503       m_RuntimeException_type(
504           ::getCppuType( (css::uno::RuntimeException const *)0 ) ),
505       m_void_type( ::getCppuVoidType() ),
506       m_XInterface_type_info( 0 )
507 {
508     JNI_context jni( this, jni_env, class_loader ); // !no proper jni_info!
509 
510     // class lookup
511     JLocalAutoRef jo_Object(
512         jni, find_class( jni, "java.lang.Object" ) );
513     JLocalAutoRef jo_Class(
514         jni, find_class( jni, "java.lang.Class" ) );
515     JLocalAutoRef jo_Throwable(
516         jni, find_class( jni, "java.lang.Throwable" ) );
517     JLocalAutoRef jo_Character(
518         jni, find_class( jni, "java.lang.Character" ) );
519     JLocalAutoRef jo_Boolean(
520         jni, find_class( jni, "java.lang.Boolean" ) );
521     JLocalAutoRef jo_Byte(
522         jni, find_class( jni, "java.lang.Byte" ) );
523     JLocalAutoRef jo_Short(
524         jni, find_class( jni, "java.lang.Short" ) );
525     JLocalAutoRef jo_Integer(
526         jni, find_class( jni, "java.lang.Integer" ) );
527     JLocalAutoRef jo_Long(
528         jni, find_class( jni, "java.lang.Long" ) );
529     JLocalAutoRef jo_Float(
530         jni, find_class( jni, "java.lang.Float" ) );
531     JLocalAutoRef jo_Double(
532         jni, find_class( jni, "java.lang.Double" ) );
533     JLocalAutoRef jo_String(
534         jni, find_class( jni, "java.lang.String" ) );
535     JLocalAutoRef jo_RuntimeException(
536         jni, find_class( jni, "com.sun.star.uno.RuntimeException" ) );
537     JLocalAutoRef jo_UnoRuntime(
538         jni, find_class( jni, "com.sun.star.uno.UnoRuntime" ) );
539     JLocalAutoRef jo_Any(
540         jni, find_class( jni, "com.sun.star.uno.Any" ) );
541     JLocalAutoRef jo_Enum(
542         jni, find_class( jni, "com.sun.star.uno.Enum" ) );
543     JLocalAutoRef jo_Type(
544         jni, find_class( jni, "com.sun.star.uno.Type" ) );
545     JLocalAutoRef jo_TypeClass(
546         jni, find_class( jni, "com.sun.star.uno.TypeClass" ) );
547     JLocalAutoRef jo_IEnvironment(
548         jni, find_class( jni, "com.sun.star.uno.IEnvironment" ) );
549     JLocalAutoRef jo_JNI_proxy(
550         jni, find_class( jni, "com.sun.star.bridges.jni_uno.JNI_proxy" ) );
551 
552     // method Object.toString()
553     m_method_Object_toString = jni->GetMethodID(
554         (jclass) jo_Object.get(), "toString", "()Ljava/lang/String;" );
555     jni.ensure_no_exception();
556     OSL_ASSERT( 0 != m_method_Object_toString );
557     // method Class.getName()
558     m_method_Class_getName = jni->GetMethodID(
559         (jclass) jo_Class.get(), "getName", "()Ljava/lang/String;" );
560     jni.ensure_no_exception();
561     OSL_ASSERT( 0 != m_method_Class_getName );
562 
563     // method Throwable.getMessage()
564     m_method_Throwable_getMessage = jni->GetMethodID(
565         (jclass) jo_Throwable.get(), "getMessage", "()Ljava/lang/String;" );
566     jni.ensure_no_exception();
567     OSL_ASSERT( 0 != m_method_Throwable_getMessage );
568 
569     // method Character.charValue()
570     m_method_Character_charValue = jni->GetMethodID(
571         (jclass) jo_Character.get(), "charValue", "()C" );
572     jni.ensure_no_exception();
573     OSL_ASSERT( 0 != m_method_Character_charValue );
574     // method Boolean.booleanValue()
575     m_method_Boolean_booleanValue = jni->GetMethodID(
576         (jclass) jo_Boolean.get(), "booleanValue", "()Z" );
577     jni.ensure_no_exception();
578     OSL_ASSERT( 0 != m_method_Boolean_booleanValue );
579     // method Byte.byteValue()
580     m_method_Byte_byteValue = jni->GetMethodID(
581         (jclass) jo_Byte.get(), "byteValue", "()B" );
582     jni.ensure_no_exception();
583     OSL_ASSERT( 0 != m_method_Byte_byteValue );
584     // method Short.shortValue()
585     m_method_Short_shortValue = jni->GetMethodID(
586         (jclass) jo_Short.get(), "shortValue", "()S" );
587     jni.ensure_no_exception();
588     OSL_ASSERT( 0 != m_method_Short_shortValue );
589     // method Integer.intValue()
590     m_method_Integer_intValue = jni->GetMethodID(
591         (jclass) jo_Integer.get(), "intValue", "()I" );
592     jni.ensure_no_exception();
593     OSL_ASSERT( 0 != m_method_Integer_intValue );
594     // method Long.longValue()
595     m_method_Long_longValue = jni->GetMethodID(
596         (jclass) jo_Long.get(), "longValue", "()J" );
597     jni.ensure_no_exception();
598     OSL_ASSERT( 0 != m_method_Long_longValue );
599     // method Float.floatValue()
600     m_method_Float_floatValue = jni->GetMethodID(
601         (jclass) jo_Float.get(), "floatValue", "()F" );
602     jni.ensure_no_exception();
603     OSL_ASSERT( 0 != m_method_Float_floatValue );
604     // method Double.doubleValue()
605     m_method_Double_doubleValue = jni->GetMethodID(
606         (jclass) jo_Double.get(), "doubleValue", "()D" );
607     jni.ensure_no_exception();
608     OSL_ASSERT( 0 != m_method_Double_doubleValue );
609 
610     // ctor Character( char )
611     m_ctor_Character_with_char = jni->GetMethodID(
612         (jclass) jo_Character.get(), "<init>", "(C)V" );
613     jni.ensure_no_exception();
614     OSL_ASSERT( 0 != m_ctor_Character_with_char );
615     // ctor Boolean( boolean )
616     m_ctor_Boolean_with_boolean = jni->GetMethodID(
617         (jclass) jo_Boolean.get(), "<init>", "(Z)V" );
618     jni.ensure_no_exception();
619     OSL_ASSERT( 0 != m_ctor_Boolean_with_boolean );
620     // ctor Byte( byte )
621     m_ctor_Byte_with_byte = jni->GetMethodID(
622         (jclass) jo_Byte.get(), "<init>", "(B)V" );
623     jni.ensure_no_exception();
624     OSL_ASSERT( 0 != m_ctor_Byte_with_byte );
625     // ctor Short( short )
626     m_ctor_Short_with_short = jni->GetMethodID(
627         (jclass) jo_Short.get(), "<init>", "(S)V" );
628     jni.ensure_no_exception();
629     OSL_ASSERT( 0 != m_ctor_Short_with_short );
630     // ctor Integer( int )
631     m_ctor_Integer_with_int = jni->GetMethodID(
632         (jclass) jo_Integer.get(), "<init>", "(I)V" );
633     jni.ensure_no_exception();
634     OSL_ASSERT( 0 != m_ctor_Integer_with_int );
635     // ctor Long( long )
636     m_ctor_Long_with_long = jni->GetMethodID(
637         (jclass) jo_Long.get(), "<init>", "(J)V" );
638     jni.ensure_no_exception();
639     OSL_ASSERT( 0 != m_ctor_Long_with_long );
640     // ctor Float( float )
641     m_ctor_Float_with_float = jni->GetMethodID(
642         (jclass) jo_Float.get(), "<init>", "(F)V" );
643     jni.ensure_no_exception();
644     OSL_ASSERT( 0 != m_ctor_Float_with_float );
645     // ctor Double( double )
646     m_ctor_Double_with_double = jni->GetMethodID(
647         (jclass) jo_Double.get(), "<init>", "(D)V" );
648     jni.ensure_no_exception();
649     OSL_ASSERT( 0 != m_ctor_Double_with_double );
650 
651     // static method UnoRuntime.generateOid()
652     m_method_UnoRuntime_generateOid = jni->GetStaticMethodID(
653         (jclass) jo_UnoRuntime.get(),
654         "generateOid", "(Ljava/lang/Object;)Ljava/lang/String;" );
655     jni.ensure_no_exception();
656     OSL_ASSERT( 0 != m_method_UnoRuntime_generateOid );
657     // static method UnoRuntime.queryInterface()
658     m_method_UnoRuntime_queryInterface = jni->GetStaticMethodID(
659         (jclass) jo_UnoRuntime.get(),
660         "queryInterface",
661         "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;" );
662     jni.ensure_no_exception();
663     OSL_ASSERT( 0 != m_method_UnoRuntime_queryInterface );
664 
665     // field Enum.m_value
666     m_field_Enum_m_value = jni->GetFieldID(
667         (jclass) jo_Enum.get(), "m_value", "I" );
668     jni.ensure_no_exception();
669     OSL_ASSERT( 0 != m_field_Enum_m_value );
670 
671     // static method TypeClass.fromInt()
672     m_method_TypeClass_fromInt = jni->GetStaticMethodID(
673         (jclass) jo_TypeClass.get(),
674         "fromInt", "(I)Lcom/sun/star/uno/TypeClass;" );
675     jni.ensure_no_exception();
676     OSL_ASSERT( 0 != m_method_TypeClass_fromInt );
677 
678     // ctor Type( Class )
679     m_ctor_Type_with_Class = jni->GetMethodID(
680         (jclass) jo_Type.get(), "<init>", "(Ljava/lang/Class;)V" );
681     jni.ensure_no_exception();
682     OSL_ASSERT( 0 != m_ctor_Type_with_Class );
683     // ctor Type( String, TypeClass )
684     m_ctor_Type_with_Name_TypeClass = jni->GetMethodID(
685         (jclass) jo_Type.get(),
686         "<init>", "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V" );
687     jni.ensure_no_exception();
688     OSL_ASSERT( 0 != m_ctor_Type_with_Name_TypeClass );
689     // field Type._typeName
690     m_field_Type__typeName = jni->GetFieldID(
691         (jclass) jo_Type.get(), "_typeName", "Ljava/lang/String;" );
692     jni.ensure_no_exception();
693     OSL_ASSERT( 0 != m_field_Type__typeName );
694 
695     // ctor Any( Type, Object )
696     m_ctor_Any_with_Type_Object = jni->GetMethodID(
697         (jclass) jo_Any.get(),
698         "<init>", "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V" );
699     jni.ensure_no_exception();
700     OSL_ASSERT( 0 != m_ctor_Any_with_Type_Object );
701 
702     // field Any._type
703     m_field_Any__type = jni->GetFieldID(
704         (jclass) jo_Any.get(), "_type", "Lcom/sun/star/uno/Type;" );
705     jni.ensure_no_exception();
706     OSL_ASSERT( 0 != m_field_Any__type );
707     // field Any._object
708     m_field_Any__object = jni->GetFieldID(
709         (jclass) jo_Any.get(), "_object", "Ljava/lang/Object;" );
710     jni.ensure_no_exception();
711     OSL_ASSERT( 0 != m_field_Any__object );
712 
713     // method IEnvironment.getRegisteredInterface()
714     m_method_IEnvironment_getRegisteredInterface = jni->GetMethodID(
715         (jclass) jo_IEnvironment.get(),
716         "getRegisteredInterface",
717         "(Ljava/lang/String;Lcom/sun/star/uno/Type;)Ljava/lang/Object;" );
718     jni.ensure_no_exception();
719     OSL_ASSERT( 0 != m_method_IEnvironment_getRegisteredInterface );
720     // method IEnvironment.registerInterface()
721     m_method_IEnvironment_registerInterface = jni->GetMethodID(
722         (jclass) jo_IEnvironment.get(), "registerInterface",
723         "(Ljava/lang/Object;[Ljava/lang/String;Lcom/sun/star/uno/Type;)"
724         "Ljava/lang/Object;" );
725     jni.ensure_no_exception();
726     OSL_ASSERT( 0 != m_method_IEnvironment_registerInterface );
727 
728     // static method JNI_proxy.get_proxy_ctor()
729     m_method_JNI_proxy_get_proxy_ctor = jni->GetStaticMethodID(
730         (jclass) jo_JNI_proxy.get(), "get_proxy_ctor",
731         "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" );
732     jni.ensure_no_exception();
733     OSL_ASSERT( 0 != m_method_JNI_proxy_get_proxy_ctor );
734     // static method JNI_proxy.create()
735     m_method_JNI_proxy_create = jni->GetStaticMethodID(
736         (jclass) jo_JNI_proxy.get(), "create",
737         "(JLcom/sun/star/uno/IEnvironment;JJLcom/sun/star/uno/Type;Ljava/lang"
738         "/String;Ljava/lang/reflect/Constructor;)Ljava/lang/Object;" );
739     jni.ensure_no_exception();
740     OSL_ASSERT( 0 != m_method_JNI_proxy_create );
741     // field JNI_proxy.m_receiver_handle
742     m_field_JNI_proxy_m_receiver_handle = jni->GetFieldID(
743         (jclass) jo_JNI_proxy.get(), "m_receiver_handle", "J" );
744     jni.ensure_no_exception();
745     OSL_ASSERT( 0 != m_field_JNI_proxy_m_receiver_handle );
746     // field JNI_proxy.m_td_handle
747     m_field_JNI_proxy_m_td_handle = jni->GetFieldID(
748         (jclass) jo_JNI_proxy.get(), "m_td_handle", "J" );
749     jni.ensure_no_exception();
750     OSL_ASSERT( 0 != m_field_JNI_proxy_m_td_handle );
751     // field JNI_proxy.m_type
752     m_field_JNI_proxy_m_type = jni->GetFieldID(
753         (jclass) jo_JNI_proxy.get(), "m_type", "Lcom/sun/star/uno/Type;" );
754     jni.ensure_no_exception();
755     OSL_ASSERT( 0 != m_field_JNI_proxy_m_type );
756     // field JNI_proxy.m_oid
757     m_field_JNI_proxy_m_oid = jni->GetFieldID(
758         (jclass) jo_JNI_proxy.get(), "m_oid", "Ljava/lang/String;" );
759     jni.ensure_no_exception();
760     OSL_ASSERT( 0 != m_field_JNI_proxy_m_oid );
761 
762     // get java env
763     OUString java_env_type_name( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_JAVA) );
764     JLocalAutoRef jo_java(
765         jni, ustring_to_jstring( jni, java_env_type_name.pData ) );
766     jvalue args[ 2 ];
767     args[ 0 ].l = jo_java.get();
768     args[ 1 ].l = 0;
769     jmethodID method_getEnvironment = jni->GetStaticMethodID(
770         (jclass) jo_UnoRuntime.get(), "getEnvironment",
771         "(Ljava/lang/String;Ljava/lang/Object;)"
772         "Lcom/sun/star/uno/IEnvironment;" );
773     jni.ensure_no_exception();
774     OSL_ASSERT( 0 != method_getEnvironment );
775     JLocalAutoRef jo_java_env(
776         jni, jni->CallStaticObjectMethodA(
777             (jclass) jo_UnoRuntime.get(), method_getEnvironment, args ) );
778 
779     // get com.sun.star.uno.Any.VOID
780     jfieldID field_Any_VOID = jni->GetStaticFieldID(
781         (jclass) jo_Any.get(), "VOID", "Lcom/sun/star/uno/Any;" );
782     jni.ensure_no_exception();
783     OSL_ASSERT( 0 != field_Any_VOID );
784     JLocalAutoRef jo_Any_VOID(
785         jni, jni->GetStaticObjectField(
786             (jclass) jo_Any.get(), field_Any_VOID ) );
787     // get com.sun.star.uno.Type.UNSIGNED_SHORT
788     jfieldID field_Type_UNSIGNED_SHORT = jni->GetStaticFieldID(
789         (jclass) jo_Type.get(), "UNSIGNED_SHORT", "Lcom/sun/star/uno/Type;" );
790     jni.ensure_no_exception();
791     OSL_ASSERT( 0 != field_Type_UNSIGNED_SHORT );
792     JLocalAutoRef jo_Type_UNSIGNED_SHORT(
793         jni, jni->GetStaticObjectField(
794             (jclass) jo_Type.get(), field_Type_UNSIGNED_SHORT ) );
795     // get com.sun.star.uno.Type.UNSIGNED_LONG
796     jfieldID field_Type_UNSIGNED_LONG = jni->GetStaticFieldID(
797         (jclass) jo_Type.get(), "UNSIGNED_LONG", "Lcom/sun/star/uno/Type;" );
798     jni.ensure_no_exception();
799     OSL_ASSERT( 0 != field_Type_UNSIGNED_LONG );
800     JLocalAutoRef jo_Type_UNSIGNED_LONG(
801         jni, jni->GetStaticObjectField(
802             (jclass) jo_Type.get(), field_Type_UNSIGNED_LONG ) );
803     // get com.sun.star.uno.Type.UNSIGNED_HYPER
804     jfieldID field_Type_UNSIGNED_HYPER = jni->GetStaticFieldID(
805         (jclass) jo_Type.get(), "UNSIGNED_HYPER", "Lcom/sun/star/uno/Type;" );
806     jni.ensure_no_exception();
807     OSL_ASSERT( 0 != field_Type_UNSIGNED_HYPER );
808     JLocalAutoRef jo_Type_UNSIGNED_HYPER(
809         jni, jni->GetStaticObjectField(
810             (jclass) jo_Type.get(), field_Type_UNSIGNED_HYPER ) );
811 
812     // make global refs
813     m_class_UnoRuntime =
814         (jclass) jni->NewGlobalRef( jo_UnoRuntime.get() );
815     m_class_RuntimeException =
816         (jclass) jni->NewGlobalRef( jo_RuntimeException.get() );
817     m_class_Any =
818         (jclass) jni->NewGlobalRef( jo_Any.get() );
819     m_class_Type =
820         (jclass) jni->NewGlobalRef( jo_Type.get() );
821     m_class_TypeClass =
822         (jclass) jni->NewGlobalRef( jo_TypeClass.get() );
823     m_class_JNI_proxy =
824         (jclass) jni->NewGlobalRef( jo_JNI_proxy.get() );
825 
826     m_class_Character =
827         (jclass) jni->NewGlobalRef( jo_Character.get() );
828     m_class_Boolean =
829         (jclass) jni->NewGlobalRef( jo_Boolean.get() );
830     m_class_Byte =
831         (jclass) jni->NewGlobalRef( jo_Byte.get() );
832     m_class_Short =
833         (jclass) jni->NewGlobalRef( jo_Short.get() );
834     m_class_Integer =
835         (jclass) jni->NewGlobalRef( jo_Integer.get() );
836     m_class_Long =
837         (jclass) jni->NewGlobalRef( jo_Long.get() );
838     m_class_Float =
839         (jclass) jni->NewGlobalRef( jo_Float.get() );
840     m_class_Double =
841         (jclass) jni->NewGlobalRef( jo_Double.get() );
842     m_class_String =
843         (jclass) jni->NewGlobalRef( jo_String.get() );
844     m_class_Object =
845         (jclass) jni->NewGlobalRef( jo_Object.get() );
846     m_class_Class =
847         (jclass) jni->NewGlobalRef( m_class_Class );
848 
849     m_object_Any_VOID =
850         jni->NewGlobalRef( jo_Any_VOID.get() );
851     m_object_Type_UNSIGNED_SHORT =
852         jni->NewGlobalRef( jo_Type_UNSIGNED_SHORT.get() );
853     m_object_Type_UNSIGNED_LONG =
854         jni->NewGlobalRef( jo_Type_UNSIGNED_LONG.get() );
855     m_object_Type_UNSIGNED_HYPER =
856         jni->NewGlobalRef( jo_Type_UNSIGNED_HYPER.get() );
857     m_object_java_env = jni->NewGlobalRef( jo_java_env.get() );
858 
859     try
860     {
861         css::uno::TypeDescription XInterface_td(
862             ::getCppuType(
863                 (css::uno::Reference< css::uno::XInterface > const *)0 ) );
864         m_XInterface_type_info =
865             new JNI_interface_type_info( jni, XInterface_td.get() );
866     }
867     catch (...)
868     {
869         destruct( jni_env );
870         throw;
871     }
872 }
873 
874 //______________________________________________________________________________
destruct(JNIEnv * jni_env)875 void JNI_info::destruct( JNIEnv * jni_env )
876 {
877     t_str2type::const_iterator iPos( m_type_map.begin() );
878     t_str2type::const_iterator const iEnd( m_type_map.begin() );
879     for ( ; iPos != iEnd; ++iPos )
880     {
881         iPos->second.m_info->destroy( jni_env );
882     }
883     if (0 != m_XInterface_type_info)
884     {
885         const_cast< JNI_interface_type_info * >(
886             m_XInterface_type_info )->destroy( jni_env );
887     }
888 
889     // free global refs
890     jni_env->DeleteGlobalRef( m_object_java_env );
891     jni_env->DeleteGlobalRef( m_object_Any_VOID );
892     jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_SHORT );
893     jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_LONG );
894     jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_HYPER );
895 
896     jni_env->DeleteGlobalRef( m_class_Class );
897     jni_env->DeleteGlobalRef( m_class_Object );
898     jni_env->DeleteGlobalRef( m_class_String );
899     jni_env->DeleteGlobalRef( m_class_Double );
900     jni_env->DeleteGlobalRef( m_class_Float );
901     jni_env->DeleteGlobalRef( m_class_Long );
902     jni_env->DeleteGlobalRef( m_class_Integer );
903     jni_env->DeleteGlobalRef( m_class_Short );
904     jni_env->DeleteGlobalRef( m_class_Byte );
905     jni_env->DeleteGlobalRef( m_class_Boolean );
906     jni_env->DeleteGlobalRef( m_class_Character );
907 
908     jni_env->DeleteGlobalRef( m_class_JNI_proxy );
909     jni_env->DeleteGlobalRef( m_class_RuntimeException );
910     jni_env->DeleteGlobalRef( m_class_UnoRuntime );
911     jni_env->DeleteGlobalRef( m_class_TypeClass );
912     jni_env->DeleteGlobalRef( m_class_Type );
913     jni_env->DeleteGlobalRef( m_class_Any );
914 }
915 
916 //______________________________________________________________________________
get_jni_info(rtl::Reference<jvmaccess::UnoVirtualMachine> const & uno_vm)917 JNI_info const * JNI_info::get_jni_info(
918     rtl::Reference< jvmaccess::UnoVirtualMachine > const & uno_vm )
919 {
920     // !!!no JNI_info available at JNI_context!!!
921     ::jvmaccess::VirtualMachine::AttachGuard guard(
922         uno_vm->getVirtualMachine() );
923     JNIEnv * jni_env = guard.getEnvironment();
924     JNI_context jni(
925         0, jni_env, static_cast< jobject >(uno_vm->getClassLoader()) );
926 
927     jclass jo_class;
928     jmethodID jo_forName;
929     jni.getClassForName( &jo_class, &jo_forName );
930     jni.ensure_no_exception();
931     JLocalAutoRef jo_JNI_info_holder(
932         jni,
933         jni.findClass(
934             "com.sun.star.bridges.jni_uno.JNI_info_holder", jo_class,
935             jo_forName, false ) );
936     // field JNI_info_holder.m_jni_info_handle
937     jfieldID field_s_jni_info_handle =
938         jni->GetStaticFieldID(
939             (jclass) jo_JNI_info_holder.get(), "s_jni_info_handle", "J" );
940     jni.ensure_no_exception();
941     OSL_ASSERT( 0 != field_s_jni_info_handle );
942 
943     JNI_info const * jni_info =
944         reinterpret_cast< JNI_info const * >(
945             jni->GetStaticLongField(
946                 (jclass) jo_JNI_info_holder.get(), field_s_jni_info_handle ) );
947     if (0 == jni_info) // un-initialized?
948     {
949         JNI_info * new_info = new JNI_info(
950             jni_env, static_cast< jobject >(uno_vm->getClassLoader()), jo_class,
951             jo_forName );
952 
953         ClearableMutexGuard g( Mutex::getGlobalMutex() );
954         jni_info =
955             reinterpret_cast< JNI_info const * >(
956                 jni->GetStaticLongField(
957                     (jclass) jo_JNI_info_holder.get(),
958                     field_s_jni_info_handle ) );
959         if (0 == jni_info) // still un-initialized?
960         {
961             jni->SetStaticLongField(
962                 (jclass) jo_JNI_info_holder.get(), field_s_jni_info_handle,
963                 reinterpret_cast< jlong >( new_info ) );
964             jni_info = new_info;
965         }
966         else
967         {
968             g.clear();
969             new_info->destroy( jni_env );
970         }
971     }
972 
973     return jni_info;
974 }
975 
976 }
977 
978 extern "C"
979 {
980 
981 //------------------------------------------------------------------------------
982 JNIEXPORT void
Java_com_sun_star_bridges_jni_1uno_JNI_1info_1holder_finalize__J(JNIEnv * jni_env,jobject,jlong jni_info_handle)983 JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1info_1holder_finalize__J(
984     JNIEnv * jni_env, jobject, jlong jni_info_handle )
985     SAL_THROW_EXTERN_C()
986 {
987     ::jni_uno::JNI_info * jni_info =
988           reinterpret_cast< ::jni_uno::JNI_info * >( jni_info_handle );
989     jni_info->destroy( jni_env );
990 }
991 
992 }
993