/**************************************************************
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_jvmfwk.hxx"
#include "boost/scoped_array.hpp"
#include "rtl/ustring.hxx"
#include "rtl/bootstrap.hxx"
#include "osl/thread.hxx"
#include "osl/file.hxx"
#include "osl/module.hxx"
#include "jvmfwk/framework.h"
#include "jvmfwk/vendorplugin.h"
#include <vector>
#include <functional>
#include <algorithm>
#include "framework.hxx"
#include "fwkutil.hxx"
#include "elements.hxx"
#include "fwkbase.hxx"

#ifdef WNT
/** The existence of the file useatjava.txt decides if a Java should be used
    that supports accessibility tools.
 */
#define USE_ACCESSIBILITY_FILE "useatjava.txt"
#endif

#define UNO_JAVA_JFW_JREHOME "UNO_JAVA_JFW_JREHOME"
namespace {
JavaVM * g_pJavaVM = NULL;

bool g_bEnabledSwitchedOn = false;

sal_Bool areEqualJavaInfo(
    JavaInfo const * pInfoA,JavaInfo const * pInfoB)
{
    return jfw_areEqualJavaInfo(pInfoA, pInfoB);
}
}

javaFrameworkError SAL_CALL jfw_findAllJREs(JavaInfo ***pparInfo, sal_Int32 *pSize)
{
    javaFrameworkError retVal = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
		javaFrameworkError errcode = JFW_E_NONE;
		if (pparInfo == NULL || pSize == NULL)
			return JFW_E_INVALID_ARG;

        jfw::VendorSettings aVendorSettings;
		//Get a list of plugins which provide Java information
        std::vector<jfw::PluginLibrary> vecPlugins =
            aVendorSettings.getPluginData();

        //Create a vector that holds the libraries, which will be later
        //dynamically loaded;
        boost::scoped_array<osl::Module> sarModules;
        sarModules.reset(new osl::Module[vecPlugins.size()]);
        osl::Module * arModules = sarModules.get();
		//Add the JavaInfos found by jfw_plugin_getAllJavaInfos to the vector
		//Make sure that the contents are destroyed if this
		//function returns with an error
		std::vector<jfw::CJavaInfo> vecInfo;
		//Add the JavaInfos found by jfw_plugin_getJavaInfoByPath to this vector
		//Make sure that the contents are destroyed if this
		//function returns with an error
		std::vector<jfw::CJavaInfo> vecInfoManual;
		typedef std::vector<jfw::CJavaInfo>::iterator it_info;
		//get the list of paths to jre locations which have been
		//added manually
		const jfw::MergedSettings settings;
		const std::vector<rtl::OUString>& vecJRELocations =
			settings.getJRELocations();
		//Use every plug-in library to get Java installations.
		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
        int cModule = 0;
 		for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++, cModule++)
 		{
			const jfw::PluginLibrary & library = *i;
			jfw::VersionInfo versionInfo =
				aVendorSettings.getVersionInformation(library.sVendor);
            arModules[cModule].load(library.sPath);
            osl::Module & pluginLib = arModules[cModule];

			if (pluginLib.is() == sal_False)
			{
				rtl::OString msg = rtl::OUStringToOString(
					library.sPath, osl_getThreadTextEncoding());
				fprintf(stderr,"[jvmfwk] Could not load plugin %s\n" \
						"Modify the javavendors.xml accordingly!\n", msg.getStr());
				return JFW_E_NO_PLUGIN;
			}
			jfw_plugin_getAllJavaInfos_ptr getAllJavaFunc =
				(jfw_plugin_getAllJavaInfos_ptr) pluginLib.getFunctionSymbol(
					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getAllJavaInfos")));

			OSL_ASSERT(getAllJavaFunc);
			if (getAllJavaFunc == NULL)
				return JFW_E_ERROR;

			//get all installations of one vendor according to minVersion,
			//maxVersion and excludeVersions
			sal_Int32 cInfos = 0;
			JavaInfo** arInfos = NULL;
			javaPluginError plerr  = (*getAllJavaFunc)(
				library.sVendor.pData,
				versionInfo.sMinVersion.pData,
				versionInfo.sMaxVersion.pData,
				versionInfo.getExcludeVersions(),
				versionInfo.getExcludeVersionSize(),
				& arInfos,
				& cInfos);

			if (plerr != JFW_PLUGIN_E_NONE)
				return JFW_E_ERROR;

			for (int j = 0; j < cInfos; j++)
                vecInfo.push_back(jfw::CJavaInfo::createWrapper(arInfos[j]));

			rtl_freeMemory(arInfos);

			//Check if the current plugin can detect JREs at the location
			// of the paths added by jfw_setJRELocations or jfw_addJRELocation
			//get the function from the plugin
			jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
				(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));

			OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
			if (jfw_plugin_getJavaInfoByPathFunc == NULL)
				return JFW_E_ERROR;

			typedef std::vector<rtl::OUString>::const_iterator citLoc;
			//Check every manually added location
			for (citLoc ii = vecJRELocations.begin();
				ii != vecJRELocations.end(); ii++)
			{
// 				rtl::OUString sLocation =
// 					rtl::OStringToOUString(*ii, RTL_TEXTENCODING_UTF8);
				jfw::CJavaInfo aInfo;
				plerr = (*jfw_plugin_getJavaInfoByPathFunc)(
					ii->pData,
                    library.sVendor.pData,
					versionInfo.sMinVersion.pData,
					versionInfo.sMaxVersion.pData,
					versionInfo.getExcludeVersions(),
					versionInfo.getExcludeVersionSize(),
					& aInfo.pInfo);
				if (plerr == JFW_PLUGIN_E_NO_JRE)
					continue;
				if (plerr == JFW_PLUGIN_E_FAILED_VERSION)
					continue;
				else if (plerr !=JFW_PLUGIN_E_NONE)
					return JFW_E_ERROR;

				if (aInfo)
				{
					//Was this JRE already added?. Different plugins could detect
					//the same JRE
					it_info it_duplicate =
						std::find_if(vecInfoManual.begin(), vecInfoManual.end(),
								std::bind2nd(std::ptr_fun(areEqualJavaInfo), aInfo));
					if (it_duplicate == vecInfoManual.end())
						vecInfoManual.push_back(aInfo);
				}
			}
		}
		//Make sure vecInfoManual contains only JavaInfos for the vendors for which
		//there is a javaSelection/plugins/library entry in the javavendors.xml
		//To obtain the JavaInfos for the manually added JRE locations the function
		//jfw_getJavaInfoByPath is called which can return a JavaInfo of any vendor.
		std::vector<jfw::CJavaInfo> vecInfoManual2;
		for (it_info ivm = vecInfoManual.begin(); ivm != vecInfoManual.end(); ivm++)
		{
			for (ci_pl ii = vecPlugins.begin(); ii != vecPlugins.end(); ii++)
			{
				if ( ii->sVendor.equals((*ivm)->sVendor))
				{
					vecInfoManual2.push_back(*ivm);
					break;
				}
			}
		}
		//Check which JavaInfo from vector vecInfoManual2 is already
		//contained in vecInfo. If it already exists then remove it from
		//vecInfoManual2
		for (it_info j = vecInfo.begin(); j != vecInfo.end(); j++)
		{
			it_info it_duplicate =
				std::find_if(vecInfoManual2.begin(), vecInfoManual2.end(),
							std::bind2nd(std::ptr_fun(areEqualJavaInfo), *j));
			if (it_duplicate != vecInfoManual2.end())
				vecInfoManual2.erase(it_duplicate);
		}
		//create an fill the array of JavaInfo*
		sal_Int32 nSize = vecInfo.size() + vecInfoManual2.size();
		*pparInfo = (JavaInfo**) rtl_allocateMemory(
			nSize * sizeof(JavaInfo*));
		if (*pparInfo == NULL)
			return JFW_E_ERROR;

		typedef std::vector<jfw::CJavaInfo>::iterator it;
		int index = 0;
		//Add the automatically detected JREs
		for (it k = vecInfo.begin(); k != vecInfo.end(); k++)
			(*pparInfo)[index++] = k->detach();
		//Add the manually detected JREs
		for (it l = vecInfoManual2.begin(); l != vecInfoManual2.end(); l++)
			(*pparInfo)[index++] = l->detach();

		*pSize = nSize;
		return errcode;
    }
    catch (jfw::FrameworkException& e)
    {
        retVal = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return retVal;
}

javaFrameworkError SAL_CALL jfw_startVM(JavaVMOption *arOptions, sal_Int32 cOptions,
                                 JavaVM **ppVM, JNIEnv **ppEnv)
{
#ifndef SOLAR_JAVA
    return JFW_E_ERROR;
#else
    javaFrameworkError errcode = JFW_E_NONE;
    if (cOptions > 0 && arOptions == NULL)
        return JFW_E_INVALID_ARG;

    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());

		//We keep this pointer so we can determine if a VM has already
		//been created.
		if (g_pJavaVM != NULL)
			return JFW_E_RUNNING_JVM;

		if (ppVM == NULL)
			return JFW_E_INVALID_ARG;

        std::vector<rtl::OString> vmParams;
        rtl::OString sUserClassPath;
		jfw::CJavaInfo aInfo;
		jfw::JFW_MODE mode = jfw::getMode();
		if (mode == jfw::JFW_MODE_APPLICATION)
		{
            const jfw::MergedSettings settings;
            if (sal_False == settings.getEnabled())
                return JFW_E_JAVA_DISABLED;
            aInfo.attach(settings.createJavaInfo());
            //check if a Java has ever been selected
			if (aInfo == NULL)
				return JFW_E_NO_SELECT;

#ifdef WNT
			//Because on Windows there is no system setting that we can use to determine
			//if Assistive Technology Tool support is needed, we ship a .reg file that the
			//user can use to create a registry setting. When the user forgets to set
			//the key before he starts the office then a JRE may be selected without access bridge.
			//When he later sets the key then we select a JRE with accessibility support but
			//only if the user has not manually changed the selected JRE in the options dialog.
			if (jfw::isAccessibilitySupportDesired())
			{
				// If no JRE has been selected then we do not select one. This function shall then
				//return JFW_E_NO_SELECT
				if (aInfo != NULL &&
					(aInfo->nFeatures & JFW_FEATURE_ACCESSBRIDGE) == 0)
				{
					//has the user manually selected a JRE?
					if (settings.getJavaInfoAttrAutoSelect() == true)
					{
                        // if not then the automatism has previously selected a JRE
                        //without accessibility support. We return JFW_E_NO_SELECT
                        //to cause that we search for another JRE. The search code will
                        //then prefer a JRE with accessibility support.
                        return JFW_E_NO_SELECT;
					}
				}
			}
#endif
			//check if the javavendors.xml has changed after a Java was selected
			rtl::OString sVendorUpdate = jfw::getElementUpdated();

			if (sVendorUpdate != settings.getJavaInfoAttrVendorUpdate())
				return JFW_E_INVALID_SETTINGS;

			//check if JAVA is disabled
			//If Java is enabled, but it was disabled when this process was started
			// then no preparational work, such as setting the LD_LIBRARY_PATH, was
			//done. Therefore if a JRE needs it it must not be started.
			if (g_bEnabledSwitchedOn &&
					(aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART))
				return JFW_E_NEED_RESTART;

			//Check if the selected Java was set in this process. If so it
			//must not have the requirments flag JFW_REQUIRE_NEEDRESTART
			if ((aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART)
				&&
				(jfw::wasJavaSelectedInSameProcess() == true))
				return JFW_E_NEED_RESTART;

            vmParams = settings.getVmParametersUtf8();
            sUserClassPath = jfw::makeClassPathOption(settings.getUserClassPath());
		} // end mode FWK_MODE_OFFICE
		else if (mode == jfw::JFW_MODE_DIRECT)
		{
            errcode = jfw_getSelectedJRE(&aInfo.pInfo);
            if (errcode != JFW_E_NONE)
                return errcode;
            //In direct mode the options are specified by bootstrap variables
            //of the form UNO_JAVA_JFW_PARAMETER_1 .. UNO_JAVA_JFW_PARAMETER_n
            vmParams = jfw::BootParams::getVMParameters();
            sUserClassPath =
                "-Djava.class.path=" + jfw::BootParams::getClasspath();
		}
		else
            OSL_ASSERT(0);

		//get the function jfw_plugin_startJavaVirtualMachine
        jfw::VendorSettings aVendorSettings;
		rtl::OUString sLibPath = aVendorSettings.getPluginLibrary(aInfo.getVendor());

		osl::Module modulePlugin(sLibPath);
		if ( ! modulePlugin)
			return JFW_E_NO_PLUGIN;

		rtl::OUString sFunctionName(
			RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_startJavaVirtualMachine"));
		jfw_plugin_startJavaVirtualMachine_ptr pFunc =
			(jfw_plugin_startJavaVirtualMachine_ptr)
			osl_getFunctionSymbol(modulePlugin, sFunctionName.pData);
		if (pFunc == NULL)
			return JFW_E_ERROR;

		// create JavaVMOptions array that is passed to the plugin
		// it contains the classpath and all options set in the
		//options dialog
		boost::scoped_array<JavaVMOption> sarJOptions(
            new JavaVMOption[cOptions + 2 + vmParams.size()]);
		JavaVMOption * arOpt = sarJOptions.get();
		if (! arOpt)
			return JFW_E_ERROR;

		//The first argument is the classpath
		arOpt[0].optionString= (char*) sUserClassPath.getStr();
		arOpt[0].extraInfo = NULL;
		// Set a flag that this JVM has been created via the JNI Invocation API
		// (used, for example, by UNO remote bridges to share a common thread pool
		// factory among Java and native bridge implementations):
		arOpt[1].optionString = (char *) "-Dorg.openoffice.native=";
		arOpt[1].extraInfo = 0;

        //add the options set by options dialog
        int index = 2;
        typedef std::vector<rtl::OString>::const_iterator cit;
        for (cit i = vmParams.begin(); i != vmParams.end(); i ++)
        {
            arOpt[index].optionString = const_cast<sal_Char*>(i->getStr());
            arOpt[index].extraInfo = 0;
            index ++;
        }
        //add all options of the arOptions argument
        for (int ii = 0; ii < cOptions; ii++)
        {
            arOpt[index].optionString = arOptions[ii].optionString;
            arOpt[index].extraInfo = arOptions[ii].extraInfo;
            index++;
        }

		//start Java
		JavaVM *pVm = NULL;
		javaPluginError plerr = (*pFunc)(aInfo, arOpt, index, & pVm, ppEnv);
		if (plerr == JFW_PLUGIN_E_VM_CREATION_FAILED)
		{
			errcode = JFW_E_VM_CREATION_FAILED;
		}
		else if (plerr != JFW_PLUGIN_E_NONE )
		{
			errcode = JFW_E_ERROR;
		}
		else
		{
			g_pJavaVM = pVm;
			*ppVM = pVm;
		}
		OSL_ASSERT(plerr != JFW_PLUGIN_E_WRONG_VENDOR);
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;
#endif
}

/** We do not use here jfw_findAllJREs and then check if a JavaInfo
    meets the requirements, because that means using all plug-ins, which
    may take quite a while. The implementation uses one plug-in and if
    it already finds a suitable JRE then it is done and does not need to
    load another plug-in
 */
javaFrameworkError SAL_CALL jfw_findAndSelectJRE(JavaInfo **pInfo)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
        osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
		sal_uInt64 nFeatureFlags = 0;
		jfw::CJavaInfo aCurrentInfo;
//Determine if accessibility support is needed
		bool bSupportAccessibility = jfw::isAccessibilitySupportDesired();
		nFeatureFlags = bSupportAccessibility ?
			JFW_FEATURE_ACCESSBRIDGE : 0L;

		//Get a list of services which provide Java information
        jfw::VendorSettings aVendorSettings;
        std::vector<jfw::PluginLibrary> vecPlugins =
 			aVendorSettings.getPluginData();
        //Create a vector that holds the libraries, which will be later
        //dynamically loaded;
        boost::scoped_array<osl::Module> sarModules;
        sarModules.reset(new osl::Module[vecPlugins.size()]);
        osl::Module * arModules = sarModules.get();

		//Use every plug-in library to get Java installations. At the first usable
		//Java the loop will break
		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
        int cModule = 0;
		for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++, cModule++)
		{
			const jfw::PluginLibrary & library = *i;
			jfw::VersionInfo versionInfo =
				aVendorSettings.getVersionInformation(library.sVendor);

            arModules[cModule].load(library.sPath);
            osl::Module & pluginLib = arModules[cModule];
			if (pluginLib.is() == sal_False)
				return JFW_E_NO_PLUGIN;

			jfw_plugin_getAllJavaInfos_ptr getAllJavaFunc =
				(jfw_plugin_getAllJavaInfos_ptr) pluginLib.getFunctionSymbol(
					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getAllJavaInfos")));

			OSL_ASSERT(getAllJavaFunc);
			if (getAllJavaFunc == NULL)
				continue;

			//get all installations of one vendor according to minVersion,
			//maxVersion and excludeVersions
			sal_Int32 cInfos = 0;
			JavaInfo** arInfos = NULL;
			javaPluginError plerr  = (*getAllJavaFunc)(
				library.sVendor.pData,
				versionInfo.sMinVersion.pData,
				versionInfo.sMaxVersion.pData,
				versionInfo.getExcludeVersions(),
				versionInfo.getExcludeVersionSize(),
				& arInfos,
				& cInfos);

			if (plerr != JFW_PLUGIN_E_NONE)
				continue;
			//iterate over all installations to find the best which has
			//all features
			if (cInfos == 0)
			{
				rtl_freeMemory(arInfos);
				continue;
			}
			bool bInfoFound = false;
			for (int ii = 0; ii < cInfos; ii++)
			{
				JavaInfo* pJInfo = arInfos[ii];

				//We remember the very first installation in aCurrentInfo
				if (aCurrentInfo.getLocation().getLength() == 0)
						aCurrentInfo = pJInfo;
				// compare features
				// If the user does not require any features (nFeatureFlags = 0)
				// then the first installation is used
				if ((pJInfo->nFeatures & nFeatureFlags) == nFeatureFlags)
				{
					//the just found Java implements all required features
					//currently there is only accessibility!!!
					aCurrentInfo = pJInfo;
					bInfoFound = true;
					break;
				}
			}
			//The array returned by jfw_plugin_getAllJavaInfos must be freed as well as
			//its contents
			for (int j = 0; j < cInfos; j++)
				jfw_freeJavaInfo(arInfos[j]);
			rtl_freeMemory(arInfos);

			if (bInfoFound == true)
				break;
			//All Java installations found by the current plug-in lib
			//do not provide the required features. Try the next plug-in
		}
		if ((JavaInfo*) aCurrentInfo == NULL)
		{//The plug-ins did not find a suitable Java. Now try the paths which have been
		//added manually.
			//get the list of paths to jre locations which have been added manually
			const jfw::MergedSettings settings;
			//node.loadFromSettings();
			const std::vector<rtl::OUString> & vecJRELocations =
				settings.getJRELocations();
			//use every plug-in to determine the JavaInfo objects
			bool bInfoFound = false;
			for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++)
			{
				const jfw::PluginLibrary & library = *i;
				jfw::VersionInfo versionInfo =
					aVendorSettings.getVersionInformation(library.sVendor);

				osl::Module pluginLib(library.sPath);
				if (pluginLib.is() == sal_False)
					return JFW_E_NO_PLUGIN;
				//Check if the current plugin can detect JREs at the location
				// of the paths added by jfw_setJRELocations or jfw_addJRELocation
				//get the function from the plugin
				jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
					(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
						rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));

				OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
				if (jfw_plugin_getJavaInfoByPathFunc == NULL)
					return JFW_E_ERROR;

				typedef std::vector<rtl::OUString>::const_iterator citLoc;
				for (citLoc it = vecJRELocations.begin();
					it != vecJRELocations.end(); it++)
				{
					jfw::CJavaInfo aInfo;
					javaPluginError err = (*jfw_plugin_getJavaInfoByPathFunc)(
						it->pData,
                        library.sVendor.pData,
						versionInfo.sMinVersion.pData,
						versionInfo.sMaxVersion.pData,
						versionInfo.getExcludeVersions(),
						versionInfo.getExcludeVersionSize(),
						& aInfo.pInfo);
					if (err == JFW_PLUGIN_E_NO_JRE)
						continue;
					if (err == JFW_PLUGIN_E_FAILED_VERSION)
						continue;
					else if (err !=JFW_PLUGIN_E_NONE)
						return JFW_E_ERROR;

					if (aInfo)
					{
						//We remember the very first installation in aCurrentInfo
						if (aCurrentInfo.getLocation().getLength() == 0)
							aCurrentInfo = aInfo;
						// compare features
						// If the user does not require any features (nFeatureFlags = 0)
						// then the first installation is used
						if ((aInfo.getFeatures() & nFeatureFlags) == nFeatureFlags)
						{
							//the just found Java implements all required features
							//currently there is only accessibility!!!
							aCurrentInfo = aInfo;
							bInfoFound = true;
							break;
						}
					}
				}//end iterate over paths
				if (bInfoFound == true)
					break;
			}// end iterate plug-ins
		}
		if ((JavaInfo*) aCurrentInfo)
		{
			jfw::NodeJava javaNode;
			javaNode.setJavaInfo(aCurrentInfo,true);
			javaNode.write();

			if (pInfo !=NULL)
			{
				//copy to out param
				*pInfo = aCurrentInfo.cloneJavaInfo();
				//remember that this JRE was selected in this process
				jfw::setJavaSelected();
			}
		}
		else
		{
			errcode = JFW_E_NO_JAVA_FOUND;
		}
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;
}
sal_Bool SAL_CALL jfw_areEqualJavaInfo(
    JavaInfo const * pInfoA,JavaInfo const * pInfoB)
{
    if (pInfoA == pInfoB)
        return sal_True;
    if (pInfoA == NULL || pInfoB == NULL)
        return sal_False;
    rtl::OUString sVendor(pInfoA->sVendor);
    rtl::OUString sLocation(pInfoA->sLocation);
    rtl::OUString sVersion(pInfoA->sVersion);
    rtl::ByteSequence sData(pInfoA->arVendorData);
    if (sVendor.equals(pInfoB->sVendor) == sal_True
        && sLocation.equals(pInfoB->sLocation) == sal_True
        && sVersion.equals(pInfoB->sVersion) == sal_True
        && pInfoA->nFeatures == pInfoB->nFeatures
#ifndef MACOSX
        && pInfoA->nRequirements == pInfoB->nRequirements
#endif
        && sData == pInfoB->arVendorData)
    {
        return sal_True;
    }
    return sal_False;
}


void SAL_CALL jfw_freeJavaInfo(JavaInfo *pInfo)
{
    if (pInfo == NULL)
        return;
    rtl_uString_release(pInfo->sVendor);
    rtl_uString_release(pInfo->sLocation);
    rtl_uString_release(pInfo->sVersion);
    rtl_byte_sequence_release(pInfo->arVendorData);
    rtl_freeMemory(pInfo);
}

javaFrameworkError SAL_CALL jfw_getSelectedJRE(JavaInfo **ppInfo)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
		if (ppInfo == NULL)
			return JFW_E_INVALID_ARG;

        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
        {
            rtl::OUString sJRE = jfw::BootParams::getJREHome();

            jfw::CJavaInfo aInfo;
            if ((errcode = jfw_getJavaInfoByPath(sJRE.pData, & aInfo.pInfo))
                != JFW_E_NONE)
                throw jfw::FrameworkException(
                    JFW_E_CONFIGURATION,
                    rtl::OString(
                        "[Java framework] The JRE specified by the bootstrap "
                        "variable UNO_JAVA_JFW_JREHOME  or  UNO_JAVA_JFW_ENV_JREHOME "
                        " could not be recognized. Check the values and make sure that you "
                        "use a plug-in library that can recognize that JRE."));

            *ppInfo = aInfo.detach();
            return JFW_E_NONE;
        }

		const jfw::MergedSettings settings;
		jfw::CJavaInfo aInfo;
		aInfo.attach(settings.createJavaInfo());
		if (! aInfo)
		{
			*ppInfo = NULL;
			return JFW_E_NONE;
		}
		//If the javavendors.xml has changed, then the current selected
		//Java is not valid anymore
		// /java/javaInfo/@vendorUpdate != javaSelection/updated (javavendors.xml)
		rtl::OString sUpdated = jfw::getElementUpdated();

		if (sUpdated.equals(settings.getJavaInfoAttrVendorUpdate()) == sal_False)
			return JFW_E_INVALID_SETTINGS;
		*ppInfo = aInfo.detach();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}

javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning)
{
    osl::MutexGuard guard(jfw::FwkMutex::get());
    if (bRunning == NULL)
        return JFW_E_INVALID_ARG;
    if (g_pJavaVM == NULL)
        *bRunning = sal_False;
    else
        *bRunning = sal_True;
    return JFW_E_NONE;
}

javaFrameworkError SAL_CALL jfw_getJavaInfoByPath(
    rtl_uString *pPath, JavaInfo **ppInfo)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
		if (pPath == NULL || ppInfo == NULL)
			return JFW_E_INVALID_ARG;

        jfw::VendorSettings aVendorSettings;
		//Get a list of plugins which provide Java information
		std::vector<jfw::PluginLibrary> vecPlugins =
			aVendorSettings.getPluginData();
        //Create a vector that holds the libraries, which will be later
        //dynamically loaded;
        boost::scoped_array<osl::Module> sarModules;
        sarModules.reset(new osl::Module[vecPlugins.size()]);
        osl::Module * arModules = sarModules.get();

		typedef std::vector<rtl::OUString>::const_iterator CIT_VENDOR;
		std::vector<rtl::OUString> vecVendors =
			aVendorSettings.getSupportedVendors();

		//Use every plug-in library to determine if the path represents a
		//JRE. If a plugin recognized it then the loop will break
		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
        int cModule = 0;
        for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end();
             i++, cModule++)
		{
			const jfw::PluginLibrary & library = *i;
			jfw::VersionInfo versionInfo =
				aVendorSettings.getVersionInformation(library.sVendor);
	        arModules[cModule].load(library.sPath);
            osl::Module & pluginLib = arModules[cModule];
			if (pluginLib.is() == sal_False)
			{
				rtl::OString msg = rtl::OUStringToOString(
					library.sPath, osl_getThreadTextEncoding());
				fprintf(stderr,"[jvmfwk] Could not load plugin %s\n" \
						"Modify the javavendors.xml accordingly!\n", msg.getStr());
				return JFW_E_NO_PLUGIN;
			}

			jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
				(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));

			OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
			if (jfw_plugin_getJavaInfoByPathFunc == NULL)
				continue;

			//ask the plugin if this is a JRE.
			//If so check if it meets the version requirements.
			//Only if it does return a JavaInfo
			JavaInfo* pInfo = NULL;
			javaPluginError plerr = (*jfw_plugin_getJavaInfoByPathFunc)(
				pPath,
                library.sVendor.pData,
				versionInfo.sMinVersion.pData,
				versionInfo.sMaxVersion.pData,
				versionInfo.getExcludeVersions(),
				versionInfo.getExcludeVersionSize(),
				& pInfo);

			if (plerr == JFW_PLUGIN_E_NONE)
			{
				//check if the vendor of the found JRE is supported
                if (vecVendors.size() == 0)
                {
                    //vendor does not matter
                    *ppInfo = pInfo;
					break;
                }
                else
                {
                    rtl::OUString sVendor(pInfo->sVendor);
                    CIT_VENDOR ivendor = std::find(vecVendors.begin(), vecVendors.end(),
                                                   sVendor);
                    if (ivendor != vecVendors.end())
                    {
                        *ppInfo = pInfo;
                    }
                    else
                    {
                        *ppInfo = NULL;
                        errcode = JFW_E_NOT_RECOGNIZED;
                    }
                    break;
                }
			}
			else if(plerr == JFW_PLUGIN_E_FAILED_VERSION)
			{//found JRE but it has the wrong version
				*ppInfo = NULL;
				errcode = JFW_E_FAILED_VERSION;
				break;
			}
			else if (plerr == JFW_PLUGIN_E_NO_JRE)
			{// plugin does not recognize this path as belonging to JRE
				continue;
			}
			OSL_ASSERT(0);
		}
		if (*ppInfo == NULL && errcode != JFW_E_FAILED_VERSION)
			errcode = JFW_E_NOT_RECOGNIZED;
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;
}


javaFrameworkError SAL_CALL jfw_setSelectedJRE(JavaInfo const *pInfo)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
		//check if pInfo is the selected JRE
		JavaInfo *currentInfo = NULL;
		errcode = jfw_getSelectedJRE( & currentInfo);
		if (errcode != JFW_E_NONE && errcode != JFW_E_INVALID_SETTINGS)
			return errcode;

		if (jfw_areEqualJavaInfo(currentInfo, pInfo) == sal_False)
		{
			jfw::NodeJava node;
			node.setJavaInfo(pInfo, false);
			node.write();
			//remember that the JRE was selected in this process
			jfw::setJavaSelected();
		}
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}
javaFrameworkError SAL_CALL jfw_setEnabled(sal_Bool bEnabled)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;

		if (g_bEnabledSwitchedOn == false && bEnabled == sal_True)
		{
			//When the process started then Enabled was false.
			//This is first time enabled is set to true.
			//That means, no preparational work has been done, such as setting the
			//LD_LIBRARY_PATH, etc.

			//check if Enabled is false;
            const jfw::MergedSettings settings;
			if (settings.getEnabled() == sal_False)
				g_bEnabledSwitchedOn = true;
		}
		jfw::NodeJava node;
		node.setEnabled(bEnabled);
		node.write();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}

javaFrameworkError SAL_CALL jfw_getEnabled(sal_Bool *pbEnabled)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
        osl::MutexGuard guard(jfw::FwkMutex::get());
		if (pbEnabled == NULL)
			return JFW_E_INVALID_ARG;
		jfw::MergedSettings settings;
		*pbEnabled = settings.getEnabled();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}


javaFrameworkError SAL_CALL jfw_setVMParameters(
    rtl_uString * * arOptions, sal_Int32 nLen)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
        jfw::NodeJava node;
		if (arOptions == NULL && nLen != 0)
			return JFW_E_INVALID_ARG;
		node.setVmParameters(arOptions, nLen);
		node.write();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;
}

javaFrameworkError SAL_CALL jfw_getVMParameters(
    rtl_uString *** parOptions, sal_Int32 * pLen)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;

		if (parOptions == NULL || pLen == NULL)
			return JFW_E_INVALID_ARG;
		const jfw::MergedSettings settings;
		settings.getVmParametersArray(parOptions, pLen);
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}

javaFrameworkError SAL_CALL jfw_setUserClassPath(rtl_uString * pCp)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
		jfw::NodeJava node;
		if (pCp == NULL)
			return JFW_E_INVALID_ARG;
		node.setUserClassPath(pCp);
		node.write();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}

javaFrameworkError SAL_CALL jfw_getUserClassPath(rtl_uString ** ppCP)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
		if (ppCP == NULL)
			return JFW_E_INVALID_ARG;
		const jfw::MergedSettings settings;
		*ppCP = settings.getUserClassPath().pData;
		rtl_uString_acquire(*ppCP);
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;
}

javaFrameworkError SAL_CALL jfw_addJRELocation(rtl_uString * sLocation)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
        jfw::NodeJava node;
		if (sLocation == NULL)
			return JFW_E_INVALID_ARG;
		node.load();
		node.addJRELocation(sLocation);
		node.write();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;

}

javaFrameworkError SAL_CALL jfw_setJRELocations(
    rtl_uString ** arLocations, sal_Int32 nLen)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;
		jfw::NodeJava node;
		if (arLocations == NULL && nLen != 0)
			return JFW_E_INVALID_ARG;
		node.setJRELocations(arLocations, nLen);
		node.write();
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }
    return errcode;

}

javaFrameworkError SAL_CALL jfw_getJRELocations(
    rtl_uString *** parLocations, sal_Int32 *pLen)
{
    javaFrameworkError errcode = JFW_E_NONE;
    try
    {
		osl::MutexGuard guard(jfw::FwkMutex::get());
        if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
            return JFW_E_DIRECT_MODE;

		if (parLocations == NULL || pLen == NULL)
			return JFW_E_INVALID_ARG;
		const jfw::MergedSettings settings;
		settings.getJRELocations(parLocations, pLen);
    }
    catch (jfw::FrameworkException& e)
    {
        errcode = e.errorCode;
        fprintf(stderr, "%s\n", e.message.getStr());
        OSL_ENSURE(0, e.message.getStr());
    }

    return errcode;
}


javaFrameworkError jfw_existJRE(const JavaInfo *pInfo, sal_Bool *exist)
{
    //get the function jfw_plugin_existJRE
    jfw::VendorSettings aVendorSettings;
    jfw::CJavaInfo aInfo;
    aInfo = (const ::JavaInfo*) pInfo; //makes a copy of pInfo
    rtl::OUString sLibPath = aVendorSettings.getPluginLibrary(aInfo.getVendor());
    osl::Module modulePlugin(sLibPath);
    if ( ! modulePlugin)
        return JFW_E_NO_PLUGIN;
    rtl::OUString sFunctionName(
        RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_existJRE"));
    jfw_plugin_existJRE_ptr pFunc =
        (jfw_plugin_existJRE_ptr)
        osl_getFunctionSymbol(modulePlugin, sFunctionName.pData);
    if (pFunc == NULL)
        return JFW_E_ERROR;

    javaPluginError plerr = (*pFunc)(pInfo, exist);

    javaFrameworkError ret = JFW_E_NONE;
    switch (plerr)
    {
    case JFW_PLUGIN_E_NONE:
        ret = JFW_E_NONE;
        break;
    case JFW_PLUGIN_E_INVALID_ARG:
        ret = JFW_E_INVALID_ARG;
        break;
    case JFW_PLUGIN_E_ERROR:
        ret = JFW_E_ERROR;
        break;
    default:
        ret = JFW_E_ERROR;
    }
    return ret;
}

void SAL_CALL jfw_lock()
{
    jfw::FwkMutex::get().acquire();
}

void SAL_CALL jfw_unlock()
{
    jfw::FwkMutex::get().release();
}


namespace jfw
{
CJavaInfo::CJavaInfo(): pInfo(0)
{
}

CJavaInfo::CJavaInfo(const CJavaInfo & info)
{
    pInfo = copyJavaInfo(info.pInfo);
}

CJavaInfo::CJavaInfo(::JavaInfo * info, _transfer_ownership)
{
    pInfo = info;
}
CJavaInfo CJavaInfo::createWrapper(::JavaInfo* info)
{
    return CJavaInfo(info, TRANSFER);
}
void CJavaInfo::attach(::JavaInfo * info)
{
    jfw_freeJavaInfo(pInfo);
    pInfo = info;
}
::JavaInfo * CJavaInfo::detach()
{
    JavaInfo * tmp = pInfo;
    pInfo = NULL;
    return tmp;
}

CJavaInfo::~CJavaInfo()
{
    jfw_freeJavaInfo(pInfo);
}

CJavaInfo::operator ::JavaInfo* ()
{
    return pInfo;
}

JavaInfo * CJavaInfo::copyJavaInfo(const JavaInfo * pInfo)
{
	if (pInfo == NULL)
		return NULL;
    JavaInfo* newInfo =
          (JavaInfo*) rtl_allocateMemory(sizeof(JavaInfo));
    if (newInfo)
    {
        rtl_copyMemory(newInfo, pInfo, sizeof(JavaInfo));
        rtl_uString_acquire(pInfo->sVendor);
        rtl_uString_acquire(pInfo->sLocation);
        rtl_uString_acquire(pInfo->sVersion);
        rtl_byte_sequence_acquire(pInfo->arVendorData);
    }
    return newInfo;
}


JavaInfo* CJavaInfo::cloneJavaInfo() const
{
    if (pInfo == NULL)
        return NULL;
    return copyJavaInfo(pInfo);
}

CJavaInfo & CJavaInfo::operator = (const CJavaInfo& info)
{
    if (&info == this)
        return *this;

    jfw_freeJavaInfo(pInfo);
    pInfo = copyJavaInfo(info.pInfo);
    return *this;
}
CJavaInfo & CJavaInfo::operator = (const ::JavaInfo* info)
{
    if (info == pInfo)
        return *this;

    jfw_freeJavaInfo(pInfo);
    pInfo = copyJavaInfo(info);
    return *this;
}

const ::JavaInfo* CJavaInfo::operator ->() const
{
    return pInfo;
}

CJavaInfo::operator JavaInfo const * () const
{
    return pInfo;
}
// ::JavaInfo** CJavaInfo::operator & ()
// {
//     return & pInfo;
// }

rtl::OUString CJavaInfo::getVendor() const
{
    if (pInfo)
        return rtl::OUString(pInfo->sVendor);
    else
        return rtl::OUString();
}

rtl::OUString CJavaInfo::getLocation() const
{
    if (pInfo)
        return rtl::OUString(pInfo->sLocation);
    else
        return rtl::OUString();
}

sal_uInt64 CJavaInfo::getFeatures() const
{
    if (pInfo)
        return pInfo->nFeatures;
    else
        return 0l;
}

}
