xref: /trunk/main/bridges/source/jni_uno/jni_info.h (revision 9eab2a37)
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 //------------------------------------------------------------------------------
type_equals(typelib_TypeDescriptionReference * type1,typelib_TypeDescriptionReference * type2)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 //------------------------------------------------------------------------------
is_XInterface(typelib_TypeDescriptionReference * type)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:
destructjni_uno::JNI_type_info76     inline void destruct( JNIEnv * jni_env )
77         { jni_env->DeleteGlobalRef( m_class ); }
~JNI_type_infojni_uno::JNI_type_info78     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;
JNI_type_info_holderjni_uno::JNI_type_info_holder114     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 );
~JNI_info()238     inline ~JNI_info() {}
239 };
240 
241 //______________________________________________________________________________
destroy(JNIEnv * jni_env)242 inline void JNI_info::destroy( JNIEnv * jni_env )
243 {
244     destruct( jni_env );
245     delete this;
246 }
247 
248 //______________________________________________________________________________
append_sig(::rtl::OStringBuffer * buf,typelib_TypeDescriptionReference * type,bool use_Object_for_type_XInterface,bool use_slashes)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