Kaydet (Commit) 40138cee authored tarafından Michael Weghorn's avatar Michael Weghorn Kaydeden (comit) Stephan Bergmann

fdo#83753: consider JAVA_HOME and PATH when selecting JRE

adapted algorithm that selects the Java runtime to be used so that
Java installations associated with the JAVA_HOME and PATH
environment variables are preferred over others

Java installations are now analysed in the following order:
* installation that the JAVA_HOME environment
    variable refers to (if it is set)
* Java installations in PATH
* other Java installation (algorithm that was used before)
Signed-off-by: 's avatarStephan Bergmann <sbergman@redhat.com>

Conflicts:
	jvmfwk/source/framework.cxx

Change-Id: I3a3ade25322def0c0432b369848f13a6b82034a1
üst 86910c87
...@@ -72,7 +72,7 @@ extern "C" { ...@@ -72,7 +72,7 @@ extern "C" {
necessary to specify the bootstrap parameter <code>UNO_JAVA_JFW_SHARED_DATA</code>. necessary to specify the bootstrap parameter <code>UNO_JAVA_JFW_SHARED_DATA</code>.
</p> </p>
<p>Setting the class path used by a Java VM should not be necesarry. The locations <p>Setting the class path used by a Java VM should not be necessary. The locations
of Jar files should be known by a class loader. If a jar file depends on another of Jar files should be known by a class loader. If a jar file depends on another
jar file then it can be referenced in the manifest file of the first jar. However, jar file then it can be referenced in the manifest file of the first jar. However,
a user may add jars to the class path by using this API. If it becomes necessary a user may add jars to the class path by using this API. If it becomes necessary
...@@ -320,16 +320,11 @@ JVMFWK_DLLPUBLIC javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning) ...@@ -320,16 +320,11 @@ JVMFWK_DLLPUBLIC javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning)
/** detects a suitable JRE and configures the framework to use it. /** detects a suitable JRE and configures the framework to use it.
<p>Which JREs can be used is determined by the file javavendors.xml, <p>Which JREs can be used is determined by the file javavendors.xml,
which contains version requirements, as well as information about available which contains version requirements.</p>
plug-in libraries. Only these libraries are responsible for locating JRE
installations.</p>
<p> <p>
JREs can be provided by different vendors. In order to find the JREs of JREs can be provided by different vendors.
a certain vendor a plug-in library must be provided. There must be only one The function obtains information about JRE installations and checks if
library for one vendor. The names of locations of those libraries have to there is one among them that supports
be put into the javavendors.xml file.<br/>
The function uses the plug-in libraries to obtain information about JRE
installation and checks if they there is one among them that supports
a set of features (currently only accessibilty is possible). If none was a set of features (currently only accessibilty is possible). If none was
found then it also uses a list of paths, which have been registered found then it also uses a list of paths, which have been registered
by <code>jfw_addJRELocation</code> by <code>jfw_addJRELocation</code>
...@@ -342,27 +337,36 @@ JVMFWK_DLLPUBLIC javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning) ...@@ -342,27 +337,36 @@ JVMFWK_DLLPUBLIC javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning)
<p> <p>
While determining a proper JRE this function takes into account if a While determining a proper JRE this function takes into account if a
user requires support for assistive technology tools. If user user requires support for assistive technology tools. If user
need that support they have to set up their system accordingly. When support need that support they have to set up their system accordingly.</p>
for assistive technology is required, then the lists of <p>
If the JAVA_HOME environment variable is set, this function prefers
the JRE which the variable refers to over other JREs.
If JAVA_HOME is not set or does not refer to a suitable JRE,
the PATH environment variable is inspected and the respective JREs
are checked for their suitability next.</p>
<p>
When support for assistive technology is required, then the
<code>JavaInfo</code> objects, <code>JavaInfo</code> objects,
which are provided by the <code>getJavaInfo</code> functions of the plug-ins, are which are provided by the <code>getJavaInfo</code> functions, are
examined for a suitable JRE. That is, the <code>JavaInfo</code> objects examined for a suitable JRE.
from the list That is, the <code>JavaInfo</code> object that refers to the JRE referred to
obtained from the first plug-in, are examined. If no <code>JavaInfo</code> by JAVA_HOME is examined. If it does not have the flag
object has the flag
<code>JFW_FEATURE_ACCESSBRIDGE</code> in the member <code>nFeatures</code> <code>JFW_FEATURE_ACCESSBRIDGE</code> in the member <code>nFeatures</code>
then the then the <JavaInfo></code> objects that are related to the PATH variable
next plug-in is used to obtain a list of <code>JavaInfo</code> objects. are examined.
If no suitable <code>JavaInfo</code> object is found, all <code>JavaInfo</code>
objects - representing Java installations on the system -, are examined.
As long as no <code>JavaInfo</code> object has the flag
<code>JFW_FEATURE_ACCESSBRIDGE</code> in the member <code>nFeatures</code>, more
<code>JavaInfo</code> objects are examined.
This goes on until a <code>JavaInfo</code> object was found which This goes on until a <code>JavaInfo</code> object was found which
represents a suitable JRE. Or neither plug-in provided such a represents a suitable JRE. Or no such <code>JavaInfo</code> object was found.
<code>JavaInfo</code> object. In that case the first In that case the first <code>JavaInfo</code> object that was detected
<code>JavaInfo</code> object from the first plug-in is used to determine by the algorithm described above is used to determine the JRE which is to be used.</p>
the JRE which is to be used.</p>
<p> <p>
If there is no need for the support of assistive technology tools then If there is no need for the support of assistive technology tools then
the first <code>JavaInfo</code> object from the list obtained by the the first <code>JavaInfo</code> object that is detected by the algorithm
first plug-in is used. If this plug-in does not find any JREs then the as described above is used.</p>
next plug-in is used, and so on.</p>
@param ppInfo @param ppInfo
[out] a <code>JavaInfo</code> pointer, representing the selected JRE. [out] a <code>JavaInfo</code> pointer, representing the selected JRE.
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
#include <jvmfwk/framework.h> #include <jvmfwk/framework.h>
#include <rtl/ustring.h> #include <rtl/ustring.h>
#include "jni.h" #include "jni.h"
#include <vector>
#include <utility>
#include "../source/elements.hxx"
/** /**
@file @file
...@@ -168,6 +171,81 @@ javaPluginError jfw_plugin_getJavaInfoByPath( ...@@ -168,6 +171,81 @@ javaPluginError jfw_plugin_getJavaInfoByPath(
sal_Int32 nSizeExcludeList, sal_Int32 nSizeExcludeList,
JavaInfo ** ppInfo); JavaInfo ** ppInfo);
/** obtains information for a JRE referenced by the JAVA_HOME environment variable.
<p>If the JAVA_HOME environment variable is set and points to a JRE whoose vendor
matches the requirements given by vecVendorInfos (i.e. it has a vendor that is
given in vecVendorInfos and the version requirements for the vendor are met),
then this function shall return a JavaInfo object for this JRE.</p>
@param vecVendorInfos
[in] vector specifying the vendor and version requirements that the JRE must fulfill.
The vector contains pairs of vendors and the respective version requirements
for those vendors. The JRE must support the requirements of one given pair in the
vector (i.e. it must be of one of the vendors and meet the version requirements
- minVersion, maxVersion, excludeVersions - for that specific vendor).
@param ppInfo
[out] if the JAVA_HOME environment variable is set and points to a suitable
JRE, then then <code>ppInfo</code> contains
on return a pointer to its <code>JavaInfo</code> object.
@return
JFW_PLUGIN_E_NONE the function ran successfully.</br>
JFW_PLUGIN_E_INVALID_ARG an argument was not valid, for example
<code>ppInfo</code> is an invalid pointer.
JFW_PLUGIN_E_NO_JRE no suitable JRE could be detected at the given location. However, that
does not mean necessarily that there is no JRE. There could be a JRE but it has
a vendor which is not supported by this API implementation or it does not
meet the version requirements.
*/
javaPluginError jfw_plugin_getJavaInfoFromJavaHome(
std::vector<std::pair<OUString, jfw::VersionInfo>> const& vecVendorInfos,
JavaInfo ** ppInfo);
/** obtains information about installations of Java Runtime Environments (JREs)
whose executable is in the PATH.
<p>The function gathers information about available JREs which are on the PATH
(PATH environment variable) and meet the vendor and version requirements given by
<code>vecVendorInfos</code> (i.e. they have a vendor that is given in
<code>vecVendorInfos</code> and the version requirements for the vendor are met).
</p>
<p>
The JavaInfo structures returned in <code>vecJavaInfosFromPath</code> should be ordered
according to their occurrence in the PATH. The one that is the first one on the PATH
is also the first element in the vector.</p>
<p>
The function allocates memory for all the JavaInfo objects returned
in <code>vecJavaInfosFromPath</code>. The caller must free each JavaInfo object by calling
<code>jfw_freeJavaInfo</code> (#include "jvmfwk/framework.h").
</p>
@param vecVendorInfos
[in] vector specifying the vendor and version requirements that the JRE must fulfill.
The vector contains pairs of vendors and the respective version requirements
for those vendors. The JRE must support the requirements of one given pair in the
vector (i.e. it must be of one of the vendors and meet the version requirements
- minVersion, maxVersion, excludeVersions - for that specific vendor).
@param vecJavaInfosFromPath
[out] if the function runs successfully then <code>vecJavaInfosFromPath</code>
contains on return a vector of pointers to <code>JavaInfo</code> objects.
On return of this function, <code>vecJavaInfosFromPath</code> references
a newly created vector rather than the same vector as before with
the <code>JavaInfo</code> objects inserted into the existing vector.
@return
JFW_PLUGIN_E_NONE the function ran successfully and at least one JRE
that meets the requirements was found.</br>
JFW_PLUGIN_E_NO_JRE no JavaInfo that meets the version criteria was found
when inspecting the PATH
*/
javaPluginError jfw_plugin_getJavaInfosFromPath(
std::vector<std::pair<OUString, jfw::VersionInfo>> const& vecVendorInfos,
std::vector<JavaInfo*> & vecJavaInfosFromPath);
/** starts a Java Virtual Machine. /** starts a Java Virtual Machine.
<p>The caller should provide all essential JavaVMOptions, such as the <p>The caller should provide all essential JavaVMOptions, such as the
......
...@@ -404,6 +404,105 @@ javaPluginError jfw_plugin_getJavaInfoByPath( ...@@ -404,6 +404,105 @@ javaPluginError jfw_plugin_getJavaInfoByPath(
return errorcode; return errorcode;
} }
javaPluginError jfw_plugin_getJavaInfoFromJavaHome(
std::vector<pair<OUString, jfw::VersionInfo>> const& vecVendorInfos,
JavaInfo ** ppInfo)
{
if (!ppInfo)
return JFW_PLUGIN_E_INVALID_ARG;
rtl::Reference<VendorBase> infoJavaHome = getJavaInfoFromJavaHome();
if (!infoJavaHome.is())
return JFW_PLUGIN_E_NO_JRE;
//Check if the detected JRE matches the version requirements
typedef std::vector<pair<OUString, jfw::VersionInfo>>::const_iterator ci_pl;
for (ci_pl vendorInfo = vecVendorInfos.begin(); vendorInfo != vecVendorInfos.end(); ++vendorInfo)
{
const OUString& vendor = vendorInfo->first;
jfw::VersionInfo versionInfo = vendorInfo->second;
if (vendor.equals(infoJavaHome->getVendor()))
{
javaPluginError errorcode = checkJavaVersionRequirements(
infoJavaHome,
versionInfo.sMinVersion,
versionInfo.sMaxVersion,
versionInfo.getExcludeVersions(),
versionInfo.getExcludeVersionSize());
if (errorcode == JFW_PLUGIN_E_NONE)
{
*ppInfo = createJavaInfo(infoJavaHome);
return JFW_PLUGIN_E_NONE;
}
}
}
return JFW_PLUGIN_E_NO_JRE;
}
javaPluginError jfw_plugin_getJavaInfosFromPath(
std::vector<std::pair<OUString, jfw::VersionInfo>> const& vecVendorInfos,
std::vector<JavaInfo*> & javaInfosFromPath)
{
// find JREs from PATH
vector<rtl::Reference<VendorBase>> vecInfosFromPath;
createJavaInfoFromPath(vecInfosFromPath);
vector<rtl::Reference<VendorBase> > vecVerifiedInfos;
// copy JREs that meet version requirements to vecVerifiedInfos
typedef vector<rtl::Reference<VendorBase> >::iterator it;
for (it i= vecInfosFromPath.begin(); i != vecInfosFromPath.end(); ++i)
{
const rtl::Reference<VendorBase>& cur = *i;
typedef std::vector<pair<OUString, jfw::VersionInfo>>::const_iterator ci_pl;
for (ci_pl vendorInfo = vecVendorInfos.begin(); vendorInfo != vecVendorInfos.end(); ++vendorInfo)
{
const OUString& vendor = vendorInfo->first;
jfw::VersionInfo versionInfo = vendorInfo->second;
if (vendor.equals(cur->getVendor()))
{
javaPluginError errorcode = checkJavaVersionRequirements(
cur,
versionInfo.sMinVersion,
versionInfo.sMaxVersion,
versionInfo.getExcludeVersions(),
versionInfo.getExcludeVersionSize());
if (errorcode == JFW_PLUGIN_E_NONE)
{
vecVerifiedInfos.push_back(*i);
}
}
}
}
if (vecVerifiedInfos.empty())
return JFW_PLUGIN_E_NO_JRE;
// Now vecVerifiedInfos contains all those JREs which meet the version requirements
// Transfer them into the vector that is passed out.
vector<JavaInfo*> infosFromPath;
typedef vector<rtl::Reference<VendorBase> >::const_iterator cit;
for (cit ii = vecVerifiedInfos.begin(); ii != vecVerifiedInfos.end(); ++ii)
{
infosFromPath.push_back(createJavaInfo(*ii));
}
javaInfosFromPath = infosFromPath;
return JFW_PLUGIN_E_NONE;
}
#if defined(WNT) #if defined(WNT)
// Load msvcr71.dll using an explicit full path from where it is // Load msvcr71.dll using an explicit full path from where it is
......
...@@ -1131,7 +1131,8 @@ void createJavaInfoFromPath(vector<rtl::Reference<VendorBase> >& vecInfos) ...@@ -1131,7 +1131,8 @@ void createJavaInfoFromPath(vector<rtl::Reference<VendorBase> >& vecInfos)
} }
} }
void createJavaInfoFromJavaHome(vector<rtl::Reference<VendorBase> >& vecInfos)
rtl::Reference<VendorBase> getJavaInfoFromJavaHome()
{ {
// Get Java from JAVA_HOME environment // Get Java from JAVA_HOME environment
...@@ -1142,11 +1143,28 @@ void createJavaInfoFromJavaHome(vector<rtl::Reference<VendorBase> >& vecInfos) ...@@ -1142,11 +1143,28 @@ void createJavaInfoFromJavaHome(vector<rtl::Reference<VendorBase> >& vecInfos)
char *szJavaHome= getenv("JAVA_HOME"); char *szJavaHome= getenv("JAVA_HOME");
if(szJavaHome) if(szJavaHome)
{ {
OUString sHome(szJavaHome,strlen(szJavaHome),osl_getThreadTextEncoding()); OUString sHome(szJavaHome, strlen(szJavaHome), osl_getThreadTextEncoding());
OUString sHomeUrl; OUString sHomeUrl;
if(File::getFileURLFromSystemPath(sHome, sHomeUrl) == File::E_None) if(File::getFileURLFromSystemPath(sHome, sHomeUrl) == File::E_None)
{ {
getJREInfoByPath(sHomeUrl, vecInfos); return getJREInfoByPath(sHomeUrl);
}
}
return NULL;
}
void createJavaInfoFromJavaHome(vector<rtl::Reference<VendorBase> >& vecInfos)
{
rtl::Reference<VendorBase> aInfo = getJavaInfoFromJavaHome();
if (aInfo.is())
{
vector<rtl::Reference<VendorBase> >::const_iterator it_impl= std::find_if(
vecInfos.begin(),vecInfos.end(), InfoFindSame(aInfo->getHome()));
if(it_impl == vecInfos.end())
{
vecInfos.push_back(aInfo);
} }
} }
} }
......
...@@ -39,6 +39,12 @@ bool getJREInfoFromBinPath( ...@@ -39,6 +39,12 @@ bool getJREInfoFromBinPath(
const OUString& path, std::vector<rtl::Reference<VendorBase> > & vecInfos); const OUString& path, std::vector<rtl::Reference<VendorBase> > & vecInfos);
inline OUString getDirFromFile(const OUString& usFilePath); inline OUString getDirFromFile(const OUString& usFilePath);
void createJavaInfoFromPath(std::vector<rtl::Reference<VendorBase> >& vecInfos); void createJavaInfoFromPath(std::vector<rtl::Reference<VendorBase> >& vecInfos);
/* Returns a VendorBase object if JAVA_HOME environment variable points
to a JRE.
*/
rtl::Reference<VendorBase> getJavaInfoFromJavaHome();
void createJavaInfoFromJavaHome(std::vector<rtl::Reference<VendorBase> > &vecInfos); void createJavaInfoFromJavaHome(std::vector<rtl::Reference<VendorBase> > &vecInfos);
void createJavaInfoDirScan(std::vector<rtl::Reference<VendorBase> >& vecInfos); void createJavaInfoDirScan(std::vector<rtl::Reference<VendorBase> >& vecInfos);
#ifdef WNT #ifdef WNT
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment