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 virtual ~JavaComponentLoader() throw(); 136 137 public: 138 // XServiceInfo 139 virtual OUString SAL_CALL getImplementationName(); 140 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName); 141 virtual Sequence<OUString> SAL_CALL getSupportedServiceNames(); 142 143 // XImplementationLoader 144 virtual css::uno::Reference<XInterface> SAL_CALL activate( 145 const OUString& implementationName, const OUString& implementationLoaderUrl, 146 const OUString& locationUrl, const css::uno::Reference<XRegistryKey>& xKey); 147 virtual sal_Bool SAL_CALL writeRegistryInfo( 148 const css::uno::Reference<XRegistryKey>& xKey, 149 const OUString& implementationLoaderUrl, const OUString& locationUrl); 150 }; 151 152 const css::uno::Reference<XImplementationLoader> & JavaComponentLoader::getJavaLoader() 153 { 154 MutexGuard aGuard(getInitMutex()); 155 156 if (m_javaLoader.is()) 157 return m_javaLoader; 158 159 uno_Environment * pJava_environment = NULL; 160 uno_Environment * pUno_environment = NULL; 161 typelib_InterfaceTypeDescription * pType_XImplementationLoader = 0; 162 163 try { 164 // get a java vm, where we can create a loader 165 css::uno::Reference<XJavaVM> javaVM_xJavaVM( 166 m_xComponentContext->getValueByName( 167 OUString(RTL_CONSTASCII_USTRINGPARAM( 168 "/singletons/" 169 "com.sun.star.java.theJavaVirtualMachine"))), 170 UNO_QUERY_THROW); 171 172 // Use the special protocol of XJavaVM.getJavaVM: If the passed in 173 // process ID has an extra 17th byte of value one, the returned any 174 // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of the 175 // underlying JavaVM pointer: 176 Sequence<sal_Int8> processID(17); 177 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8 *>(processID.getArray())); 178 processID[16] = 1; 179 180 // We get a non-refcounted pointer to a jvmaccess::UnoVirtualMachine 181 // from the XJavaVM service (the pointer is guaranteed to be valid 182 // as long as our reference to the XJavaVM service lasts), and 183 // convert the non-refcounted pointer into a refcounted one 184 // immediately: 185 OSL_ENSURE(sizeof (sal_Int64) 186 >= sizeof (jvmaccess::UnoVirtualMachine *), 187 "Pointer cannot be represented as sal_Int64"); 188 sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( 189 static_cast< jvmaccess::UnoVirtualMachine * >(0)); 190 javaVM_xJavaVM->getJavaVM(processID) >>= nPointer; 191 rtl::Reference< jvmaccess::UnoVirtualMachine > xVirtualMachine( 192 reinterpret_cast< jvmaccess::UnoVirtualMachine * >(nPointer)); 193 if (!xVirtualMachine.is()) 194 //throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 195 // "javaloader error - JavaVirtualMachine service could not provide a VM")), 196 // css::uno::Reference<XInterface>()); 197 // We must not throw a RuntimeException, because this might end the applications. 198 // It is ok if java components 199 // are not working because the office can be installed without Java support. 200 return m_javaLoader; // null-ref 201 202 try 203 { 204 jvmaccess::VirtualMachine::AttachGuard aGuard2( 205 xVirtualMachine->getVirtualMachine()); 206 JNIEnv * pJNIEnv = aGuard2.getEnvironment(); 207 208 // instantiate the java JavaLoader 209 jclass jcClassLoader = pJNIEnv->FindClass("java/lang/ClassLoader"); 210 if(pJNIEnv->ExceptionOccurred()) 211 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 212 "javaloader error - could not find class java/lang/ClassLoader")), 213 css::uno::Reference<XInterface>()); 214 jmethodID jmLoadClass = pJNIEnv->GetMethodID( 215 jcClassLoader, "loadClass", 216 "(Ljava/lang/String;)Ljava/lang/Class;"); 217 if(pJNIEnv->ExceptionOccurred()) 218 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 219 "javaloader error - could not find method java/lang/ClassLoader.loadClass")), 220 css::uno::Reference<XInterface>()); 221 jvalue arg; 222 arg.l = pJNIEnv->NewStringUTF( 223 "com.sun.star.comp.loader.JavaLoader"); 224 if(pJNIEnv->ExceptionOccurred()) 225 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 226 "javaloader error - could not create string")), 227 css::uno::Reference<XInterface>()); 228 jclass jcJavaLoader = static_cast< jclass >( 229 pJNIEnv->CallObjectMethodA( 230 static_cast< jobject >(xVirtualMachine->getClassLoader()), 231 jmLoadClass, &arg)); 232 if(pJNIEnv->ExceptionOccurred()) 233 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 234 "javaloader error - could not find class com/sun/star/comp/loader/JavaLoader")), 235 css::uno::Reference<XInterface>()); 236 jmethodID jmJavaLoader_init = pJNIEnv->GetMethodID(jcJavaLoader, "<init>", "()V"); 237 if(pJNIEnv->ExceptionOccurred()) 238 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 239 "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")), 240 css::uno::Reference<XInterface>()); 241 jobject joJavaLoader = pJNIEnv->NewObject(jcJavaLoader, jmJavaLoader_init); 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 247 // map the java JavaLoader to this environment 248 OUString sJava(RTL_CONSTASCII_USTRINGPARAM("java")); 249 uno_getEnvironment(&pJava_environment, sJava.pData, 250 xVirtualMachine.get()); 251 if(!pJava_environment) 252 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 253 "javaloader error - no Java environment available")), css::uno::Reference<XInterface>()); 254 255 // why is there no convenient constructor? 256 OUString sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)); 257 uno_getEnvironment(&pUno_environment, sCppu_current_lb_name.pData, NULL); 258 if(!pUno_environment) 259 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 260 "javaloader error - no C++ environment available")), css::uno::Reference<XInterface>()); 261 262 Mapping java_curr(pJava_environment, pUno_environment); 263 if(!java_curr.is()) 264 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 265 "javaloader error - no mapping from java to C++ ")), css::uno::Reference<XInterface>()); 266 267 // release java environment 268 pJava_environment->release(pJava_environment); 269 pJava_environment = NULL; 270 271 // release uno environment 272 pUno_environment->release(pUno_environment); 273 pUno_environment = NULL; 274 275 getCppuType((css::uno::Reference<XImplementationLoader> *) 0). 276 getDescription((typelib_TypeDescription **) & pType_XImplementationLoader); 277 if(!pType_XImplementationLoader) 278 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 279 "javaloader error - no type information for XImplementationLoader")), 280 css::uno::Reference<XInterface>()); 281 282 m_javaLoader = css::uno::Reference<XImplementationLoader>(reinterpret_cast<XImplementationLoader *>( 283 java_curr.mapInterface(joJavaLoader, pType_XImplementationLoader))); 284 pJNIEnv->DeleteLocalRef( joJavaLoader ); 285 if(!m_javaLoader.is()) 286 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 287 "javaloader error - mapping of java XImplementationLoader to c++ failed")), 288 css::uno::Reference<XInterface>()); 289 290 typelib_typedescription_release(reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); 291 pType_XImplementationLoader = NULL; 292 } 293 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) 294 { 295 throw RuntimeException( 296 OUString(RTL_CONSTASCII_USTRINGPARAM( 297 "jvmaccess::VirtualMachine::AttachGuard" 298 "::CreationException")),0); 299 } 300 301 // set the service manager at the javaloader 302 css::uno::Reference<XInitialization> javaLoader_XInitialization(m_javaLoader, UNO_QUERY); 303 if(!javaLoader_XInitialization.is()) 304 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( 305 "javaloader error - initialization of java javaloader failed, no XInitialization")), 306 css::uno::Reference<XInterface>()); 307 308 Any any; 309 any <<= css::uno::Reference<XMultiComponentFactory>( 310 m_xComponentContext->getServiceManager()); 311 312 javaLoader_XInitialization->initialize(Sequence<Any>(&any, 1)); 313 } 314 catch(RuntimeException &) { 315 if(pJava_environment) 316 pJava_environment->release(pJava_environment); 317 318 if(pUno_environment) 319 pUno_environment->release(pUno_environment); 320 321 if(pType_XImplementationLoader) 322 typelib_typedescription_release( 323 reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); 324 throw; 325 } 326 OSL_TRACE("javaloader.cxx: mapped javaloader - 0x%x", m_javaLoader.get()); 327 return m_javaLoader; 328 } 329 330 JavaComponentLoader::JavaComponentLoader(const css::uno::Reference<XComponentContext> & xCtx) : 331 m_xComponentContext(xCtx) 332 333 { 334 335 } 336 337 JavaComponentLoader::~JavaComponentLoader() throw() 338 { 339 } 340 341 // XServiceInfo 342 OUString SAL_CALL JavaComponentLoader::getImplementationName() 343 { 344 return loader_getImplementationName(); 345 } 346 347 sal_Bool SAL_CALL JavaComponentLoader::supportsService(const OUString & ServiceName) 348 { 349 sal_Bool bSupport = sal_False; 350 351 Sequence<OUString> aSNL = getSupportedServiceNames(); 352 const OUString * pArray = aSNL.getArray(); 353 for(sal_Int32 i = 0; i < aSNL.getLength() && !bSupport; ++ i) 354 bSupport = pArray[i] == ServiceName; 355 356 return bSupport; 357 } 358 359 Sequence<OUString> SAL_CALL JavaComponentLoader::getSupportedServiceNames() 360 { 361 return loader_getSupportedServiceNames(); 362 } 363 364 365 366 // XImplementationLoader 367 sal_Bool SAL_CALL JavaComponentLoader::writeRegistryInfo( 368 const css::uno::Reference<XRegistryKey> & xKey, const OUString & blabla, 369 const OUString & rLibName) 370 { 371 const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); 372 if (loader.is()) 373 return loader->writeRegistryInfo(xKey, blabla, rLibName); 374 else 375 throw CannotRegisterImplementationException( 376 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); 377 } 378 379 380 css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader::activate( 381 const OUString & rImplName, const OUString & blabla, const OUString & rLibName, 382 const css::uno::Reference<XRegistryKey> & xKey) 383 { 384 const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); 385 if (loader.is()) 386 return loader->activate(rImplName, blabla, rLibName, xKey); 387 else 388 throw CannotActivateFactoryException( 389 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); 390 } 391 392 static Mutex & getInitMutex() 393 { 394 static Mutex * pMutex = 0; 395 if( ! pMutex ) 396 { 397 MutexGuard guard( Mutex::getGlobalMutex() ); 398 if( ! pMutex ) 399 { 400 static Mutex mutex; 401 pMutex = &mutex; 402 } 403 } 404 return *pMutex; 405 } 406 407 css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader_CreateInstance(const css::uno::Reference<XComponentContext> & xCtx) 408 { 409 css::uno::Reference<XInterface> xRet; 410 411 try { 412 MutexGuard guard( getInitMutex() ); 413 // The javaloader is never destroyed and there can be only one! 414 // Note that the first context wins .... 415 static css::uno::Reference< XInterface > *pStaticRef = 0; 416 if( pStaticRef ) 417 { 418 xRet = *pStaticRef; 419 } 420 else 421 { 422 xRet = *new JavaComponentLoader(xCtx); 423 pStaticRef = new css::uno::Reference< XInterface > ( xRet ); 424 } 425 } 426 catch(RuntimeException & runtimeException) { 427 OString message = OUStringToOString(runtimeException.Message, RTL_TEXTENCODING_ASCII_US); 428 osl_trace("javaloader - could not init javaloader cause of %s", message.getStr()); 429 throw; 430 } 431 432 return xRet; 433 } 434 435 } //end namespace 436 437 438 using namespace stoc_javaloader; 439 440 static struct ImplementationEntry g_entries[] = 441 { 442 { 443 JavaComponentLoader_CreateInstance, loader_getImplementationName, 444 loader_getSupportedServiceNames, createSingleComponentFactory, 445 0 , 0 446 }, 447 { 0, 0, 0, 0, 0, 0 } 448 }; 449 450 extern "C" 451 { 452 // NOTE: component_canUnload is not exported, as the library cannot be unloaded. 453 454 //================================================================================================== 455 void SAL_CALL component_getImplementationEnvironment( 456 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 457 { 458 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 459 } 460 //================================================================================================== 461 void * SAL_CALL component_getFactory( 462 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 463 { 464 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); 465 } 466 } 467