/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Properties of the javavm can be put // as a comma separated list in this // environment variable #ifdef UNIX #define TIMEZONE "MEZ" #else #define TIMEZONE "MET" #endif
/* Within this implementation of the com.sun.star.java.JavaVirtualMachine * service and com.sun.star.java.theJavaVirtualMachine singleton, the method * com.sun.star.java.XJavaVM.getJavaVM relies on the following: * 1 The string "$URE_INTERNAL_JAVA_DIR/" is expanded via the * com.sun.star.util.theMacroExpander singleton into an internal (see the * com.sun.star.uri.ExternalUriReferenceTranslator service), hierarchical URI * reference relative to which the URE JAR files can be addressed. * 2 The string "$URE_INTERNAL_JAVA_CLASSPATH" is either not expandable via the * com.sun.star.util.theMacroExpander singleton * (com.sun.star.lang.IllegalArgumentException), or is expanded via the * com.sun.star.util.theMacroExpander singleton into a list of zero or more * internal (see the com.sun.star.uri.ExternalUriReferenceTranslator service) * URIs, where any space characters (U+0020) are ignored (and, in particular, * separate adjacent URIs). * If either of these requirements is not met, getJavaVM raises a * com.sun.star.uno.RuntimeException.
*/
using stoc_javavm::JavaVirtualMachine;
namespace {
class NoJavaIniException: public css::uno::Exception
{
};
// Only gets the properties if the "Proxy Server" entry in the option dialog is // set to manual (i.e. not to none) /// @throws css::uno::Exception void getINetPropsFromConfig(stoc_javavm::JVM * pjvm, const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr, const css::uno::Reference<css::uno::XComponentContext> &xCtx )
{
css::uno::Reference<css::uno::XInterface> xConfRegistry = xSMgr->createInstanceWithContext(
u"com.sun.star.configuration.ConfigurationRegistry"_ustr,
xCtx ); if(!xConfRegistry.is()) throw css::uno::RuntimeException(u"javavm.cxx: couldn't get ConfigurationRegistry"_ustr, nullptr);
// Read system locale.
css::uno::Reference<css::registry::XRegistryKey> xLocale = xRegistryRootKey->openKey(u"L10N/ooSetupSystemLocale"_ustr); if(xLocale.is() && !xLocale->getStringValue().isEmpty()) {
LanguageTag aLanguageTag( xLocale->getStringValue());
OUString language;
OUString script;
OUString country; // Java knows nothing but plain old ISO codes, unless Locale.Builder or // Locale.forLanguageTag() are used, or non-standardized variant field // content which we ignore.
aLanguageTag.getIsoLanguageScriptCountry( language, script, country);
// Java 7 FORMAT category is our system locale. if(!language.isEmpty()) {
OUString prop = "user.language.format=" + language;
pjvm->pushProp(prop);
}
try {
getDefaultLocaleFromConfig(&jvm, xSMgr,xCtx);
} catch(const css::uno::Exception & exception) {
SAL_INFO("stoc", "can not get locale because of " << exception);
}
try
{
getJavaPropsFromJavaSettings(&jvm, xCtx);
} catch(const css::uno::Exception & exception) {
SAL_INFO("stoc", "couldn't get Java settings because of " << exception);
}
*pjvm = std::move(jvm);
// rhbz#1285356, native look will be gtk2, which crashes // when gtk3 is already loaded. Until there is a solution // java-side force look and feel to something that doesn't // crash when we are using gtk3 if (getenv("STOC_FORCE_SYSTEM_LAF"))
pjvm->pushProp(u"swing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel"_ustr);
setTimeZone(pjvm);
}
class DetachCurrentThread { public: explicit DetachCurrentThread(JavaVM * jvm): m_jvm(jvm) {}
~DetachCurrentThread() { #ifdef MACOSX // tdf#101376 don't detach thread if it is the main thread on macOS // On macOS, many AWT classes do their work on the main thread // deep in native methods in the java.awt.* classes. The problem // is that Oracle's and OpenJDK's JVMs don't bracket their // "perform on main thread" native calls with "attach/detach // current thread" calls to the JVM. if (CFRunLoopGetCurrent() != CFRunLoopGetMain()) #endif if (m_jvm->DetachCurrentThread() != 0) {
OSL_ASSERT(false);
}
}
bool bStarted = false; switch (errcode)
{ case JFW_E_NONE: bStarted = true; break; case JFW_E_NO_SELECT:
{ // No Java configured. We silently run the Java configuration
info.reset();
javaFrameworkError errFind; if (getenv("STOC_FORCE_NO_JRE"))
errFind = JFW_E_NO_JAVA_FOUND; else
errFind = jfw_findAndSelectJRE(&info); if (errFind == JFW_E_NONE)
{ continue;
} elseif (errFind == JFW_E_NO_JAVA_FOUND)
{
//Warning MessageBox: //%PRODUCTNAME requires a Java runtime environment (JRE) to perform this task. //Please install a JRE and restart %PRODUCTNAME.
css::java::JavaNotFoundException exc(
u"JavaVirtualMachine::getJavaVM failed because" " No suitable JRE found!"_ustr,
getXWeak());
askForRetry(css::uno::Any(exc)); return css::uno::Any();
} else
{ //An unexpected error occurred throw css::uno::RuntimeException( "[JavaVirtualMachine]:An unexpected error occurred" " while searching for a Java, " + OUString::number(errFind), nullptr);
}
} case JFW_E_INVALID_SETTINGS:
{ //Warning MessageBox: // The %PRODUCTNAME configuration has been changed. Under Tools // - Options - %PRODUCTNAME - Java, select the Java runtime environment // you want to have used by %PRODUCTNAME.
css::java::InvalidJavaSettingsException exc(
u"JavaVirtualMachine::getJavaVM failed because" " Java settings have changed!"_ustr,
getXWeak());
askForRetry(css::uno::Any(exc)); return css::uno::Any();
} case JFW_E_JAVA_DISABLED:
{ //QueryBox: //%PRODUCTNAME requires a Java runtime environment (JRE) to perform //this task. However, use of a JRE has been disabled. Do you want to //enable the use of a JRE now?
css::java::JavaDisabledException exc(
u"JavaVirtualMachine::getJavaVM failed because Java is disabled!"_ustr,
getXWeak()); if( ! askForRetry(css::uno::Any(exc))) return css::uno::Any(); continue;
} case JFW_E_VM_CREATION_FAILED:
{ //If the creation failed because the JRE has been uninstalled then //we search another one. As long as there is a javaldx, we should //never come into this situation. javaldx checks always if the JRE //still exist.
std::unique_ptr<JavaInfo> aJavaInfo; if (JFW_E_NONE == jfw_getSelectedJRE(&aJavaInfo))
{ bool bExist = false; if (JFW_E_NONE == jfw_existJRE(aJavaInfo.get(), &bExist))
{ if (!bExist
&& ! (aJavaInfo->nRequirements & JFW_REQUIRE_NEEDRESTART))
{
info.reset();
javaFrameworkError errFind = jfw_findAndSelectJRE(
&info); if (errFind == JFW_E_NONE)
{ continue;
}
}
}
}
//Error: %PRODUCTNAME requires a Java //runtime environment (JRE) to perform this task. The selected JRE //is defective. Please select another version or install a new JRE //and select it under Tools - Options - %PRODUCTNAME - Java.
css::java::JavaVMCreationFailureException exc(
u"JavaVirtualMachine::getJavaVM failed because Java is defective!"_ustr,
getXWeak(), 0);
askForRetry(css::uno::Any(exc)); return css::uno::Any();
} case JFW_E_RUNNING_JVM:
{ //This service should make sure that we do not start java twice.
OSL_ASSERT(false); break;
} case JFW_E_NEED_RESTART:
{ //Error: //For the selected Java runtime environment to work properly, //%PRODUCTNAME must be restarted. Please restart %PRODUCTNAME now.
css::java::RestartRequiredException exc(
u"JavaVirtualMachine::getJavaVM failed because " "Office must be restarted before Java can be used!"_ustr,
getXWeak());
askForRetry(css::uno::Any(exc)); return css::uno::Any();
} default: //RuntimeException: error is somewhere in the java framework. //An unexpected error occurred throw css::uno::RuntimeException(
u"[JavaVirtualMachine]:An unexpected error occurred" " while starting Java!"_ustr, nullptr);
}
if (bStarted)
{
{
DetachCurrentThread detach(m_pJavaVm); // necessary to make debugging work; this thread will be // suspended when the destructor of detach returns
m_xVirtualMachine = new jvmaccess::VirtualMachine(
m_pJavaVm, JNI_VERSION_1_2, true, pMainThreadEnv);
setUpUnoVirtualMachine(pMainThreadEnv);
} // Listen for changes in the configuration (e.g. proxy settings): // TODO this is done too late; changes to the configuration done // after the above call to initVMConfiguration are lost
registerConfigChangesListener();
break;
}
} if (!m_xUnoVirtualMachine.is()) { try {
jvmaccess::VirtualMachine::AttachGuard guard(m_xVirtualMachine);
setUpUnoVirtualMachine(guard.getEnvironment());
} catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) {
css::uno::Any anyEx = cppu::getCaughtException(); throw css::lang::WrappedTargetRuntimeException(
u"jvmaccess::VirtualMachine::AttachGuard::CreationException occurred"_ustr,
getXWeak(), anyEx );
}
} switch (returnType) { default: // RETURN_JAVAVM if (m_pJavaVm == nullptr) { throw css::uno::RuntimeException(
u"JavaVirtualMachine service was initialized in a way" " that the requested JavaVM pointer is not available"_ustr,
getXWeak());
} return css::uno::Any(reinterpret_cast< sal_IntPtr >(m_pJavaVm)); case RETURN_VIRTUALMACHINE:
OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *)); return css::uno::Any( reinterpret_cast< sal_Int64 >(
m_xUnoVirtualMachine->getVirtualMachine().get())); case RETURN_UNOVIRTUALMACHINE:
OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *)); return css::uno::Any( reinterpret_cast< sal_Int64 >(m_xUnoVirtualMachine.get()));
}
}
// If a user changes the setting, for example for proxy settings, then this // function will be called from the configuration manager. Even if the .xml // file does not contain an entry yet and that entry has to be inserted, this // function will be called. We call java.lang.System.setProperty for the new // values. void SAL_CALL JavaVirtualMachine::elementReplaced(
css::container::ContainerEvent const & rEvent)
{ // TODO Using the new value stored in rEvent is wrong here. If two threads // receive different elementReplaced calls in quick succession, it is // unspecified which changes the JVM's system properties last. A correct // solution must atomically (i.e., protected by a mutex) read the latest // value from the configuration and set it as a system property at the JVM.
// remove the property if it does not have a value ( user left the dialog field empty) // or if the port is set to 0
aPropertyValue= aPropertyValue.trim(); if( aPropertyValue.isEmpty() ||
((aPropertyName == "http.proxyPort"/*|| aPropertyName == "socksProxyPort"*/) && aPropertyValue == "0")
)
{ // call java.lang.System.getProperties
jmethodID jmGetProps= pJNIEnv->GetStaticMethodID( jcSystem, "getProperties","()Ljava/util/Properties;"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:GetStaticMethodID java.lang.System.getProperties"_ustr, nullptr);
jobject joProperties= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetProps); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:CallStaticObjectMethod java.lang.System.getProperties"_ustr, nullptr); // call java.util.Properties.remove
jclass jcProperties= pJNIEnv->FindClass("java/util/Properties"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:FindClass java/util/Properties"_ustr, nullptr);
jmethodID jmRemove= pJNIEnv->GetMethodID( jcProperties, "remove", "(Ljava/lang/Object;)Ljava/lang/Object;"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:GetMethodID java.util.Properties.remove"_ustr, nullptr);
pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsPropName);
} else
{ // Change the Value of the property
jstring jsPropValue= pJNIEnv->NewString( reinterpret_cast<jchar const *>(aPropertyValue.getStr()), aPropertyValue.getLength()); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:NewString"_ustr, nullptr);
pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsPropName, jsPropValue); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:CallStaticObjectMethod java.lang.System.setProperty"_ustr, nullptr);
}
// If the settings for Security and NetAccess changed then we have to notify the SandboxSecurity // SecurityManager // call System.getSecurityManager() if (bSecurityChanged)
{
jmethodID jmGetSecur= pJNIEnv->GetStaticMethodID( jcSystem,"getSecurityManager","()Ljava/lang/SecurityManager;"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:GetStaticMethodID java.lang.System.getSecurityManager"_ustr, nullptr);
jobject joSecur= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetSecur); if (joSecur != nullptr)
{ // Make sure the SecurityManager is our SandboxSecurity // FindClass("com.sun.star.lib.sandbox.SandboxSecurityManager" only worked at the first time // this code was executed. Maybe it is a security feature. However, all attempts to debug the // SandboxSecurity class (maybe the VM invokes checkPackageAccess) failed. // jclass jcSandboxSec= pJNIEnv->FindClass("com.sun.star.lib.sandbox.SandboxSecurity"); // if(pJNIEnv->ExceptionOccurred()) throw RuntimeException("JNI:FindClass com.sun.star.lib.sandbox.SandboxSecurity"); // jboolean bIsSand= pJNIEnv->IsInstanceOf( joSecur, jcSandboxSec); // The SecurityManagers class Name must be com.sun.star.lib.sandbox.SandboxSecurity
jclass jcSec= pJNIEnv->GetObjectClass( joSecur);
jclass jcClass= pJNIEnv->FindClass("java/lang/Class"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:FindClass java.lang.Class"_ustr, nullptr);
jmethodID jmName= pJNIEnv->GetMethodID( jcClass,"getName","()Ljava/lang/String;"); if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(u"JNI:GetMethodID java.lang.Class.getName"_ustr, nullptr);
jstring jsClass= static_cast<jstring>(pJNIEnv->CallObjectMethod( jcSec, jmName)); const jchar* jcharName= pJNIEnv->GetStringChars( jsClass, nullptr);
OUString sName(reinterpret_cast<sal_Unicode const *>(jcharName)); bool bIsSandbox;
bIsSandbox = sName == "com.sun.star.lib.sandbox.SandboxSecurity";
pJNIEnv->ReleaseStringChars( jsClass, jcharName);
JavaVirtualMachine::~JavaVirtualMachine()
{ if (m_xInetConfiguration.is()) // We should never get here, but just in case... try
{
m_xInetConfiguration->removeContainerListener(this);
} catch (css::uno::Exception &)
{
OSL_FAIL("com.sun.star.uno.Exception caught");
} if (m_xJavaConfiguration.is()) // We should never get here, but just in case... try
{
m_xJavaConfiguration->removeContainerListener(this);
} catch (css::uno::Exception &)
{
OSL_FAIL("com.sun.star.uno.Exception caught");
}
}
/*We listen to changes in the configuration. For example, the user changes the proxy settings in the options dialog (menu tools). Then we are notified of this change and if the java vm is already running we change the properties (System.lang.System.setProperties) through JNI. To receive notifications this class implements XContainerListener.
*/ void JavaVirtualMachine::registerConfigChangesListener()
{ try
{
css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
m_xContext->getValueByName(
u"/singletons/com.sun.star.configuration.theDefaultProvider"_ustr),
css::uno::UNO_QUERY);
if (xConfigProvider.is())
{ // We register this instance as listener to changes in org.openoffice.Inet/Settings // arguments for ConfigurationAccess
css::uno::Sequence<css::uno::Any> aArguments(comphelper::InitAnyPropertySequence(
{
{"nodepath", css::uno::Any(u"org.openoffice.Inet/Settings"_ustr)},
{"depth", css::uno::Any(sal_Int32(-1))}
}));
m_xInetConfiguration.set(
xConfigProvider->createInstanceWithArguments(
u"com.sun.star.configuration.ConfigurationAccess"_ustr,
aArguments),
css::uno::UNO_QUERY);
if (m_xInetConfiguration.is())
m_xInetConfiguration->addContainerListener(this);
// now register as listener to changes in org.openoffice.Java/VirtualMachine
css::uno::Sequence<css::uno::Any> aArguments2(comphelper::InitAnyPropertySequence(
{
{"nodepath", css::uno::Any(u"org.openoffice.Office.Java/VirtualMachine"_ustr)},
{"depth", css::uno::Any(sal_Int32(-1))} // depth: -1 means unlimited
}));
m_xJavaConfiguration.set(
xConfigProvider->createInstanceWithArguments(
u"com.sun.star.configuration.ConfigurationAccess"_ustr,
aArguments2),
css::uno::UNO_QUERY);
if (m_xJavaConfiguration.is())
m_xJavaConfiguration->addContainerListener(this);
}
}catch(const css::uno::Exception & e)
{
SAL_INFO("stoc", "could not set up listener for Configuration because of >" << e << "<");
}
}
// param true: all Inet setting are set as Java Properties on a live VM. // false: the Java net properties are set to empty value. void JavaVirtualMachine::setINetSettingsInVM(bool set_reset)
{
osl::MutexGuard aGuard(m_aMutex); try
{ if (m_xUnoVirtualMachine.is())
{
jvmaccess::VirtualMachine::AttachGuard aAttachGuard(
m_xUnoVirtualMachine->getVirtualMachine());
JNIEnv * pJNIEnv = aAttachGuard.getEnvironment();
// The Java Properties
OUString sHttpProxyHost(u"http.proxyHost"_ustr);
OUString sHttpProxyPort(u"http.proxyPort"_ustr);
OUString sHttpNonProxyHosts(u"http.nonProxyHosts"_ustr);
if (set_reset)
{ // Set all network properties with the VM
JVM jvm;
getINetPropsFromConfig( &jvm, m_xContext->getServiceManager(), m_xContext); const ::std::vector< OUString> & Props = jvm.getProperties();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.