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