Files
libreoffice/jvmfwk/source/elements.cxx

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

972 lines
34 KiB
C++
Raw Normal View History

/* -*- 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>
tdf#124503: Support JRE installations with unknown java.vendor property After recent additions of 61c4f96d6ae6a80370774e53287edb27cbce8067 "Support AdoptOpenJDK" and 41507db590b24e1b9b45d95cad55c71ba2e4091d "Support Amazon Corretto" to our hard-coded list, there is now reports that at least Debian and Ubuntu tried to distribute versions of OpenJDK with the java.vendor propety set to string like "Debian" or "Ubuntu". Instead of trying to catch up with an ever-growing hard-coded list, it is probably better to stop relying exclusively on such a hard-coded list, and for unknown vendor values, try out whether the SunInfo backend (which supports the "generic" OpenJDK) would be able to handle the given JRE. (For simplicity, assume that any versions of such JREs are supported. Our baseline is Java 6, and there are unlikely any older versions of JREs from unknown vendors out there. If this turns out to be problematic, we could include information about problematic vendors after all, or add a general check that JREs from unknown vendors are at least Java 6.) Many functions in jvmfwk/inc/vendorplugin.hxx that used to take a set of sVendor/sMinVersion/sMaxVerison/arExcludeList paramters had to be revised to take a vendorSettings parameter instead, and VendorSettings::getVersionInformation has been changed to return a boost::optional, so that unknown vendors can be handled gracefully. Change-Id: Ibf915f2ddd59e09b77e2c03be688cac0547b9ac9 Reviewed-on: https://gerrit.libreoffice.org/70460 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-04-09 14:51:54 +02:00
#include <fwkbase.hxx>
#include "framework.hxx"
tdf#124503: Support JRE installations with unknown java.vendor property After recent additions of 61c4f96d6ae6a80370774e53287edb27cbce8067 "Support AdoptOpenJDK" and 41507db590b24e1b9b45d95cad55c71ba2e4091d "Support Amazon Corretto" to our hard-coded list, there is now reports that at least Debian and Ubuntu tried to distribute versions of OpenJDK with the java.vendor propety set to string like "Debian" or "Ubuntu". Instead of trying to catch up with an ever-growing hard-coded list, it is probably better to stop relying exclusively on such a hard-coded list, and for unknown vendor values, try out whether the SunInfo backend (which supports the "generic" OpenJDK) would be able to handle the given JRE. (For simplicity, assume that any versions of such JREs are supported. Our baseline is Java 6, and there are unlikely any older versions of JREs from unknown vendors out there. If this turns out to be problematic, we could include information about problematic vendors after all, or add a general check that JREs from unknown vendors are at least Java 6.) Many functions in jvmfwk/inc/vendorplugin.hxx that used to take a set of sVendor/sMinVersion/sMaxVerison/arExcludeList paramters had to be revised to take a vendorSettings parameter instead, and VendorSettings::getVersionInformation has been changed to return a boost::optional, so that unknown vendors can be handled gracefully. Change-Id: Ibf915f2ddd59e09b77e2c03be688cac0547b9ac9 Reviewed-on: https://gerrit.libreoffice.org/70460 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-04-09 14:51:54 +02:00
#include <libxmlutil.hxx>
2004-04-21 08:30:36 +00:00
#include <algorithm>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <optional>
#include <string.h>
2004-04-19 14:57:02 +00:00
// 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).
2004-05-05 09:14:01 +00:00
using namespace osl;
2004-04-19 14:57:02 +00:00
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)");
2004-04-27 14:22:15 +00:00
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)");
CXPathObjectPtr pathObj = xmlXPathEvalExpression(pathExpression, context);
OString sValue;
if (xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
{
throw FrameworkException(
JFW_E_ERROR,
"[Java framework] Error in function getElement (elements.cxx)");
}
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).");
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);
2011-03-04 01:41:18 +09:00
//<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)
2004-04-19 14:57:02 +00:00
{
//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.");
2004-04-19 14:57:02 +00:00
}
void NodeJava::load()
2004-04-19 14:57:02 +00:00
{
const OString sExcMsg("[Java framework] Error in function NodeJava::load"
"(elements.cxx).");
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.");
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.");
}
2004-04-19 14:57:02 +00:00
//Read the user elements
OString sSettingsPath = getSettingsPath();
2004-04-19 14:57:02 +00:00
//There must not be a share settings file
CXmlDocPtr docUser(xmlParseFile(sSettingsPath.getStr()));
if (docUser == nullptr)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
xmlNode * cur = xmlDocGetRootElement(docUser);
if (cur == nullptr || cur->children == nullptr)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
2004-04-27 14:22:15 +00:00
CXmlCharPtr sNil;
2004-04-19 14:57:02 +00:00
cur = cur->children;
while (cur != nullptr)
2004-04-19 14:57:02 +00:00
{
if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("enabled")) == 0)
2004-04-19 14:57:02 +00:00
{
//only overwrite share settings if xsi:nil="false"
2004-04-27 14:22:15 +00:00
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)
2004-04-19 14:57:02 +00:00
{
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);
2004-04-19 14:57:02 +00:00
}
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("userClassPath")) == 0)
2004-04-19 14:57:02 +00:00
{
2004-04-27 14:22:15 +00:00
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)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr sUser(xmlNodeListGetString(
docUser, cur->children, 1));
m_userClassPath = std::optional<OUString>(OUString(sUser));
2004-04-19 14:57:02 +00:00
}
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("javaInfo")) == 0)
2004-04-19 14:57:02 +00:00
{
2004-04-27 14:22:15 +00:00
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)
2004-04-19 14:57:02 +00:00
{
if (! m_javaInfo)
m_javaInfo = std::optional<CNodeJavaInfo>(CNodeJavaInfo());
m_javaInfo->loadFromNode(docUser, cur);
2004-04-19 14:57:02 +00:00
}
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vmParameters")) == 0)
2004-04-19 14:57:02 +00:00
{
2004-04-27 14:22:15 +00:00
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)
2004-04-19 14:57:02 +00:00
{
if ( ! m_vmParameters)
m_vmParameters = std::optional<std::vector<OUString> >(
std::vector<OUString> ());
2004-04-19 14:57:02 +00:00
xmlNode * pOpt = cur->children;
while (pOpt != nullptr)
2004-04-19 14:57:02 +00:00
{
if (xmlStrcmp(pOpt->name, reinterpret_cast<xmlChar const *>("param")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr sOpt = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
docUser, pOpt->children, 1);
m_vmParameters->push_back(sOpt);
2004-04-19 14:57:02 +00:00
}
pOpt = pOpt->next;
}
}
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("jreLocations")) == 0)
2004-04-21 08:30:36 +00:00
{
2004-04-27 14:22:15 +00:00
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)
2004-04-21 08:30:36 +00:00
{
if (! m_JRELocations)
m_JRELocations = std::optional<std::vector<OUString> >(
std::vector<OUString>());
2004-04-21 08:30:36 +00:00
xmlNode * pLoc = cur->children;
while (pLoc != nullptr)
2004-04-21 08:30:36 +00:00
{
if (xmlStrcmp(pLoc->name, reinterpret_cast<xmlChar const *>("location")) == 0)
2004-04-21 08:30:36 +00:00
{
CXmlCharPtr sLoc = xmlNodeListGetString(
2004-04-21 08:30:36 +00:00
docUser, pLoc->children, 1);
m_JRELocations->push_back(sLoc);
2004-04-21 08:30:36 +00:00
}
pLoc = pLoc->next;
}
}
}
2004-04-19 14:57:02 +00:00
cur = cur->next;
}
}
OString NodeJava::getSettingsPath() const
2004-04-19 14:57:02 +00:00
{
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;
}
2004-04-19 14:57:02 +00:00
bool NodeJava::prepareSettingsDocument() const
{
OString sExcMsg(
"[Java framework] Error in function prepareSettingsDocument"
" (elements.cxx).");
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)
2004-04-19 14:57:02 +00:00
{
if (xmlSaveFormatFileEnc(
sSettings.getStr(), doc,"UTF-8", 1) == -1)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
}
return true;
2004-04-19 14:57:02 +00:00
}
void NodeJava::write() const
2004-04-19 14:57:02 +00:00
{
OString sExcMsg("[Java framework] Error in function NodeJava::writeSettings "
"(elements.cxx).");
2004-04-19 14:57:02 +00:00
CXmlDocPtr docUser;
CXPathContextPtr contextUser;
CXPathObjectPtr pathObj;
if (!prepareSettingsDocument())
{
SAL_INFO("jfw.level1", "no path to write settings document to");
return;
}
2004-05-20 07:50:59 +00:00
2004-04-19 14:57:02 +00:00
//Read the user elements
OString sSettingsPath = getSettingsPath();
2004-04-19 14:57:02 +00:00
docUser = xmlParseFile(sSettingsPath.getStr());
if (docUser == nullptr)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
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);
2004-04-19 14:57:02 +00:00
xmlNode * root = xmlDocGetRootElement(docUser);
//Get xsi:nil namespace
xmlNs* nsXsi = xmlSearchNsByHref(docUser,
root,
reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
2004-04-19 14:57:02 +00:00
//set the <enabled> element
//The element must exist
if (m_enabled)
2004-04-19 14:57:02 +00:00
{
pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:enabled"),
2004-04-19 14:57:02 +00:00
contextUser);
if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
xmlNode * nodeEnabled = pathObj->nodesetval->nodeTab[0];
xmlSetNsProp(nodeEnabled,
nsXsi,
reinterpret_cast<xmlChar const *>("nil"),
reinterpret_cast<xmlChar const *>("false"));
2004-04-19 14:57:02 +00:00
if (m_enabled == std::optional<sal_Bool>(true))
xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("true"));
2004-04-19 14:57:02 +00:00
else
xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("false"));
2004-04-19 14:57:02 +00:00
}
//set the <userClassPath> element
//The element must exist
if (m_userClassPath)
2004-04-19 14:57:02 +00:00
{
pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:userClassPath"),
2004-04-19 14:57:02 +00:00
contextUser);
if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
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)));
2004-04-19 14:57:02 +00:00
}
//set <javaInfo> element
if (m_javaInfo)
2004-04-19 14:57:02 +00:00
{
pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:javaInfo"),
2004-04-19 14:57:02 +00:00
contextUser);
if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
throw FrameworkException(JFW_E_ERROR, sExcMsg);
m_javaInfo->writeToNode(
2004-04-19 14:57:02 +00:00
docUser, pathObj->nodesetval->nodeTab[0]);
}
//set <vmParameters> element
if (m_vmParameters)
2004-04-19 14:57:02 +00:00
{
pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:vmParameters"),
2004-04-19 14:57:02 +00:00
contextUser);
if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
xmlNode* vmParameters = pathObj->nodesetval->nodeTab[0];
//set xsi:nil = false;
xmlSetNsProp(vmParameters, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
reinterpret_cast<xmlChar const *>("false"));
2004-04-19 14:57:02 +00:00
//remove option elements
xmlNode* cur = vmParameters->children;
while (cur != nullptr)
2004-04-19 14:57:02 +00:00
{
xmlNode* lastNode = cur;
cur = cur->next;
xmlUnlinkNode(lastNode);
xmlFreeNode(lastNode);
}
//add a new line after <vmParameters>
if (!m_vmParameters->empty())
2004-04-19 14:57:02 +00:00
{
xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(vmParameters, nodeCrLf);
}
for (auto const & vmParameter : *m_vmParameters)
2004-04-19 14:57:02 +00:00
{
xmlNewTextChild(vmParameters, nullptr, reinterpret_cast<xmlChar const *>("param"),
CXmlCharPtr(vmParameter));
2004-04-19 14:57:02 +00:00
//add a new line
xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(vmParameters, nodeCrLf);
}
}
2004-04-21 08:30:36 +00:00
//set <jreLocations> element
if (m_JRELocations)
2004-04-21 08:30:36 +00:00
{
pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:jreLocations"),
2004-04-21 08:30:36 +00:00
contextUser);
if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-21 08:30:36 +00:00
xmlNode* jreLocationsNode = pathObj->nodesetval->nodeTab[0];
//set xsi:nil = false;
xmlSetNsProp(jreLocationsNode, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
reinterpret_cast<xmlChar const *>("false"));
2004-04-21 08:30:36 +00:00
//remove option elements
xmlNode* cur = jreLocationsNode->children;
while (cur != nullptr)
2004-04-21 08:30:36 +00:00
{
xmlNode* lastNode = cur;
cur = cur->next;
xmlUnlinkNode(lastNode);
xmlFreeNode(lastNode);
}
//add a new line after <vmParameters>
if (!m_JRELocations->empty())
2004-04-21 08:30:36 +00:00
{
xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-21 08:30:36 +00:00
xmlAddChild(jreLocationsNode, nodeCrLf);
}
for (auto const & JRELocation : *m_JRELocations)
2004-04-21 08:30:36 +00:00
{
xmlNewTextChild(jreLocationsNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
CXmlCharPtr(JRELocation));
2004-04-21 08:30:36 +00:00
//add a new line
xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-21 08:30:36 +00:00
xmlAddChild(jreLocationsNode, nodeCrLf);
}
}
2004-04-19 14:57:02 +00:00
if (xmlSaveFormatFile(sSettingsPath.getStr(), docUser, 1) == -1)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
}
void NodeJava::setEnabled(bool bEnabled)
2004-04-19 14:57:02 +00:00
{
m_enabled = std::optional<sal_Bool>(bEnabled);
2004-04-19 14:57:02 +00:00
}
void NodeJava::setUserClassPath(const OUString & sClassPath)
2004-04-19 14:57:02 +00:00
{
m_userClassPath = std::optional<OUString>(sClassPath);
2004-04-19 14:57:02 +00:00
}
void NodeJava::setJavaInfo(const JavaInfo * pInfo, bool bAutoSelect)
2004-04-19 14:57:02 +00:00
{
if (!m_javaInfo)
m_javaInfo = std::optional<CNodeJavaInfo>(CNodeJavaInfo());
m_javaInfo->bAutoSelect = bAutoSelect;
m_javaInfo->bNil = false;
if (pInfo != nullptr)
2004-04-19 14:57:02 +00:00
{
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;
2004-04-19 14:57:02 +00:00
}
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();
2004-04-19 14:57:02 +00:00
}
}
void NodeJava::setVmParameters(std::vector<OUString> const & arOptions)
2004-04-19 14:57:02 +00:00
{
m_vmParameters = std::optional<std::vector<OUString> >(arOptions);
2004-04-19 14:57:02 +00:00
}
void NodeJava::addJRELocation(OUString const & sLocation)
2004-04-21 08:30:36 +00:00
{
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);
}
2004-04-21 08:30:36 +00:00
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)
2004-04-21 08:30:36 +00:00
{
::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;
}
2004-04-21 08:30:36 +00:00
}
else if(File::E_NOENT == rc)
{
ret = FILE_DOES_NOT_EXIST;
}
else
{
ret = FILE_INVALID;
}
return ret;
2004-04-21 08:30:36 +00:00
}
bool NodeJava::createSettingsDocument() const
2004-05-13 10:15:02 +00:00
{
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).");
// 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;
2004-05-13 10:15:02 +00:00
}
2004-04-19 14:57:02 +00:00
CNodeJavaInfo::CNodeJavaInfo() :
m_bEmptyNode(false), bNil(true), bAutoSelect(true),
nRequirements(0)
2004-04-19 14:57:02 +00:00
{
}
void CNodeJavaInfo::loadFromNode(xmlDoc * pDoc, xmlNode * pJavaInfo)
2004-04-19 14:57:02 +00:00
{
OString sExcMsg("[Java framework] Error in function NodeJavaInfo::loadFromNode "
"(elements.cxx).");
OSL_ASSERT(pJavaInfo && pDoc);
if (pJavaInfo->children == nullptr)
return;
2004-04-19 14:57:02 +00:00
//Get the xsi:nil attribute;
CXmlCharPtr sNil = xmlGetNsProp(
pJavaInfo, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
2004-04-19 14:57:02 +00:00
if ( ! sNil)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-05-13 10:15:02 +00:00
if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("true")) == 0)
2004-04-19 14:57:02 +00:00
bNil = true;
else if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
2004-04-19 14:57:02 +00:00
bNil = false;
else
throw FrameworkException(JFW_E_ERROR, sExcMsg);
if (bNil)
return;
2004-04-19 14:57:02 +00:00
2004-05-13 10:15:02 +00:00
//Get javaInfo@manuallySelected attribute
CXmlCharPtr sAutoSelect = xmlGetProp(
pJavaInfo, reinterpret_cast<xmlChar const *>("autoSelect"));
2004-05-13 10:15:02 +00:00
if ( ! sAutoSelect)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-05-13 10:15:02 +00:00
if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("true")) == 0)
2004-05-13 10:15:02 +00:00
bAutoSelect = true;
else if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("false")) == 0)
2004-05-13 10:15:02 +00:00
bAutoSelect = false;
else
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-05-13 10:15:02 +00:00
2004-04-19 14:57:02 +00:00
xmlNode * cur = pJavaInfo->children;
while (cur != nullptr)
2004-04-19 14:57:02 +00:00
{
if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendor")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr xmlVendor = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
pDoc, cur->children, 1);
if (! xmlVendor)
return;
2004-04-19 14:57:02 +00:00
sVendor = xmlVendor;
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("location")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr xmlLocation = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
pDoc, cur->children, 1);
sLocation = xmlLocation;
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("version")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr xmlVersion = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
pDoc, cur->children, 1);
sVersion = xmlVersion;
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("requirements")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr xmlRequire = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
pDoc, cur->children, 1);
OUString sRequire = xmlRequire;
2004-04-19 14:57:02 +00:00
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
2004-04-19 14:57:02 +00:00
}
else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendorData")) == 0)
2004-04-19 14:57:02 +00:00
{
CXmlCharPtr xmlData = xmlNodeListGetString(
2004-04-19 14:57:02 +00:00
pDoc, cur->children, 1);
xmlChar* _data = static_cast<xmlChar*>(xmlData);
2004-04-19 14:57:02 +00:00
if (_data)
{
rtl::ByteSequence seq(reinterpret_cast<sal_Int8*>(_data), strlen(reinterpret_cast<char*>(_data)));
2004-04-19 14:57:02 +00:00
arVendorData = decodeBase16(seq);
}
}
cur = cur->next;
}
if (sVendor.isEmpty())
2004-05-13 07:10:46 +00:00
m_bEmptyNode = true;
2004-04-19 14:57:02 +00:00
//Get the javainfo attributes
CXmlCharPtr sVendorUpdate = xmlGetProp(pJavaInfo,
reinterpret_cast<xmlChar const *>("vendorUpdate"));
2004-04-19 14:57:02 +00:00
if ( ! sVendorUpdate)
throw FrameworkException(JFW_E_ERROR, sExcMsg);
2004-04-19 14:57:02 +00:00
sAttrVendorUpdate = sVendorUpdate;
}
void CNodeJavaInfo::writeToNode(xmlDoc* pDoc,
xmlNode* pJavaInfoNode) const
2004-04-19 14:57:02 +00:00
{
OSL_ASSERT(pJavaInfoNode && pDoc);
2004-04-19 14:57:02 +00:00
//write the attribute vendorSettings
2004-05-13 10:15:02 +00:00
//javaInfo@vendorUpdate
2004-04-19 14:57:02 +00:00
//creates the attribute if necessary
OString sUpdated = getElementUpdated();
xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("vendorUpdate"),
reinterpret_cast<xmlChar const *>(sUpdated.getStr()));
2004-05-13 10:15:02 +00:00
//javaInfo@autoSelect
xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("autoSelect"),
reinterpret_cast<xmlChar const *>(bAutoSelect ? "true" : "false"));
2004-04-19 14:57:02 +00:00
//Set xsi:nil in javaInfo element to false
//the xmlNs pointer must not be destroyed
xmlNs* nsXsi = xmlSearchNsByHref(pDoc,
2004-04-19 14:57:02 +00:00
pJavaInfoNode,
reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
2004-04-19 14:57:02 +00:00
xmlSetNsProp(pJavaInfoNode,
nsXsi,
reinterpret_cast<xmlChar const *>("nil"),
reinterpret_cast<xmlChar const *>("false"));
2004-04-19 14:57:02 +00:00
2004-04-21 08:30:36 +00:00
//Delete the children of JavaInfo
xmlNode* cur = pJavaInfoNode->children;
while (cur != nullptr)
2004-04-19 14:57:02 +00:00
{
2004-04-21 08:30:36 +00:00
xmlNode* lastNode = cur;
cur = cur->next;
xmlUnlinkNode(lastNode);
xmlFreeNode(lastNode);
2004-04-19 14:57:02 +00:00
}
2004-04-21 08:30:36 +00:00
//If the JavaInfo was set with an empty value,
//then we are done.
if (m_bEmptyNode)
return;
2004-04-21 08:30:36 +00:00
2004-04-19 14:57:02 +00:00
//add a new line after <javaInfo>
xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
//Create the vendor element
xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("vendor"),
CXmlCharPtr(sVendor));
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
//Create the location element
xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
CXmlCharPtr(sLocation));
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
//Create the version element
xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("version"),
CXmlCharPtr(sVersion));
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
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"));
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
//Create the requirements element
OUString sRequirements = OUString::number(
nRequirements, 16);
xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("requirements"),
CXmlCharPtr(sRequirements));
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
//Create the vendorData element
2004-04-19 14:57:02 +00:00
rtl::ByteSequence data = encodeBase16(arVendorData);
xmlNode* dataNode = xmlNewChild(pJavaInfoNode, nullptr,
reinterpret_cast<xmlChar const *>("vendorData"),
reinterpret_cast<xmlChar const *>(""));
2004-04-19 14:57:02 +00:00
xmlNodeSetContentLen(dataNode,
reinterpret_cast<xmlChar*>(data.getArray()), data.getLength());
2004-04-19 14:57:02 +00:00
//add a new line for better readability
nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
2004-04-19 14:57:02 +00:00
xmlAddChild(pJavaInfoNode, nodeCrLf);
}
std::unique_ptr<JavaInfo> CNodeJavaInfo::makeJavaInfo() const
2004-04-19 14:57:02 +00:00
{
if (bNil || m_bEmptyNode)
return std::unique_ptr<JavaInfo>();
return std::unique_ptr<JavaInfo>(
new JavaInfo{
sVendor, sLocation, sVersion, nRequirements,
arVendorData});
2004-04-19 14:57:02 +00:00
}
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;
}
2004-04-19 14:57:02 +00:00
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */