1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/ustring.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <sal/log.hxx>
23 #include <libxml/xpathInternals.h>
24 #include <osl/diagnose.h>
25 #include <osl/file.hxx>
26 #include <osl/thread.hxx>
27 #include <o3tl/string_view.hxx>
28 #include "framework.hxx"
29 #include <fwkutil.hxx>
30 #include <elements.hxx>
31 #include <fwkbase.hxx>
36 #define UNO_JAVA_JFW_PARAMETER "UNO_JAVA_JFW_PARAMETER_"
37 #define UNO_JAVA_JFW_JREHOME "UNO_JAVA_JFW_JREHOME"
38 #define UNO_JAVA_JFW_ENV_JREHOME "UNO_JAVA_JFW_ENV_JREHOME"
39 #define UNO_JAVA_JFW_CLASSPATH "UNO_JAVA_JFW_CLASSPATH"
40 #define UNO_JAVA_JFW_ENV_CLASSPATH "UNO_JAVA_JFW_ENV_CLASSPATH"
41 #define UNO_JAVA_JFW_CLASSPATH_URLS "UNO_JAVA_JFW_CLASSPATH_URLS"
42 #define UNO_JAVA_JFW_VENDOR_SETTINGS "UNO_JAVA_JFW_VENDOR_SETTINGS"
46 static bool g_bJavaSet
= false;
51 // The paths are used in libxml. On Windows, it takes UTF-8 paths.
52 constexpr rtl_TextEncoding
PathEncoding() { return RTL_TEXTENCODING_UTF8
; }
54 rtl_TextEncoding
PathEncoding() { return osl_getThreadTextEncoding(); }
57 OString
getVendorSettingsPath(OUString
const & sURL
)
61 OUString sSystemPathSettings
;
62 if (osl_getSystemPathFromFileURL(sURL
.pData
,
63 & sSystemPathSettings
.pData
) != osl_File_E_None
)
64 throw FrameworkException(
66 "[Java framework] Error in function getVendorSettingsPath (fwkbase.cxx) "_ostr
);
67 OString osSystemPathSettings
= OUStringToOString(sSystemPathSettings
, PathEncoding());
68 return osSystemPathSettings
;
71 OUString
getParam(OUString
const & name
)
74 bool b
= Bootstrap()->getFrom(name
, retVal
);
77 "Using bootstrap parameter " << name
<< " = \"" << retVal
<< "\""
78 << (b
? "" : " (undefined)"));
82 OUString
getParamFirstUrl(OUString
const & name
)
84 // Some parameters can consist of multiple URLs (separated by space
85 // characters, although trim() harmlessly also removes other white-space),
86 // of which only the first is used:
87 return getParam(name
).trim().getToken(0, ' ');
93 VendorSettings::VendorSettings()
95 OUString
xmlDocVendorSettingsFileUrl(BootParams::getVendorSettings());
96 //Prepare the xml document and context
97 OString sSettingsPath
= getVendorSettingsPath(xmlDocVendorSettingsFileUrl
);
98 if (sSettingsPath
.isEmpty())
100 OString
sMsg("[Java framework] A vendor settings file was not specified."
101 "Check the bootstrap parameter " UNO_JAVA_JFW_VENDOR_SETTINGS
"."_ostr
);
102 SAL_WARN( "jfw", sMsg
);
103 throw FrameworkException(JFW_E_CONFIGURATION
, sMsg
);
105 if (sSettingsPath
.isEmpty())
108 m_xmlDocVendorSettings
= xmlParseFile(sSettingsPath
.getStr());
109 if (m_xmlDocVendorSettings
== nullptr)
110 throw FrameworkException(
112 OString::Concat("[Java framework] Error while parsing file: ")
113 + sSettingsPath
+ ".");
115 m_xmlPathContextVendorSettings
= xmlXPathNewContext(m_xmlDocVendorSettings
);
116 int res
= xmlXPathRegisterNs(
117 m_xmlPathContextVendorSettings
, reinterpret_cast<xmlChar
const *>("jf"),
118 reinterpret_cast<xmlChar
const *>(NS_JAVA_FRAMEWORK
));
120 throw FrameworkException(JFW_E_ERROR
,
121 "[Java framework] Error in constructor VendorSettings::VendorSettings() (fwkbase.cxx)"_ostr
);
124 VersionInfo
VendorSettings::getVersionInformation(std::u16string_view sVendor
) const
126 OSL_ASSERT(!sVendor
.empty());
127 OString osVendor
= OUStringToOString(sVendor
, RTL_TEXTENCODING_UTF8
);
128 CXPathObjectPtr pathObject
= xmlXPathEvalExpression(
129 reinterpret_cast<xmlChar
const *>(
131 "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" + osVendor
132 + "\"]/jf:minVersion").getStr()),
133 m_xmlPathContextVendorSettings
);
134 if (xmlXPathNodeSetIsEmpty(pathObject
->nodesetval
))
138 #if defined MACOSX && defined __aarch64__
146 VersionInfo aVersionInfo
;
148 OString sExpression
=
149 "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
150 osVendor
+ "\"]/jf:minVersion";
152 CXPathObjectPtr xPathObjectMin
=
153 xmlXPathEvalExpression(reinterpret_cast<xmlChar
const *>(sExpression
.getStr()),
154 m_xmlPathContextVendorSettings
);
155 if (xmlXPathNodeSetIsEmpty(xPathObjectMin
->nodesetval
))
157 aVersionInfo
.sMinVersion
.clear();
161 CXmlCharPtr sVersion
= xmlNodeListGetString(
162 m_xmlDocVendorSettings
,
163 xPathObjectMin
->nodesetval
->nodeTab
[0]->xmlChildrenNode
, 1);
164 aVersionInfo
.sMinVersion
= sVersion
;
168 sExpression
= "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
169 osVendor
+ "\"]/jf:maxVersion";
170 CXPathObjectPtr xPathObjectMax
= xmlXPathEvalExpression(
171 reinterpret_cast<xmlChar
const *>(sExpression
.getStr()),
172 m_xmlPathContextVendorSettings
);
173 if (xmlXPathNodeSetIsEmpty(xPathObjectMax
->nodesetval
))
175 aVersionInfo
.sMaxVersion
.clear();
179 CXmlCharPtr sVersion
= xmlNodeListGetString(
180 m_xmlDocVendorSettings
,
181 xPathObjectMax
->nodesetval
->nodeTab
[0]->xmlChildrenNode
, 1);
182 aVersionInfo
.sMaxVersion
= sVersion
;
185 //Get excludeVersions
186 sExpression
= "/jf:javaSelection/jf:vendorInfos/jf:vendor[@name=\"" +
187 osVendor
+ "\"]/jf:excludeVersions/jf:version";
188 CXPathObjectPtr xPathObjectVersions
=
189 xmlXPathEvalExpression(reinterpret_cast<xmlChar
const *>(sExpression
.getStr()),
190 m_xmlPathContextVendorSettings
);
191 if (!xmlXPathNodeSetIsEmpty(xPathObjectVersions
->nodesetval
))
193 xmlNode
* cur
= xPathObjectVersions
->nodesetval
->nodeTab
[0];
194 while (cur
!= nullptr)
196 if (cur
->type
== XML_ELEMENT_NODE
)
198 if (xmlStrcmp(cur
->name
, reinterpret_cast<xmlChar
const *>("version")) == 0)
200 CXmlCharPtr sVersion
= xmlNodeListGetString(
201 m_xmlDocVendorSettings
, cur
->xmlChildrenNode
, 1);
202 OUString usVersion
= sVersion
;
203 aVersionInfo
.vecExcludeVersions
.push_back(usVersion
);
212 ::std::vector
<OString
> BootParams::getVMParameters()
214 ::std::vector
<OString
> vecParams
;
216 for (sal_Int32 i
= 1; ; i
++)
218 OUString sName
= UNO_JAVA_JFW_PARAMETER
+ OUString::number(i
);
220 if (Bootstrap()->getFrom(sName
, sValue
))
223 OUStringToOString(sValue
, osl_getThreadTextEncoding());
224 vecParams
.push_back(sParam
);
227 "Using bootstrap parameter " << sName
<< " = " << sParam
);
235 OUString
BootParams::getUserData()
237 return getParamFirstUrl(u
"UNO_JAVA_JFW_USER_DATA"_ustr
);
240 OUString
BootParams::getSharedData()
242 return getParamFirstUrl(u
"UNO_JAVA_JFW_SHARED_DATA"_ustr
);
245 OString
BootParams::getClasspath()
249 if (Bootstrap()->getFrom( u
"" UNO_JAVA_JFW_CLASSPATH
""_ustr
, sCP
))
251 sClassPath
= OUStringToOString(sCP
, PathEncoding());
254 "Using bootstrap parameter " UNO_JAVA_JFW_CLASSPATH
" = "
259 if (Bootstrap()->getFrom( u
"" UNO_JAVA_JFW_ENV_CLASSPATH
""_ustr
, sEnvCP
))
261 char * pCp
= getenv("CLASSPATH");
264 sClassPath
+= OStringChar(SAL_PATHSEPARATOR
) + pCp
;
268 "Using bootstrap parameter " UNO_JAVA_JFW_ENV_CLASSPATH
269 " and class path is: " << (pCp
? pCp
: ""));
275 OUString
BootParams::getVendorSettings()
278 if (Bootstrap()->getFrom(u
"" UNO_JAVA_JFW_VENDOR_SETTINGS
""_ustr
, sVendor
))
280 //check the value of the bootstrap variable
281 jfw::FileStatus s
= checkFileURL(sVendor
);
284 //This bootstrap parameter can contain a relative URL
285 OUString sAbsoluteUrl
;
286 OUString sBaseDir
= getLibraryLocation();
287 if (File::getAbsoluteFileURL(sBaseDir
, sVendor
, sAbsoluteUrl
)
289 throw FrameworkException(
291 "[Java framework] Invalid value for bootstrap variable: "
292 UNO_JAVA_JFW_VENDOR_SETTINGS
""_ostr
);
293 sVendor
= sAbsoluteUrl
;
294 s
= checkFileURL(sVendor
);
295 if (s
== jfw::FILE_INVALID
|| s
== jfw::FILE_DOES_NOT_EXIST
)
297 throw FrameworkException(
299 "[Java framework] Invalid value for bootstrap variable: "
300 UNO_JAVA_JFW_VENDOR_SETTINGS
""_ostr
);
305 "Using bootstrap parameter " UNO_JAVA_JFW_VENDOR_SETTINGS
" = "
311 OUString
BootParams::getJREHome()
315 bool bJRE
= Bootstrap()->getFrom(u
"" UNO_JAVA_JFW_JREHOME
""_ustr
, sJRE
);
316 bool bEnvJRE
= Bootstrap()->getFrom(u
"" UNO_JAVA_JFW_ENV_JREHOME
""_ustr
, sEnvJRE
);
320 throw FrameworkException(
322 "[Java framework] Both bootstrap parameter "
323 UNO_JAVA_JFW_JREHOME
" and "
324 UNO_JAVA_JFW_ENV_JREHOME
" are set. However only one of them can be set."
325 "Check bootstrap parameters: environment variables, command line "
326 "arguments, rc/ini files for executable and java framework library."_ostr
);
330 const char * pJRE
= getenv("JAVA_HOME");
333 throw FrameworkException(
335 "[Java framework] Both bootstrap parameter "
336 UNO_JAVA_JFW_ENV_JREHOME
" is set, but the environment variable "
337 "JAVA_HOME is not set."_ostr
);
339 std::string_view
osJRE(pJRE
);
340 OUString usJRE
= OStringToOUString(osJRE
, osl_getThreadTextEncoding());
341 if (File::getFileURLFromSystemPath(usJRE
, sJRE
) != File::E_None
)
342 throw FrameworkException(
344 "[Java framework] Error in function BootParams::getJREHome() "
345 "(fwkbase.cxx)."_ostr
);
348 "Using bootstrap parameter " UNO_JAVA_JFW_ENV_JREHOME
349 " with JAVA_HOME = " << pJRE
);
351 else if (getMode() == JFW_MODE_DIRECT
&& !bJRE
)
353 throw FrameworkException(
355 "[Java framework] The bootstrap parameter "
356 UNO_JAVA_JFW_ENV_JREHOME
" or " UNO_JAVA_JFW_JREHOME
357 " must be set in direct mode."_ostr
);
362 "Using bootstrap parameter " UNO_JAVA_JFW_JREHOME
" = " << sJRE
);
366 OUString
BootParams::getClasspathUrls()
369 Bootstrap()->getFrom( u
"" UNO_JAVA_JFW_CLASSPATH_URLS
""_ustr
, sParams
);
372 "Using bootstrap parameter " UNO_JAVA_JFW_CLASSPATH_URLS
" = "
379 static bool g_bMode
= false;
380 static JFW_MODE g_mode
= JFW_MODE_APPLICATION
;
384 //check if either of the "direct mode" bootstrap variables is set
385 bool bDirectMode
= true;
387 const rtl::Bootstrap
* aBoot
= Bootstrap();
388 if (!aBoot
->getFrom(u
"" UNO_JAVA_JFW_JREHOME
""_ustr
, sValue
))
390 if (!aBoot
->getFrom(u
"" UNO_JAVA_JFW_ENV_JREHOME
""_ustr
, sValue
))
392 if (!aBoot
->getFrom(u
"" UNO_JAVA_JFW_CLASSPATH
""_ustr
, sValue
))
394 if (!aBoot
->getFrom(u
"" UNO_JAVA_JFW_ENV_CLASSPATH
""_ustr
, sValue
))
396 OUString sParams
= UNO_JAVA_JFW_PARAMETER
+
398 if (!aBoot
->getFrom(sParams
, sValue
))
408 g_mode
= JFW_MODE_DIRECT
;
410 g_mode
= JFW_MODE_APPLICATION
;
417 OUString
getApplicationClassPath()
419 OSL_ASSERT(getMode() == JFW_MODE_APPLICATION
);
420 OUString sParams
= BootParams::getClasspathUrls();
421 if (sParams
.isEmpty())
428 OUString
token( o3tl::trim(o3tl::getToken(sParams
, 0, ' ', index
)) );
429 if (!token
.isEmpty())
431 OUString systemPathElement
;
432 oslFileError rc
= osl_getSystemPathFromFileURL(
433 token
.pData
, &systemPathElement
.pData
);
434 OSL_ASSERT( rc
== osl_File_E_None
);
435 if (rc
== osl_File_E_None
&& !systemPathElement
.isEmpty())
437 if (buf
.getLength() > 0)
438 buf
.append( SAL_PATHSEPARATOR
);
439 buf
.append( systemPathElement
);
444 return buf
.makeStringAndClear();
447 OString
makeClassPathOption(std::u16string_view sUserClassPath
)
449 //Compose the class path
451 OUStringBuffer
sBufCP(4096);
453 // append all user selected jars to the class path
454 if (!sUserClassPath
.empty())
455 sBufCP
.append(sUserClassPath
);
457 //append all jar libraries and components to the class path
458 OUString sAppCP
= getApplicationClassPath();
459 if (!sAppCP
.isEmpty())
461 if (!sUserClassPath
.empty())
463 sBufCP
.append(SAL_PATHSEPARATOR
);
465 sBufCP
.append(sAppCP
);
468 sPaths
= OUStringToOString(sBufCP
, PathEncoding());
469 if (sPaths
.isEmpty()) {
473 OString sOptionClassPath
= "-Djava.class.path=" + sPaths
;
474 return sOptionClassPath
;
477 OString
getUserSettingsPath()
479 return getSettingsPath(BootParams::getUserData());
482 OString
getSharedSettingsPath()
484 return getSettingsPath(BootParams::getSharedData());
487 OString
getSettingsPath( const OUString
& sURL
)
492 if (osl_getSystemPathFromFileURL(sURL
.pData
,
493 & sPath
.pData
) != osl_File_E_None
)
494 throw FrameworkException(
496 "[Java framework] Error in function ::getSettingsPath (fwkbase.cxx)."_ostr
);
497 return OUStringToOString(sPath
, PathEncoding());
500 OString
getVendorSettingsPath()
502 return getVendorSettingsPath(BootParams::getVendorSettings());
505 void setJavaSelected()
510 bool wasJavaSelectedInSameProcess()
512 //g_setJavaProcId not set means no Java selected
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */