1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: javaloader.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
36 #include <osl/diagnose.h>
37 #include <osl/process.h>
39 #include <rtl/process.h>
40 #include <rtl/ustrbuf.hxx>
42 #include <uno/environment.h>
43 #include <uno/mapping.hxx>
44 #include "com/sun/star/uno/RuntimeException.hpp"
46 #include <cppuhelper/servicefactory.hxx>
53 #include <com/sun/star/java/XJavaVM.hpp>
55 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
59 #include <cppuhelper/factory.hxx>
60 #include <cppuhelper/implementationentry.hxx>
62 #include <cppuhelper/implbase2.hxx>
64 #include <com/sun/star/loader/XImplementationLoader.hpp>
65 #include <com/sun/star/lang/IllegalArgumentException.hpp>
66 #include <com/sun/star/lang/XServiceInfo.hpp>
67 #include <com/sun/star/lang/XInitialization.hpp>
68 #include <com/sun/star/registry/XRegistryKey.hpp>
70 #include "jvmaccess/unovirtualmachine.hxx"
71 #include "jvmaccess/virtualmachine.hxx"
73 namespace css
= com::sun::star
;
75 using namespace ::com::sun::star::java
;
76 using namespace ::com::sun::star::lang
;
77 using namespace ::com::sun::star::loader
;
78 using namespace ::com::sun::star::uno
;
79 using namespace ::com::sun::star::registry
;
81 using namespace ::cppu
;
82 using namespace ::rtl
;
83 using namespace ::osl
;
85 namespace stoc_javaloader
{
87 static Mutex
& getInitMutex();
89 static Sequence
< OUString
> loader_getSupportedServiceNames()
91 static Sequence
< OUString
> *pNames
= 0;
94 MutexGuard
guard( Mutex::getGlobalMutex() );
97 static Sequence
< OUString
> seqNames(2);
98 seqNames
.getArray()[0] = OUString(
99 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java") );
100 seqNames
.getArray()[1] = OUString(
101 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java2") );
108 static OUString
loader_getImplementationName()
110 static OUString
*pImplName
= 0;
113 MutexGuard
guard( Mutex::getGlobalMutex() );
116 static OUString
implName(
117 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.JavaComponentLoader" ) );
118 pImplName
= &implName
;
124 class JavaComponentLoader
: public WeakImplHelper2
<XImplementationLoader
, XServiceInfo
>
126 css::uno::Reference
<XComponentContext
> m_xComponentContext
;
127 /** Do not use m_javaLoader directly. Instead use getJavaLoader.
129 css::uno::Reference
<XImplementationLoader
> m_javaLoader
;
130 /** The retured Reference contains a null pointer if the office is not configured
133 @exception com::sun::star::uno::RuntimeException
134 If the Java implementation of the loader could not be obtained, for reasons other
135 then that java was not configured the RuntimeException is thrown.
137 const css::uno::Reference
<XImplementationLoader
> & getJavaLoader();
141 JavaComponentLoader(const css::uno::Reference
<XComponentContext
> & xCtx
)
142 throw(RuntimeException
);
143 virtual ~JavaComponentLoader() throw();
147 virtual OUString SAL_CALL
getImplementationName() throw(RuntimeException
);
148 virtual sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
)
149 throw(RuntimeException
);
150 virtual Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
151 throw(RuntimeException
);
153 // XImplementationLoader
154 virtual css::uno::Reference
<XInterface
> SAL_CALL
activate(
155 const OUString
& implementationName
, const OUString
& implementationLoaderUrl
,
156 const OUString
& locationUrl
, const css::uno::Reference
<XRegistryKey
>& xKey
)
157 throw(CannotActivateFactoryException
, RuntimeException
);
158 virtual sal_Bool SAL_CALL
writeRegistryInfo(
159 const css::uno::Reference
<XRegistryKey
>& xKey
,
160 const OUString
& implementationLoaderUrl
, const OUString
& locationUrl
)
161 throw(CannotRegisterImplementationException
, RuntimeException
);
164 const css::uno::Reference
<XImplementationLoader
> & JavaComponentLoader::getJavaLoader()
166 MutexGuard
aGuard(getInitMutex());
168 if (m_javaLoader
.is())
171 uno_Environment
* pJava_environment
= NULL
;
172 uno_Environment
* pUno_environment
= NULL
;
173 typelib_InterfaceTypeDescription
* pType_XImplementationLoader
= 0;
176 // get a java vm, where we can create a loader
177 css::uno::Reference
<XJavaVM
> javaVM_xJavaVM(
178 m_xComponentContext
->getValueByName(
179 OUString(RTL_CONSTASCII_USTRINGPARAM(
181 "com.sun.star.java.theJavaVirtualMachine"))),
184 // Use the special protocol of XJavaVM.getJavaVM: If the passed in
185 // process ID has an extra 17th byte of value one, the returned any
186 // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of the
187 // underlying JavaVM pointer:
188 Sequence
<sal_Int8
> processID(17);
189 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8
*>(processID
.getArray()));
192 // We get a non-refcounted pointer to a jvmaccess::UnoVirtualMachine
193 // from the XJavaVM service (the pointer is guaranteed to be valid
194 // as long as our reference to the XJavaVM service lasts), and
195 // convert the non-refcounted pointer into a refcounted one
197 OSL_ENSURE(sizeof (sal_Int64
)
198 >= sizeof (jvmaccess::UnoVirtualMachine
*),
199 "Pointer cannot be represented as sal_Int64");
200 sal_Int64 nPointer
= reinterpret_cast< sal_Int64
>(
201 static_cast< jvmaccess::UnoVirtualMachine
* >(0));
202 javaVM_xJavaVM
->getJavaVM(processID
) >>= nPointer
;
203 rtl::Reference
< jvmaccess::UnoVirtualMachine
> xVirtualMachine(
204 reinterpret_cast< jvmaccess::UnoVirtualMachine
* >(nPointer
));
205 if (!xVirtualMachine
.is())
206 //throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
207 // "javaloader error - JavaVirtualMachine service could not provide a VM")),
208 // css::uno::Reference<XInterface>());
209 // We must not throw a RuntimeException, because this might end the applications.
210 // It is ok if java components
211 // are not working because the office can be installed without Java support.
212 return m_javaLoader
; // null-ref
216 jvmaccess::VirtualMachine::AttachGuard
aGuard2(
217 xVirtualMachine
->getVirtualMachine());
218 JNIEnv
* pJNIEnv
= aGuard2
.getEnvironment();
220 // instantiate the java JavaLoader
221 jclass jcClassLoader
= pJNIEnv
->FindClass("java/lang/ClassLoader");
222 if(pJNIEnv
->ExceptionOccurred())
223 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
224 "javaloader error - could not find class java/lang/ClassLoader")),
225 css::uno::Reference
<XInterface
>());
226 jmethodID jmLoadClass
= pJNIEnv
->GetMethodID(
227 jcClassLoader
, "loadClass",
228 "(Ljava/lang/String;)Ljava/lang/Class;");
229 if(pJNIEnv
->ExceptionOccurred())
230 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
231 "javaloader error - could not find method java/lang/ClassLoader.loadClass")),
232 css::uno::Reference
<XInterface
>());
234 arg
.l
= pJNIEnv
->NewStringUTF(
235 "com.sun.star.comp.loader.JavaLoader");
236 if(pJNIEnv
->ExceptionOccurred())
237 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
238 "javaloader error - could not create string")),
239 css::uno::Reference
<XInterface
>());
240 jclass jcJavaLoader
= static_cast< jclass
>(
241 pJNIEnv
->CallObjectMethodA(
242 static_cast< jobject
>(xVirtualMachine
->getClassLoader()),
244 if(pJNIEnv
->ExceptionOccurred())
245 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
246 "javaloader error - could not find class com/sun/star/comp/loader/JavaLoader")),
247 css::uno::Reference
<XInterface
>());
248 jmethodID jmJavaLoader_init
= pJNIEnv
->GetMethodID(jcJavaLoader
, "<init>", "()V");
249 if(pJNIEnv
->ExceptionOccurred())
250 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
251 "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")),
252 css::uno::Reference
<XInterface
>());
253 jobject joJavaLoader
= pJNIEnv
->NewObject(jcJavaLoader
, jmJavaLoader_init
);
254 if(pJNIEnv
->ExceptionOccurred())
255 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
256 "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")),
257 css::uno::Reference
<XInterface
>());
259 // map the java JavaLoader to this environment
260 OUString
sJava(RTL_CONSTASCII_USTRINGPARAM("java"));
261 uno_getEnvironment(&pJava_environment
, sJava
.pData
,
262 xVirtualMachine
.get());
263 if(!pJava_environment
)
264 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
265 "javaloader error - no Java environment available")), css::uno::Reference
<XInterface
>());
267 // why is there no convinient contructor?
268 OUString
sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME
));
269 uno_getEnvironment(&pUno_environment
, sCppu_current_lb_name
.pData
, NULL
);
270 if(!pUno_environment
)
271 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
272 "javaloader error - no C++ environment available")), css::uno::Reference
<XInterface
>());
274 Mapping
java_curr(pJava_environment
, pUno_environment
);
276 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
277 "javaloader error - no mapping from java to C++ ")), css::uno::Reference
<XInterface
>());
279 // release java environment
280 pJava_environment
->release(pJava_environment
);
281 pJava_environment
= NULL
;
283 // release uno environment
284 pUno_environment
->release(pUno_environment
);
285 pUno_environment
= NULL
;
287 getCppuType((css::uno::Reference
<XImplementationLoader
> *) 0).
288 getDescription((typelib_TypeDescription
**) & pType_XImplementationLoader
);
289 if(!pType_XImplementationLoader
)
290 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
291 "javaloader error - no type information for XImplementationLoader")),
292 css::uno::Reference
<XInterface
>());
294 m_javaLoader
= css::uno::Reference
<XImplementationLoader
>(reinterpret_cast<XImplementationLoader
*>(
295 java_curr
.mapInterface(joJavaLoader
, pType_XImplementationLoader
)));
296 pJNIEnv
->DeleteLocalRef( joJavaLoader
);
297 if(!m_javaLoader
.is())
298 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
299 "javaloader error - mapping of java XImplementationLoader to c++ failed")),
300 css::uno::Reference
<XInterface
>());
302 typelib_typedescription_release(reinterpret_cast<typelib_TypeDescription
*>(pType_XImplementationLoader
));
303 pType_XImplementationLoader
= NULL
;
305 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException
&)
307 throw RuntimeException(
308 OUString(RTL_CONSTASCII_USTRINGPARAM(
309 "jvmaccess::VirtualMachine::AttachGuard"
310 "::CreationException")),0);
313 // set the service manager at the javaloader
314 css::uno::Reference
<XInitialization
> javaLoader_XInitialization(m_javaLoader
, UNO_QUERY
);
315 if(!javaLoader_XInitialization
.is())
316 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
317 "javaloader error - initialization of java javaloader failed, no XInitialization")),
318 css::uno::Reference
<XInterface
>());
321 any
<<= css::uno::Reference
<XMultiComponentFactory
>(
322 m_xComponentContext
->getServiceManager());
324 javaLoader_XInitialization
->initialize(Sequence
<Any
>(&any
, 1));
326 catch(RuntimeException
&) {
327 if(pJava_environment
)
328 pJava_environment
->release(pJava_environment
);
331 pUno_environment
->release(pUno_environment
);
333 if(pType_XImplementationLoader
)
334 typelib_typedescription_release(
335 reinterpret_cast<typelib_TypeDescription
*>(pType_XImplementationLoader
));
338 OSL_TRACE("javaloader.cxx: mapped javaloader - 0x%x", m_javaLoader
.get());
342 JavaComponentLoader::JavaComponentLoader(const css::uno::Reference
<XComponentContext
> & xCtx
) throw(RuntimeException
) :
343 m_xComponentContext(xCtx
)
349 JavaComponentLoader::~JavaComponentLoader() throw()
354 OUString SAL_CALL
JavaComponentLoader::getImplementationName()
355 throw(::com::sun::star::uno::RuntimeException
)
357 return loader_getImplementationName();
360 sal_Bool SAL_CALL
JavaComponentLoader::supportsService(const OUString
& ServiceName
)
361 throw(::com::sun::star::uno::RuntimeException
)
363 sal_Bool bSupport
= sal_False
;
365 Sequence
<OUString
> aSNL
= getSupportedServiceNames();
366 const OUString
* pArray
= aSNL
.getArray();
367 for(sal_Int32 i
= 0; i
< aSNL
.getLength() && !bSupport
; ++ i
)
368 bSupport
= pArray
[i
] == ServiceName
;
373 Sequence
<OUString
> SAL_CALL
JavaComponentLoader::getSupportedServiceNames()
374 throw(::com::sun::star::uno::RuntimeException
)
376 return loader_getSupportedServiceNames();
381 // XImplementationLoader
382 sal_Bool SAL_CALL
JavaComponentLoader::writeRegistryInfo(
383 const css::uno::Reference
<XRegistryKey
> & xKey
, const OUString
& blabla
,
384 const OUString
& rLibName
)
385 throw(CannotRegisterImplementationException
, RuntimeException
)
387 const css::uno::Reference
<XImplementationLoader
> & loader
= getJavaLoader();
389 return loader
->writeRegistryInfo(xKey
, blabla
, rLibName
);
391 throw CannotRegisterImplementationException(
392 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL
);
396 css::uno::Reference
<XInterface
> SAL_CALL
JavaComponentLoader::activate(
397 const OUString
& rImplName
, const OUString
& blabla
, const OUString
& rLibName
,
398 const css::uno::Reference
<XRegistryKey
> & xKey
)
399 throw(CannotActivateFactoryException
, RuntimeException
)
401 const css::uno::Reference
<XImplementationLoader
> & loader
= getJavaLoader();
403 return loader
->activate(rImplName
, blabla
, rLibName
, xKey
);
405 throw CannotActivateFactoryException(
406 OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL
);
409 static Mutex
& getInitMutex()
411 static Mutex
* pMutex
= 0;
414 MutexGuard
guard( Mutex::getGlobalMutex() );
424 css::uno::Reference
<XInterface
> SAL_CALL
JavaComponentLoader_CreateInstance(const css::uno::Reference
<XComponentContext
> & xCtx
) throw(Exception
)
426 css::uno::Reference
<XInterface
> xRet
;
429 MutexGuard
guard( getInitMutex() );
430 // The javaloader is never destroyed and there can be only one!
431 // Note that the first context wins ....
432 static css::uno::Reference
< XInterface
> *pStaticRef
= 0;
439 xRet
= *new JavaComponentLoader(xCtx
);
440 pStaticRef
= new css::uno::Reference
< XInterface
> ( xRet
);
443 catch(RuntimeException
& runtimeException
) {
444 OString message
= OUStringToOString(runtimeException
.Message
, RTL_TEXTENCODING_ASCII_US
);
445 osl_trace("javaloader - could not init javaloader cause of %s", message
.getStr());
455 using namespace stoc_javaloader
;
457 static struct ImplementationEntry g_entries
[] =
460 JavaComponentLoader_CreateInstance
, loader_getImplementationName
,
461 loader_getSupportedServiceNames
, createSingleComponentFactory
,
469 // NOTE: component_canUnload is not exported, as the library cannot be unloaded.
471 //==================================================================================================
472 void SAL_CALL
component_getImplementationEnvironment(
473 const sal_Char
** ppEnvTypeName
, uno_Environment
** )
475 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
477 //==================================================================================================
478 sal_Bool SAL_CALL
component_writeInfo(
479 void * pServiceManager
, void * pRegistryKey
)
481 return component_writeInfoHelper( pServiceManager
, pRegistryKey
, g_entries
);
483 //==================================================================================================
484 void * SAL_CALL
component_getFactory(
485 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
487 return component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, g_entries
);