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_BASE_H 25 #define INCLUDED_JNI_BASE_H 26 27 #if defined (__SUNPRO_CC) || defined (__SUNPRO_C) 28 // workaround solaris include trouble on jumbo 29 #include <stdarg.h> 30 namespace std 31 { 32 typedef __va_list va_list; 33 } 34 #endif 35 #include <memory> 36 37 #include "jvmaccess/unovirtualmachine.hxx" 38 #include "jvmaccess/virtualmachine.hxx" 39 40 #include "osl/diagnose.h" 41 42 #include "rtl/alloc.h" 43 #include "rtl/ustring.hxx" 44 45 #include "uno/environment.h" 46 #include "typelib/typedescription.h" 47 48 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 49 50 51 namespace jni_uno 52 { 53 54 class JNI_info; 55 56 //============================================================================== 57 struct BridgeRuntimeError 58 { 59 ::rtl::OUString m_message; 60 61 inline BridgeRuntimeError( ::rtl::OUString const & message ) 62 : m_message( message ) 63 {} 64 }; 65 66 67 //============================================================================== 68 class JNI_context 69 { 70 JNI_info const * m_jni_info; 71 JNIEnv * m_env; 72 jobject m_class_loader; 73 74 JNI_context( JNI_context & ); // not impl 75 void operator = ( JNI_context ); // not impl 76 77 void java_exc_occured() const; 78 public: 79 inline explicit JNI_context( 80 JNI_info const * jni_info, JNIEnv * env, jobject class_loader ) 81 : m_jni_info( jni_info ), 82 m_env( env ), 83 m_class_loader( class_loader ) 84 {} 85 86 inline JNI_info const * get_info() const 87 { return m_jni_info; } 88 89 inline JNIEnv * operator -> () const 90 { return m_env; } 91 inline JNIEnv * get_jni_env() const 92 { return m_env; } 93 94 // does not handle exceptions, *classClass will be null if exception 95 // occurred: 96 void getClassForName(jclass * classClass, jmethodID * methodForName) const; 97 98 // if inException, does not handle exceptions, in which case returned value 99 // will be null if exception occurred: 100 jclass findClass( 101 char const * name, jclass classClass, jmethodID methodForName, 102 bool inException) const; 103 104 inline void ensure_no_exception() const; // throws BridgeRuntimeError 105 inline bool assert_no_exception() const; // asserts and clears exception 106 107 ::rtl::OUString get_stack_trace( jobject jo_exc = 0 ) const; 108 }; 109 110 //______________________________________________________________________________ 111 inline void JNI_context::ensure_no_exception() const 112 { 113 if (JNI_FALSE != m_env->ExceptionCheck()) 114 { 115 java_exc_occured(); 116 } 117 } 118 119 //______________________________________________________________________________ 120 inline bool JNI_context::assert_no_exception() const 121 { 122 if (JNI_FALSE != m_env->ExceptionCheck()) 123 { 124 m_env->ExceptionClear(); 125 OSL_ENSURE( 0, "unexpected java exception occured!" ); 126 return false; 127 } 128 return true; 129 } 130 131 132 //============================================================================== 133 class JNI_guarded_context 134 : private ::jvmaccess::VirtualMachine::AttachGuard, 135 public JNI_context 136 { 137 JNI_guarded_context( JNI_guarded_context & ); // not impl 138 void operator = ( JNI_guarded_context ); // not impl 139 140 public: 141 inline explicit JNI_guarded_context( 142 JNI_info const * jni_info, ::jvmaccess::UnoVirtualMachine * vm_access ) 143 : AttachGuard( vm_access->getVirtualMachine() ), 144 JNI_context( 145 jni_info, AttachGuard::getEnvironment(), 146 static_cast< jobject >(vm_access->getClassLoader()) ) 147 {} 148 }; 149 150 151 //============================================================================== 152 class JLocalAutoRef 153 { 154 JNI_context const & m_jni; 155 jobject m_jo; 156 157 public: 158 inline JLocalAutoRef( JNI_context const & jni ) 159 : m_jni( jni ), 160 m_jo( 0 ) 161 {} 162 inline explicit JLocalAutoRef( JNI_context const & jni, jobject jo ) 163 : m_jni( jni ), 164 m_jo( jo ) 165 {} 166 inline JLocalAutoRef( JLocalAutoRef & auto_ref ); 167 inline ~JLocalAutoRef() SAL_THROW( () ); 168 169 inline jobject get() const 170 { return m_jo; } 171 inline bool is() const 172 { return (0 != m_jo); } 173 inline jobject release(); 174 inline void reset(); 175 inline void reset( jobject jo ); 176 inline JLocalAutoRef & operator = ( JLocalAutoRef & auto_ref ); 177 }; 178 179 //______________________________________________________________________________ 180 inline JLocalAutoRef::~JLocalAutoRef() SAL_THROW( () ) 181 { 182 if (0 != m_jo) 183 m_jni->DeleteLocalRef( m_jo ); 184 } 185 186 //______________________________________________________________________________ 187 inline JLocalAutoRef::JLocalAutoRef( JLocalAutoRef & auto_ref ) 188 : m_jni( auto_ref.m_jni ), 189 m_jo( auto_ref.m_jo ) 190 { 191 auto_ref.m_jo = 0; 192 } 193 194 //______________________________________________________________________________ 195 inline jobject JLocalAutoRef::release() 196 { 197 jobject jo = m_jo; 198 m_jo = 0; 199 return jo; 200 } 201 202 //______________________________________________________________________________ 203 inline void JLocalAutoRef::reset() 204 { 205 if (0 != m_jo) 206 m_jni->DeleteLocalRef( m_jo ); 207 m_jo = 0; 208 } 209 210 //______________________________________________________________________________ 211 inline void JLocalAutoRef::reset( jobject jo ) 212 { 213 if (jo != m_jo) 214 { 215 if (0 != m_jo) 216 m_jni->DeleteLocalRef( m_jo ); 217 m_jo = jo; 218 } 219 } 220 221 //______________________________________________________________________________ 222 inline JLocalAutoRef & JLocalAutoRef::operator = ( JLocalAutoRef & auto_ref ) 223 { 224 OSL_ASSERT( m_jni.get_jni_env() == auto_ref.m_jni.get_jni_env() ); 225 reset( auto_ref.m_jo ); 226 auto_ref.m_jo = 0; 227 return *this; 228 } 229 230 231 //============================================================================== 232 struct rtl_mem 233 { 234 inline static void * operator new ( size_t nSize ) 235 { return rtl_allocateMemory( nSize ); } 236 inline static void operator delete ( void * mem ) 237 { if (mem) rtl_freeMemory( mem ); } 238 inline static void * operator new ( size_t, void * mem ) 239 { return mem; } 240 inline static void operator delete ( void *, void * ) 241 {} 242 243 static inline ::std::auto_ptr< rtl_mem > allocate( ::std::size_t bytes ); 244 }; 245 246 //______________________________________________________________________________ 247 inline ::std::auto_ptr< rtl_mem > rtl_mem::allocate( ::std::size_t bytes ) 248 { 249 void * p = rtl_allocateMemory( bytes ); 250 if (0 == p) 251 throw BridgeRuntimeError( OUSTR("out of memory!") ); 252 return ::std::auto_ptr< rtl_mem >( (rtl_mem *)p ); 253 } 254 255 256 //============================================================================== 257 class TypeDescr 258 { 259 typelib_TypeDescription * m_td; 260 261 TypeDescr( TypeDescr & ); // not impl 262 void operator = ( TypeDescr ); // not impl 263 264 public: 265 inline explicit TypeDescr( typelib_TypeDescriptionReference * td_ref ); 266 inline ~TypeDescr() SAL_THROW( () ) 267 { TYPELIB_DANGER_RELEASE( m_td ); } 268 269 inline typelib_TypeDescription * get() const 270 { return m_td; } 271 }; 272 273 //______________________________________________________________________________ 274 inline TypeDescr::TypeDescr( typelib_TypeDescriptionReference * td_ref ) 275 : m_td( 0 ) 276 { 277 TYPELIB_DANGER_GET( &m_td, td_ref ); 278 if (0 == m_td) 279 { 280 throw BridgeRuntimeError( 281 OUSTR("cannot get comprehensive type description for ") + 282 ::rtl::OUString::unacquired( &td_ref->pTypeName ) ); 283 } 284 } 285 286 } 287 288 #endif 289