summaryrefslogtreecommitdiffstats
path: root/jvmfwk/source
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /jvmfwk/source
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'jvmfwk/source')
-rw-r--r--jvmfwk/source/elements.cxx971
-rw-r--r--jvmfwk/source/framework.cxx805
-rw-r--r--jvmfwk/source/framework.hxx42
-rw-r--r--jvmfwk/source/fwkbase.cxx518
-rw-r--r--jvmfwk/source/fwkutil.cxx194
-rw-r--r--jvmfwk/source/javasettings.xsd70
-rw-r--r--jvmfwk/source/javasettings_template.xml52
-rw-r--r--jvmfwk/source/libxmlutil.cxx136
8 files changed, 2788 insertions, 0 deletions
diff --git a/jvmfwk/source/elements.cxx b/jvmfwk/source/elements.cxx
new file mode 100644
index 0000000000..d47af20f2e
--- /dev/null
+++ b/jvmfwk/source/elements.cxx
@@ -0,0 +1,971 @@
+/* -*- 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <cassert>
+#include <memory>
+
+#include <elements.hxx>
+#include <osl/mutex.hxx>
+#include <osl/file.hxx>
+#include <fwkutil.hxx>
+#include <fwkbase.hxx>
+#include "framework.hxx"
+#include <libxmlutil.hxx>
+#include <algorithm>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <optional>
+#include <string.h>
+
+// For backwards compatibility, the nRequirements flag word is
+// read/written as potentially signed hexadecimal number (though that has no
+// practical relevance given that it has only one flag with value 0x01
+// defined).
+
+using namespace osl;
+namespace jfw
+{
+
+static OString getElement(OString const & docPath,
+ xmlChar const * pathExpression)
+{
+ //Prepare the xml document and context
+ OSL_ASSERT(!docPath.isEmpty());
+ jfw::CXmlDocPtr doc(xmlParseFile(docPath.getStr()));
+ if (doc == nullptr)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function getElement (elements.cxx)"_ostr);
+
+ jfw::CXPathContextPtr context(xmlXPathNewContext(doc));
+ if (xmlXPathRegisterNs(context, reinterpret_cast<xmlChar const *>("jf"),
+ reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK)) == -1)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function getElement (elements.cxx)"_ostr);
+
+ CXPathObjectPtr pathObj = xmlXPathEvalExpression(pathExpression, context);
+ OString sValue;
+ if (xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ {
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function getElement (elements.cxx)"_ostr);
+ }
+ sValue = reinterpret_cast<char*>(pathObj->nodesetval->nodeTab[0]->content);
+ return sValue;
+}
+
+OString getElementUpdated()
+{
+ return getElement(jfw::getVendorSettingsPath(),
+ reinterpret_cast<xmlChar const *>("/jf:javaSelection/jf:updated/text()"));
+}
+
+void createSettingsStructure(xmlDoc * document, bool * bNeedsSave)
+{
+ OString sExcMsg("[Java framework] Error in function createSettingsStructure "
+ "(elements.cxx)."_ostr);
+ xmlNode * root = xmlDocGetRootElement(document);
+ if (root == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ bool bFound = false;
+ xmlNode * cur = root->children;
+ while (cur != nullptr)
+ {
+ if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("enabled")) == 0)
+ {
+ bFound = true;
+ break;
+ }
+ cur = cur->next;
+ }
+ if (bFound)
+ {
+ *bNeedsSave = false;
+ return;
+ }
+ //We will modify this document
+ *bNeedsSave = true;
+ // Now we create the child elements ------------------
+ //Get xsi:nil namespace
+ xmlNs* nsXsi = xmlSearchNsByHref(
+ document, root, reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+
+ //<enabled xsi:nil="true"
+ xmlNode * nodeEn = xmlNewTextChild(
+ root, nullptr, reinterpret_cast<xmlChar const *>("enabled"), reinterpret_cast<xmlChar const *>(""));
+ if (nodeEn == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlSetNsProp(nodeEn, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
+ //add a new line
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(root, nodeCrLf);
+
+ //<userClassPath xsi:nil="true">
+ xmlNode * nodeUs = xmlNewTextChild(
+ root, nullptr, reinterpret_cast<xmlChar const *>("userClassPath"), reinterpret_cast<xmlChar const *>(""));
+ if (nodeUs == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlSetNsProp(nodeUs, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
+ //add a new line
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(root, nodeCrLf);
+
+ //<vmParameters xsi:nil="true">
+ xmlNode * nodeVm = xmlNewTextChild(
+ root, nullptr, reinterpret_cast<xmlChar const *>("vmParameters"), reinterpret_cast<xmlChar const *>(""));
+ if (nodeVm == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlSetNsProp(nodeVm, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
+ //add a new line
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(root, nodeCrLf);
+
+ //<jreLocations xsi:nil="true">
+ xmlNode * nodeJre = xmlNewTextChild(
+ root, nullptr, reinterpret_cast<xmlChar const *>("jreLocations"), reinterpret_cast<xmlChar const *>(""));
+ if (nodeJre == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlSetNsProp(nodeJre, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
+ //add a new line
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(root, nodeCrLf);
+
+ //<javaInfo xsi:nil="true">
+ xmlNode * nodeJava = xmlNewTextChild(
+ root, nullptr, reinterpret_cast<xmlChar const *>("javaInfo"), reinterpret_cast<xmlChar const *>(""));
+ if (nodeJava == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlSetNsProp(nodeJava, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
+ //add a new line
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(root, nodeCrLf);
+}
+
+NodeJava::NodeJava(Layer layer):
+ m_layer(layer)
+{
+ //This class reads and write to files which should only be done in
+ //application mode
+ if (getMode() == JFW_MODE_DIRECT)
+ throw FrameworkException(
+ JFW_E_DIRECT_MODE,
+ "[Java framework] Trying to access settings files in direct mode."_ostr);
+}
+
+
+void NodeJava::load()
+{
+ static constexpr OString sExcMsg("[Java framework] Error in function NodeJava::load"
+ "(elements.cxx)."_ostr);
+ if (SHARED == m_layer)
+ {
+ //we do not support yet to write into the shared installation
+
+ //check if shared settings exist at all.
+ OUString sURL(BootParams::getSharedData());
+ jfw::FileStatus s = sURL.isEmpty()
+ ? FILE_DOES_NOT_EXIST : checkFileURL(sURL);
+ if (s == FILE_INVALID)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Invalid file for shared Java settings."_ostr);
+ else if (s == FILE_DOES_NOT_EXIST)
+ //Writing shared data is not supported yet.
+ return;
+ }
+ else if (USER == m_layer)
+ {
+ if (!prepareSettingsDocument())
+ {
+ SAL_INFO("jfw.level1", "no path to load user settings document from");
+ return;
+ }
+ }
+ else
+ {
+ OSL_FAIL("[Java framework] Unknown enum used.");
+ }
+
+
+ //Read the user elements
+ OString sSettingsPath = getSettingsPath();
+ //There must not be a share settings file
+ CXmlDocPtr docUser(xmlParseFile(sSettingsPath.getStr()));
+ if (docUser == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ xmlNode * cur = xmlDocGetRootElement(docUser);
+ if (cur == nullptr || cur->children == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ CXmlCharPtr sNil;
+ cur = cur->children;
+ while (cur != nullptr)
+ {
+ if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("enabled")) == 0)
+ {
+ //only overwrite share settings if xsi:nil="false"
+ sNil = xmlGetNsProp(
+ cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if (sNil == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ {
+ CXmlCharPtr sEnabled( xmlNodeListGetString(
+ docUser, cur->children, 1));
+ if (xmlStrcmp(sEnabled, reinterpret_cast<xmlChar const *>("true")) == 0)
+ m_enabled = std::optional<sal_Bool>(true);
+ else if (xmlStrcmp(sEnabled, reinterpret_cast<xmlChar const *>("false")) == 0)
+ m_enabled = std::optional<sal_Bool>(false);
+ }
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("userClassPath")) == 0)
+ {
+ sNil = xmlGetNsProp(
+ cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if (sNil == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ {
+ CXmlCharPtr sUser(xmlNodeListGetString(
+ docUser, cur->children, 1));
+ m_userClassPath = std::optional<OUString>(OUString(sUser));
+ }
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("javaInfo")) == 0)
+ {
+ sNil = xmlGetNsProp(
+ cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if (sNil == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ {
+ if (! m_javaInfo)
+ m_javaInfo = std::optional<CNodeJavaInfo>(CNodeJavaInfo());
+ m_javaInfo->loadFromNode(docUser, cur);
+ }
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vmParameters")) == 0)
+ {
+ sNil = xmlGetNsProp(
+ cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if (sNil == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ {
+ if ( ! m_vmParameters)
+ m_vmParameters = std::optional<std::vector<OUString> >(
+ std::vector<OUString> ());
+
+ xmlNode * pOpt = cur->children;
+ while (pOpt != nullptr)
+ {
+ if (xmlStrcmp(pOpt->name, reinterpret_cast<xmlChar const *>("param")) == 0)
+ {
+ CXmlCharPtr sOpt = xmlNodeListGetString(
+ docUser, pOpt->children, 1);
+ m_vmParameters->push_back(sOpt);
+ }
+ pOpt = pOpt->next;
+ }
+ }
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("jreLocations")) == 0)
+ {
+ sNil = xmlGetNsProp(
+ cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if (sNil == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ {
+ if (! m_JRELocations)
+ m_JRELocations = std::optional<std::vector<OUString> >(
+ std::vector<OUString>());
+
+ xmlNode * pLoc = cur->children;
+ while (pLoc != nullptr)
+ {
+ if (xmlStrcmp(pLoc->name, reinterpret_cast<xmlChar const *>("location")) == 0)
+ {
+ CXmlCharPtr sLoc = xmlNodeListGetString(
+ docUser, pLoc->children, 1);
+ m_JRELocations->push_back(sLoc);
+ }
+ pLoc = pLoc->next;
+ }
+ }
+ }
+ cur = cur->next;
+ }
+}
+
+OString NodeJava::getSettingsPath() const
+{
+ OString ret;
+ switch (m_layer)
+ {
+ case USER: ret = getUserSettingsPath(); break;
+ case SHARED: ret = getSharedSettingsPath(); break;
+ default:
+ OSL_FAIL("[Java framework] NodeJava::getSettingsPath()");
+ }
+ return ret;
+}
+
+OUString NodeJava::getSettingsURL() const
+{
+ OUString ret;
+ switch (m_layer)
+ {
+ case USER: ret = BootParams::getUserData(); break;
+ case SHARED: ret = BootParams::getSharedData(); break;
+ default:
+ OSL_FAIL("[Java framework] NodeJava::getSettingsURL()");
+ }
+ return ret;
+}
+
+bool NodeJava::prepareSettingsDocument() const
+{
+ OString sExcMsg(
+ "[Java framework] Error in function prepareSettingsDocument"
+ " (elements.cxx)."_ostr);
+ if (!createSettingsDocument())
+ {
+ return false;
+ }
+ OString sSettings = getSettingsPath();
+ CXmlDocPtr doc(xmlParseFile(sSettings.getStr()));
+ if (!doc)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ bool bNeedsSave = false;
+ createSettingsStructure(doc, & bNeedsSave);
+ if (bNeedsSave)
+ {
+ if (xmlSaveFormatFileEnc(
+ sSettings.getStr(), doc,"UTF-8", 1) == -1)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ }
+ return true;
+}
+
+void NodeJava::write() const
+{
+ OString sExcMsg("[Java framework] Error in function NodeJava::writeSettings "
+ "(elements.cxx)."_ostr);
+ CXmlDocPtr docUser;
+ CXPathContextPtr contextUser;
+ CXPathObjectPtr pathObj;
+
+ if (!prepareSettingsDocument())
+ {
+ SAL_INFO("jfw.level1", "no path to write settings document to");
+ return;
+ }
+
+ //Read the user elements
+ OString sSettingsPath = getSettingsPath();
+ docUser = xmlParseFile(sSettingsPath.getStr());
+ if (docUser == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ contextUser = xmlXPathNewContext(docUser);
+ if (xmlXPathRegisterNs(contextUser, reinterpret_cast<xmlChar const *>("jf"),
+ reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK)) == -1)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ xmlNode * root = xmlDocGetRootElement(docUser);
+ //Get xsi:nil namespace
+ xmlNs* nsXsi = xmlSearchNsByHref(docUser,
+ root,
+ reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+
+ //set the <enabled> element
+ //The element must exist
+ if (m_enabled)
+ {
+ pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:enabled"),
+ contextUser);
+ if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ xmlNode * nodeEnabled = pathObj->nodesetval->nodeTab[0];
+ xmlSetNsProp(nodeEnabled,
+ nsXsi,
+ reinterpret_cast<xmlChar const *>("nil"),
+ reinterpret_cast<xmlChar const *>("false"));
+
+ if (m_enabled == std::optional<sal_Bool>(true))
+ xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("true"));
+ else
+ xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("false"));
+ }
+
+ //set the <userClassPath> element
+ //The element must exist
+ if (m_userClassPath)
+ {
+ pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:userClassPath"),
+ contextUser);
+ if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ xmlNode * nodeEnabled = pathObj->nodesetval->nodeTab[0];
+ xmlSetNsProp(nodeEnabled, nsXsi, reinterpret_cast<xmlChar const *>("nil"),reinterpret_cast<xmlChar const *>("false"));
+ xmlNodeSetContent(nodeEnabled,static_cast<xmlChar*>(CXmlCharPtr(*m_userClassPath)));
+ }
+
+ //set <javaInfo> element
+ if (m_javaInfo)
+ {
+ pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:javaInfo"),
+ contextUser);
+ if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ m_javaInfo->writeToNode(
+ docUser, pathObj->nodesetval->nodeTab[0]);
+ }
+
+ //set <vmParameters> element
+ if (m_vmParameters)
+ {
+ pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:vmParameters"),
+ contextUser);
+ if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlNode* vmParameters = pathObj->nodesetval->nodeTab[0];
+ //set xsi:nil = false;
+ xmlSetNsProp(vmParameters, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
+ reinterpret_cast<xmlChar const *>("false"));
+
+ //remove option elements
+ xmlNode* cur = vmParameters->children;
+ while (cur != nullptr)
+ {
+ xmlNode* lastNode = cur;
+ cur = cur->next;
+ xmlUnlinkNode(lastNode);
+ xmlFreeNode(lastNode);
+ }
+ //add a new line after <vmParameters>
+ if (!m_vmParameters->empty())
+ {
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(vmParameters, nodeCrLf);
+ }
+
+ for (auto const & vmParameter : *m_vmParameters)
+ {
+ xmlNewTextChild(vmParameters, nullptr, reinterpret_cast<xmlChar const *>("param"),
+ CXmlCharPtr(vmParameter));
+ //add a new line
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(vmParameters, nodeCrLf);
+ }
+ }
+
+ //set <jreLocations> element
+ if (m_JRELocations)
+ {
+ pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:jreLocations"),
+ contextUser);
+ if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlNode* jreLocationsNode = pathObj->nodesetval->nodeTab[0];
+ //set xsi:nil = false;
+ xmlSetNsProp(jreLocationsNode, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
+ reinterpret_cast<xmlChar const *>("false"));
+
+ //remove option elements
+ xmlNode* cur = jreLocationsNode->children;
+ while (cur != nullptr)
+ {
+ xmlNode* lastNode = cur;
+ cur = cur->next;
+ xmlUnlinkNode(lastNode);
+ xmlFreeNode(lastNode);
+ }
+ //add a new line after <vmParameters>
+ if (!m_JRELocations->empty())
+ {
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(jreLocationsNode, nodeCrLf);
+ }
+
+ for (auto const & JRELocation : *m_JRELocations)
+ {
+ xmlNewTextChild(jreLocationsNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
+ CXmlCharPtr(JRELocation));
+ //add a new line
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(jreLocationsNode, nodeCrLf);
+ }
+ }
+
+ if (xmlSaveFormatFile(sSettingsPath.getStr(), docUser, 1) == -1)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+}
+
+void NodeJava::setEnabled(bool bEnabled)
+{
+ m_enabled = std::optional<sal_Bool>(bEnabled);
+}
+
+
+void NodeJava::setUserClassPath(const OUString & sClassPath)
+{
+ m_userClassPath = std::optional<OUString>(sClassPath);
+}
+
+void NodeJava::setJavaInfo(const JavaInfo * pInfo, bool bAutoSelect)
+{
+ if (!m_javaInfo)
+ m_javaInfo = std::optional<CNodeJavaInfo>(CNodeJavaInfo());
+ m_javaInfo->bAutoSelect = bAutoSelect;
+ m_javaInfo->bNil = false;
+
+ if (pInfo != nullptr)
+ {
+ m_javaInfo->m_bEmptyNode = false;
+ m_javaInfo->sVendor = pInfo->sVendor;
+ m_javaInfo->sLocation = pInfo->sLocation;
+ m_javaInfo->sVersion = pInfo->sVersion;
+ m_javaInfo->nRequirements = pInfo->nRequirements;
+ m_javaInfo->arVendorData = pInfo->arVendorData;
+ }
+ else
+ {
+ m_javaInfo->m_bEmptyNode = true;
+ m_javaInfo->sVendor.clear();
+ m_javaInfo->sLocation.clear();
+ m_javaInfo->sVersion.clear();
+ m_javaInfo->nRequirements = 0;
+ m_javaInfo->arVendorData = rtl::ByteSequence();
+ }
+}
+
+void NodeJava::setVmParameters(std::vector<OUString> const & arOptions)
+{
+ m_vmParameters = std::optional<std::vector<OUString> >(arOptions);
+}
+
+void NodeJava::addJRELocation(OUString const & sLocation)
+{
+ if (!m_JRELocations)
+ m_JRELocations = std::optional<std::vector<OUString> >(
+ std::vector<OUString> ());
+ //only add the path if not already present
+ std::vector<OUString>::const_iterator it =
+ std::find(m_JRELocations->begin(), m_JRELocations->end(), sLocation);
+ if (it == m_JRELocations->end())
+ m_JRELocations->push_back(sLocation);
+}
+
+jfw::FileStatus NodeJava::checkSettingsFileStatus(OUString const & sURL)
+{
+ jfw::FileStatus ret = FILE_DOES_NOT_EXIST;
+
+ //check the file time
+ ::osl::DirectoryItem item;
+ File::RC rc = ::osl::DirectoryItem::get(sURL, item);
+ if (File::E_None == rc)
+ {
+ ::osl::FileStatus stat(osl_FileStatus_Mask_Validate);
+ File::RC rc_stat = item.getFileStatus(stat);
+ if (File::E_None == rc_stat)
+ {
+ ret = FILE_OK;
+ }
+ else if (File::E_NOENT == rc_stat)
+ {
+ ret = FILE_DOES_NOT_EXIST;
+ }
+ else
+ {
+ ret = FILE_INVALID;
+ }
+ }
+ else if(File::E_NOENT == rc)
+ {
+ ret = FILE_DOES_NOT_EXIST;
+ }
+ else
+ {
+ ret = FILE_INVALID;
+ }
+ return ret;
+}
+
+bool NodeJava::createSettingsDocument() const
+{
+ const OUString sURL = getSettingsURL();
+ if (sURL.isEmpty())
+ {
+ return false;
+ }
+ //make sure there is a user directory
+ OString sExcMsg("[Java framework] Error in function createSettingsDocument "
+ "(elements.cxx)."_ostr);
+ // check if javasettings.xml already exist
+ if (FILE_OK == checkSettingsFileStatus(sURL))
+ return true;
+
+ //make sure that the directories are created in case they do not exist
+ FileBase::RC rcFile = Directory::createPath(getDirFromFile(sURL));
+ if (rcFile != FileBase::E_EXIST && rcFile != FileBase::E_None)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ //javasettings.xml does not exist yet
+ CXmlDocPtr doc(xmlNewDoc(reinterpret_cast<xmlChar const *>("1.0")));
+ if (! doc)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ //Create the root element and name spaces
+ xmlNodePtr root = xmlNewDocNode(
+ doc, nullptr, reinterpret_cast<xmlChar const *>("java"), reinterpret_cast<xmlChar const *>("\n"));
+
+ if (root == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ if (xmlNewNs(root, reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK),nullptr) == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (xmlNewNs(root,reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE),reinterpret_cast<xmlChar const *>("xsi")) == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ xmlDocSetRootElement(doc, root);
+
+ //Create a comment
+ xmlNodePtr com = xmlNewComment(
+ reinterpret_cast<xmlChar const *>("This is a generated file. Do not alter this file!"));
+ if (com == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ if (xmlAddPrevSibling(root, com) == nullptr)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ const OString path = getSettingsPath();
+ if (xmlSaveFormatFileEnc(path.getStr(), doc,"UTF-8", 1) == -1)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ return true;
+}
+
+
+CNodeJavaInfo::CNodeJavaInfo() :
+ m_bEmptyNode(false), bNil(true), bAutoSelect(true),
+ nRequirements(0)
+{
+}
+
+void CNodeJavaInfo::loadFromNode(xmlDoc * pDoc, xmlNode * pJavaInfo)
+{
+ OString sExcMsg("[Java framework] Error in function NodeJavaInfo::loadFromNode "
+ "(elements.cxx)."_ostr);
+
+ OSL_ASSERT(pJavaInfo && pDoc);
+ if (pJavaInfo->children == nullptr)
+ return;
+ //Get the xsi:nil attribute;
+ CXmlCharPtr sNil = xmlGetNsProp(
+ pJavaInfo, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+ if ( ! sNil)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("true")) == 0)
+ bNil = true;
+ else if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
+ bNil = false;
+ else
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ if (bNil)
+ return;
+
+ //Get javaInfo@manuallySelected attribute
+ CXmlCharPtr sAutoSelect = xmlGetProp(
+ pJavaInfo, reinterpret_cast<xmlChar const *>("autoSelect"));
+ if ( ! sAutoSelect)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("true")) == 0)
+ bAutoSelect = true;
+ else if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("false")) == 0)
+ bAutoSelect = false;
+ else
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+
+ xmlNode * cur = pJavaInfo->children;
+
+ while (cur != nullptr)
+ {
+ if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendor")) == 0)
+ {
+ CXmlCharPtr xmlVendor = xmlNodeListGetString(
+ pDoc, cur->children, 1);
+ if (! xmlVendor)
+ return;
+ sVendor = xmlVendor;
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("location")) == 0)
+ {
+ CXmlCharPtr xmlLocation = xmlNodeListGetString(
+ pDoc, cur->children, 1);
+ sLocation = xmlLocation;
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("version")) == 0)
+ {
+ CXmlCharPtr xmlVersion = xmlNodeListGetString(
+ pDoc, cur->children, 1);
+ sVersion = xmlVersion;
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("requirements")) == 0)
+ {
+ CXmlCharPtr xmlRequire = xmlNodeListGetString(
+ pDoc, cur->children, 1);
+ OUString sRequire = xmlRequire;
+ nRequirements = sRequire.toInt64(16);
+#ifdef MACOSX
+ //javaldx is not used anymore in the mac build. In case the Java
+ //corresponding to the saved settings does not exist anymore the
+ //javavm services will look for an existing Java after creation of
+ //the JVM failed. See stoc/source/javavm/javavm.cxx. Only if
+ //nRequirements does not have the flag JFW_REQUIRE_NEEDRESTART the
+ //jvm of the new selected JRE will be started. Old settings (before
+ //OOo 3.3) still contain the flag which can be safely ignored.
+ nRequirements &= ~JFW_REQUIRE_NEEDRESTART;
+#endif
+ }
+ else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendorData")) == 0)
+ {
+ CXmlCharPtr xmlData = xmlNodeListGetString(
+ pDoc, cur->children, 1);
+ xmlChar* _data = static_cast<xmlChar*>(xmlData);
+ if (_data)
+ {
+ rtl::ByteSequence seq(reinterpret_cast<sal_Int8*>(_data), strlen(reinterpret_cast<char*>(_data)));
+ arVendorData = decodeBase16(seq);
+ }
+ }
+ cur = cur->next;
+ }
+
+ if (sVendor.isEmpty())
+ m_bEmptyNode = true;
+ //Get the javainfo attributes
+ CXmlCharPtr sVendorUpdate = xmlGetProp(pJavaInfo,
+ reinterpret_cast<xmlChar const *>("vendorUpdate"));
+ if ( ! sVendorUpdate)
+ throw FrameworkException(JFW_E_ERROR, sExcMsg);
+ sAttrVendorUpdate = sVendorUpdate;
+}
+
+
+void CNodeJavaInfo::writeToNode(xmlDoc* pDoc,
+ xmlNode* pJavaInfoNode) const
+
+{
+ OSL_ASSERT(pJavaInfoNode && pDoc);
+ //write the attribute vendorSettings
+
+ //javaInfo@vendorUpdate
+ //creates the attribute if necessary
+ OString sUpdated = getElementUpdated();
+
+ xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("vendorUpdate"),
+ reinterpret_cast<xmlChar const *>(sUpdated.getStr()));
+
+ //javaInfo@autoSelect
+ xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("autoSelect"),
+ reinterpret_cast<xmlChar const *>(bAutoSelect ? "true" : "false"));
+
+ //Set xsi:nil in javaInfo element to false
+ //the xmlNs pointer must not be destroyed
+ xmlNs* nsXsi = xmlSearchNsByHref(pDoc,
+ pJavaInfoNode,
+ reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
+
+ xmlSetNsProp(pJavaInfoNode,
+ nsXsi,
+ reinterpret_cast<xmlChar const *>("nil"),
+ reinterpret_cast<xmlChar const *>("false"));
+
+ //Delete the children of JavaInfo
+ xmlNode* cur = pJavaInfoNode->children;
+ while (cur != nullptr)
+ {
+ xmlNode* lastNode = cur;
+ cur = cur->next;
+ xmlUnlinkNode(lastNode);
+ xmlFreeNode(lastNode);
+ }
+
+ //If the JavaInfo was set with an empty value,
+ //then we are done.
+ if (m_bEmptyNode)
+ return;
+
+ //add a new line after <javaInfo>
+ xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+ //Create the vendor element
+ xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("vendor"),
+ CXmlCharPtr(sVendor));
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+ //Create the location element
+ xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
+ CXmlCharPtr(sLocation));
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+ //Create the version element
+ xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("version"),
+ CXmlCharPtr(sVersion));
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+ //Create the features element, for backwards compatibility (it used to support one flag
+ // JFW_FEATURE_ACCESSBRIDGE = 0x01, but is ignored and always written as zero now)
+ xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("features"),
+ reinterpret_cast<xmlChar const *>("0"));
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+
+ //Create the requirements element
+ OUString sRequirements = OUString::number(
+ nRequirements, 16);
+ xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("requirements"),
+ CXmlCharPtr(sRequirements));
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+
+
+ //Create the vendorData element
+ rtl::ByteSequence data = encodeBase16(arVendorData);
+ xmlNode* dataNode = xmlNewChild(pJavaInfoNode, nullptr,
+ reinterpret_cast<xmlChar const *>("vendorData"),
+ reinterpret_cast<xmlChar const *>(""));
+ xmlNodeSetContentLen(dataNode,
+ reinterpret_cast<xmlChar*>(data.getArray()), data.getLength());
+ //add a new line for better readability
+ nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
+ xmlAddChild(pJavaInfoNode, nodeCrLf);
+}
+
+std::unique_ptr<JavaInfo> CNodeJavaInfo::makeJavaInfo() const
+{
+ if (bNil || m_bEmptyNode)
+ return std::unique_ptr<JavaInfo>();
+ return std::unique_ptr<JavaInfo>(
+ new JavaInfo{
+ sVendor, sLocation, sVersion, nRequirements,
+ arVendorData});
+}
+
+
+MergedSettings::MergedSettings():
+ m_bEnabled(false)
+{
+ NodeJava settings(NodeJava::USER);
+ settings.load();
+ NodeJava sharedSettings(NodeJava::SHARED);
+ sharedSettings.load();
+ merge(sharedSettings, settings);
+}
+
+MergedSettings::~MergedSettings()
+{
+}
+
+void MergedSettings::merge(const NodeJava & share, const NodeJava & user)
+{
+ if (user.getEnabled())
+ m_bEnabled = * user.getEnabled();
+ else if (share.getEnabled())
+ m_bEnabled = * share.getEnabled();
+ else
+ m_bEnabled = true;
+
+ if (user.getUserClassPath())
+ m_sClassPath = * user.getUserClassPath();
+ else if (share.getUserClassPath())
+ m_sClassPath = * share.getUserClassPath();
+
+ if (user.getJavaInfo())
+ m_javaInfo = * user.getJavaInfo();
+ else if (share.getJavaInfo())
+ m_javaInfo = * share.getJavaInfo();
+
+ if (user.getVmParameters())
+ m_vmParams = * user.getVmParameters();
+ else if (share.getVmParameters())
+ m_vmParams = * share.getVmParameters();
+
+ if (user.getJRELocations())
+ m_JRELocations = * user.getJRELocations();
+ else if (share.getJRELocations())
+ m_JRELocations = * share.getJRELocations();
+}
+
+
+::std::vector< OString> MergedSettings::getVmParametersUtf8() const
+{
+ ::std::vector< OString> ret;
+ for (auto const & vmParam : m_vmParams)
+ {
+ ret.push_back( OUStringToOString(vmParam, RTL_TEXTENCODING_UTF8));
+ }
+ return ret;
+}
+
+
+std::unique_ptr<JavaInfo> MergedSettings::createJavaInfo() const
+{
+ return m_javaInfo.makeJavaInfo();
+}
+#ifdef _WIN32
+bool MergedSettings::getJavaInfoAttrAutoSelect() const
+{
+ return m_javaInfo.bAutoSelect;
+}
+#endif
+void MergedSettings::getVmParametersArray(std::vector<OUString> * parParams)
+ const
+{
+ assert(parParams != nullptr);
+ osl::MutexGuard guard(FwkMutex());
+
+ *parParams = m_vmParams;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/jvmfwk/source/framework.cxx b/jvmfwk/source/framework.cxx
new file mode 100644
index 0000000000..0e74420e39
--- /dev/null
+++ b/jvmfwk/source/framework.cxx
@@ -0,0 +1,805 @@
+/* -*- 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <cassert>
+#include <memory>
+
+#include <rtl/bootstrap.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+#include <osl/file.hxx>
+#ifdef _WIN32
+#include <osl/process.h>
+#endif
+#include <osl/thread.hxx>
+#include <jvmfwk/framework.hxx>
+#include <vendorbase.hxx>
+#include <vendorplugin.hxx>
+#include <vector>
+#include <algorithm>
+#include "framework.hxx"
+#include <fwkutil.hxx>
+#include <elements.hxx>
+#include <fwkbase.hxx>
+
+namespace {
+
+bool g_bEnabledSwitchedOn = false;
+
+JavaVM * g_pJavaVM = nullptr;
+
+bool areEqualJavaInfo(
+ JavaInfo const * pInfoA,JavaInfo const * pInfoB)
+{
+ return jfw_areEqualJavaInfo(pInfoA, pInfoB);
+}
+
+}
+
+javaFrameworkError jfw_findAllJREs(std::vector<std::unique_ptr<JavaInfo>> *pparInfo)
+{
+ assert(pparInfo != nullptr);
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+
+ jfw::VendorSettings aVendorSettings;
+ std::vector<std::unique_ptr<JavaInfo>> vecInfo;
+
+ //Use all plug-in libraries to get Java installations.
+ std::vector<std::unique_ptr<JavaInfo>> arInfos;
+ std::vector<rtl::Reference<jfw_plugin::VendorBase>> infos;
+ javaPluginError plerr = jfw_plugin_getAllJavaInfos(
+ true,
+ aVendorSettings,
+ & arInfos,
+ infos);
+
+ if (plerr != javaPluginError::NONE)
+ return JFW_E_ERROR;
+
+ for (auto & j: arInfos)
+ vecInfo.push_back(std::move(j));
+
+ // direct mode disregards Java settings, so only retrieve
+ // JREs from settings when application mode is used
+ if (jfw::getMode() == jfw::JFW_MODE_APPLICATION)
+ {
+ //get the list of paths to jre locations which have been
+ //added manually
+ const jfw::MergedSettings settings;
+ const std::vector<OUString> vecJRELocations =
+ settings.getJRELocations();
+ //Check if any plugin can detect JREs at the location
+ // of the paths added by jfw_addJRELocation
+ //Check every manually added location
+ for (auto const & ii: vecJRELocations)
+ {
+ std::unique_ptr<JavaInfo> aInfo;
+ plerr = jfw_plugin_getJavaInfoByPath(
+ ii,
+ aVendorSettings,
+ &aInfo);
+ if (plerr == javaPluginError::NoJre)
+ continue;
+ if (plerr == javaPluginError::FailedVersion)
+ continue;
+ if (plerr == javaPluginError::WrongArch)
+ continue;
+ else if (plerr != javaPluginError::NONE)
+ return JFW_E_ERROR;
+
+ // Was this JRE already added?
+ if (std::none_of(
+ vecInfo.begin(), vecInfo.end(),
+ [&aInfo](std::unique_ptr<JavaInfo> const & info) {
+ return areEqualJavaInfo(
+ info.get(), aInfo.get());
+ }))
+ {
+ vecInfo.push_back(std::move(aInfo));
+ }
+ }
+ }
+
+ *pparInfo = std::move(vecInfo);
+
+ return JFW_E_NONE;
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ SAL_WARN( "jfw", e.message);
+ return e.errorCode;
+ }
+}
+
+std::vector<OUString> jfw_convertUserPathList(OUString const& sUserPath)
+{
+ std::vector<OUString> result;
+ sal_Int32 nIdx = 0;
+ do
+ {
+ sal_Int32 nextColon = sUserPath.indexOf(SAL_PATHSEPARATOR, nIdx);
+ OUString sToken(sUserPath.subView(nIdx, nextColon > 0 ? nextColon - nIdx
+ : sUserPath.getLength() - nIdx));
+
+ // Check if we are in bootstrap variable mode (class path starts with '$').
+ // Then the class path must be in URL format.
+ if (sToken.startsWith("$"))
+ {
+ // Detect open bootstrap variables - they might contain colons - we need to skip those.
+ sal_Int32 nBootstrapVarStart = sToken.indexOf("${");
+ if (nBootstrapVarStart >= 0)
+ {
+ sal_Int32 nBootstrapVarEnd = sToken.indexOf("}", nBootstrapVarStart);
+ if (nBootstrapVarEnd == -1)
+ {
+ // Current colon is part of bootstrap variable - skip it!
+ nextColon = sUserPath.indexOf(SAL_PATHSEPARATOR, nextColon + 1);
+ sToken = sUserPath.subView(nIdx, nextColon > 0 ? nextColon - nIdx
+ : sUserPath.getLength() - nIdx);
+ }
+ }
+ }
+ result.emplace_back(sToken);
+ nIdx = nextColon + 1;
+ } while (nIdx > 0);
+ return result;
+}
+
+javaFrameworkError jfw_startVM(
+ JavaInfo const * pInfo, std::vector<OUString> const & arOptions,
+ JavaVM ** ppVM, JNIEnv ** ppEnv)
+{
+ assert(ppVM != nullptr);
+ javaFrameworkError errcode = JFW_E_NONE;
+
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+
+ //We keep this pointer so we can determine if a VM has already
+ //been created.
+ if (g_pJavaVM != nullptr)
+ return JFW_E_RUNNING_JVM;
+
+ std::vector<OString> vmParams;
+ OString sUserClassPath;
+ std::unique_ptr<JavaInfo> aInfo;
+ if (pInfo == nullptr)
+ {
+ jfw::JFW_MODE mode = jfw::getMode();
+ if (mode == jfw::JFW_MODE_APPLICATION)
+ {
+ const jfw::MergedSettings settings;
+ if (!settings.getEnabled())
+ return JFW_E_JAVA_DISABLED;
+ aInfo = settings.createJavaInfo();
+ //check if a Java has ever been selected
+ if (!aInfo)
+ return JFW_E_NO_SELECT;
+
+ //check if the javavendors.xml has changed after a Java was selected
+ OString sVendorUpdate = jfw::getElementUpdated();
+
+ if (sVendorUpdate != settings.getJavaInfoAttrVendorUpdate())
+ return JFW_E_INVALID_SETTINGS;
+
+ //check if JAVA is disabled
+ //If Java is enabled, but it was disabled when this process was started
+ // then no preparational work, such as setting the LD_LIBRARY_PATH, was
+ //done. Therefore if a JRE needs it, it must not be started.
+ if (g_bEnabledSwitchedOn &&
+ (aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART))
+ return JFW_E_NEED_RESTART;
+
+ //Check if the selected Java was set in this process. If so it
+ //must not have the requirements flag JFW_REQUIRE_NEEDRESTART
+ if ((aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART)
+ && jfw::wasJavaSelectedInSameProcess())
+ return JFW_E_NEED_RESTART;
+
+ vmParams = settings.getVmParametersUtf8();
+ // Expand user classpath (might contain bootstrap vars)
+ OUString sUserPath(settings.getUserClassPath());
+ std::vector paths = jfw_convertUserPathList(sUserPath);
+ OUString sUserPathExpanded;
+ for (auto& path : paths)
+ {
+ if (!sUserPathExpanded.isEmpty())
+ sUserPathExpanded += OUStringChar(SAL_PATHSEPARATOR);
+ if (path.startsWith("$"))
+ {
+ OUString sURL = path;
+ rtl::Bootstrap::expandMacros(sURL);
+ osl::FileBase::getSystemPathFromFileURL(sURL, path);
+ }
+ sUserPathExpanded += path;
+ }
+ sUserClassPath = jfw::makeClassPathOption(sUserPathExpanded);
+ } // end mode FWK_MODE_OFFICE
+ else if (mode == jfw::JFW_MODE_DIRECT)
+ {
+ errcode = jfw_getSelectedJRE(&aInfo);
+ if (errcode != JFW_E_NONE)
+ return errcode;
+ //In direct mode the options are specified by bootstrap variables
+ //of the form UNO_JAVA_JFW_PARAMETER_1 .. UNO_JAVA_JFW_PARAMETER_n
+ vmParams = jfw::BootParams::getVMParameters();
+ auto const cp = jfw::BootParams::getClasspath();
+ if (!cp.isEmpty())
+ {
+ sUserClassPath =
+ "-Djava.class.path=" + cp;
+ }
+ }
+ else
+ OSL_ASSERT(false);
+ pInfo = aInfo.get();
+ }
+ assert(pInfo != nullptr);
+
+#ifdef _WIN32
+ // Alternative JREs (AdoptOpenJDK, Azul Zulu) are missing the bin/ folder in
+ // java.library.path. Somehow setting java.library.path accordingly doesn't work,
+ // but the PATH gets picked up, so add it there.
+ // Without this hack, some features don't work in alternative JREs.
+ OUString sPATH;
+ osl_getEnvironment(OUString("PATH").pData, &sPATH.pData);
+ OUString sJRELocation;
+ osl::FileBase::getSystemPathFromFileURL(pInfo->sLocation + "/bin", sJRELocation);
+ if (sPATH.isEmpty())
+ sPATH = sJRELocation;
+ else
+ sPATH = sJRELocation + OUStringChar(SAL_PATHSEPARATOR) + sPATH;
+ osl_setEnvironment(OUString("PATH").pData, sPATH.pData);
+#endif // _WIN32
+
+ // create JavaVMOptions array that is passed to the plugin
+ // it contains the classpath and all options set in the
+ //options dialog
+ std::unique_ptr<JavaVMOption[]> sarJOptions(
+ new JavaVMOption[
+ arOptions.size() + (sUserClassPath.isEmpty() ? 2 : 3) + vmParams.size()]);
+ JavaVMOption * arOpt = sarJOptions.get();
+ if (! arOpt)
+ return JFW_E_ERROR;
+
+ //The first argument is the classpath
+ int index = 0;
+ if (!sUserClassPath.isEmpty()) {
+ arOpt[index].optionString= const_cast<char*>(sUserClassPath.getStr());
+ arOpt[index].extraInfo = nullptr;
+ ++index;
+ }
+ // Set a flag that this JVM has been created via the JNI Invocation API
+ // (used, for example, by UNO remote bridges to share a common thread pool
+ // factory among Java and native bridge implementations):
+ arOpt[index].optionString = const_cast<char *>("-Dorg.openoffice.native=");
+ arOpt[index].extraInfo = nullptr;
+ ++index;
+
+ // Don't intercept SIGTERM
+ arOpt[index].optionString = const_cast<char *>("-Xrs");
+ arOpt[index].extraInfo = nullptr;
+ ++index;
+
+ //add the options set by options dialog
+ for (auto const & vmParam : vmParams)
+ {
+ arOpt[index].optionString = const_cast<char*>(vmParam.getStr());
+ arOpt[index].extraInfo = nullptr;
+ index ++;
+ }
+ //add all options of the arOptions argument
+ std::vector<OString> convertedOptions;
+ for (auto const & ii: arOptions)
+ {
+ OString conv = OUStringToOString(ii, osl_getThreadTextEncoding());
+ convertedOptions.push_back(conv);
+ // keep conv.getStr() alive until after the call to
+ // jfw_plugin_startJavaVirtualMachine below
+ arOpt[index].optionString = const_cast<char *>(conv.getStr());
+ arOpt[index].extraInfo = nullptr;
+ index++;
+ }
+
+ //start Java
+ JavaVM *pVm = nullptr;
+ SAL_INFO("jfw", "Starting Java");
+ javaPluginError plerr = jfw_plugin_startJavaVirtualMachine(pInfo, arOpt, index, & pVm, ppEnv);
+ if (plerr == javaPluginError::VmCreationFailed)
+ {
+ errcode = JFW_E_VM_CREATION_FAILED;
+ }
+ else if (plerr != javaPluginError::NONE )
+ {
+ errcode = JFW_E_ERROR;
+ }
+ else
+ {
+ g_pJavaVM = pVm;
+ *ppVM = pVm;
+ }
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message);
+ }
+
+ return errcode;
+}
+
+/** We do not use here jfw_findAllJREs and then check if a JavaInfo
+ meets the requirements, because that means using all plug-ins, which
+ may take quite a while. The implementation first inspects JAVA_HOME and
+ PATH environment variables. If no suitable JavaInfo is found there, it
+ inspects all JavaInfos found by the jfw_plugin_get* functions.
+ */
+javaFrameworkError jfw_findAndSelectJRE(std::unique_ptr<JavaInfo> *pInfo)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ std::unique_ptr<JavaInfo> aCurrentInfo;
+
+
+ // 'bInfoFound' indicates whether a Java installation has been found
+ bool bInfoFound = false;
+
+ // get list of vendors for Java installations
+ jfw::VendorSettings aVendorSettings;
+
+ std::vector<rtl::Reference<jfw_plugin::VendorBase>> infos;
+
+ // first inspect Java installation that the JAVA_HOME
+ // environment variable points to (if it is set)
+ if (jfw_plugin_getJavaInfoFromJavaHome(
+ aVendorSettings, &aCurrentInfo, infos)
+ == javaPluginError::NONE)
+ {
+ bInfoFound = true;
+ }
+
+ // if no Java installation was detected by using JAVA_HOME,
+ // query PATH for Java installations
+ if (!bInfoFound)
+ {
+ std::vector<std::unique_ptr<JavaInfo>> vecJavaInfosFromPath;
+ if (jfw_plugin_getJavaInfosFromPath(
+ aVendorSettings, vecJavaInfosFromPath, infos)
+ == javaPluginError::NONE)
+ {
+ assert(!vecJavaInfosFromPath.empty());
+ aCurrentInfo = std::move(vecJavaInfosFromPath[0]);
+ bInfoFound = true;
+ }
+ }
+
+
+ // if no suitable Java installation has been found yet:
+ // first use jfw_plugin_getAllJavaInfos to find a suitable Java installation,
+ // then try paths that have been added manually
+ if (!bInfoFound)
+ {
+ //get all installations
+ std::vector<std::unique_ptr<JavaInfo>> arInfos;
+ javaPluginError plerr = jfw_plugin_getAllJavaInfos(
+ false,
+ aVendorSettings,
+ & arInfos,
+ infos);
+
+ if (plerr == javaPluginError::NONE && !arInfos.empty())
+ {
+ aCurrentInfo = std::move(arInfos[0]);
+ }
+
+ if (!aCurrentInfo)
+ {//The plug-ins did not find a suitable Java. Now try the paths which have been
+ //added manually.
+ //get the list of paths to jre locations which have been added manually
+ const jfw::MergedSettings settings;
+ //node.loadFromSettings();
+ const std::vector<OUString> & vecJRELocations =
+ settings.getJRELocations();
+ //use all plug-ins to determine the JavaInfo objects
+ for (auto const & JRELocation : vecJRELocations)
+ {
+ std::unique_ptr<JavaInfo> aInfo;
+ javaPluginError err = jfw_plugin_getJavaInfoByPath(
+ JRELocation,
+ aVendorSettings,
+ &aInfo);
+ if (err == javaPluginError::NoJre)
+ continue;
+ if (err == javaPluginError::FailedVersion)
+ continue;
+ else if (err !=javaPluginError::NONE)
+ return JFW_E_ERROR;
+
+ if (aInfo)
+ {
+ aCurrentInfo = std::move(aInfo);
+ break;
+ }
+ }//end iterate over paths
+ }
+ }
+ if (aCurrentInfo)
+ {
+ jfw::NodeJava javaNode(jfw::NodeJava::USER);
+ javaNode.setJavaInfo(aCurrentInfo.get(),true);
+ javaNode.write();
+ //remember that this JRE was selected in this process
+ jfw::setJavaSelected();
+
+ if (pInfo !=nullptr)
+ {
+ *pInfo = std::move(aCurrentInfo);
+ }
+ }
+ else
+ {
+ errcode = JFW_E_NO_JAVA_FOUND;
+ }
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+
+ return errcode;
+}
+
+bool jfw_areEqualJavaInfo(JavaInfo const * pInfoA,JavaInfo const * pInfoB)
+{
+ if (pInfoA == pInfoB)
+ return true;
+ if (pInfoA == nullptr || pInfoB == nullptr)
+ return false;
+ if (pInfoA->sVendor == pInfoB->sVendor
+ && pInfoA->sLocation == pInfoB->sLocation
+ && pInfoA->sVersion == pInfoB->sVersion
+ && pInfoA->nRequirements == pInfoB->nRequirements
+ && pInfoA->arVendorData == pInfoB->arVendorData)
+ {
+ return true;
+ }
+ return false;
+}
+
+javaFrameworkError jfw_getSelectedJRE(std::unique_ptr<JavaInfo> *ppInfo)
+{
+ assert(ppInfo != nullptr);
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ {
+ if ((errcode = jfw_getJavaInfoByPath(
+ jfw::BootParams::getJREHome(), ppInfo))
+ != JFW_E_NONE)
+ throw jfw::FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] The JRE specified by the bootstrap "
+ "variable UNO_JAVA_JFW_JREHOME or UNO_JAVA_JFW_ENV_JREHOME "
+ " could not be recognized. Check the values and make sure that you "
+ "use a plug-in library that can recognize that JRE."_ostr);
+
+ return JFW_E_NONE;
+ }
+
+ const jfw::MergedSettings settings;
+ *ppInfo = settings.createJavaInfo();
+ if (!*ppInfo)
+ {
+ return JFW_E_NONE;
+ }
+ //If the javavendors.xml has changed, then the current selected
+ //Java is not valid anymore
+ // /java/javaInfo/@vendorUpdate != javaSelection/updated (javavendors.xml)
+ OString sUpdated = jfw::getElementUpdated();
+
+ if (sUpdated != settings.getJavaInfoAttrVendorUpdate())
+ {
+ ppInfo->reset();
+ return JFW_E_INVALID_SETTINGS;
+ }
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+bool jfw_isVMRunning()
+{
+ osl::MutexGuard guard(jfw::FwkMutex());
+ return g_pJavaVM != nullptr;
+}
+
+javaFrameworkError jfw_getJavaInfoByPath(OUString const & pPath, std::unique_ptr<JavaInfo> *ppInfo)
+{
+ assert(ppInfo != nullptr);
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+
+ jfw::VendorSettings aVendorSettings;
+
+ //ask all plugins if this is a JRE.
+ //If so check if it meets the version requirements.
+ //Only if it does return a JavaInfo
+ javaPluginError plerr = jfw_plugin_getJavaInfoByPath(
+ pPath,
+ aVendorSettings,
+ ppInfo);
+
+ if(plerr == javaPluginError::FailedVersion)
+ {//found JRE but it has the wrong version
+ ppInfo->reset();
+ errcode = JFW_E_FAILED_VERSION;
+ }
+ OSL_ASSERT(plerr == javaPluginError::NONE || plerr == javaPluginError::NoJre);
+ if (!*ppInfo && errcode != JFW_E_FAILED_VERSION)
+ errcode = JFW_E_NOT_RECOGNIZED;
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+
+ return errcode;
+}
+
+
+javaFrameworkError jfw_setSelectedJRE(JavaInfo const *pInfo)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ //check if pInfo is the selected JRE
+ std::unique_ptr<JavaInfo> currentInfo;
+ errcode = jfw_getSelectedJRE( & currentInfo);
+ if (errcode != JFW_E_NONE && errcode != JFW_E_INVALID_SETTINGS)
+ return errcode;
+
+ if (!jfw_areEqualJavaInfo(currentInfo.get(), pInfo))
+ {
+ jfw::NodeJava node(jfw::NodeJava::USER);
+ node.setJavaInfo(pInfo, false);
+ node.write();
+ //remember that the JRE was selected in this process
+ jfw::setJavaSelected();
+ }
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+javaFrameworkError jfw_setEnabled(bool bEnabled)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+
+ if (!g_bEnabledSwitchedOn && bEnabled)
+ {
+ //When the process started then Enabled was false.
+ //This is first time enabled is set to true.
+ //That means, no preparational work has been done, such as setting the
+ //LD_LIBRARY_PATH, etc.
+
+ //check if Enabled is false;
+ const jfw::MergedSettings settings;
+ if (!settings.getEnabled())
+ g_bEnabledSwitchedOn = true;
+ }
+ jfw::NodeJava node(jfw::NodeJava::USER);
+ node.setEnabled(bEnabled);
+ node.write();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+javaFrameworkError jfw_getEnabled(bool *pbEnabled)
+{
+ assert(pbEnabled != nullptr);
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ osl::MutexGuard guard(jfw::FwkMutex());
+ jfw::MergedSettings settings;
+ *pbEnabled = settings.getEnabled();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+
+javaFrameworkError jfw_setVMParameters(std::vector<OUString> const & arOptions)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ jfw::NodeJava node(jfw::NodeJava::USER);
+ node.setVmParameters(arOptions);
+ node.write();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+
+ return errcode;
+}
+
+javaFrameworkError jfw_getVMParameters(std::vector<OUString> * parOptions)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+
+ const jfw::MergedSettings settings;
+ settings.getVmParametersArray(parOptions);
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+javaFrameworkError jfw_setUserClassPath(OUString const & pCp)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ jfw::NodeJava node(jfw::NodeJava::USER);
+ node.setUserClassPath(pCp);
+ node.write();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+javaFrameworkError jfw_getUserClassPath(OUString * ppCP)
+{
+ assert(ppCP != nullptr);
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ const jfw::MergedSettings settings;
+ *ppCP = settings.getUserClassPath();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+ return errcode;
+}
+
+javaFrameworkError jfw_addJRELocation(OUString const & sLocation)
+{
+ javaFrameworkError errcode = JFW_E_NONE;
+ try
+ {
+ osl::MutexGuard guard(jfw::FwkMutex());
+ if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
+ return JFW_E_DIRECT_MODE;
+ jfw::NodeJava node(jfw::NodeJava::USER);
+ node.load();
+ node.addJRELocation(sLocation);
+ node.write();
+ }
+ catch (const jfw::FrameworkException& e)
+ {
+ errcode = e.errorCode;
+ SAL_WARN( "jfw", e.message );
+ }
+
+ return errcode;
+
+}
+
+javaFrameworkError jfw_existJRE(const JavaInfo *pInfo, bool *exist)
+{
+ javaPluginError plerr = jfw_plugin_existJRE(pInfo, exist);
+
+ javaFrameworkError ret = JFW_E_NONE;
+ switch (plerr)
+ {
+ case javaPluginError::NONE:
+ ret = JFW_E_NONE;
+ break;
+ case javaPluginError::Error:
+ ret = JFW_E_ERROR;
+ break;
+ default:
+ ret = JFW_E_ERROR;
+ }
+ return ret;
+}
+
+void jfw_lock()
+{
+ jfw::FwkMutex().acquire();
+}
+
+void jfw_unlock()
+{
+ jfw::FwkMutex().release();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/jvmfwk/source/framework.hxx b/jvmfwk/source/framework.hxx
new file mode 100644
index 0000000000..2ab1266148
--- /dev/null
+++ b/jvmfwk/source/framework.hxx
@@ -0,0 +1,42 @@
+/* -*- 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 .
+ */
+#ifndef INCLUDED_JVMFWK_SOURCE_FRAMEWORK_HXX
+#define INCLUDED_JVMFWK_SOURCE_FRAMEWORK_HXX
+
+#include <jvmfwk/framework.hxx>
+#include <utility>
+
+namespace jfw
+{
+
+class FrameworkException : public std::exception
+{
+public:
+
+ FrameworkException(javaFrameworkError err, OString msg):
+ errorCode(err), message(std::move(msg))
+ {
+ }
+ javaFrameworkError errorCode;
+ OString message;
+};
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/jvmfwk/source/fwkbase.cxx b/jvmfwk/source/fwkbase.cxx
new file mode 100644
index 0000000000..8275359ceb
--- /dev/null
+++ b/jvmfwk/source/fwkbase.cxx
@@ -0,0 +1,518 @@
+/* -*- 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 .
+ */
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <libxml/xpathInternals.h>
+#include <osl/file.hxx>
+#include <osl/thread.hxx>
+#include <o3tl/string_view.hxx>
+#include "framework.hxx"
+#include <fwkutil.hxx>
+#include <elements.hxx>
+#include <fwkbase.hxx>
+
+using namespace osl;
+
+
+#define UNO_JAVA_JFW_PARAMETER "UNO_JAVA_JFW_PARAMETER_"
+#define UNO_JAVA_JFW_JREHOME "UNO_JAVA_JFW_JREHOME"
+#define UNO_JAVA_JFW_ENV_JREHOME "UNO_JAVA_JFW_ENV_JREHOME"
+#define UNO_JAVA_JFW_CLASSPATH "UNO_JAVA_JFW_CLASSPATH"
+#define UNO_JAVA_JFW_ENV_CLASSPATH "UNO_JAVA_JFW_ENV_CLASSPATH"
+#define UNO_JAVA_JFW_CLASSPATH_URLS "UNO_JAVA_JFW_CLASSPATH_URLS"
+#define UNO_JAVA_JFW_VENDOR_SETTINGS "UNO_JAVA_JFW_VENDOR_SETTINGS"
+
+namespace jfw
+{
+static bool g_bJavaSet = false;
+
+namespace {
+
+#if defined _WIN32
+ // The paths are used in libxml. On Windows, it takes UTF-8 paths.
+constexpr rtl_TextEncoding PathEncoding() { return RTL_TEXTENCODING_UTF8; }
+#else
+rtl_TextEncoding PathEncoding() { return osl_getThreadTextEncoding(); }
+#endif
+
+OString getVendorSettingsPath(OUString const & sURL)
+{
+ if (sURL.isEmpty())
+ return OString();
+ OUString sSystemPathSettings;
+ if (osl_getSystemPathFromFileURL(sURL.pData,
+ & sSystemPathSettings.pData) != osl_File_E_None)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function getVendorSettingsPath (fwkbase.cxx) "_ostr);
+ OString osSystemPathSettings = OUStringToOString(sSystemPathSettings, PathEncoding());
+ return osSystemPathSettings;
+}
+
+OUString getParam(OUString const & name)
+{
+ OUString retVal;
+ bool b = Bootstrap()->getFrom(name, retVal);
+ SAL_INFO(
+ "jfw",
+ "Using bootstrap parameter " << name << " = \"" << retVal << "\""
+ << (b ? "" : " (undefined)"));
+ return retVal;
+}
+
+OUString getParamFirstUrl(OUString const & name)
+{
+ // Some parameters can consist of multiple URLs (separated by space
+ // characters, although trim() harmlessly also removes other white-space),
+ // of which only the first is used:
+ return getParam(name).trim().getToken(0, ' ');
+}
+
+}//blind namespace
+
+
+VendorSettings::VendorSettings()
+{
+ OUString xmlDocVendorSettingsFileUrl(BootParams::getVendorSettings());
+ //Prepare the xml document and context
+ OString sSettingsPath = getVendorSettingsPath(xmlDocVendorSettingsFileUrl);
+ if (sSettingsPath.isEmpty())
+ {
+ OString sMsg("[Java framework] A vendor settings file was not specified."
+ "Check the bootstrap parameter " UNO_JAVA_JFW_VENDOR_SETTINGS "."_ostr);
+ SAL_WARN( "jfw", sMsg );
+ throw FrameworkException(JFW_E_CONFIGURATION, sMsg);
+ }
+ if (sSettingsPath.isEmpty())
+ return;
+
+ m_xmlDocVendorSettings = xmlParseFile(sSettingsPath.getStr());
+ if (m_xmlDocVendorSettings == nullptr)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ OString::Concat("[Java framework] Error while parsing file: ")
+ + sSettingsPath + ".");
+
+ m_xmlPathContextVendorSettings = xmlXPathNewContext(m_xmlDocVendorSettings);
+ int res = xmlXPathRegisterNs(
+ m_xmlPathContextVendorSettings, reinterpret_cast<xmlChar const *>("jf"),
+ reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK));
+ if (res == -1)
+ throw FrameworkException(JFW_E_ERROR,
+ "[Java framework] Error in constructor VendorSettings::VendorSettings() (fwkbase.cxx)"_ostr);
+}
+
+VersionInfo VendorSettings::getVersionInformation(std::u16string_view sVendor) const
+{
+ OSL_ASSERT(!sVendor.empty());
+ OString osVendor = OUStringToOString(sVendor, RTL_TEXTENCODING_UTF8);
+ CXPathObjectPtr pathObject = xmlXPathEvalExpression(
+ reinterpret_cast<xmlChar const *>(
+ OString(
+ "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" + osVendor
+ + "\"]/jf:minVersion").getStr()),
+ m_xmlPathContextVendorSettings);
+ if (xmlXPathNodeSetIsEmpty(pathObject->nodesetval))
+ {
+ return {
+ {},
+#if defined MACOSX && defined __aarch64__
+ "17",
+#else
+ "1.8.0",
+#endif
+ ""};
+ }
+
+ VersionInfo aVersionInfo;
+ //Get minVersion
+ OString sExpression =
+ "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
+ osVendor + "\"]/jf:minVersion";
+
+ CXPathObjectPtr xPathObjectMin =
+ xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>(sExpression.getStr()),
+ m_xmlPathContextVendorSettings);
+ if (xmlXPathNodeSetIsEmpty(xPathObjectMin->nodesetval))
+ {
+ aVersionInfo.sMinVersion.clear();
+ }
+ else
+ {
+ CXmlCharPtr sVersion = xmlNodeListGetString(
+ m_xmlDocVendorSettings,
+ xPathObjectMin->nodesetval->nodeTab[0]->xmlChildrenNode, 1);
+ aVersionInfo.sMinVersion = sVersion;
+ }
+
+ //Get maxVersion
+ sExpression = "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
+ osVendor + "\"]/jf:maxVersion";
+ CXPathObjectPtr xPathObjectMax = xmlXPathEvalExpression(
+ reinterpret_cast<xmlChar const *>(sExpression.getStr()),
+ m_xmlPathContextVendorSettings);
+ if (xmlXPathNodeSetIsEmpty(xPathObjectMax->nodesetval))
+ {
+ aVersionInfo.sMaxVersion.clear();
+ }
+ else
+ {
+ CXmlCharPtr sVersion = xmlNodeListGetString(
+ m_xmlDocVendorSettings,
+ xPathObjectMax->nodesetval->nodeTab[0]->xmlChildrenNode, 1);
+ aVersionInfo.sMaxVersion = sVersion;
+ }
+
+ //Get excludeVersions
+ sExpression = "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
+ osVendor + "\"]/jf:excludeVersions/jf:version";
+ CXPathObjectPtr xPathObjectVersions =
+ xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>(sExpression.getStr()),
+ m_xmlPathContextVendorSettings);
+ if (!xmlXPathNodeSetIsEmpty(xPathObjectVersions->nodesetval))
+ {
+ xmlNode* cur = xPathObjectVersions->nodesetval->nodeTab[0];
+ while (cur != nullptr)
+ {
+ if (cur->type == XML_ELEMENT_NODE )
+ {
+ if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("version")) == 0)
+ {
+ CXmlCharPtr sVersion = xmlNodeListGetString(
+ m_xmlDocVendorSettings, cur->xmlChildrenNode, 1);
+ OUString usVersion = sVersion;
+ aVersionInfo.vecExcludeVersions.push_back(usVersion);
+ }
+ }
+ cur = cur->next;
+ }
+ }
+ return aVersionInfo;
+}
+
+::std::vector<OString> BootParams::getVMParameters()
+{
+ ::std::vector<OString> vecParams;
+
+ for (sal_Int32 i = 1; ; i++)
+ {
+ OUString sName = UNO_JAVA_JFW_PARAMETER + OUString::number(i);
+ OUString sValue;
+ if (Bootstrap()->getFrom(sName, sValue))
+ {
+ OString sParam =
+ OUStringToOString(sValue, osl_getThreadTextEncoding());
+ vecParams.push_back(sParam);
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " << sName << " = " << sParam);
+ }
+ else
+ break;
+ }
+ return vecParams;
+}
+
+OUString BootParams::getUserData()
+{
+ return getParamFirstUrl("UNO_JAVA_JFW_USER_DATA");
+}
+
+OUString BootParams::getSharedData()
+{
+ return getParamFirstUrl("UNO_JAVA_JFW_SHARED_DATA");
+}
+
+OString BootParams::getClasspath()
+{
+ OString sClassPath;
+ OUString sCP;
+ if (Bootstrap()->getFrom( UNO_JAVA_JFW_CLASSPATH, sCP ))
+ {
+ sClassPath = OUStringToOString(sCP, PathEncoding());
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_CLASSPATH " = "
+ << sClassPath);
+ }
+
+ OUString sEnvCP;
+ if (Bootstrap()->getFrom( UNO_JAVA_JFW_ENV_CLASSPATH, sEnvCP ))
+ {
+ char * pCp = getenv("CLASSPATH");
+ if (pCp)
+ {
+ sClassPath += OStringChar(SAL_PATHSEPARATOR) + pCp;
+ }
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_ENV_CLASSPATH
+ " and class path is: " << (pCp ? pCp : ""));
+ }
+
+ return sClassPath;
+}
+
+OUString BootParams::getVendorSettings()
+{
+ OUString sVendor;
+ if (Bootstrap()->getFrom(UNO_JAVA_JFW_VENDOR_SETTINGS, sVendor))
+ {
+ //check the value of the bootstrap variable
+ jfw::FileStatus s = checkFileURL(sVendor);
+ if (s != FILE_OK)
+ {
+ //This bootstrap parameter can contain a relative URL
+ OUString sAbsoluteUrl;
+ OUString sBaseDir = getLibraryLocation();
+ if (File::getAbsoluteFileURL(sBaseDir, sVendor, sAbsoluteUrl)
+ != File::E_None)
+ throw FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] Invalid value for bootstrap variable: "
+ UNO_JAVA_JFW_VENDOR_SETTINGS ""_ostr);
+ sVendor = sAbsoluteUrl;
+ s = checkFileURL(sVendor);
+ if (s == jfw::FILE_INVALID || s == jfw::FILE_DOES_NOT_EXIST)
+ {
+ throw FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] Invalid value for bootstrap variable: "
+ UNO_JAVA_JFW_VENDOR_SETTINGS ""_ostr);
+ }
+ }
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_VENDOR_SETTINGS " = "
+ << sVendor);
+ }
+ return sVendor;
+}
+
+OUString BootParams::getJREHome()
+{
+ OUString sJRE;
+ OUString sEnvJRE;
+ bool bJRE = Bootstrap()->getFrom(UNO_JAVA_JFW_JREHOME, sJRE);
+ bool bEnvJRE = Bootstrap()->getFrom(UNO_JAVA_JFW_ENV_JREHOME, sEnvJRE);
+
+ if (bJRE && bEnvJRE)
+ {
+ throw FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] Both bootstrap parameter "
+ UNO_JAVA_JFW_JREHOME" and "
+ UNO_JAVA_JFW_ENV_JREHOME" are set. However only one of them can be set."
+ "Check bootstrap parameters: environment variables, command line "
+ "arguments, rc/ini files for executable and java framework library."_ostr);
+ }
+ else if (bEnvJRE)
+ {
+ const char * pJRE = getenv("JAVA_HOME");
+ if (pJRE == nullptr)
+ {
+ throw FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] Both bootstrap parameter "
+ UNO_JAVA_JFW_ENV_JREHOME" is set, but the environment variable "
+ "JAVA_HOME is not set."_ostr);
+ }
+ std::string_view osJRE(pJRE);
+ OUString usJRE = OStringToOUString(osJRE, osl_getThreadTextEncoding());
+ if (File::getFileURLFromSystemPath(usJRE, sJRE) != File::E_None)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function BootParams::getJREHome() "
+ "(fwkbase.cxx)."_ostr);
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_ENV_JREHOME
+ " with JAVA_HOME = " << pJRE);
+ }
+ else if (getMode() == JFW_MODE_DIRECT && !bJRE)
+ {
+ throw FrameworkException(
+ JFW_E_CONFIGURATION,
+ "[Java framework] The bootstrap parameter "
+ UNO_JAVA_JFW_ENV_JREHOME" or " UNO_JAVA_JFW_JREHOME
+ " must be set in direct mode."_ostr);
+ }
+
+ SAL_INFO_IF(
+ bJRE, "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_JREHOME " = " << sJRE);
+ return sJRE;
+}
+
+OUString BootParams::getClasspathUrls()
+{
+ OUString sParams;
+ Bootstrap()->getFrom( UNO_JAVA_JFW_CLASSPATH_URLS, sParams);
+ SAL_INFO(
+ "jfw.level2",
+ "Using bootstrap parameter " UNO_JAVA_JFW_CLASSPATH_URLS " = "
+ << sParams);
+ return sParams;
+}
+
+JFW_MODE getMode()
+{
+ static bool g_bMode = false;
+ static JFW_MODE g_mode = JFW_MODE_APPLICATION;
+
+ if (!g_bMode)
+ {
+ //check if either of the "direct mode" bootstrap variables is set
+ bool bDirectMode = true;
+ OUString sValue;
+ const rtl::Bootstrap * aBoot = Bootstrap();
+ if (!aBoot->getFrom(UNO_JAVA_JFW_JREHOME, sValue))
+ {
+ if (!aBoot->getFrom(UNO_JAVA_JFW_ENV_JREHOME, sValue))
+ {
+ if (!aBoot->getFrom(UNO_JAVA_JFW_CLASSPATH, sValue))
+ {
+ if (!aBoot->getFrom(UNO_JAVA_JFW_ENV_CLASSPATH, sValue))
+ {
+ OUString sParams = UNO_JAVA_JFW_PARAMETER +
+ OUString::number(1);
+ if (!aBoot->getFrom(sParams, sValue))
+ {
+ bDirectMode = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (bDirectMode)
+ g_mode = JFW_MODE_DIRECT;
+ else
+ g_mode = JFW_MODE_APPLICATION;
+ g_bMode = true;
+ }
+
+ return g_mode;
+}
+
+OUString getApplicationClassPath()
+{
+ OSL_ASSERT(getMode() == JFW_MODE_APPLICATION);
+ OUString sParams = BootParams::getClasspathUrls();
+ if (sParams.isEmpty())
+ return OUString();
+
+ OUStringBuffer buf;
+ sal_Int32 index = 0;
+ do
+ {
+ OUString token( o3tl::trim(o3tl::getToken(sParams, 0, ' ', index )) );
+ if (!token.isEmpty())
+ {
+ OUString systemPathElement;
+ oslFileError rc = osl_getSystemPathFromFileURL(
+ token.pData, &systemPathElement.pData );
+ OSL_ASSERT( rc == osl_File_E_None );
+ if (rc == osl_File_E_None && !systemPathElement.isEmpty())
+ {
+ if (buf.getLength() > 0)
+ buf.append( SAL_PATHSEPARATOR );
+ buf.append( systemPathElement );
+ }
+ }
+ }
+ while (index >= 0);
+ return buf.makeStringAndClear();
+}
+
+OString makeClassPathOption(std::u16string_view sUserClassPath)
+{
+ //Compose the class path
+ OString sPaths;
+ OUStringBuffer sBufCP(4096);
+
+ // append all user selected jars to the class path
+ if (!sUserClassPath.empty())
+ sBufCP.append(sUserClassPath);
+
+ //append all jar libraries and components to the class path
+ OUString sAppCP = getApplicationClassPath();
+ if (!sAppCP.isEmpty())
+ {
+ if (!sUserClassPath.empty())
+ {
+ sBufCP.append(SAL_PATHSEPARATOR);
+ }
+ sBufCP.append(sAppCP);
+ }
+
+ sPaths = OUStringToOString(sBufCP, PathEncoding());
+ if (sPaths.isEmpty()) {
+ return ""_ostr;
+ }
+
+ OString sOptionClassPath = "-Djava.class.path=" + sPaths;
+ return sOptionClassPath;
+}
+
+OString getUserSettingsPath()
+{
+ return getSettingsPath(BootParams::getUserData());
+}
+
+OString getSharedSettingsPath()
+{
+ return getSettingsPath(BootParams::getSharedData());
+}
+
+OString getSettingsPath( const OUString & sURL)
+{
+ if (sURL.isEmpty())
+ return OString();
+ OUString sPath;
+ if (osl_getSystemPathFromFileURL(sURL.pData,
+ & sPath.pData) != osl_File_E_None)
+ throw FrameworkException(
+ JFW_E_ERROR,
+ "[Java framework] Error in function ::getSettingsPath (fwkbase.cxx)."_ostr);
+ return OUStringToOString(sPath, PathEncoding());
+}
+
+OString getVendorSettingsPath()
+{
+ return getVendorSettingsPath(BootParams::getVendorSettings());
+}
+
+void setJavaSelected()
+{
+ g_bJavaSet = true;
+}
+
+bool wasJavaSelectedInSameProcess()
+{
+ //g_setJavaProcId not set means no Java selected
+ return g_bJavaSet;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/jvmfwk/source/fwkutil.cxx b/jvmfwk/source/fwkutil.cxx
new file mode 100644
index 0000000000..0c3c8f4beb
--- /dev/null
+++ b/jvmfwk/source/fwkutil.cxx
@@ -0,0 +1,194 @@
+/* -*- 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 .
+ */
+
+
+#if defined(_WIN32)
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <algorithm>
+#endif
+
+#include <osl/module.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+
+#include "framework.hxx"
+#include <fwkutil.hxx>
+#include <memory>
+
+using namespace osl;
+
+
+namespace jfw
+{
+
+/** provides a bootstrap class which already knows the values from the
+ jvmfkwrc file.
+*/
+const rtl::Bootstrap* Bootstrap()
+{
+ static const rtl::Bootstrap* SINGLETON = []()
+ {
+ OUString sIni = getLibraryLocation() +
+#ifdef MACOSX
+ // For some reason the jvmfwk3rc file is traditionally in
+ // LIBO_URE_ETC_FOLDER
+ "/../" LIBO_URE_ETC_FOLDER
+#endif
+ SAL_CONFIGFILE("/jvmfwk3");
+ ::rtl::Bootstrap * bootstrap = new ::rtl::Bootstrap(sIni);
+ SAL_INFO("jfw.level2", "Using configuration file " << sIni);
+ return bootstrap;
+ }();
+ return SINGLETON;
+};
+
+osl::Mutex& FwkMutex()
+{
+ static osl::Mutex SINGLETON;
+ return SINGLETON;
+}
+
+
+rtl::ByteSequence encodeBase16(const rtl::ByteSequence& rawData)
+{
+ static const char EncodingTable[] =
+ {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+ sal_Int32 lenRaw = rawData.getLength();
+ std::unique_ptr<char[]> pBuf(new char[lenRaw * 2]);
+ const sal_Int8* arRaw = rawData.getConstArray();
+
+ char* pCurBuf = pBuf.get();
+ for (int i = 0; i < lenRaw; i++)
+ {
+ unsigned char curChar = arRaw[i];
+ curChar >>= 4;
+
+ *pCurBuf = EncodingTable[curChar];
+ pCurBuf++;
+
+ curChar = arRaw[i];
+ curChar &= 0x0F;
+
+ *pCurBuf = EncodingTable[curChar];
+ pCurBuf++;
+ }
+
+ rtl::ByteSequence ret(reinterpret_cast<sal_Int8*>(pBuf.get()), lenRaw * 2);
+ return ret;
+}
+
+rtl::ByteSequence decodeBase16(const rtl::ByteSequence& data)
+{
+ static const char decodingTable[] =
+ {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+ sal_Int32 lenData = data.getLength();
+ sal_Int32 lenBuf = lenData / 2; //always divisible by two
+ std::unique_ptr<unsigned char[]> pBuf(new unsigned char[lenBuf]);
+ const sal_Int8* pData = data.getConstArray();
+ for (sal_Int32 i = 0; i < lenBuf; i++)
+ {
+ sal_Int8 curChar = *pData++;
+ //find the index of the first 4bits
+ // TODO What happens if text is not valid Hex characters?
+ unsigned char nibble = 0;
+ for (unsigned char j = 0; j < 16; j++)
+ {
+ if (curChar == decodingTable[j])
+ {
+ nibble = j;
+ break;
+ }
+ }
+ nibble <<= 4;
+ curChar = *pData++;
+ //find the index for the next 4bits
+ for (unsigned char j = 0; j < 16; j++)
+ {
+ if (curChar == decodingTable[j])
+ {
+ nibble |= j;
+ break;
+ }
+ }
+ pBuf[i] = nibble;
+ }
+ rtl::ByteSequence ret(reinterpret_cast<sal_Int8*>(pBuf.get()), lenBuf );
+ return ret;
+}
+
+OUString getDirFromFile(std::u16string_view usFilePath)
+{
+ size_t index = usFilePath.rfind('/');
+ return OUString(usFilePath.substr(0, index));
+}
+
+OUString getLibraryLocation()
+{
+ OUString libraryFileUrl;
+
+ if (!osl::Module::getUrlFromAddress(
+ reinterpret_cast< oslGenericFunction >(getLibraryLocation),
+ libraryFileUrl))
+ throw FrameworkException(JFW_E_ERROR,
+ "[Java framework] Error in function getLibraryLocation (fwkutil.cxx)."_ostr);
+
+ return getDirFromFile(libraryFileUrl);
+}
+
+jfw::FileStatus checkFileURL(const OUString & sURL)
+{
+ jfw::FileStatus ret = jfw::FILE_OK;
+ DirectoryItem item;
+ File::RC rc_item = DirectoryItem::get(sURL, item);
+ if (File::E_None == rc_item)
+ {
+ osl::FileStatus status(osl_FileStatus_Mask_Validate);
+
+ File::RC rc_stat = item.getFileStatus(status);
+ if (File::E_None == rc_stat)
+ {
+ ret = FILE_OK;
+ }
+ else if (File::E_NOENT == rc_stat)
+ {
+ ret = FILE_DOES_NOT_EXIST;
+ }
+ else
+ {
+ ret = FILE_INVALID;
+ }
+ }
+ else if (File::E_NOENT == rc_item)
+ {
+ ret = FILE_DOES_NOT_EXIST;
+ }
+ else
+ {
+ ret = FILE_INVALID;
+ }
+ return ret;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/jvmfwk/source/javasettings.xsd b/jvmfwk/source/javasettings.xsd
new file mode 100644
index 0000000000..e0ccbd47e3
--- /dev/null
+++ b/jvmfwk/source/javasettings.xsd
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+-->
+
+<!--
+ Document : javasettings.xsd
+ Created on : 25. März 2004, 16:16
+ Author : jl97489
+ Description:
+ Purpose of XML Schema document follows.
+-->
+
+<schema targetNamespace="http://openoffice.org/2004/java/framework/1.0"
+ xmlns:jf="http://openoffice.org/2004/java/framework/1.0"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified">
+
+<element name="java">
+ <complexType>
+ <sequence>
+ <element name="enabled" nillable="true" default="true" type="boolean"/>
+ <element name="userClassPath" nillable="true" type="string"/>
+ <element name="vmParameters" nillable="true" type="jf:vmParametersType"/>
+ <element name="jreLocations" nillable="true" type="jf:jreLocationsType"/>
+ <element name="javaInfo" nillable="true" type="jf:javaInfoType"/>
+ </sequence>
+ </complexType>
+
+</element>
+
+<complexType name="javaInfoType">
+ <sequence>
+ <element name="vendor" type="string"/>
+ <element name="location" type="string"/>
+ <element name="version" type="string"/>
+ <element name="features" default="0" type="unsignedLong"/>
+ <element name="requirements" default="0" type="unsignedLong"/>
+ <element name="vendorData" type="base64Binary"/>
+ </sequence>
+ <attribute name="vendorUpdate" type="date"/>
+</complexType>
+
+<complexType name="vmParametersType">
+ <sequence>
+ <element name="param" minOccurs="0" maxOccurs="unbounded" type="string"/>
+ </sequence>
+</complexType>
+
+<complexType name="jreLocationsType">
+ <sequence>
+ <element name="location" minOccurs="0" maxOccurs="unbounded" type="string"/>
+ </sequence>
+</complexType>
+
+</schema>
diff --git a/jvmfwk/source/javasettings_template.xml b/jvmfwk/source/javasettings_template.xml
new file mode 100644
index 0000000000..c73404c696
--- /dev/null
+++ b/jvmfwk/source/javasettings_template.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+-->
+
+<!--
+This file shows what elements the javasettings_platform.xml can contain.
+The children of javaInfo are only created when a JRE is selected. The children of
+vmParameters are only created when parameters are added and the children of
+jreLocations are only created when the paths are added.
+See CNodeJava::loadFromSettings and CNodeJava::writeSettings for details.
+When extending the javavendors.xml then use the schema to verify it.
+-->
+
+<java xmlns='http://openoffice.org/2004/java/framework/1.0'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xsi:schemaLocation='http://openoffice.org/2004/java/framework/1.0 file:/D:/cws-jl6/jvmfwk/source/javasettings.xsd'>
+ <classesDirectory>program/classes</classesDirectory>
+ <enabled xsi:nil="true"></enabled>
+ <userClassPath xsi:nil="true"></userClassPath>
+ <vmParameters xsi:nil="true"/>
+ <!--param>-Xdebug</param-->
+ <!--</vmParameters>-->
+ <jreLocations xsi:nil="true"/>
+ <!--location></location-->
+ <!--</jreLocations>-->
+ <javaInfo xsi:nil="true"/>
+ <!--javaInfo vendorUpdate="2004-03-27" xsi:nil="false"-->
+ <!--vendor></vendor>
+ <location></location>
+ <version></version>
+ <features></features>
+ <requirements></requirements>
+ <vendorData></vendorData>
+ </javaInfo-->
+ </java>
+
+
diff --git a/jvmfwk/source/libxmlutil.cxx b/jvmfwk/source/libxmlutil.cxx
new file mode 100644
index 0000000000..fa8f6eeee1
--- /dev/null
+++ b/jvmfwk/source/libxmlutil.cxx
@@ -0,0 +1,136 @@
+/* -*- 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 .
+ */
+
+#include <libxmlutil.hxx>
+
+namespace jfw
+{
+
+CXPathObjectPtr::CXPathObjectPtr():_object(nullptr)
+{
+}
+CXPathObjectPtr::CXPathObjectPtr(xmlXPathObject* pObj):_object(pObj)
+{
+}
+CXPathObjectPtr::~CXPathObjectPtr()
+{
+ xmlXPathFreeObject(_object);
+}
+CXPathObjectPtr & CXPathObjectPtr::operator = (xmlXPathObject* pObj)
+{
+ if (_object == pObj)
+ return *this;
+
+ xmlXPathFreeObject(_object);
+ _object = pObj;
+ return *this;
+}
+
+CXPathContextPtr::CXPathContextPtr(xmlXPathContextPtr aContext)
+ : _object(aContext)
+{
+}
+
+CXPathContextPtr::CXPathContextPtr():_object(nullptr)
+{
+}
+
+CXPathContextPtr::~CXPathContextPtr()
+{
+ xmlXPathFreeContext(_object);
+}
+
+CXPathContextPtr & CXPathContextPtr::operator = (xmlXPathContextPtr pObj)
+{
+ if (_object == pObj)
+ return *this;
+ xmlXPathFreeContext(_object);
+ _object = pObj;
+ return *this;
+}
+
+
+CXmlDocPtr::CXmlDocPtr(xmlDoc* aDoc)
+ : _object(aDoc)
+{
+}
+
+CXmlDocPtr::CXmlDocPtr():_object(nullptr)
+{
+}
+
+CXmlDocPtr::~CXmlDocPtr()
+{
+ xmlFreeDoc(_object);
+}
+CXmlDocPtr & CXmlDocPtr::operator = (xmlDoc* pObj)
+{
+ if (_object == pObj)
+ return *this;
+ xmlFreeDoc(_object);
+ _object = pObj;
+ return *this;
+}
+
+
+CXmlCharPtr::CXmlCharPtr(xmlChar * aChar)
+ : _object(aChar)
+{
+}
+
+CXmlCharPtr::CXmlCharPtr(std::u16string_view s):
+ _object(nullptr)
+{
+ OString o = OUStringToOString(s, RTL_TEXTENCODING_UTF8);
+ _object = xmlCharStrdup(o.getStr());
+}
+CXmlCharPtr::CXmlCharPtr():_object(nullptr)
+{
+}
+
+CXmlCharPtr::~CXmlCharPtr()
+{
+ xmlFree(_object);
+}
+
+CXmlCharPtr & CXmlCharPtr::operator = (xmlChar* pObj)
+{
+ if (pObj == _object)
+ return *this;
+ xmlFree(_object);
+ _object = pObj;
+ return *this;
+}
+
+
+CXmlCharPtr::operator OUString()
+{
+ OUString ret;
+ if (_object != nullptr)
+ {
+ std::string_view aOStr(reinterpret_cast<char*>(_object));
+ ret = OStringToOUString(aOStr, RTL_TEXTENCODING_UTF8);
+ }
+ return ret;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */