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_stoc.hxx" 26 27 28 #include <cstdarg> 29 #include <osl/diagnose.h> 30 #include <osl/process.h> 31 32 #include <rtl/process.h> 33 #include <rtl/ustrbuf.hxx> 34 35 #include <uno/environment.h> 36 #include <uno/mapping.hxx> 37 #include "com/sun/star/uno/RuntimeException.hpp" 38 39 #include <cppuhelper/servicefactory.hxx> 40 41 #ifdef LINUX 42 #undef minor 43 #undef major 44 #endif 45 46 #include <com/sun/star/java/XJavaVM.hpp> 47 48 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 49 50 #include "jni.h" 51 52 #include <cppuhelper/factory.hxx> 53 #include <cppuhelper/implementationentry.hxx> 54 55 #include <cppuhelper/implbase2.hxx> 56 57 #include <com/sun/star/loader/XImplementationLoader.hpp> 58 #include <com/sun/star/lang/IllegalArgumentException.hpp> 59 #include <com/sun/star/lang/XServiceInfo.hpp> 60 #include <com/sun/star/lang/XInitialization.hpp> 61 #include <com/sun/star/registry/XRegistryKey.hpp> 62 63 #include "jvmaccess/unovirtualmachine.hxx" 64 #include "jvmaccess/virtualmachine.hxx" 65 66 namespace css = com::sun::star; 67 68 using namespace ::com::sun::star::java; 69 using namespace ::com::sun::star::lang; 70 using namespace ::com::sun::star::loader; 71 using namespace ::com::sun::star::uno; 72 using namespace ::com::sun::star::registry; 73 74 using namespace ::cppu; 75 using namespace ::rtl; 76 using namespace ::osl; 77 78 namespace stoc_javaloader { 79 80 static Mutex & getInitMutex(); 81 82 static Sequence< OUString > loader_getSupportedServiceNames() 83 { 84 static Sequence < OUString > *pNames = 0; 85 if( ! pNames ) 86 { 87 MutexGuard guard( Mutex::getGlobalMutex() ); 88 if( !pNames ) 89 { 90 static Sequence< OUString > seqNames(2); 91 seqNames.getArray()[0] = OUString( 92 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java") ); 93 seqNames.getArray()[1] = OUString( 94 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java2") ); 95 pNames = &seqNames; 96 } 97 } 98 return *pNames; 99 } 100 101 static OUString loader_getImplementationName() 102 { 103 static OUString *pImplName = 0; 104 if( ! pImplName ) 105 { 106 MutexGuard guard( Mutex::getGlobalMutex() ); 107 if( ! pImplName ) 108 { 109 static OUString implName( 110 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.JavaComponentLoader" ) ); 111 pImplName = &implName; 112 } 113 } 114 return *pImplName; 115 } 116 117 class JavaComponentLoader : public WeakImplHelper2<XImplementationLoader, XServiceInfo> 118 { 119 css::uno::Reference<XComponentContext> m_xComponentContext; 120 /** Do not use m_javaLoader directly. Instead use getJavaLoader. 121 */ 122 css::uno::Reference<XImplementationLoader> m_javaLoader; 123 /** The retured Reference contains a null pointer if the office is not configured 124 to run java. 125 126 @exception com::sun::star::uno::RuntimeException 127 If the Java implementation of the loader could not be obtained, for reasons other 128 then that java was not configured the RuntimeException is thrown. 129 */ 130 const css::uno::Reference<XImplementationLoader> & getJavaLoader(); 131 132 133 public: 134 JavaComponentLoader(const css::uno::Reference<XComponentContext> & xCtx) 135 throw(RuntimeException); 136 virtual ~JavaComponentLoader() throw(); 137 138 public: 139 // XServiceInfo 140 virtual OUString SAL_CALL getImplementationName() throw(RuntimeException); 141 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) 142 throw(RuntimeException); 143 virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() 144 throw(RuntimeException); 145 146 // XImplementationLoader 147 virtual css::uno::Reference<XInterface> SAL_CALL activate( 148 const OUString& implementationName, const OUString& implementationLoaderUrl, 149 const OUString& locationUrl, const css::uno::Reference<XRegistryKey>& xKey) 150 throw(CannotActivateFactoryException, RuntimeException); 151 virtual sal_Bool SAL_CALL writeRegistryInfo( 152 const css::uno::Reference<XRegistryKey>& xKey, 153 const OUString& implementationLoaderUrl, const OUString& locationUrl) 154 throw(CannotRegisterImplementationException, RuntimeException); 155 }; 156 157 const css::uno::Reference<XImplementationLoader> & JavaComponentLoader::getJavaLoader() 158 { 159 MutexGuard aGuard(getInitMutex()); 160 161 if (m_javaLoader.is()) 162 return m_javaLoader; 163 164 uno_Environment * pJava_environment = NULL; 165 uno_Environment * pUno_environment = NULL; 166 typelib_InterfaceTypeDescription * pType_XImplementationLoader = 0; 167 168 try { 169 // get a java vm, where we can create a loader 170 css::uno::Reference<XJavaVM> javaVM_xJavaVM( 171 m_xComponentContext->getValueByName( 172 OUString(RTL_CONSTASCII_USTRINGPARAM( 173 "/singletons/" 174 "com.sun.star.java.theJavaVirtualMachine"))), 175 UNO_QUERY_THROW); 176 177 // Use the special protocol of XJavaVM.getJavaVM: If the passed in 178 // process ID has an extra 17th byte of value one, the returned any 179 // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of the 180 // underlying JavaVM pointer: 181 Sequence<sal_Int8> processID(17); 182 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8 *>(processID.getArray())); 183 processID[16] = 1; 184 185 // We get a non-refcounted pointer to a jvmaccess::UnoVirtualMachine 186 // from the XJavaVM service (the pointer is guaranteed to be valid 187 // as long as our reference to the XJavaVM service lasts), and 188 // convert the non-refcounted pointer into a refcounted one 189 // immediately: 190 OSL_ENSURE(sizeof (sal_Int64) 191 >= sizeof (jvmaccess::UnoVirtualMachine *), 192 "Pointer cannot be represented as sal_Int64"); 193 sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( 194 static_cast< jvmaccess::UnoVirtualMachine * >(0)); 195 javaVM_xJavaVM->getJavaVM(processID) >>= nPointer; 196 rtl::Reference< jvmaccess::UnoVirtualMachine > xVirtualMachine( 197 reinterpret_cast< jvmaccess::UnoVirtualMachine * >(nPointer)); 198 if (!xVirtualMachine.is()) 199 //throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 200 // "javaloader error - JavaVirtualMachine service could not provide a VM")), 201 // css::uno::Reference<XInterface>()); 202 // We must not throw a RuntimeException, because this might end the applications. 203 // It is ok if java components 204 // are not working because the office can be installed without Java support. 205 return m_javaLoader; // null-ref 206 207 try 208 { 209 jvmaccess::VirtualMachine::AttachGuard aGuard2( 210 xVirtualMachine->getVirtualMachine()); 211 JNIEnv * pJNIEnv = aGuard2.getEnvironment(); 212 213 // instantiate the java JavaLoader 214 jclass jcClassLoader = pJNIEnv->FindClass("java/lang/ClassLoader"); 215 if(pJNIEnv->ExceptionOccurred()) 216 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 217 "javaloader error - could not find class java/lang/ClassLoader")), 218 css::uno::Reference<XInterface>()); 219 jmethodID jmLoadClass = pJNIEnv->GetMethodID( 220 jcClassLoader, "loadClass", 221 "(Ljava/lang/String;)Ljava/lang/Class;"); 222 if(pJNIEnv->ExceptionOccurred()) 223 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 224 "javaloader error - could not find method java/lang/ClassLoader.loadClass")), 225 css::uno::Reference<XInterface>()); 226 jvalue arg; 227 arg.l = pJNIEnv->NewStringUTF( 228 "com.sun.star.comp.loader.JavaLoader"); 229 if(pJNIEnv->ExceptionOccurred()) 230 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 231 "javaloader error - could not create string")), 232 css::uno::Reference<XInterface>()); 233 jclass jcJavaLoader = static_cast< jclass >( 234 pJNIEnv->CallObjectMethodA( 235 static_cast< jobject >(xVirtualMachine->getClassLoader()), 236 jmLoadClass, &arg)); 237 if(pJNIEnv->ExceptionOccurred()) 238 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 239 "javaloader error - could not find class com/sun/star/comp/loader/JavaLoader")), 240 css::uno::Reference<XInterface>()); 241 jmethodID jmJavaLoader_init = pJNIEnv->GetMethodID(jcJavaLoader, "<init>", "()V"); 242 if(pJNIEnv->ExceptionOccurred()) 243 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 244 "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")), 245 css::uno::Reference<XInterface>()); 246 jobject joJavaLoader = pJNIEnv->NewObject(jcJavaLoader, jmJavaLoader_init); 247 if(pJNIEnv->ExceptionOccurred()) 248 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 249 "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")), 250 css::uno::Reference<XInterface>()); 251 252 // map the java JavaLoader to this environment 253 OUString sJava(RTL_CONSTASCII_USTRINGPARAM("java")); 254 uno_getEnvironment(&pJava_environment, sJava.pData, 255 xVirtualMachine.get()); 256 if(!pJava_environment) 257 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 258 "javaloader error - no Java environment available")), css::uno::Reference<XInterface>()); 259 260 // why is there no convinient contructor? 261 OUString sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)); 262 uno_getEnvironment(&pUno_environment, sCppu_current_lb_name.pData, NULL); 263 if(!pUno_environment) 264 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 265 "javaloader error - no C++ environment available")), css::uno::Reference<XInterface>()); 266 267 Mapping java_curr(pJava_environment, pUno_environment); 268 if(!java_curr.is()) 269 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 270 "javaloader error - no mapping from java to C++ ")), css::uno::Reference<XInterface>()); 271 272 // release java environment 273 pJava_environment->release(pJava_environment); 274 pJava_environment = NULL; 275 276 // release uno environment 277 pUno_environment->release(pUno_environment); 278 pUno_environment = NULL; 279 280 getCppuType((css::uno::Reference<XImplementationLoader> *) 0). 281 getDescription((typelib_TypeDescription **) & pType_XImplementationLoader); 282 if(!pType_XImplementationLoader) 283 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 284 "javaloader error - no type information for XImplementationLoader")), 285 css::uno::Reference<XInterface>()); 286 287 m_javaLoader = css::uno::Reference<XImplementationLoader>(reinterpret_cast<XImplementationLoader *>( 288 java_curr.mapInterface(joJavaLoader, pType_XImplementationLoader))); 289 pJNIEnv->DeleteLocalRef( joJavaLoader ); 290 if(!m_javaLoader.is()) 291 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 292 "javaloader error - mapping of java XImplementationLoader to c++ failed")), 293 css::uno::Reference<XInterface>()); 294 295 typelib_typedescription_release(reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); 296 pType_XImplementationLoader = NULL; 297 } 298 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) 299 { 300 throw RuntimeException( 301 OUString(RTL_CONSTASCII_USTRINGPARAM( 302 "jvmaccess::VirtualMachine::AttachGuard" 303 "::CreationException")),0); 304 } 305 306 // set the service manager at the javaloader 307 css::uno::Reference<XInitialization> javaLoader_XInitialization(m_javaLoader, UNO_QUERY); 308 if(!javaLoader_XInitialization.is()) 309 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 310 "javaloader error - initialization of java javaloader failed, no XInitialization")), 311 css::uno::Reference<XInterface>()); 312 313 Any any; 314 any <<= css::uno::Reference<XMultiComponentFactory>( 315 m_xComponentContext->getServiceManager()); 316 317 javaLoader_XInitialization->initialize(Sequence<Any>(&any, 1)); 318 } 319 catch(RuntimeException &) { 320 if(pJava_environment) 321 pJava_environment->release(pJava_environment); 322 323 if(pUno_environment) 324 pUno_environment->release(pUno_environment); 325 326 if(pType_XImplementationLoader) 327 typelib_typedescription_release( 328 reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); 329 throw; 330 } 331 OSL_TRACE("javaloader.cxx: mapped javaloader - 0x%x", m_javaLoader.get()); 332 return m_javaLoader; 333 } 334 335 JavaComponentLoader::JavaComponentLoader(const css::uno::Reference<XComponentContext> & xCtx) throw(RuntimeException) : 336 m_xComponentContext(xCtx) 337 338 { 339 340 } 341 342 JavaComponentLoader::~JavaComponentLoader() throw() 343 { 344 } 345 346 // XServiceInfo 347 OUString SAL_CALL JavaComponentLoader::getImplementationName() 348 throw(::com::sun::star::uno::RuntimeException) 349 { 350 return loader_getImplementationName(); 351 } 352 353 sal_Bool SAL_CALL JavaComponentLoader::supportsService(const OUString & ServiceName) 354 throw(::com::sun::star::uno::RuntimeException) 355 { 356 sal_Bool bSupport = sal_False; 357 358 Sequence<OUString> aSNL = getSupportedServiceNames(); 359 const OUString * pArray = aSNL.getArray(); 360 for(sal_Int32 i = 0; i < aSNL.getLength() && !bSupport; ++ i) 361 bSupport = pArray[i] == ServiceName; 362 363 return bSupport; 364 } 365 366 Sequence<OUString> SAL_CALL JavaComponentLoader::getSupportedServiceNames() 367 throw(::com::sun::star::uno::RuntimeException) 368 { 369 return loader_getSupportedServiceNames(); 370 } 371 372 373 374 // XImplementationLoader 375 sal_Bool SAL_CALL JavaComponentLoader::writeRegistryInfo( 376 const css::uno::Reference<XRegistryKey> & xKey, const OUString & blabla, 377 const OUString & rLibName) 378 throw(CannotRegisterImplementationException, RuntimeException) 379 { 380 const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); 381 if (loader.is()) 382 return loader->writeRegistryInfo(xKey, blabla, rLibName); 383 else 384 throw CannotRegisterImplementationException( 385 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); 386 } 387 388 389 css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader::activate( 390 const OUString & rImplName, const OUString & blabla, const OUString & rLibName, 391 const css::uno::Reference<XRegistryKey> & xKey) 392 throw(CannotActivateFactoryException, RuntimeException) 393 { 394 const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); 395 if (loader.is()) 396 return loader->activate(rImplName, blabla, rLibName, xKey); 397 else 398 throw CannotActivateFactoryException( 399 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); 400 } 401 402 static Mutex & getInitMutex() 403 { 404 static Mutex * pMutex = 0; 405 if( ! pMutex ) 406 { 407 MutexGuard guard( Mutex::getGlobalMutex() ); 408 if( ! pMutex ) 409 { 410 static Mutex mutex; 411 pMutex = &mutex; 412 } 413 } 414 return *pMutex; 415 } 416 417 css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader_CreateInstance(const css::uno::Reference<XComponentContext> & xCtx) throw(Exception) 418 { 419 css::uno::Reference<XInterface> xRet; 420 421 try { 422 MutexGuard guard( getInitMutex() ); 423 // The javaloader is never destroyed and there can be only one! 424 // Note that the first context wins .... 425 static css::uno::Reference< XInterface > *pStaticRef = 0; 426 if( pStaticRef ) 427 { 428 xRet = *pStaticRef; 429 } 430 else 431 { 432 xRet = *new JavaComponentLoader(xCtx); 433 pStaticRef = new css::uno::Reference< XInterface > ( xRet ); 434 } 435 } 436 catch(RuntimeException & runtimeException) { 437 OString message = OUStringToOString(runtimeException.Message, RTL_TEXTENCODING_ASCII_US); 438 osl_trace("javaloader - could not init javaloader cause of %s", message.getStr()); 439 throw; 440 } 441 442 return xRet; 443 } 444 445 } //end namespace 446 447 448 using namespace stoc_javaloader; 449 450 static struct ImplementationEntry g_entries[] = 451 { 452 { 453 JavaComponentLoader_CreateInstance, loader_getImplementationName, 454 loader_getSupportedServiceNames, createSingleComponentFactory, 455 0 , 0 456 }, 457 { 0, 0, 0, 0, 0, 0 } 458 }; 459 460 extern "C" 461 { 462 // NOTE: component_canUnload is not exported, as the library cannot be unloaded. 463 464 //================================================================================================== 465 void SAL_CALL component_getImplementationEnvironment( 466 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 467 { 468 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 469 } 470 //================================================================================================== 471 void * SAL_CALL component_getFactory( 472 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 473 { 474 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); 475 } 476 } 477