office-gobmx/jvmfwk/source/elements.cxx
Noel Grandin 1170db278d rtl::Static->thread-safe static in jvmfwk
Change-Id: I049148d82eb306e8ba7fdc9f0cc650f45b05da0c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125257
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2021-11-16 12:29:38 +01:00

971 lines
34 KiB
C++

/* -*- 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)");
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);
//<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.");
}
void NodeJava::load()
{
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.");
}
//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).");
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).");
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).");
// 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).");
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: */