Bump version to 21.06.18.1
[LibreOffice.git] / stoc / source / javavm / javavm.cxx
blobbbc962c17466915d008a18641aa53b1508f9b7e2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "javavm.hxx"
23 #include "interact.hxx"
24 #include "jvmargs.hxx"
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/container/XContainer.hpp>
28 #include <com/sun/star/java/JavaNotFoundException.hpp>
29 #include <com/sun/star/java/InvalidJavaSettingsException.hpp>
30 #include <com/sun/star/java/RestartRequiredException.hpp>
31 #include <com/sun/star/java/JavaDisabledException.hpp>
32 #include <com/sun/star/java/JavaVMCreationFailureException.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/lang/IllegalArgumentException.hpp>
35 #include <com/sun/star/lang/XEventListener.hpp>
36 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
39 #include <com/sun/star/registry/XRegistryKey.hpp>
40 #include <com/sun/star/registry/XSimpleRegistry.hpp>
41 #include <com/sun/star/task/XInteractionHandler.hpp>
42 #include <com/sun/star/uno/Exception.hpp>
43 #include <com/sun/star/uno/Reference.hxx>
44 #include <com/sun/star/uno/RuntimeException.hpp>
45 #include <com/sun/star/uno/Sequence.hxx>
46 #include <com/sun/star/uno/XComponentContext.hpp>
47 #include <com/sun/star/uno/XCurrentContext.hpp>
48 #include <com/sun/star/uno/XInterface.hpp>
49 #include <com/sun/star/util/theMacroExpander.hpp>
50 #include <comphelper/propertysequence.hxx>
51 #include <comphelper/SetFlagContextHelper.hxx>
52 #include <cppuhelper/exc_hlp.hxx>
53 #include <cppuhelper/factory.hxx>
54 #include <cppuhelper/implbase.hxx>
55 #include <cppuhelper/implementationentry.hxx>
56 #include <cppuhelper/supportsservice.hxx>
57 #include <jvmaccess/classpath.hxx>
58 #include <jvmaccess/unovirtualmachine.hxx>
59 #include <jvmaccess/virtualmachine.hxx>
60 #include <rtl/process.h>
61 #include <rtl/ustring.hxx>
62 #include <sal/types.h>
63 #include <sal/log.hxx>
64 #include <tools/diagnose_ex.h>
65 #include <uno/current_context.hxx>
66 #include <jvmfwk/framework.hxx>
67 #include <i18nlangtag/languagetag.hxx>
68 #include <jni.h>
70 #include <stack>
71 #include <string.h>
72 #include <time.h>
73 #include <memory>
74 #include <vector>
76 // Properties of the javavm can be put
77 // as a comma separated list in this
78 // environment variable
79 #ifdef UNIX
80 #define TIMEZONE "MEZ"
81 #else
82 #define TIMEZONE "MET"
83 #endif
85 /* Within this implementation of the com.sun.star.java.JavaVirtualMachine
86 * service and com.sun.star.java.theJavaVirtualMachine singleton, the method
87 * com.sun.star.java.XJavaVM.getJavaVM relies on the following:
88 * 1 The string "$URE_INTERNAL_JAVA_DIR/" is expanded via the
89 * com.sun.star.util.theMacroExpander singleton into an internal (see the
90 * com.sun.star.uri.ExternalUriReferenceTranslator service), hierarchical URI
91 * reference relative to which the URE JAR files can be addressed.
92 * 2 The string "$URE_INTERNAL_JAVA_CLASSPATH" is either not expandable via the
93 * com.sun.star.util.theMacroExpander singleton
94 * (com.sun.star.lang.IllegalArgumentException), or is expanded via the
95 * com.sun.star.util.theMacroExpander singleton into a list of zero or more
96 * internal (see the com.sun.star.uri.ExternalUriReferenceTranslator service)
97 * URIs, where any space characters (U+0020) are ignored (and, in particular,
98 * separate adjacent URIs).
99 * If either of these requirements is not met, getJavaVM raises a
100 * com.sun.star.uno.RuntimeException.
103 using stoc_javavm::JavaVirtualMachine;
105 namespace {
108 class NoJavaIniException: public css::uno::Exception
112 typedef std::stack< jvmaccess::VirtualMachine::AttachGuard * > GuardStack;
114 extern "C" {
116 static void destroyAttachGuards(void * pData)
118 GuardStack * pStack = static_cast< GuardStack * >(pData);
119 if (pStack != nullptr)
121 while (!pStack->empty())
123 delete pStack->top();
124 pStack->pop();
126 delete pStack;
132 bool askForRetry(css::uno::Any const & rException)
134 css::uno::Reference< css::uno::XCurrentContext > xContext(
135 css::uno::getCurrentContext());
136 if (xContext.is())
138 css::uno::Reference< css::task::XInteractionHandler > xHandler;
139 xContext->getValueByName("java-vm.interaction-handler")
140 >>= xHandler;
141 if (xHandler.is())
143 rtl::Reference< stoc_javavm::InteractionRequest > xRequest(
144 new stoc_javavm::InteractionRequest(rException));
145 xHandler->handle(xRequest.get());
146 return xRequest->retry();
149 return false;
152 // Only gets the properties if the "Proxy Server" entry in the option dialog is
153 // set to manual (i.e. not to none)
154 /// @throws css::uno::Exception
155 void getINetPropsFromConfig(stoc_javavm::JVM * pjvm,
156 const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr,
157 const css::uno::Reference<css::uno::XComponentContext> &xCtx )
159 css::uno::Reference<css::uno::XInterface> xConfRegistry = xSMgr->createInstanceWithContext(
160 "com.sun.star.configuration.ConfigurationRegistry",
161 xCtx );
162 if(!xConfRegistry.is()) throw css::uno::RuntimeException("javavm.cxx: couldn't get ConfigurationRegistry", nullptr);
164 css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple(xConfRegistry, css::uno::UNO_QUERY_THROW);
165 xConfRegistry_simple->open("org.openoffice.Inet", true, false);
166 css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey = xConfRegistry_simple->getRootKey();
168 // if ooInetProxyType is not 0 then read the settings
169 css::uno::Reference<css::registry::XRegistryKey> proxyEnable= xRegistryRootKey->openKey("Settings/ooInetProxyType");
170 if( proxyEnable.is() && 0 != proxyEnable->getLongValue())
172 // read ftp proxy name
173 css::uno::Reference<css::registry::XRegistryKey> ftpProxy_name = xRegistryRootKey->openKey("Settings/ooInetFTPProxyName");
174 if(ftpProxy_name.is() && !ftpProxy_name->getStringValue().isEmpty()) {
175 OUString ftpHost = "ftp.proxyHost=" + ftpProxy_name->getStringValue();
177 // read ftp proxy port
178 css::uno::Reference<css::registry::XRegistryKey> ftpProxy_port = xRegistryRootKey->openKey("Settings/ooInetFTPProxyPort");
179 if(ftpProxy_port.is() && ftpProxy_port->getLongValue()) {
180 OUString ftpPort = "ftp.proxyPort=" + OUString::number(ftpProxy_port->getLongValue());
182 pjvm->pushProp(ftpHost);
183 pjvm->pushProp(ftpPort);
187 // read http proxy name
188 css::uno::Reference<css::registry::XRegistryKey> httpProxy_name = xRegistryRootKey->openKey("Settings/ooInetHTTPProxyName");
189 if(httpProxy_name.is() && !httpProxy_name->getStringValue().isEmpty()) {
190 OUString httpHost = "http.proxyHost=" + httpProxy_name->getStringValue();
192 // read http proxy port
193 css::uno::Reference<css::registry::XRegistryKey> httpProxy_port = xRegistryRootKey->openKey("Settings/ooInetHTTPProxyPort");
194 if(httpProxy_port.is() && httpProxy_port->getLongValue()) {
195 OUString httpPort = "http.proxyPort=" + OUString::number(httpProxy_port->getLongValue());
197 pjvm->pushProp(httpHost);
198 pjvm->pushProp(httpPort);
202 // read https proxy name
203 css::uno::Reference<css::registry::XRegistryKey> httpsProxy_name = xRegistryRootKey->openKey("Settings/ooInetHTTPSProxyName");
204 if(httpsProxy_name.is() && !httpsProxy_name->getStringValue().isEmpty()) {
205 OUString httpsHost = "https.proxyHost=" + httpsProxy_name->getStringValue();
207 // read https proxy port
208 css::uno::Reference<css::registry::XRegistryKey> httpsProxy_port = xRegistryRootKey->openKey("Settings/ooInetHTTPSProxyPort");
209 if(httpsProxy_port.is() && httpsProxy_port->getLongValue()) {
210 OUString httpsPort = "https.proxyPort=" + OUString::number(httpsProxy_port->getLongValue());
212 pjvm->pushProp(httpsHost);
213 pjvm->pushProp(httpsPort);
217 // read nonProxyHosts
218 css::uno::Reference<css::registry::XRegistryKey> nonProxies_name = xRegistryRootKey->openKey("Settings/ooInetNoProxy");
219 if(nonProxies_name.is() && !nonProxies_name->getStringValue().isEmpty()) {
220 OUString value = nonProxies_name->getStringValue();
221 // replace the separator ";" by "|"
222 value = value.replace(';', '|');
224 OUString httpNonProxyHosts = "http.nonProxyHosts=" + value;
225 OUString ftpNonProxyHosts = "ftp.nonProxyHosts=" + value;
227 pjvm->pushProp(httpNonProxyHosts);
228 pjvm->pushProp(ftpNonProxyHosts);
231 xConfRegistry_simple->close();
234 /// @throws css::uno::Exception
235 void getDefaultLocaleFromConfig(
236 stoc_javavm::JVM * pjvm,
237 const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr,
238 const css::uno::Reference<css::uno::XComponentContext> &xCtx )
240 css::uno::Reference<css::uno::XInterface> xConfRegistry =
241 xSMgr->createInstanceWithContext( "com.sun.star.configuration.ConfigurationRegistry", xCtx );
242 if(!xConfRegistry.is())
243 throw css::uno::RuntimeException(
244 "javavm.cxx: couldn't get ConfigurationRegistry", nullptr);
246 css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple(
247 xConfRegistry, css::uno::UNO_QUERY_THROW);
248 xConfRegistry_simple->open("org.openoffice.Setup", true, false);
249 css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey = xConfRegistry_simple->getRootKey();
251 // Since 1.7 Java knows DISPLAY and FORMAT locales, which match our UI and
252 // system locale. See
253 // http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/file/569b1b644416/src/share/classes/java/util/Locale.java
254 // https://docs.oracle.com/javase/tutorial/i18n/locale/scope.html
255 // https://docs.oracle.com/javase/7/docs/api/java/util/Locale.html
257 // Read UI language/locale.
258 css::uno::Reference<css::registry::XRegistryKey> xUILocale = xRegistryRootKey->openKey("L10N/ooLocale");
259 if(xUILocale.is() && !xUILocale->getStringValue().isEmpty()) {
260 LanguageTag aLanguageTag( xUILocale->getStringValue());
261 OUString language;
262 OUString script;
263 OUString country;
264 // Java knows nothing but plain old ISO codes, unless Locale.Builder or
265 // Locale.forLanguageTag() are used, or non-standardized variant field
266 // content which we ignore.
267 aLanguageTag.getIsoLanguageScriptCountry( language, script, country);
269 if(!language.isEmpty()) {
270 OUString prop = "user.language=" + language;
271 pjvm->pushProp(prop);
274 // As of Java 7 also script is supported.
275 if(!script.isEmpty()) {
276 OUString prop = "user.script=" + script;
277 pjvm->pushProp(prop);
280 if(!country.isEmpty()) {
281 OUString prop = "user.country=" + country;
282 pjvm->pushProp(prop);
285 // Java 7 DISPLAY category is our UI language/locale.
286 if(!language.isEmpty()) {
287 OUString prop = "user.language.display=" + language;
288 pjvm->pushProp(prop);
291 if(!script.isEmpty()) {
292 OUString prop = "user.script.display=" + script;
293 pjvm->pushProp(prop);
296 if(!country.isEmpty()) {
297 OUString prop = "user.country.display=" + country;
298 pjvm->pushProp(prop);
302 // Read system locale.
303 css::uno::Reference<css::registry::XRegistryKey> xLocale = xRegistryRootKey->openKey("L10N/ooSetupSystemLocale");
304 if(xLocale.is() && !xLocale->getStringValue().isEmpty()) {
305 LanguageTag aLanguageTag( xLocale->getStringValue());
306 OUString language;
307 OUString script;
308 OUString country;
309 // Java knows nothing but plain old ISO codes, unless Locale.Builder or
310 // Locale.forLanguageTag() are used, or non-standardized variant field
311 // content which we ignore.
312 aLanguageTag.getIsoLanguageScriptCountry( language, script, country);
314 // Java 7 FORMAT category is our system locale.
315 if(!language.isEmpty()) {
316 OUString prop = "user.language.format=" + language;
317 pjvm->pushProp(prop);
320 if(!script.isEmpty()) {
321 OUString prop = "user.script.format=" + script;
322 pjvm->pushProp(prop);
325 if(!country.isEmpty()) {
326 OUString prop = "user.country.format=" + country;
327 pjvm->pushProp(prop);
331 xConfRegistry_simple->close();
334 /// @throws css::uno::Exception
335 void getJavaPropsFromSafetySettings(
336 stoc_javavm::JVM * pjvm,
337 const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr,
338 const css::uno::Reference<css::uno::XComponentContext> &xCtx)
340 css::uno::Reference<css::uno::XInterface> xConfRegistry =
341 xSMgr->createInstanceWithContext(
342 "com.sun.star.configuration.ConfigurationRegistry",
343 xCtx);
344 if(!xConfRegistry.is())
345 throw css::uno::RuntimeException(
346 "javavm.cxx: couldn't get ConfigurationRegistry", nullptr);
348 css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple(
349 xConfRegistry, css::uno::UNO_QUERY_THROW);
350 xConfRegistry_simple->open(
351 "org.openoffice.Office.Java",
352 true, false);
353 css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey =
354 xConfRegistry_simple->getRootKey();
356 if (xRegistryRootKey.is())
358 css::uno::Reference<css::registry::XRegistryKey> key_NetAccess= xRegistryRootKey->openKey("VirtualMachine/NetAccess");
359 if (key_NetAccess.is())
361 sal_Int32 val= key_NetAccess->getLongValue();
362 OUString sVal;
363 switch( val)
365 case 0: sVal = "host";
366 break;
367 case 1: sVal = "unrestricted";
368 break;
369 case 3: sVal = "none";
370 break;
372 OUString sProperty = "appletviewer.security.mode=" + sVal;
373 pjvm->pushProp(sProperty);
375 css::uno::Reference<css::registry::XRegistryKey> key_CheckSecurity= xRegistryRootKey->openKey(
376 "VirtualMachine/Security");
377 if( key_CheckSecurity.is())
379 bool val = static_cast<bool>(key_CheckSecurity->getLongValue());
380 OUString sProperty("stardiv.security.disableSecurity=");
381 if( val)
382 sProperty += "false";
383 else
384 sProperty += "true";
385 pjvm->pushProp( sProperty);
388 xConfRegistry_simple->close();
391 void setTimeZone(stoc_javavm::JVM * pjvm) throw() {
392 /* A Bug in the Java function
393 ** struct Hjava_util_Properties * java_lang_System_initProperties(
394 ** struct Hjava_lang_System *this,
395 ** struct Hjava_util_Properties *props);
396 ** This function doesn't detect MEZ, MET or "W. Europe Standard Time"
398 struct tm *tmData;
399 time_t clock = time(nullptr);
400 tzset();
401 tmData = localtime(&clock);
402 #ifdef MACOSX
403 char * p = tmData->tm_zone;
404 #elif defined(_MSC_VER)
405 char * p = _tzname[0];
406 (void)tmData;
407 #else
408 char * p = tzname[0];
409 (void)tmData;
410 #endif
412 if (!strcmp(TIMEZONE, p))
413 pjvm->pushProp("user.timezone=ECT");
416 /// @throws css::uno::Exception
417 void initVMConfiguration(
418 stoc_javavm::JVM * pjvm,
419 const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr,
420 const css::uno::Reference<css::uno::XComponentContext > &xCtx)
422 stoc_javavm::JVM jvm;
423 try {
424 getINetPropsFromConfig(&jvm, xSMgr, xCtx);
426 catch(const css::uno::Exception &) {
427 TOOLS_INFO_EXCEPTION("stoc", "can not get INETProps");
430 try {
431 getDefaultLocaleFromConfig(&jvm, xSMgr,xCtx);
433 catch(const css::uno::Exception &) {
434 TOOLS_INFO_EXCEPTION("stoc", "can not get locale");
439 getJavaPropsFromSafetySettings(&jvm, xSMgr, xCtx);
441 catch(const css::uno::Exception &) {
442 TOOLS_INFO_EXCEPTION("stoc", "couldn't get safety settings");
445 *pjvm= jvm;
447 // rhbz#1285356, native look will be gtk2, which crashes
448 // when gtk3 is already loaded. Until there is a solution
449 // java-side force look and feel to something that doesn't
450 // crash when we are using gtk3
451 if (getenv("STOC_FORCE_SYSTEM_LAF"))
452 pjvm->pushProp("swing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel");
454 setTimeZone(pjvm);
457 class DetachCurrentThread {
458 public:
459 explicit DetachCurrentThread(JavaVM * jvm): m_jvm(jvm) {}
461 ~DetachCurrentThread() {
462 if (m_jvm->DetachCurrentThread() != 0) {
463 OSL_ASSERT(false);
467 DetachCurrentThread(const DetachCurrentThread&) = delete;
468 DetachCurrentThread& operator=(const DetachCurrentThread&) = delete;
470 private:
471 JavaVM * m_jvm;
476 JavaVirtualMachine::JavaVirtualMachine(
477 css::uno::Reference< css::uno::XComponentContext > const & rContext):
478 JavaVirtualMachine_Impl(m_aMutex),
479 m_xContext(rContext),
480 m_bDisposed(false),
481 m_pJavaVm(nullptr),
482 m_aAttachGuards(destroyAttachGuards) // TODO check for validity
485 void SAL_CALL
486 JavaVirtualMachine::initialize(css::uno::Sequence< css::uno::Any > const &
487 rArguments)
489 osl::MutexGuard aGuard(m_aMutex);
490 if (m_bDisposed)
491 throw css::lang::DisposedException(
492 "", static_cast< cppu::OWeakObject * >(this));
493 if (m_xUnoVirtualMachine.is())
494 throw css::uno::RuntimeException(
495 "bad call to initialize",
496 static_cast< cppu::OWeakObject * >(this));
497 css::beans::NamedValue val;
498 if (rArguments.getLength() == 1 && (rArguments[0] >>= val) && val.Name == "UnoVirtualMachine" )
500 OSL_ENSURE(
501 sizeof (sal_Int64) >= sizeof (jvmaccess::UnoVirtualMachine *),
502 "Pointer cannot be represented as sal_Int64");
503 sal_Int64 nPointer = reinterpret_cast< sal_Int64 >(
504 static_cast< jvmaccess::UnoVirtualMachine * >(nullptr));
505 val.Value >>= nPointer;
506 m_xUnoVirtualMachine =
507 reinterpret_cast< jvmaccess::UnoVirtualMachine * >(nPointer);
508 } else {
509 OSL_ENSURE(
510 sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *),
511 "Pointer cannot be represented as sal_Int64");
512 sal_Int64 nPointer = reinterpret_cast< sal_Int64 >(
513 static_cast< jvmaccess::VirtualMachine * >(nullptr));
514 if (rArguments.getLength() == 1)
515 rArguments[0] >>= nPointer;
516 rtl::Reference< jvmaccess::VirtualMachine > vm(
517 reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer));
518 if (vm.is()) {
519 try {
520 m_xUnoVirtualMachine = new jvmaccess::UnoVirtualMachine(vm, nullptr);
521 } catch (jvmaccess::UnoVirtualMachine::CreationException &) {
522 css::uno::Any anyEx = cppu::getCaughtException();
523 throw css::lang::WrappedTargetRuntimeException(
524 "jvmaccess::UnoVirtualMachine::CreationException",
525 static_cast< cppu::OWeakObject * >(this), anyEx );
529 if (!m_xUnoVirtualMachine.is()) {
530 throw css::lang::IllegalArgumentException(
531 "sequence of exactly one any containing either (a) a"
532 " com.sun.star.beans.NamedValue with Name"
533 " \"UnoVirtualMachine\" and Value a hyper representing a"
534 " non-null pointer to a jvmaccess:UnoVirtualMachine, or (b)"
535 " a hyper representing a non-null pointer to a"
536 " jvmaccess::VirtualMachine required",
537 static_cast< cppu::OWeakObject * >(this), 0);
539 m_xVirtualMachine = m_xUnoVirtualMachine->getVirtualMachine();
542 OUString SAL_CALL JavaVirtualMachine::getImplementationName()
544 return "com.sun.star.comp.stoc.JavaVirtualMachine";
547 sal_Bool SAL_CALL
548 JavaVirtualMachine::supportsService(OUString const & rServiceName)
550 return cppu::supportsService(this, rServiceName);
553 css::uno::Sequence< OUString > SAL_CALL
554 JavaVirtualMachine::getSupportedServiceNames()
556 return { "com.sun.star.java.JavaVirtualMachine" };
559 css::uno::Any SAL_CALL
560 JavaVirtualMachine::getJavaVM(css::uno::Sequence< sal_Int8 > const & rProcessId)
562 osl::MutexGuard aGuard(m_aMutex);
563 if (m_bDisposed)
564 throw css::lang::DisposedException(
565 "", static_cast< cppu::OWeakObject * >(this));
566 css::uno::Sequence< sal_Int8 > aId(16);
567 rtl_getGlobalProcessId(reinterpret_cast< sal_uInt8 * >(aId.getArray()));
568 enum ReturnType {
569 RETURN_JAVAVM, RETURN_VIRTUALMACHINE, RETURN_UNOVIRTUALMACHINE };
570 ReturnType returnType =
571 rProcessId.getLength() == 17 && rProcessId[16] == 0
572 ? RETURN_VIRTUALMACHINE
573 : rProcessId.getLength() == 17 && rProcessId[16] == 1
574 ? RETURN_UNOVIRTUALMACHINE
575 : RETURN_JAVAVM;
576 css::uno::Sequence< sal_Int8 > aProcessId(rProcessId);
577 if (returnType != RETURN_JAVAVM)
578 aProcessId.realloc(16);
579 if (aId != aProcessId)
580 return css::uno::Any();
582 std::unique_ptr<JavaInfo> info;
583 while (!m_xVirtualMachine.is()) // retry until successful
585 stoc_javavm::JVM aJvm;
586 initVMConfiguration(&aJvm, m_xContext->getServiceManager(),
587 m_xContext);
588 const std::vector<OUString> & props = aJvm.getProperties();
589 std::vector<OUString> options;
590 options.reserve(props.size());
591 for (auto const& i : props)
593 options.push_back(i.startsWith("-") ? i : "-D" + i);
596 JNIEnv * pMainThreadEnv = nullptr;
597 javaFrameworkError errcode = JFW_E_NONE;
599 if (getenv("STOC_FORCE_NO_JRE"))
600 errcode = JFW_E_NO_SELECT;
601 else
602 errcode = jfw_startVM(info.get(), options, & m_pJavaVm,
603 & pMainThreadEnv);
605 bool bStarted = false;
606 switch (errcode)
608 case JFW_E_NONE: bStarted = true; break;
609 case JFW_E_NO_SELECT:
611 // No Java configured. We silently run the Java configuration
612 info.reset();
613 javaFrameworkError errFind = jfw_findAndSelectJRE(&info);
614 if (getenv("STOC_FORCE_NO_JRE"))
615 errFind = JFW_E_NO_JAVA_FOUND;
616 if (errFind == JFW_E_NONE)
618 continue;
620 else if (errFind == JFW_E_NO_JAVA_FOUND)
623 //Warning MessageBox:
624 //%PRODUCTNAME requires a Java runtime environment (JRE) to perform this task.
625 //Please install a JRE and restart %PRODUCTNAME.
626 css::java::JavaNotFoundException exc(
627 "JavaVirtualMachine::getJavaVM failed because"
628 " No suitable JRE found!",
629 static_cast< cppu::OWeakObject * >(this));
630 askForRetry(css::uno::makeAny(exc));
631 return css::uno::Any();
633 else
635 //An unexpected error occurred
636 throw css::uno::RuntimeException(
637 "[JavaVirtualMachine]:An unexpected error occurred"
638 " while searching for a Java, " + OUString::number(errFind), nullptr);
641 case JFW_E_INVALID_SETTINGS:
643 //Warning MessageBox:
644 // The %PRODUCTNAME configuration has been changed. Under Tools
645 // - Options - %PRODUCTNAME - Java, select the Java runtime environment
646 // you want to have used by %PRODUCTNAME.
647 css::java::InvalidJavaSettingsException exc(
648 "JavaVirtualMachine::getJavaVM failed because"
649 " Java settings have changed!",
650 static_cast< cppu::OWeakObject * >(this));
651 askForRetry(css::uno::makeAny(exc));
652 return css::uno::Any();
654 case JFW_E_JAVA_DISABLED:
656 if (comphelper::IsContextFlagActive("DontEnableJava"))
657 return css::uno::Any();
659 //QueryBox:
660 //%PRODUCTNAME requires a Java runtime environment (JRE) to perform
661 //this task. However, use of a JRE has been disabled. Do you want to
662 //enable the use of a JRE now?
663 css::java::JavaDisabledException exc(
664 "JavaVirtualMachine::getJavaVM failed because Java is disabled!",
665 static_cast< cppu::OWeakObject * >(this));
666 if( ! askForRetry(css::uno::makeAny(exc)))
667 return css::uno::Any();
668 continue;
670 case JFW_E_VM_CREATION_FAILED:
672 //If the creation failed because the JRE has been uninstalled then
673 //we search another one. As long as there is a javaldx, we should
674 //never come into this situation. javaldx checks always if the JRE
675 //still exist.
676 std::unique_ptr<JavaInfo> aJavaInfo;
677 if (JFW_E_NONE == jfw_getSelectedJRE(&aJavaInfo))
679 bool bExist = false;
680 if (JFW_E_NONE == jfw_existJRE(aJavaInfo.get(), &bExist))
682 if (!bExist
683 && ! (aJavaInfo->nRequirements & JFW_REQUIRE_NEEDRESTART))
685 info.reset();
686 javaFrameworkError errFind = jfw_findAndSelectJRE(
687 &info);
688 if (errFind == JFW_E_NONE)
690 continue;
696 //Error: %PRODUCTNAME requires a Java
697 //runtime environment (JRE) to perform this task. The selected JRE
698 //is defective. Please select another version or install a new JRE
699 //and select it under Tools - Options - %PRODUCTNAME - Java.
700 css::java::JavaVMCreationFailureException exc(
701 "JavaVirtualMachine::getJavaVM failed because Java is defective!",
702 static_cast< cppu::OWeakObject * >(this), 0);
703 askForRetry(css::uno::makeAny(exc));
704 return css::uno::Any();
706 case JFW_E_RUNNING_JVM:
708 //This service should make sure that we do not start java twice.
709 OSL_ASSERT(false);
710 break;
712 case JFW_E_NEED_RESTART:
714 //Error:
715 //For the selected Java runtime environment to work properly,
716 //%PRODUCTNAME must be restarted. Please restart %PRODUCTNAME now.
717 css::java::RestartRequiredException exc(
718 "JavaVirtualMachine::getJavaVM failed because "
719 "Office must be restarted before Java can be used!",
720 static_cast< cppu::OWeakObject * >(this));
721 askForRetry(css::uno::makeAny(exc));
722 return css::uno::Any();
724 default:
725 //RuntimeException: error is somewhere in the java framework.
726 //An unexpected error occurred
727 throw css::uno::RuntimeException(
728 "[JavaVirtualMachine]:An unexpected error occurred"
729 " while starting Java!", nullptr);
732 if (bStarted)
735 DetachCurrentThread detach(m_pJavaVm);
736 // necessary to make debugging work; this thread will be
737 // suspended when the destructor of detach returns
738 m_xVirtualMachine = new jvmaccess::VirtualMachine(
739 m_pJavaVm, JNI_VERSION_1_2, true, pMainThreadEnv);
740 setUpUnoVirtualMachine(pMainThreadEnv);
742 // Listen for changes in the configuration (e.g. proxy settings):
743 // TODO this is done too late; changes to the configuration done
744 // after the above call to initVMConfiguration are lost
745 registerConfigChangesListener();
747 break;
750 if (!m_xUnoVirtualMachine.is()) {
751 try {
752 jvmaccess::VirtualMachine::AttachGuard guard(m_xVirtualMachine);
753 setUpUnoVirtualMachine(guard.getEnvironment());
754 } catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) {
755 css::uno::Any anyEx = cppu::getCaughtException();
756 throw css::lang::WrappedTargetRuntimeException(
757 "jvmaccess::VirtualMachine::AttachGuard::CreationException occurred",
758 static_cast< cppu::OWeakObject * >(this), anyEx );
761 switch (returnType) {
762 default: // RETURN_JAVAVM
763 if (m_pJavaVm == nullptr) {
764 throw css::uno::RuntimeException(
765 "JavaVirtualMachine service was initialized in a way"
766 " that the requested JavaVM pointer is not available",
767 static_cast< cppu::OWeakObject * >(this));
769 return css::uno::makeAny(reinterpret_cast< sal_IntPtr >(m_pJavaVm));
770 case RETURN_VIRTUALMACHINE:
771 OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *));
772 return css::uno::makeAny(
773 reinterpret_cast< sal_Int64 >(
774 m_xUnoVirtualMachine->getVirtualMachine().get()));
775 case RETURN_UNOVIRTUALMACHINE:
776 OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *));
777 return css::uno::makeAny(
778 reinterpret_cast< sal_Int64 >(m_xUnoVirtualMachine.get()));
782 sal_Bool SAL_CALL JavaVirtualMachine::isVMStarted()
784 osl::MutexGuard aGuard(m_aMutex);
785 if (m_bDisposed)
786 throw css::lang::DisposedException(
787 OUString(), static_cast< cppu::OWeakObject * >(this));
788 return m_xUnoVirtualMachine.is();
791 sal_Bool SAL_CALL JavaVirtualMachine::isVMEnabled()
794 osl::MutexGuard aGuard(m_aMutex);
795 if (m_bDisposed)
796 throw css::lang::DisposedException(
797 OUString(), static_cast< cppu::OWeakObject * >(this));
799 // stoc_javavm::JVM aJvm;
800 // initVMConfiguration(&aJvm, m_xContext->getServiceManager(), m_xContext);
801 // return aJvm.isEnabled();
802 //ToDo
803 bool bEnabled = false;
804 if (jfw_getEnabled( & bEnabled) != JFW_E_NONE)
805 throw css::uno::RuntimeException();
806 return bEnabled;
809 sal_Bool SAL_CALL JavaVirtualMachine::isThreadAttached()
811 osl::MutexGuard aGuard(m_aMutex);
812 if (m_bDisposed)
813 throw css::lang::DisposedException(
814 OUString(), static_cast< cppu::OWeakObject * >(this));
815 // TODO isThreadAttached only returns true if the thread was attached via
816 // registerThread:
817 GuardStack * pStack
818 = static_cast< GuardStack * >(m_aAttachGuards.getData());
819 return pStack != nullptr && !pStack->empty();
822 void SAL_CALL JavaVirtualMachine::registerThread()
824 osl::MutexGuard aGuard(m_aMutex);
825 if (m_bDisposed)
826 throw css::lang::DisposedException(
827 "", static_cast< cppu::OWeakObject * >(this));
828 if (!m_xUnoVirtualMachine.is())
829 throw css::uno::RuntimeException(
830 "JavaVirtualMachine::registerThread: null VirtualMachine",
831 static_cast< cppu::OWeakObject * >(this));
832 GuardStack * pStack
833 = static_cast< GuardStack * >(m_aAttachGuards.getData());
834 if (pStack == nullptr)
836 pStack = new GuardStack;
837 m_aAttachGuards.setData(pStack);
841 pStack->push(
842 new jvmaccess::VirtualMachine::AttachGuard(
843 m_xUnoVirtualMachine->getVirtualMachine()));
845 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &)
847 css::uno::Any anyEx = cppu::getCaughtException();
848 throw css::lang::WrappedTargetRuntimeException(
849 "JavaVirtualMachine::registerThread: jvmaccess::"
850 "VirtualMachine::AttachGuard::CreationException",
851 static_cast< cppu::OWeakObject * >(this), anyEx );
855 void SAL_CALL JavaVirtualMachine::revokeThread()
857 osl::MutexGuard aGuard(m_aMutex);
858 if (m_bDisposed)
859 throw css::lang::DisposedException(
860 "", static_cast< cppu::OWeakObject * >(this));
861 if (!m_xUnoVirtualMachine.is())
862 throw css::uno::RuntimeException(
863 "JavaVirtualMachine::revokeThread: null VirtualMachine",
864 static_cast< cppu::OWeakObject * >(this));
865 GuardStack * pStack
866 = static_cast< GuardStack * >(m_aAttachGuards.getData());
867 if (pStack == nullptr || pStack->empty())
868 throw css::uno::RuntimeException(
869 "JavaVirtualMachine::revokeThread: no matching registerThread",
870 static_cast< cppu::OWeakObject * >(this));
871 delete pStack->top();
872 pStack->pop();
875 void SAL_CALL
876 JavaVirtualMachine::disposing(css::lang::EventObject const & rSource)
878 osl::MutexGuard aGuard(m_aMutex);
879 if (rSource.Source == m_xInetConfiguration)
880 m_xInetConfiguration.clear();
881 if (rSource.Source == m_xJavaConfiguration)
882 m_xJavaConfiguration.clear();
885 void SAL_CALL JavaVirtualMachine::elementInserted(
886 css::container::ContainerEvent const &)
889 void SAL_CALL JavaVirtualMachine::elementRemoved(
890 css::container::ContainerEvent const &)
893 // If a user changes the setting, for example for proxy settings, then this
894 // function will be called from the configuration manager. Even if the .xml
895 // file does not contain an entry yet and that entry has to be inserted, this
896 // function will be called. We call java.lang.System.setProperty for the new
897 // values.
898 void SAL_CALL JavaVirtualMachine::elementReplaced(
899 css::container::ContainerEvent const & rEvent)
901 // TODO Using the new value stored in rEvent is wrong here. If two threads
902 // receive different elementReplaced calls in quick succession, it is
903 // unspecified which changes the JVM's system properties last. A correct
904 // solution must atomically (i.e., protected by a mutex) read the latest
905 // value from the configuration and set it as a system property at the JVM.
907 OUString aAccessor;
908 rEvent.Accessor >>= aAccessor;
909 OUString aPropertyName;
910 OUString aPropertyName2;
911 OUString aPropertyValue;
912 bool bSecurityChanged = false;
913 if ( aAccessor == "ooInetProxyType" )
915 // Proxy none, manually
916 sal_Int32 value = 0;
917 rEvent.Element >>= value;
918 setINetSettingsInVM(value != 0);
919 return;
921 else if ( aAccessor == "ooInetHTTPProxyName" )
923 aPropertyName = "http.proxyHost";
924 rEvent.Element >>= aPropertyValue;
926 else if ( aAccessor == "ooInetHTTPProxyPort" )
928 aPropertyName = "http.proxyPort";
929 sal_Int32 n = 0;
930 rEvent.Element >>= n;
931 aPropertyValue = OUString::number(n);
933 else if ( aAccessor == "ooInetHTTPSProxyName" )
935 aPropertyName = "https.proxyHost";
936 rEvent.Element >>= aPropertyValue;
938 else if ( aAccessor == "ooInetHTTPSProxyPort" )
940 aPropertyName = "https.proxyPort";
941 sal_Int32 n = 0;
942 rEvent.Element >>= n;
943 aPropertyValue = OUString::number(n);
945 else if ( aAccessor == "ooInetFTPProxyName" )
947 aPropertyName = "ftp.proxyHost";
948 rEvent.Element >>= aPropertyValue;
950 else if ( aAccessor == "ooInetFTPProxyPort" )
952 aPropertyName = "ftp.proxyPort";
953 sal_Int32 n = 0;
954 rEvent.Element >>= n;
955 aPropertyValue = OUString::number(n);
957 else if ( aAccessor == "ooInetNoProxy" )
959 aPropertyName = "http.nonProxyHosts";
960 aPropertyName2 = "ftp.nonProxyHosts";
961 rEvent.Element >>= aPropertyValue;
962 aPropertyValue = aPropertyValue.replace(';', '|');
964 else if ( aAccessor == "NetAccess" )
966 aPropertyName = "appletviewer.security.mode";
967 sal_Int32 n = 0;
968 if (rEvent.Element >>= n)
969 switch (n)
971 case 0:
972 aPropertyValue = "host";
973 break;
974 case 1:
975 aPropertyValue = "unrestricted";
976 break;
977 case 3:
978 aPropertyValue = "none";
979 break;
981 else
982 return;
983 bSecurityChanged = true;
985 else if ( aAccessor == "Security" )
987 aPropertyName = "stardiv.security.disableSecurity";
988 bool b;
989 if (rEvent.Element >>= b)
990 if (b)
991 aPropertyValue = "false";
992 else
993 aPropertyValue = "true";
994 else
995 return;
996 bSecurityChanged = true;
998 else
999 return;
1001 rtl::Reference< jvmaccess::VirtualMachine > xVirtualMachine;
1003 osl::MutexGuard aGuard(m_aMutex);
1004 if (m_xUnoVirtualMachine.is()) {
1005 xVirtualMachine = m_xUnoVirtualMachine->getVirtualMachine();
1008 if (!xVirtualMachine.is())
1009 return;
1013 jvmaccess::VirtualMachine::AttachGuard aAttachGuard(
1014 xVirtualMachine);
1015 JNIEnv * pJNIEnv = aAttachGuard.getEnvironment();
1017 // call java.lang.System.setProperty
1018 // String setProperty( String key, String value)
1019 jclass jcSystem= pJNIEnv->FindClass("java/lang/System");
1020 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:FindClass java/lang/System", nullptr);
1021 jmethodID jmSetProps= pJNIEnv->GetStaticMethodID( jcSystem, "setProperty","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
1022 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetStaticMethodID java.lang.System.setProperty", nullptr);
1024 jstring jsPropName= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyName.getStr()), aPropertyName.getLength());
1025 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1027 // remove the property if it does not have a value ( user left the dialog field empty)
1028 // or if the port is set to 0
1029 aPropertyValue= aPropertyValue.trim();
1030 if( aPropertyValue.isEmpty() ||
1031 ( ( aPropertyName == "ftp.proxyPort" || aPropertyName == "http.proxyPort" /*|| aPropertyName == "socksProxyPort"*/ ) && aPropertyValue == "0" )
1034 // call java.lang.System.getProperties
1035 jmethodID jmGetProps= pJNIEnv->GetStaticMethodID( jcSystem, "getProperties","()Ljava/util/Properties;");
1036 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetStaticMethodID java.lang.System.getProperties", nullptr);
1037 jobject joProperties= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetProps);
1038 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.getProperties", nullptr);
1039 // call java.util.Properties.remove
1040 jclass jcProperties= pJNIEnv->FindClass("java/util/Properties");
1041 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:FindClass java/util/Properties", nullptr);
1042 jmethodID jmRemove= pJNIEnv->GetMethodID( jcProperties, "remove", "(Ljava/lang/Object;)Ljava/lang/Object;");
1043 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetMethodID java.util.Properties.remove", nullptr);
1044 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsPropName);
1046 // special case for ftp.nonProxyHosts and http.nonProxyHosts. The office only
1047 // has a value for two java properties
1048 if (!aPropertyName2.isEmpty())
1050 jstring jsPropName2= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyName2.getStr()), aPropertyName2.getLength());
1051 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1052 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsPropName2);
1055 else
1057 // Change the Value of the property
1058 jstring jsPropValue= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyValue.getStr()), aPropertyValue.getLength());
1059 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1060 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsPropName, jsPropValue);
1061 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1063 // special case for ftp.nonProxyHosts and http.nonProxyHosts. The office only
1064 // has a value for two java properties
1065 if (!aPropertyName2.isEmpty())
1067 jstring jsPropName2= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyName2.getStr()), aPropertyName2.getLength());
1068 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1069 jsPropValue= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyValue.getStr()), aPropertyValue.getLength());
1070 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1071 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsPropName2, jsPropValue);
1072 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1076 // If the settings for Security and NetAccess changed then we have to notify the SandboxSecurity
1077 // SecurityManager
1078 // call System.getSecurityManager()
1079 if (bSecurityChanged)
1081 jmethodID jmGetSecur= pJNIEnv->GetStaticMethodID( jcSystem,"getSecurityManager","()Ljava/lang/SecurityManager;");
1082 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetStaticMethodID java.lang.System.getSecurityManager", nullptr);
1083 jobject joSecur= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetSecur);
1084 if (joSecur != nullptr)
1086 // Make sure the SecurityManager is our SandboxSecurity
1087 // FindClass("com.sun.star.lib.sandbox.SandboxSecurityManager" only worked at the first time
1088 // this code was executed. Maybe it is a security feature. However, all attempts to debug the
1089 // SandboxSecurity class (maybe the VM invokes checkPackageAccess) failed.
1090 // jclass jcSandboxSec= pJNIEnv->FindClass("com.sun.star.lib.sandbox.SandboxSecurity");
1091 // if(pJNIEnv->ExceptionOccurred()) throw RuntimeException("JNI:FindClass com.sun.star.lib.sandbox.SandboxSecurity");
1092 // jboolean bIsSand= pJNIEnv->IsInstanceOf( joSecur, jcSandboxSec);
1093 // The SecurityManagers class Name must be com.sun.star.lib.sandbox.SandboxSecurity
1094 jclass jcSec= pJNIEnv->GetObjectClass( joSecur);
1095 jclass jcClass= pJNIEnv->FindClass("java/lang/Class");
1096 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:FindClass java.lang.Class", nullptr);
1097 jmethodID jmName= pJNIEnv->GetMethodID( jcClass,"getName","()Ljava/lang/String;");
1098 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetMethodID java.lang.Class.getName", nullptr);
1099 jstring jsClass= static_cast<jstring>(pJNIEnv->CallObjectMethod( jcSec, jmName));
1100 const jchar* jcharName= pJNIEnv->GetStringChars( jsClass, nullptr);
1101 OUString sName(reinterpret_cast<sal_Unicode const *>(jcharName));
1102 bool bIsSandbox;
1103 bIsSandbox = sName == "com.sun.star.lib.sandbox.SandboxSecurity";
1104 pJNIEnv->ReleaseStringChars( jsClass, jcharName);
1106 if (bIsSandbox)
1108 // call SandboxSecurity.reset
1109 jmethodID jmReset= pJNIEnv->GetMethodID( jcSec,"reset","()V");
1110 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetMethodID com.sun.star.lib.sandbox.SandboxSecurity.reset", nullptr);
1111 pJNIEnv->CallVoidMethod( joSecur, jmReset);
1112 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallVoidMethod com.sun.star.lib.sandbox.SandboxSecurity.reset", nullptr);
1117 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &)
1119 css::uno::Any anyEx = cppu::getCaughtException();
1120 throw css::lang::WrappedTargetRuntimeException(
1121 "jvmaccess::VirtualMachine::AttachGuard::CreationException",
1122 static_cast< cppu::OWeakObject * >(this), anyEx );
1126 JavaVirtualMachine::~JavaVirtualMachine()
1128 if (m_xInetConfiguration.is())
1129 // We should never get here, but just in case...
1132 m_xInetConfiguration->removeContainerListener(this);
1134 catch (css::uno::Exception &)
1136 TOOLS_WARN_EXCEPTION( "stoc", "");
1138 if (m_xJavaConfiguration.is())
1139 // We should never get here, but just in case...
1142 m_xJavaConfiguration->removeContainerListener(this);
1144 catch (css::uno::Exception &)
1146 TOOLS_WARN_EXCEPTION( "stoc", "");
1150 void SAL_CALL JavaVirtualMachine::disposing()
1152 css::uno::Reference< css::container::XContainer > xContainer1;
1153 css::uno::Reference< css::container::XContainer > xContainer2;
1155 osl::MutexGuard aGuard(m_aMutex);
1156 m_bDisposed = true;
1157 xContainer1 = m_xInetConfiguration;
1158 m_xInetConfiguration.clear();
1159 xContainer2 = m_xJavaConfiguration;
1160 m_xJavaConfiguration.clear();
1162 if (xContainer1.is())
1163 xContainer1->removeContainerListener(this);
1164 if (xContainer2.is())
1165 xContainer2->removeContainerListener(this);
1168 /*We listen to changes in the configuration. For example, the user changes the proxy
1169 settings in the options dialog (menu tools). Then we are notified of this change and
1170 if the java vm is already running we change the properties (System.lang.System.setProperties)
1171 through JNI.
1172 To receive notifications this class implements XContainerListener.
1174 void JavaVirtualMachine::registerConfigChangesListener()
1178 css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
1179 m_xContext->getValueByName(
1180 "/singletons/com.sun.star.configuration.theDefaultProvider"),
1181 css::uno::UNO_QUERY);
1183 if (xConfigProvider.is())
1185 // We register this instance as listener to changes in org.openoffice.Inet/Settings
1186 // arguments for ConfigurationAccess
1187 css::uno::Sequence<css::uno::Any> aArguments(comphelper::InitAnyPropertySequence(
1189 {"nodepath", css::uno::Any(OUString("org.openoffice.Inet/Settings"))},
1190 {"depth", css::uno::Any(sal_Int32(-1))}
1191 }));
1192 m_xInetConfiguration.set(
1193 xConfigProvider->createInstanceWithArguments(
1194 "com.sun.star.configuration.ConfigurationAccess",
1195 aArguments),
1196 css::uno::UNO_QUERY);
1198 if (m_xInetConfiguration.is())
1199 m_xInetConfiguration->addContainerListener(this);
1201 // now register as listener to changes in org.openoffice.Java/VirtualMachine
1202 css::uno::Sequence<css::uno::Any> aArguments2(comphelper::InitAnyPropertySequence(
1204 {"nodepath", css::uno::Any(OUString("org.openoffice.Office.Java/VirtualMachine"))},
1205 {"depth", css::uno::Any(sal_Int32(-1))} // depth: -1 means unlimited
1206 }));
1207 m_xJavaConfiguration.set(
1208 xConfigProvider->createInstanceWithArguments(
1209 "com.sun.star.configuration.ConfigurationAccess",
1210 aArguments2),
1211 css::uno::UNO_QUERY);
1213 if (m_xJavaConfiguration.is())
1214 m_xJavaConfiguration->addContainerListener(this);
1216 }catch(const css::uno::Exception &)
1218 TOOLS_INFO_EXCEPTION("stoc", "could not set up listener for Configuration");
1222 // param true: all Inet setting are set as Java Properties on a live VM.
1223 // false: the Java net properties are set to empty value.
1224 void JavaVirtualMachine::setINetSettingsInVM(bool set_reset)
1226 osl::MutexGuard aGuard(m_aMutex);
1229 if (m_xUnoVirtualMachine.is())
1231 jvmaccess::VirtualMachine::AttachGuard aAttachGuard(
1232 m_xUnoVirtualMachine->getVirtualMachine());
1233 JNIEnv * pJNIEnv = aAttachGuard.getEnvironment();
1235 // The Java Properties
1236 OUString sFtpProxyHost("ftp.proxyHost");
1237 OUString sFtpProxyPort("ftp.proxyPort");
1238 OUString sFtpNonProxyHosts ("ftp.nonProxyHosts");
1239 OUString sHttpProxyHost("http.proxyHost");
1240 OUString sHttpProxyPort("http.proxyPort");
1241 OUString sHttpNonProxyHosts("http.nonProxyHosts");
1243 // create Java Properties as JNI strings
1244 jstring jsFtpProxyHost= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sFtpProxyHost.getStr()), sFtpProxyHost.getLength());
1245 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1246 jstring jsFtpProxyPort= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sFtpProxyPort.getStr()), sFtpProxyPort.getLength());
1247 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1248 jstring jsFtpNonProxyHosts= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sFtpNonProxyHosts.getStr()), sFtpNonProxyHosts.getLength());
1249 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1250 jstring jsHttpProxyHost= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sHttpProxyHost.getStr()), sHttpProxyHost.getLength());
1251 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1252 jstring jsHttpProxyPort= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sHttpProxyPort.getStr()), sHttpProxyPort.getLength());
1253 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1254 jstring jsHttpNonProxyHosts= pJNIEnv->NewString( reinterpret_cast<jchar const *>(sHttpNonProxyHosts.getStr()), sHttpNonProxyHosts.getLength());
1255 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1257 // prepare java.lang.System.setProperty
1258 jclass jcSystem= pJNIEnv->FindClass("java/lang/System");
1259 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:FindClass java/lang/System", nullptr);
1260 jmethodID jmSetProps= pJNIEnv->GetStaticMethodID( jcSystem, "setProperty","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
1261 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetStaticMethodID java.lang.System.setProperty", nullptr);
1263 // call java.lang.System.getProperties
1264 jmethodID jmGetProps= pJNIEnv->GetStaticMethodID( jcSystem, "getProperties","()Ljava/util/Properties;");
1265 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetStaticMethodID java.lang.System.getProperties", nullptr);
1266 jobject joProperties= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetProps);
1267 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.getProperties", nullptr);
1268 // prepare java.util.Properties.remove
1269 jclass jcProperties= pJNIEnv->FindClass("java/util/Properties");
1270 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:FindClass java/util/Properties", nullptr);
1272 if (set_reset)
1274 // Set all network properties with the VM
1275 JVM jvm;
1276 getINetPropsFromConfig( &jvm, m_xContext->getServiceManager(), m_xContext);
1277 const ::std::vector< OUString> & Props = jvm.getProperties();
1279 for( auto& prop : Props)
1281 sal_Int32 index= prop.indexOf( '=');
1282 OUString propName= prop.copy( 0, index);
1283 OUString propValue= prop.copy( index + 1);
1285 if( propName == sFtpProxyHost)
1287 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1288 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1289 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpProxyHost, jsVal);
1290 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1292 else if( propName == sFtpProxyPort)
1294 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1295 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1296 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpProxyPort, jsVal);
1297 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1299 else if( propName == sFtpNonProxyHosts)
1301 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1302 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1303 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpNonProxyHosts, jsVal);
1304 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1306 else if( propName == sHttpProxyHost)
1308 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1309 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1310 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpProxyHost, jsVal);
1311 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1313 else if( propName == sHttpProxyPort)
1315 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1316 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1317 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpProxyPort, jsVal);
1318 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1320 else if( propName == sHttpNonProxyHosts)
1322 jstring jsVal= pJNIEnv->NewString( reinterpret_cast<jchar const *>(propValue.getStr()), propValue.getLength());
1323 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:NewString", nullptr);
1324 pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpNonProxyHosts, jsVal);
1325 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:CallStaticObjectMethod java.lang.System.setProperty", nullptr);
1329 else
1331 // call java.util.Properties.remove
1332 jmethodID jmRemove= pJNIEnv->GetMethodID( jcProperties, "remove", "(Ljava/lang/Object;)Ljava/lang/Object;");
1333 if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException("JNI:GetMethodID java.util.Property.remove", nullptr);
1334 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpProxyHost);
1335 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpProxyPort);
1336 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpNonProxyHosts);
1337 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpProxyHost);
1338 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpProxyPort);
1339 pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpNonProxyHosts);
1343 catch (css::uno::RuntimeException &)
1345 TOOLS_WARN_EXCEPTION( "stoc", "");
1347 catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &)
1349 TOOLS_WARN_EXCEPTION( "stoc", "");
1353 void JavaVirtualMachine::setUpUnoVirtualMachine(JNIEnv * environment) {
1354 css::uno::Reference< css::util::XMacroExpander > exp = css::util::theMacroExpander::get(m_xContext);
1355 OUString baseUrl;
1356 try {
1357 baseUrl = exp->expandMacros("$URE_INTERNAL_JAVA_DIR/");
1358 } catch (css::lang::IllegalArgumentException &) {
1359 css::uno::Any anyEx = cppu::getCaughtException();
1360 throw css::lang::WrappedTargetRuntimeException(
1361 "css::lang::IllegalArgumentException",
1362 static_cast< cppu::OWeakObject * >(this), anyEx );
1364 OUString classPath;
1365 try {
1366 classPath = exp->expandMacros("$URE_INTERNAL_JAVA_CLASSPATH");
1367 } catch (css::lang::IllegalArgumentException &) {}
1368 jclass class_URLClassLoader = environment->FindClass(
1369 "java/net/URLClassLoader");
1370 if (class_URLClassLoader == nullptr) {
1371 handleJniException(environment);
1373 jmethodID ctor_URLClassLoader = environment->GetMethodID(
1374 class_URLClassLoader, "<init>", "([Ljava/net/URL;)V");
1375 if (ctor_URLClassLoader == nullptr) {
1376 handleJniException(environment);
1378 jclass class_URL = environment->FindClass("java/net/URL");
1379 if (class_URL == nullptr) {
1380 handleJniException(environment);
1382 jmethodID ctor_URL_1 = environment->GetMethodID(
1383 class_URL, "<init>", "(Ljava/lang/String;)V");
1384 if (ctor_URL_1 == nullptr) {
1385 handleJniException(environment);
1387 jvalue args[3];
1388 args[0].l = environment->NewString(
1389 reinterpret_cast< jchar const * >(baseUrl.getStr()),
1390 static_cast< jsize >(baseUrl.getLength()));
1391 if (args[0].l == nullptr) {
1392 handleJniException(environment);
1394 jobject base = environment->NewObjectA(class_URL, ctor_URL_1, args);
1395 if (base == nullptr) {
1396 handleJniException(environment);
1398 jmethodID ctor_URL_2 = environment->GetMethodID(
1399 class_URL, "<init>", "(Ljava/net/URL;Ljava/lang/String;)V");
1400 if (ctor_URL_2 == nullptr) {
1401 handleJniException(environment);
1403 jobjectArray classpath = jvmaccess::ClassPath::translateToUrls(
1404 m_xContext, environment, classPath);
1405 if (classpath == nullptr) {
1406 handleJniException(environment);
1408 args[0].l = base;
1409 args[1].l = environment->NewStringUTF("unoloader.jar");
1410 if (args[1].l == nullptr) {
1411 handleJniException(environment);
1413 args[0].l = environment->NewObjectA(class_URL, ctor_URL_2, args);
1414 if (args[0].l == nullptr) {
1415 handleJniException(environment);
1417 args[0].l = environment->NewObjectArray(1, class_URL, args[0].l);
1418 if (args[0].l == nullptr) {
1419 handleJniException(environment);
1421 jobject cl1 = environment->NewObjectA(
1422 class_URLClassLoader, ctor_URLClassLoader, args);
1423 if (cl1 == nullptr) {
1424 handleJniException(environment);
1426 jmethodID method_loadClass = environment->GetMethodID(
1427 class_URLClassLoader, "loadClass",
1428 "(Ljava/lang/String;)Ljava/lang/Class;");
1429 if (method_loadClass == nullptr) {
1430 handleJniException(environment);
1432 args[0].l = environment->NewStringUTF(
1433 "com.sun.star.lib.unoloader.UnoClassLoader");
1434 if (args[0].l == nullptr) {
1435 handleJniException(environment);
1437 jclass class_UnoClassLoader = static_cast< jclass >(
1438 environment->CallObjectMethodA(cl1, method_loadClass, args));
1439 if (class_UnoClassLoader == nullptr) {
1440 handleJniException(environment);
1442 jmethodID ctor_UnoClassLoader = environment->GetMethodID(
1443 class_UnoClassLoader, "<init>",
1444 "(Ljava/net/URL;[Ljava/net/URL;Ljava/lang/ClassLoader;)V");
1445 if (ctor_UnoClassLoader == nullptr) {
1446 handleJniException(environment);
1448 args[0].l = base;
1449 args[1].l = classpath;
1450 args[2].l = cl1;
1451 jobject cl2 = environment->NewObjectA(
1452 class_UnoClassLoader, ctor_UnoClassLoader, args);
1453 if (cl2 == nullptr) {
1454 handleJniException(environment);
1456 try {
1457 m_xUnoVirtualMachine = new jvmaccess::UnoVirtualMachine(
1458 m_xVirtualMachine, cl2);
1459 } catch (jvmaccess::UnoVirtualMachine::CreationException &) {
1460 css::uno::Any anyEx = cppu::getCaughtException();
1461 throw css::lang::WrappedTargetRuntimeException(
1462 "jvmaccess::UnoVirtualMachine::CreationException",
1463 static_cast< cppu::OWeakObject * >(this), anyEx );
1467 void JavaVirtualMachine::handleJniException(JNIEnv * environment) {
1468 #if defined DBG_UTIL
1469 environment->ExceptionDescribe();
1470 #else
1471 environment->ExceptionClear();
1472 #endif
1473 throw css::uno::RuntimeException(
1474 "JNI exception occurred",
1475 static_cast< cppu::OWeakObject * >(this));
1479 static osl::Mutex m_aMutex;
1480 static rtl::Reference< JavaVirtualMachine > m_xSingleton;
1483 void JavaVirtualMachine::dispose() {
1484 JavaVirtualMachine_Impl::dispose();
1485 osl::MutexGuard aGuard(m_aMutex);
1486 m_xSingleton.clear();
1489 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1490 stoc_JavaVM_get_implementation(
1491 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
1493 // Only one single instance of this service is ever constructed, and is
1494 // available until the component context used to create this instance is
1495 // disposed. Afterwards, this function throws a DisposedException (as do
1496 // all relevant methods on the single service instance).
1497 osl::MutexGuard aGuard(m_aMutex);
1498 if (!m_xSingleton.is())
1499 m_xSingleton.set(new JavaVirtualMachine(context));
1500 m_xSingleton->acquire();
1501 return static_cast<cppu::OWeakObject*>(m_xSingleton.get());
1505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */