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