xref: /aoo42x/main/jvmfwk/source/framework.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_jvmfwk.hxx"
30 #include "boost/scoped_array.hpp"
31 #include "rtl/ustring.hxx"
32 #include "rtl/bootstrap.hxx"
33 #include "osl/thread.hxx"
34 #include "osl/file.hxx"
35 #include "osl/module.hxx"
36 #include "jvmfwk/framework.h"
37 #include "jvmfwk/vendorplugin.h"
38 #include <vector>
39 #include <functional>
40 #include <algorithm>
41 #include "framework.hxx"
42 #include "fwkutil.hxx"
43 #include "elements.hxx"
44 #include "fwkbase.hxx"
45 
46 #ifdef WNT
47 /** The existence of the file useatjava.txt decides if a Java should be used
48     that supports accessibility tools.
49  */
50 #define USE_ACCESSIBILITY_FILE "useatjava.txt"
51 #endif
52 
53 #define UNO_JAVA_JFW_JREHOME "UNO_JAVA_JFW_JREHOME"
54 namespace {
55 JavaVM * g_pJavaVM = NULL;
56 
57 bool g_bEnabledSwitchedOn = false;
58 
59 sal_Bool areEqualJavaInfo(
60     JavaInfo const * pInfoA,JavaInfo const * pInfoB)
61 {
62     return jfw_areEqualJavaInfo(pInfoA, pInfoB);
63 }
64 }
65 
66 javaFrameworkError SAL_CALL jfw_findAllJREs(JavaInfo ***pparInfo, sal_Int32 *pSize)
67 {
68     javaFrameworkError retVal = JFW_E_NONE;
69     try
70     {
71 		osl::MutexGuard guard(jfw::FwkMutex::get());
72 		javaFrameworkError errcode = JFW_E_NONE;
73 		if (pparInfo == NULL || pSize == NULL)
74 			return JFW_E_INVALID_ARG;
75 
76         jfw::VendorSettings aVendorSettings;
77 		//Get a list of plugins which provide Java information
78         std::vector<jfw::PluginLibrary> vecPlugins =
79             aVendorSettings.getPluginData();
80 
81         //Create a vector that holds the libraries, which will be later
82         //dynamically loaded;
83         boost::scoped_array<osl::Module> sarModules;
84         sarModules.reset(new osl::Module[vecPlugins.size()]);
85         osl::Module * arModules = sarModules.get();
86 		//Add the JavaInfos found by jfw_plugin_getAllJavaInfos to the vector
87 		//Make sure that the contents are destroyed if this
88 		//function returns with an error
89 		std::vector<jfw::CJavaInfo> vecInfo;
90 		//Add the JavaInfos found by jfw_plugin_getJavaInfoByPath to this vector
91 		//Make sure that the contents are destroyed if this
92 		//function returns with an error
93 		std::vector<jfw::CJavaInfo> vecInfoManual;
94 		typedef std::vector<jfw::CJavaInfo>::iterator it_info;
95 		//get the list of paths to jre locations which have been
96 		//added manually
97 		const jfw::MergedSettings settings;
98 		const std::vector<rtl::OUString>& vecJRELocations =
99 			settings.getJRELocations();
100 		//Use every plug-in library to get Java installations.
101 		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
102         int cModule = 0;
103  		for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++, cModule++)
104  		{
105 			const jfw::PluginLibrary & library = *i;
106 			jfw::VersionInfo versionInfo =
107 				aVendorSettings.getVersionInformation(library.sVendor);
108             arModules[cModule].load(library.sPath);
109             osl::Module & pluginLib = arModules[cModule];
110 
111 			if (pluginLib.is() == sal_False)
112 			{
113 				rtl::OString msg = rtl::OUStringToOString(
114 					library.sPath, osl_getThreadTextEncoding());
115 				fprintf(stderr,"[jvmfwk] Could not load plugin %s\n" \
116 						"Modify the javavendors.xml accordingly!\n", msg.getStr());
117 				return JFW_E_NO_PLUGIN;
118 			}
119 			jfw_plugin_getAllJavaInfos_ptr getAllJavaFunc =
120 				(jfw_plugin_getAllJavaInfos_ptr) pluginLib.getFunctionSymbol(
121 					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getAllJavaInfos")));
122 
123 			OSL_ASSERT(getAllJavaFunc);
124 			if (getAllJavaFunc == NULL)
125 				return JFW_E_ERROR;
126 
127 			//get all installations of one vendor according to minVersion,
128 			//maxVersion and excludeVersions
129 			sal_Int32 cInfos = 0;
130 			JavaInfo** arInfos = NULL;
131 			javaPluginError plerr  = (*getAllJavaFunc)(
132 				library.sVendor.pData,
133 				versionInfo.sMinVersion.pData,
134 				versionInfo.sMaxVersion.pData,
135 				versionInfo.getExcludeVersions(),
136 				versionInfo.getExcludeVersionSize(),
137 				& arInfos,
138 				& cInfos);
139 
140 			if (plerr != JFW_PLUGIN_E_NONE)
141 				return JFW_E_ERROR;
142 
143 			for (int j = 0; j < cInfos; j++)
144                 vecInfo.push_back(jfw::CJavaInfo::createWrapper(arInfos[j]));
145 
146 			rtl_freeMemory(arInfos);
147 
148 			//Check if the current plugin can detect JREs at the location
149 			// of the paths added by jfw_setJRELocations or jfw_addJRELocation
150 			//get the function from the plugin
151 			jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
152 				(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
153 					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));
154 
155 			OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
156 			if (jfw_plugin_getJavaInfoByPathFunc == NULL)
157 				return JFW_E_ERROR;
158 
159 			typedef std::vector<rtl::OUString>::const_iterator citLoc;
160 			//Check every manually added location
161 			for (citLoc ii = vecJRELocations.begin();
162 				ii != vecJRELocations.end(); ii++)
163 			{
164 // 				rtl::OUString sLocation =
165 // 					rtl::OStringToOUString(*ii, RTL_TEXTENCODING_UTF8);
166 				jfw::CJavaInfo aInfo;
167 				plerr = (*jfw_plugin_getJavaInfoByPathFunc)(
168 					ii->pData,
169                     library.sVendor.pData,
170 					versionInfo.sMinVersion.pData,
171 					versionInfo.sMaxVersion.pData,
172 					versionInfo.getExcludeVersions(),
173 					versionInfo.getExcludeVersionSize(),
174 					& aInfo.pInfo);
175 				if (plerr == JFW_PLUGIN_E_NO_JRE)
176 					continue;
177 				if (plerr == JFW_PLUGIN_E_FAILED_VERSION)
178 					continue;
179 				else if (plerr !=JFW_PLUGIN_E_NONE)
180 					return JFW_E_ERROR;
181 
182 				if (aInfo)
183 				{
184 					//Was this JRE already added?. Different plugins could detect
185 					//the same JRE
186 					it_info it_duplicate =
187 						std::find_if(vecInfoManual.begin(), vecInfoManual.end(),
188 								std::bind2nd(std::ptr_fun(areEqualJavaInfo), aInfo));
189 					if (it_duplicate == vecInfoManual.end())
190 						vecInfoManual.push_back(aInfo);
191 				}
192 			}
193 		}
194 		//Make sure vecInfoManual contains only JavaInfos for the vendors for which
195 		//there is a javaSelection/plugins/library entry in the javavendors.xml
196 		//To obtain the JavaInfos for the manually added JRE locations the function
197 		//jfw_getJavaInfoByPath is called which can return a JavaInfo of any vendor.
198 		std::vector<jfw::CJavaInfo> vecInfoManual2;
199 		for (it_info ivm = vecInfoManual.begin(); ivm != vecInfoManual.end(); ivm++)
200 		{
201 			for (ci_pl ii = vecPlugins.begin(); ii != vecPlugins.end(); ii++)
202 			{
203 				if ( ii->sVendor.equals((*ivm)->sVendor))
204 				{
205 					vecInfoManual2.push_back(*ivm);
206 					break;
207 				}
208 			}
209 		}
210 		//Check which JavaInfo from vector vecInfoManual2 is already
211 		//contained in vecInfo. If it already exists then remove it from
212 		//vecInfoManual2
213 		for (it_info j = vecInfo.begin(); j != vecInfo.end(); j++)
214 		{
215 			it_info it_duplicate =
216 				std::find_if(vecInfoManual2.begin(), vecInfoManual2.end(),
217 							std::bind2nd(std::ptr_fun(areEqualJavaInfo), *j));
218 			if (it_duplicate != vecInfoManual2.end())
219 				vecInfoManual2.erase(it_duplicate);
220 		}
221 		//create an fill the array of JavaInfo*
222 		sal_Int32 nSize = vecInfo.size() + vecInfoManual2.size();
223 		*pparInfo = (JavaInfo**) rtl_allocateMemory(
224 			nSize * sizeof(JavaInfo*));
225 		if (*pparInfo == NULL)
226 			return JFW_E_ERROR;
227 
228 		typedef std::vector<jfw::CJavaInfo>::iterator it;
229 		int index = 0;
230 		//Add the automatically detected JREs
231 		for (it k = vecInfo.begin(); k != vecInfo.end(); k++)
232 			(*pparInfo)[index++] = k->detach();
233 		//Add the manually detected JREs
234 		for (it l = vecInfoManual2.begin(); l != vecInfoManual2.end(); l++)
235 			(*pparInfo)[index++] = l->detach();
236 
237 		*pSize = nSize;
238 		return errcode;
239     }
240     catch (jfw::FrameworkException& e)
241     {
242         retVal = e.errorCode;
243         fprintf(stderr, "%s\n", e.message.getStr());
244         OSL_ENSURE(0, e.message.getStr());
245     }
246     return retVal;
247 }
248 
249 javaFrameworkError SAL_CALL jfw_startVM(JavaVMOption *arOptions, sal_Int32 cOptions,
250                                  JavaVM **ppVM, JNIEnv **ppEnv)
251 {
252 #ifndef SOLAR_JAVA
253     return JFW_E_ERROR;
254 #else
255     javaFrameworkError errcode = JFW_E_NONE;
256     if (cOptions > 0 && arOptions == NULL)
257         return JFW_E_INVALID_ARG;
258 
259     try
260     {
261 		osl::MutexGuard guard(jfw::FwkMutex::get());
262 
263 		//We keep this pointer so we can determine if a VM has already
264 		//been created.
265 		if (g_pJavaVM != NULL)
266 			return JFW_E_RUNNING_JVM;
267 
268 		if (ppVM == NULL)
269 			return JFW_E_INVALID_ARG;
270 
271         std::vector<rtl::OString> vmParams;
272         rtl::OString sUserClassPath;
273 		jfw::CJavaInfo aInfo;
274 		jfw::JFW_MODE mode = jfw::getMode();
275 		if (mode == jfw::JFW_MODE_APPLICATION)
276 		{
277             const jfw::MergedSettings settings;
278             if (sal_False == settings.getEnabled())
279                 return JFW_E_JAVA_DISABLED;
280             aInfo.attach(settings.createJavaInfo());
281             //check if a Java has ever been selected
282 			if (aInfo == NULL)
283 				return JFW_E_NO_SELECT;
284 
285 #ifdef WNT
286 			//Because on Windows there is no system setting that we can use to determine
287 			//if Assistive Technology Tool support is needed, we ship a .reg file that the
288 			//user can use to create a registry setting. When the user forgets to set
289 			//the key before he starts the office then a JRE may be selected without access bridge.
290 			//When he later sets the key then we select a JRE with accessibility support but
291 			//only if the user has not manually changed the selected JRE in the options dialog.
292 			if (jfw::isAccessibilitySupportDesired())
293 			{
294 				// If no JRE has been selected then we do not select one. This function shall then
295 				//return JFW_E_NO_SELECT
296 				if (aInfo != NULL &&
297 					(aInfo->nFeatures & JFW_FEATURE_ACCESSBRIDGE) == 0)
298 				{
299 					//has the user manually selected a JRE?
300 					if (settings.getJavaInfoAttrAutoSelect() == true)
301 					{
302                         // if not then the automatism has previously selected a JRE
303                         //without accessibility support. We return JFW_E_NO_SELECT
304                         //to cause that we search for another JRE. The search code will
305                         //then prefer a JRE with accessibility support.
306                         return JFW_E_NO_SELECT;
307 					}
308 				}
309 			}
310 #endif
311 			//check if the javavendors.xml has changed after a Java was selected
312 			rtl::OString sVendorUpdate = jfw::getElementUpdated();
313 
314 			if (sVendorUpdate != settings.getJavaInfoAttrVendorUpdate())
315 				return JFW_E_INVALID_SETTINGS;
316 
317 			//check if JAVA is disabled
318 			//If Java is enabled, but it was disabled when this process was started
319 			// then no preparational work, such as setting the LD_LIBRARY_PATH, was
320 			//done. Therefore if a JRE needs it it must not be started.
321 			if (g_bEnabledSwitchedOn &&
322 					(aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART))
323 				return JFW_E_NEED_RESTART;
324 
325 			//Check if the selected Java was set in this process. If so it
326 			//must not have the requirments flag JFW_REQUIRE_NEEDRESTART
327 			if ((aInfo->nRequirements & JFW_REQUIRE_NEEDRESTART)
328 				&&
329 				(jfw::wasJavaSelectedInSameProcess() == true))
330 				return JFW_E_NEED_RESTART;
331 
332             vmParams = settings.getVmParametersUtf8();
333             sUserClassPath = jfw::makeClassPathOption(settings.getUserClassPath());
334 		} // end mode FWK_MODE_OFFICE
335 		else if (mode == jfw::JFW_MODE_DIRECT)
336 		{
337             errcode = jfw_getSelectedJRE(&aInfo.pInfo);
338             if (errcode != JFW_E_NONE)
339                 return errcode;
340             //In direct mode the options are specified by bootstrap variables
341             //of the form UNO_JAVA_JFW_PARAMETER_1 .. UNO_JAVA_JFW_PARAMETER_n
342             vmParams = jfw::BootParams::getVMParameters();
343             sUserClassPath =
344                 "-Djava.class.path=" + jfw::BootParams::getClasspath();
345 		}
346 		else
347             OSL_ASSERT(0);
348 
349 		//get the function jfw_plugin_startJavaVirtualMachine
350         jfw::VendorSettings aVendorSettings;
351 		rtl::OUString sLibPath = aVendorSettings.getPluginLibrary(aInfo.getVendor());
352 
353 		osl::Module modulePlugin(sLibPath);
354 		if ( ! modulePlugin)
355 			return JFW_E_NO_PLUGIN;
356 
357 		rtl::OUString sFunctionName(
358 			RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_startJavaVirtualMachine"));
359 		jfw_plugin_startJavaVirtualMachine_ptr pFunc =
360 			(jfw_plugin_startJavaVirtualMachine_ptr)
361 			osl_getFunctionSymbol(modulePlugin, sFunctionName.pData);
362 		if (pFunc == NULL)
363 			return JFW_E_ERROR;
364 
365 		// create JavaVMOptions array that is passed to the plugin
366 		// it contains the classpath and all options set in the
367 		//options dialog
368 		boost::scoped_array<JavaVMOption> sarJOptions(
369             new JavaVMOption[cOptions + 2 + vmParams.size()]);
370 		JavaVMOption * arOpt = sarJOptions.get();
371 		if (! arOpt)
372 			return JFW_E_ERROR;
373 
374 		//The first argument is the classpath
375 		arOpt[0].optionString= (char*) sUserClassPath.getStr();
376 		arOpt[0].extraInfo = NULL;
377 		// Set a flag that this JVM has been created via the JNI Invocation API
378 		// (used, for example, by UNO remote bridges to share a common thread pool
379 		// factory among Java and native bridge implementations):
380 		arOpt[1].optionString = (char *) "-Dorg.openoffice.native=";
381 		arOpt[1].extraInfo = 0;
382 
383         //add the options set by options dialog
384         int index = 2;
385         typedef std::vector<rtl::OString>::const_iterator cit;
386         for (cit i = vmParams.begin(); i != vmParams.end(); i ++)
387         {
388             arOpt[index].optionString = const_cast<sal_Char*>(i->getStr());
389             arOpt[index].extraInfo = 0;
390             index ++;
391         }
392         //add all options of the arOptions argument
393         for (int ii = 0; ii < cOptions; ii++)
394         {
395             arOpt[index].optionString = arOptions[ii].optionString;
396             arOpt[index].extraInfo = arOptions[ii].extraInfo;
397             index++;
398         }
399 
400 		//start Java
401 		JavaVM *pVm = NULL;
402 		javaPluginError plerr = (*pFunc)(aInfo, arOpt, index, & pVm, ppEnv);
403 		if (plerr == JFW_PLUGIN_E_VM_CREATION_FAILED)
404 		{
405 			errcode = JFW_E_VM_CREATION_FAILED;
406 		}
407 		else if (plerr != JFW_PLUGIN_E_NONE )
408 		{
409 			errcode = JFW_E_ERROR;
410 		}
411 		else
412 		{
413 			g_pJavaVM = pVm;
414 			*ppVM = pVm;
415 		}
416 		OSL_ASSERT(plerr != JFW_PLUGIN_E_WRONG_VENDOR);
417     }
418     catch (jfw::FrameworkException& e)
419     {
420         errcode = e.errorCode;
421         fprintf(stderr, "%s\n", e.message.getStr());
422         OSL_ENSURE(0, e.message.getStr());
423     }
424 
425     return errcode;
426 #endif
427 }
428 
429 /** We do not use here jfw_findAllJREs and then check if a JavaInfo
430     meets the requirements, because that means using all plug-ins, which
431     may take quite a while. The implementation uses one plug-in and if
432     it already finds a suitable JRE then it is done and does not need to
433     load another plug-in
434  */
435 javaFrameworkError SAL_CALL jfw_findAndSelectJRE(JavaInfo **pInfo)
436 {
437     javaFrameworkError errcode = JFW_E_NONE;
438     try
439     {
440         osl::MutexGuard guard(jfw::FwkMutex::get());
441         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
442             return JFW_E_DIRECT_MODE;
443 		sal_uInt64 nFeatureFlags = 0;
444 		jfw::CJavaInfo aCurrentInfo;
445 //Determine if accessibility support is needed
446 		bool bSupportAccessibility = jfw::isAccessibilitySupportDesired();
447 		nFeatureFlags = bSupportAccessibility ?
448 			JFW_FEATURE_ACCESSBRIDGE : 0L;
449 
450 		//Get a list of services which provide Java information
451         jfw::VendorSettings aVendorSettings;
452         std::vector<jfw::PluginLibrary> vecPlugins =
453  			aVendorSettings.getPluginData();
454         //Create a vector that holds the libraries, which will be later
455         //dynamically loaded;
456         boost::scoped_array<osl::Module> sarModules;
457         sarModules.reset(new osl::Module[vecPlugins.size()]);
458         osl::Module * arModules = sarModules.get();
459 
460 		//Use every plug-in library to get Java installations. At the first usable
461 		//Java the loop will break
462 		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
463         int cModule = 0;
464 		for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++, cModule++)
465 		{
466 			const jfw::PluginLibrary & library = *i;
467 			jfw::VersionInfo versionInfo =
468 				aVendorSettings.getVersionInformation(library.sVendor);
469 
470             arModules[cModule].load(library.sPath);
471             osl::Module & pluginLib = arModules[cModule];
472 			if (pluginLib.is() == sal_False)
473 				return JFW_E_NO_PLUGIN;
474 
475 			jfw_plugin_getAllJavaInfos_ptr getAllJavaFunc =
476 				(jfw_plugin_getAllJavaInfos_ptr) pluginLib.getFunctionSymbol(
477 					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getAllJavaInfos")));
478 
479 			OSL_ASSERT(getAllJavaFunc);
480 			if (getAllJavaFunc == NULL)
481 				continue;
482 
483 			//get all installations of one vendor according to minVersion,
484 			//maxVersion and excludeVersions
485 			sal_Int32 cInfos = 0;
486 			JavaInfo** arInfos = NULL;
487 			javaPluginError plerr  = (*getAllJavaFunc)(
488 				library.sVendor.pData,
489 				versionInfo.sMinVersion.pData,
490 				versionInfo.sMaxVersion.pData,
491 				versionInfo.getExcludeVersions(),
492 				versionInfo.getExcludeVersionSize(),
493 				& arInfos,
494 				& cInfos);
495 
496 			if (plerr != JFW_PLUGIN_E_NONE)
497 				continue;
498 			//iterate over all installations to find the best which has
499 			//all features
500 			if (cInfos == 0)
501 			{
502 				rtl_freeMemory(arInfos);
503 				continue;
504 			}
505 			bool bInfoFound = false;
506 			for (int ii = 0; ii < cInfos; ii++)
507 			{
508 				JavaInfo* pJInfo = arInfos[ii];
509 
510 				//We remember the very first installation in aCurrentInfo
511 				if (aCurrentInfo.getLocation().getLength() == 0)
512 						aCurrentInfo = pJInfo;
513 				// compare features
514 				// If the user does not require any features (nFeatureFlags = 0)
515 				// then the first installation is used
516 				if ((pJInfo->nFeatures & nFeatureFlags) == nFeatureFlags)
517 				{
518 					//the just found Java implements all required features
519 					//currently there is only accessibility!!!
520 					aCurrentInfo = pJInfo;
521 					bInfoFound = true;
522 					break;
523 				}
524 			}
525 			//The array returned by jfw_plugin_getAllJavaInfos must be freed as well as
526 			//its contents
527 			for (int j = 0; j < cInfos; j++)
528 				jfw_freeJavaInfo(arInfos[j]);
529 			rtl_freeMemory(arInfos);
530 
531 			if (bInfoFound == true)
532 				break;
533 			//All Java installations found by the current plug-in lib
534 			//do not provide the required features. Try the next plug-in
535 		}
536 		if ((JavaInfo*) aCurrentInfo == NULL)
537 		{//The plug-ins did not find a suitable Java. Now try the paths which have been
538 		//added manually.
539 			//get the list of paths to jre locations which have been added manually
540 			const jfw::MergedSettings settings;
541 			//node.loadFromSettings();
542 			const std::vector<rtl::OUString> & vecJRELocations =
543 				settings.getJRELocations();
544 			//use every plug-in to determine the JavaInfo objects
545 			bool bInfoFound = false;
546 			for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end(); i++)
547 			{
548 				const jfw::PluginLibrary & library = *i;
549 				jfw::VersionInfo versionInfo =
550 					aVendorSettings.getVersionInformation(library.sVendor);
551 
552 				osl::Module pluginLib(library.sPath);
553 				if (pluginLib.is() == sal_False)
554 					return JFW_E_NO_PLUGIN;
555 				//Check if the current plugin can detect JREs at the location
556 				// of the paths added by jfw_setJRELocations or jfw_addJRELocation
557 				//get the function from the plugin
558 				jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
559 					(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
560 						rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));
561 
562 				OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
563 				if (jfw_plugin_getJavaInfoByPathFunc == NULL)
564 					return JFW_E_ERROR;
565 
566 				typedef std::vector<rtl::OUString>::const_iterator citLoc;
567 				for (citLoc it = vecJRELocations.begin();
568 					it != vecJRELocations.end(); it++)
569 				{
570 					jfw::CJavaInfo aInfo;
571 					javaPluginError err = (*jfw_plugin_getJavaInfoByPathFunc)(
572 						it->pData,
573                         library.sVendor.pData,
574 						versionInfo.sMinVersion.pData,
575 						versionInfo.sMaxVersion.pData,
576 						versionInfo.getExcludeVersions(),
577 						versionInfo.getExcludeVersionSize(),
578 						& aInfo.pInfo);
579 					if (err == JFW_PLUGIN_E_NO_JRE)
580 						continue;
581 					if (err == JFW_PLUGIN_E_FAILED_VERSION)
582 						continue;
583 					else if (err !=JFW_PLUGIN_E_NONE)
584 						return JFW_E_ERROR;
585 
586 					if (aInfo)
587 					{
588 						//We remember the very first installation in aCurrentInfo
589 						if (aCurrentInfo.getLocation().getLength() == 0)
590 							aCurrentInfo = aInfo;
591 						// compare features
592 						// If the user does not require any features (nFeatureFlags = 0)
593 						// then the first installation is used
594 						if ((aInfo.getFeatures() & nFeatureFlags) == nFeatureFlags)
595 						{
596 							//the just found Java implements all required features
597 							//currently there is only accessibility!!!
598 							aCurrentInfo = aInfo;
599 							bInfoFound = true;
600 							break;
601 						}
602 					}
603 				}//end iterate over paths
604 				if (bInfoFound == true)
605 					break;
606 			}// end iterate plug-ins
607 		}
608 		if ((JavaInfo*) aCurrentInfo)
609 		{
610 			jfw::NodeJava javaNode;
611 			javaNode.setJavaInfo(aCurrentInfo,true);
612 			javaNode.write();
613 
614 			if (pInfo !=NULL)
615 			{
616 				//copy to out param
617 				*pInfo = aCurrentInfo.cloneJavaInfo();
618 				//remember that this JRE was selected in this process
619 				jfw::setJavaSelected();
620 			}
621 		}
622 		else
623 		{
624 			errcode = JFW_E_NO_JAVA_FOUND;
625 		}
626     }
627     catch (jfw::FrameworkException& e)
628     {
629         errcode = e.errorCode;
630         fprintf(stderr, "%s\n", e.message.getStr());
631         OSL_ENSURE(0, e.message.getStr());
632     }
633 
634     return errcode;
635 }
636 sal_Bool SAL_CALL jfw_areEqualJavaInfo(
637     JavaInfo const * pInfoA,JavaInfo const * pInfoB)
638 {
639     if (pInfoA == pInfoB)
640         return sal_True;
641     if (pInfoA == NULL || pInfoB == NULL)
642         return sal_False;
643     rtl::OUString sVendor(pInfoA->sVendor);
644     rtl::OUString sLocation(pInfoA->sLocation);
645     rtl::OUString sVersion(pInfoA->sVersion);
646     rtl::ByteSequence sData(pInfoA->arVendorData);
647     if (sVendor.equals(pInfoB->sVendor) == sal_True
648         && sLocation.equals(pInfoB->sLocation) == sal_True
649         && sVersion.equals(pInfoB->sVersion) == sal_True
650         && pInfoA->nFeatures == pInfoB->nFeatures
651         && pInfoA->nRequirements == pInfoB->nRequirements
652         && sData == pInfoB->arVendorData)
653     {
654         return sal_True;
655     }
656     return sal_False;
657 }
658 
659 
660 void SAL_CALL jfw_freeJavaInfo(JavaInfo *pInfo)
661 {
662     if (pInfo == NULL)
663         return;
664     rtl_uString_release(pInfo->sVendor);
665     rtl_uString_release(pInfo->sLocation);
666     rtl_uString_release(pInfo->sVersion);
667     rtl_byte_sequence_release(pInfo->arVendorData);
668     rtl_freeMemory(pInfo);
669 }
670 
671 javaFrameworkError SAL_CALL jfw_getSelectedJRE(JavaInfo **ppInfo)
672 {
673     javaFrameworkError errcode = JFW_E_NONE;
674     try
675     {
676 		osl::MutexGuard guard(jfw::FwkMutex::get());
677 		if (ppInfo == NULL)
678 			return JFW_E_INVALID_ARG;
679 
680         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
681         {
682             rtl::OUString sJRE = jfw::BootParams::getJREHome();
683 
684             jfw::CJavaInfo aInfo;
685             if ((errcode = jfw_getJavaInfoByPath(sJRE.pData, & aInfo.pInfo))
686                 != JFW_E_NONE)
687                 throw jfw::FrameworkException(
688                     JFW_E_CONFIGURATION,
689                     rtl::OString(
690                         "[Java framework] The JRE specified by the bootstrap "
691                         "variable UNO_JAVA_JFW_JREHOME  or  UNO_JAVA_JFW_ENV_JREHOME "
692                         " could not be recognized. Check the values and make sure that you "
693                         "use a plug-in library that can recognize that JRE."));
694 
695             *ppInfo = aInfo.detach();
696             return JFW_E_NONE;
697         }
698 
699 		const jfw::MergedSettings settings;
700 		jfw::CJavaInfo aInfo;
701 		aInfo.attach(settings.createJavaInfo());
702 		if (! aInfo)
703 		{
704 			*ppInfo = NULL;
705 			return JFW_E_NONE;
706 		}
707 		//If the javavendors.xml has changed, then the current selected
708 		//Java is not valid anymore
709 		// /java/javaInfo/@vendorUpdate != javaSelection/updated (javavendors.xml)
710 		rtl::OString sUpdated = jfw::getElementUpdated();
711 
712 		if (sUpdated.equals(settings.getJavaInfoAttrVendorUpdate()) == sal_False)
713 			return JFW_E_INVALID_SETTINGS;
714 		*ppInfo = aInfo.detach();
715     }
716     catch (jfw::FrameworkException& e)
717     {
718         errcode = e.errorCode;
719         fprintf(stderr, "%s\n", e.message.getStr());
720         OSL_ENSURE(0, e.message.getStr());
721     }
722     return errcode;
723 }
724 
725 javaFrameworkError SAL_CALL jfw_isVMRunning(sal_Bool *bRunning)
726 {
727     osl::MutexGuard guard(jfw::FwkMutex::get());
728     if (bRunning == NULL)
729         return JFW_E_INVALID_ARG;
730     if (g_pJavaVM == NULL)
731         *bRunning = sal_False;
732     else
733         *bRunning = sal_True;
734     return JFW_E_NONE;
735 }
736 
737 javaFrameworkError SAL_CALL jfw_getJavaInfoByPath(
738     rtl_uString *pPath, JavaInfo **ppInfo)
739 {
740     javaFrameworkError errcode = JFW_E_NONE;
741     try
742     {
743 		osl::MutexGuard guard(jfw::FwkMutex::get());
744 		if (pPath == NULL || ppInfo == NULL)
745 			return JFW_E_INVALID_ARG;
746 
747         jfw::VendorSettings aVendorSettings;
748 		//Get a list of plugins which provide Java information
749 		std::vector<jfw::PluginLibrary> vecPlugins =
750 			aVendorSettings.getPluginData();
751         //Create a vector that holds the libraries, which will be later
752         //dynamically loaded;
753         boost::scoped_array<osl::Module> sarModules;
754         sarModules.reset(new osl::Module[vecPlugins.size()]);
755         osl::Module * arModules = sarModules.get();
756 
757 		typedef std::vector<rtl::OUString>::const_iterator CIT_VENDOR;
758 		std::vector<rtl::OUString> vecVendors =
759 			aVendorSettings.getSupportedVendors();
760 
761 		//Use every plug-in library to determine if the path represents a
762 		//JRE. If a plugin recognized it then the loop will break
763 		typedef std::vector<jfw::PluginLibrary>::const_iterator ci_pl;
764         int cModule = 0;
765         for (ci_pl i = vecPlugins.begin(); i != vecPlugins.end();
766              i++, cModule++)
767 		{
768 			const jfw::PluginLibrary & library = *i;
769 			jfw::VersionInfo versionInfo =
770 				aVendorSettings.getVersionInformation(library.sVendor);
771 	        arModules[cModule].load(library.sPath);
772             osl::Module & pluginLib = arModules[cModule];
773 			if (pluginLib.is() == sal_False)
774 			{
775 				rtl::OString msg = rtl::OUStringToOString(
776 					library.sPath, osl_getThreadTextEncoding());
777 				fprintf(stderr,"[jvmfwk] Could not load plugin %s\n" \
778 						"Modify the javavendors.xml accordingly!\n", msg.getStr());
779 				return JFW_E_NO_PLUGIN;
780 			}
781 
782 			jfw_plugin_getJavaInfoByPath_ptr jfw_plugin_getJavaInfoByPathFunc =
783 				(jfw_plugin_getJavaInfoByPath_ptr) pluginLib.getFunctionSymbol(
784 					rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_getJavaInfoByPath")));
785 
786 			OSL_ASSERT(jfw_plugin_getJavaInfoByPathFunc);
787 			if (jfw_plugin_getJavaInfoByPathFunc == NULL)
788 				continue;
789 
790 			//ask the plugin if this is a JRE.
791 			//If so check if it meets the version requirements.
792 			//Only if it does return a JavaInfo
793 			JavaInfo* pInfo = NULL;
794 			javaPluginError plerr = (*jfw_plugin_getJavaInfoByPathFunc)(
795 				pPath,
796                 library.sVendor.pData,
797 				versionInfo.sMinVersion.pData,
798 				versionInfo.sMaxVersion.pData,
799 				versionInfo.getExcludeVersions(),
800 				versionInfo.getExcludeVersionSize(),
801 				& pInfo);
802 
803 			if (plerr == JFW_PLUGIN_E_NONE)
804 			{
805 				//check if the vendor of the found JRE is supported
806                 if (vecVendors.size() == 0)
807                 {
808                     //vendor does not matter
809                     *ppInfo = pInfo;
810 					break;
811                 }
812                 else
813                 {
814                     rtl::OUString sVendor(pInfo->sVendor);
815                     CIT_VENDOR ivendor = std::find(vecVendors.begin(), vecVendors.end(),
816                                                    sVendor);
817                     if (ivendor != vecVendors.end())
818                     {
819                         *ppInfo = pInfo;
820                     }
821                     else
822                     {
823                         *ppInfo = NULL;
824                         errcode = JFW_E_NOT_RECOGNIZED;
825                     }
826                     break;
827                 }
828 			}
829 			else if(plerr == JFW_PLUGIN_E_FAILED_VERSION)
830 			{//found JRE but it has the wrong version
831 				*ppInfo = NULL;
832 				errcode = JFW_E_FAILED_VERSION;
833 				break;
834 			}
835 			else if (plerr == JFW_PLUGIN_E_NO_JRE)
836 			{// plugin does not recognize this path as belonging to JRE
837 				continue;
838 			}
839 			OSL_ASSERT(0);
840 		}
841 		if (*ppInfo == NULL && errcode != JFW_E_FAILED_VERSION)
842 			errcode = JFW_E_NOT_RECOGNIZED;
843     }
844     catch (jfw::FrameworkException& e)
845     {
846         errcode = e.errorCode;
847         fprintf(stderr, "%s\n", e.message.getStr());
848         OSL_ENSURE(0, e.message.getStr());
849     }
850 
851     return errcode;
852 }
853 
854 
855 javaFrameworkError SAL_CALL jfw_setSelectedJRE(JavaInfo const *pInfo)
856 {
857     javaFrameworkError errcode = JFW_E_NONE;
858     try
859     {
860 		osl::MutexGuard guard(jfw::FwkMutex::get());
861         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
862             return JFW_E_DIRECT_MODE;
863 		//check if pInfo is the selected JRE
864 		JavaInfo *currentInfo = NULL;
865 		errcode = jfw_getSelectedJRE( & currentInfo);
866 		if (errcode != JFW_E_NONE && errcode != JFW_E_INVALID_SETTINGS)
867 			return errcode;
868 
869 		if (jfw_areEqualJavaInfo(currentInfo, pInfo) == sal_False)
870 		{
871 			jfw::NodeJava node;
872 			node.setJavaInfo(pInfo, false);
873 			node.write();
874 			//remember that the JRE was selected in this process
875 			jfw::setJavaSelected();
876 		}
877     }
878     catch (jfw::FrameworkException& e)
879     {
880         errcode = e.errorCode;
881         fprintf(stderr, "%s\n", e.message.getStr());
882         OSL_ENSURE(0, e.message.getStr());
883     }
884     return errcode;
885 }
886 javaFrameworkError SAL_CALL jfw_setEnabled(sal_Bool bEnabled)
887 {
888     javaFrameworkError errcode = JFW_E_NONE;
889     try
890     {
891 		osl::MutexGuard guard(jfw::FwkMutex::get());
892         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
893             return JFW_E_DIRECT_MODE;
894 
895 		if (g_bEnabledSwitchedOn == false && bEnabled == sal_True)
896 		{
897 			//When the process started then Enabled was false.
898 			//This is first time enabled is set to true.
899 			//That means, no preparational work has been done, such as setting the
900 			//LD_LIBRARY_PATH, etc.
901 
902 			//check if Enabled is false;
903             const jfw::MergedSettings settings;
904 			if (settings.getEnabled() == sal_False)
905 				g_bEnabledSwitchedOn = true;
906 		}
907 		jfw::NodeJava node;
908 		node.setEnabled(bEnabled);
909 		node.write();
910     }
911     catch (jfw::FrameworkException& e)
912     {
913         errcode = e.errorCode;
914         fprintf(stderr, "%s\n", e.message.getStr());
915         OSL_ENSURE(0, e.message.getStr());
916     }
917     return errcode;
918 }
919 
920 javaFrameworkError SAL_CALL jfw_getEnabled(sal_Bool *pbEnabled)
921 {
922     javaFrameworkError errcode = JFW_E_NONE;
923     try
924     {
925         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
926             return JFW_E_DIRECT_MODE;
927         osl::MutexGuard guard(jfw::FwkMutex::get());
928 		if (pbEnabled == NULL)
929 			return JFW_E_INVALID_ARG;
930 		jfw::MergedSettings settings;
931 		*pbEnabled = settings.getEnabled();
932     }
933     catch (jfw::FrameworkException& e)
934     {
935         errcode = e.errorCode;
936         fprintf(stderr, "%s\n", e.message.getStr());
937         OSL_ENSURE(0, e.message.getStr());
938     }
939     return errcode;
940 }
941 
942 
943 javaFrameworkError SAL_CALL jfw_setVMParameters(
944     rtl_uString * * arOptions, sal_Int32 nLen)
945 {
946     javaFrameworkError errcode = JFW_E_NONE;
947     try
948     {
949 		osl::MutexGuard guard(jfw::FwkMutex::get());
950         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
951             return JFW_E_DIRECT_MODE;
952         jfw::NodeJava node;
953 		if (arOptions == NULL && nLen != 0)
954 			return JFW_E_INVALID_ARG;
955 		node.setVmParameters(arOptions, nLen);
956 		node.write();
957     }
958     catch (jfw::FrameworkException& e)
959     {
960         errcode = e.errorCode;
961         fprintf(stderr, "%s\n", e.message.getStr());
962         OSL_ENSURE(0, e.message.getStr());
963     }
964 
965     return errcode;
966 }
967 
968 javaFrameworkError SAL_CALL jfw_getVMParameters(
969     rtl_uString *** parOptions, sal_Int32 * pLen)
970 {
971     javaFrameworkError errcode = JFW_E_NONE;
972     try
973     {
974 		osl::MutexGuard guard(jfw::FwkMutex::get());
975         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
976             return JFW_E_DIRECT_MODE;
977 
978 		if (parOptions == NULL || pLen == NULL)
979 			return JFW_E_INVALID_ARG;
980 		const jfw::MergedSettings settings;
981 		settings.getVmParametersArray(parOptions, pLen);
982     }
983     catch (jfw::FrameworkException& e)
984     {
985         errcode = e.errorCode;
986         fprintf(stderr, "%s\n", e.message.getStr());
987         OSL_ENSURE(0, e.message.getStr());
988     }
989     return errcode;
990 }
991 
992 javaFrameworkError SAL_CALL jfw_setUserClassPath(rtl_uString * pCp)
993 {
994     javaFrameworkError errcode = JFW_E_NONE;
995     try
996     {
997 		osl::MutexGuard guard(jfw::FwkMutex::get());
998         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
999             return JFW_E_DIRECT_MODE;
1000 		jfw::NodeJava node;
1001 		if (pCp == NULL)
1002 			return JFW_E_INVALID_ARG;
1003 		node.setUserClassPath(pCp);
1004 		node.write();
1005     }
1006     catch (jfw::FrameworkException& e)
1007     {
1008         errcode = e.errorCode;
1009         fprintf(stderr, "%s\n", e.message.getStr());
1010         OSL_ENSURE(0, e.message.getStr());
1011     }
1012     return errcode;
1013 }
1014 
1015 javaFrameworkError SAL_CALL jfw_getUserClassPath(rtl_uString ** ppCP)
1016 {
1017     javaFrameworkError errcode = JFW_E_NONE;
1018     try
1019     {
1020 		osl::MutexGuard guard(jfw::FwkMutex::get());
1021         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
1022             return JFW_E_DIRECT_MODE;
1023 		if (ppCP == NULL)
1024 			return JFW_E_INVALID_ARG;
1025 		const jfw::MergedSettings settings;
1026 		*ppCP = settings.getUserClassPath().pData;
1027 		rtl_uString_acquire(*ppCP);
1028     }
1029     catch (jfw::FrameworkException& e)
1030     {
1031         errcode = e.errorCode;
1032         fprintf(stderr, "%s\n", e.message.getStr());
1033         OSL_ENSURE(0, e.message.getStr());
1034     }
1035     return errcode;
1036 }
1037 
1038 javaFrameworkError SAL_CALL jfw_addJRELocation(rtl_uString * sLocation)
1039 {
1040     javaFrameworkError errcode = JFW_E_NONE;
1041     try
1042     {
1043 		osl::MutexGuard guard(jfw::FwkMutex::get());
1044         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
1045             return JFW_E_DIRECT_MODE;
1046         jfw::NodeJava node;
1047 		if (sLocation == NULL)
1048 			return JFW_E_INVALID_ARG;
1049 		node.load();
1050 		node.addJRELocation(sLocation);
1051 		node.write();
1052     }
1053     catch (jfw::FrameworkException& e)
1054     {
1055         errcode = e.errorCode;
1056         fprintf(stderr, "%s\n", e.message.getStr());
1057         OSL_ENSURE(0, e.message.getStr());
1058     }
1059 
1060     return errcode;
1061 
1062 }
1063 
1064 javaFrameworkError SAL_CALL jfw_setJRELocations(
1065     rtl_uString ** arLocations, sal_Int32 nLen)
1066 {
1067     javaFrameworkError errcode = JFW_E_NONE;
1068     try
1069     {
1070 		osl::MutexGuard guard(jfw::FwkMutex::get());
1071         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
1072             return JFW_E_DIRECT_MODE;
1073 		jfw::NodeJava node;
1074 		if (arLocations == NULL && nLen != 0)
1075 			return JFW_E_INVALID_ARG;
1076 		node.setJRELocations(arLocations, nLen);
1077 		node.write();
1078     }
1079     catch (jfw::FrameworkException& e)
1080     {
1081         errcode = e.errorCode;
1082         fprintf(stderr, "%s\n", e.message.getStr());
1083         OSL_ENSURE(0, e.message.getStr());
1084     }
1085     return errcode;
1086 
1087 }
1088 
1089 javaFrameworkError SAL_CALL jfw_getJRELocations(
1090     rtl_uString *** parLocations, sal_Int32 *pLen)
1091 {
1092     javaFrameworkError errcode = JFW_E_NONE;
1093     try
1094     {
1095 		osl::MutexGuard guard(jfw::FwkMutex::get());
1096         if (jfw::getMode() == jfw::JFW_MODE_DIRECT)
1097             return JFW_E_DIRECT_MODE;
1098 
1099 		if (parLocations == NULL || pLen == NULL)
1100 			return JFW_E_INVALID_ARG;
1101 		const jfw::MergedSettings settings;
1102 		settings.getJRELocations(parLocations, pLen);
1103     }
1104     catch (jfw::FrameworkException& e)
1105     {
1106         errcode = e.errorCode;
1107         fprintf(stderr, "%s\n", e.message.getStr());
1108         OSL_ENSURE(0, e.message.getStr());
1109     }
1110 
1111     return errcode;
1112 }
1113 
1114 
1115 javaFrameworkError jfw_existJRE(const JavaInfo *pInfo, sal_Bool *exist)
1116 {
1117     //get the function jfw_plugin_existJRE
1118     jfw::VendorSettings aVendorSettings;
1119     jfw::CJavaInfo aInfo;
1120     aInfo = (const ::JavaInfo*) pInfo; //makes a copy of pInfo
1121     rtl::OUString sLibPath = aVendorSettings.getPluginLibrary(aInfo.getVendor());
1122     osl::Module modulePlugin(sLibPath);
1123     if ( ! modulePlugin)
1124         return JFW_E_NO_PLUGIN;
1125     rtl::OUString sFunctionName(
1126         RTL_CONSTASCII_USTRINGPARAM("jfw_plugin_existJRE"));
1127     jfw_plugin_existJRE_ptr pFunc =
1128         (jfw_plugin_existJRE_ptr)
1129         osl_getFunctionSymbol(modulePlugin, sFunctionName.pData);
1130     if (pFunc == NULL)
1131         return JFW_E_ERROR;
1132 
1133     javaPluginError plerr = (*pFunc)(pInfo, exist);
1134 
1135     javaFrameworkError ret = JFW_E_NONE;
1136     switch (plerr)
1137     {
1138     case JFW_PLUGIN_E_NONE:
1139         ret = JFW_E_NONE;
1140         break;
1141     case JFW_PLUGIN_E_INVALID_ARG:
1142         ret = JFW_E_INVALID_ARG;
1143         break;
1144     case JFW_PLUGIN_E_ERROR:
1145         ret = JFW_E_ERROR;
1146         break;
1147     default:
1148         ret = JFW_E_ERROR;
1149     }
1150     return ret;
1151 }
1152 
1153 void SAL_CALL jfw_lock()
1154 {
1155     jfw::FwkMutex::get().acquire();
1156 }
1157 
1158 void SAL_CALL jfw_unlock()
1159 {
1160     jfw::FwkMutex::get().release();
1161 }
1162 
1163 
1164 namespace jfw
1165 {
1166 CJavaInfo::CJavaInfo(): pInfo(0)
1167 {
1168 }
1169 
1170 CJavaInfo::CJavaInfo(const CJavaInfo & info)
1171 {
1172     pInfo = copyJavaInfo(info.pInfo);
1173 }
1174 
1175 CJavaInfo::CJavaInfo(::JavaInfo * info, _transfer_ownership)
1176 {
1177     pInfo = info;
1178 }
1179 CJavaInfo CJavaInfo::createWrapper(::JavaInfo* info)
1180 {
1181     return CJavaInfo(info, TRANSFER);
1182 }
1183 void CJavaInfo::attach(::JavaInfo * info)
1184 {
1185     jfw_freeJavaInfo(pInfo);
1186     pInfo = info;
1187 }
1188 ::JavaInfo * CJavaInfo::detach()
1189 {
1190     JavaInfo * tmp = pInfo;
1191     pInfo = NULL;
1192     return tmp;
1193 }
1194 
1195 CJavaInfo::~CJavaInfo()
1196 {
1197     jfw_freeJavaInfo(pInfo);
1198 }
1199 
1200 CJavaInfo::operator ::JavaInfo* ()
1201 {
1202     return pInfo;
1203 }
1204 
1205 JavaInfo * CJavaInfo::copyJavaInfo(const JavaInfo * pInfo)
1206 {
1207 	if (pInfo == NULL)
1208 		return NULL;
1209     JavaInfo* newInfo =
1210           (JavaInfo*) rtl_allocateMemory(sizeof(JavaInfo));
1211     if (newInfo)
1212     {
1213         rtl_copyMemory(newInfo, pInfo, sizeof(JavaInfo));
1214         rtl_uString_acquire(pInfo->sVendor);
1215         rtl_uString_acquire(pInfo->sLocation);
1216         rtl_uString_acquire(pInfo->sVersion);
1217         rtl_byte_sequence_acquire(pInfo->arVendorData);
1218     }
1219     return newInfo;
1220 }
1221 
1222 
1223 JavaInfo* CJavaInfo::cloneJavaInfo() const
1224 {
1225     if (pInfo == NULL)
1226         return NULL;
1227     return copyJavaInfo(pInfo);
1228 }
1229 
1230 CJavaInfo & CJavaInfo::operator = (const CJavaInfo& info)
1231 {
1232     if (&info == this)
1233         return *this;
1234 
1235     jfw_freeJavaInfo(pInfo);
1236     pInfo = copyJavaInfo(info.pInfo);
1237     return *this;
1238 }
1239 CJavaInfo & CJavaInfo::operator = (const ::JavaInfo* info)
1240 {
1241     if (info == pInfo)
1242         return *this;
1243 
1244     jfw_freeJavaInfo(pInfo);
1245     pInfo = copyJavaInfo(info);
1246     return *this;
1247 }
1248 
1249 const ::JavaInfo* CJavaInfo::operator ->() const
1250 {
1251     return pInfo;
1252 }
1253 
1254 CJavaInfo::operator JavaInfo const * () const
1255 {
1256     return pInfo;
1257 }
1258 // ::JavaInfo** CJavaInfo::operator & ()
1259 // {
1260 //     return & pInfo;
1261 // }
1262 
1263 rtl::OUString CJavaInfo::getVendor() const
1264 {
1265     if (pInfo)
1266         return rtl::OUString(pInfo->sVendor);
1267     else
1268         return rtl::OUString();
1269 }
1270 
1271 rtl::OUString CJavaInfo::getLocation() const
1272 {
1273     if (pInfo)
1274         return rtl::OUString(pInfo->sLocation);
1275     else
1276         return rtl::OUString();
1277 }
1278 
1279 sal_uInt64 CJavaInfo::getFeatures() const
1280 {
1281     if (pInfo)
1282         return pInfo->nFeatures;
1283     else
1284         return 0l;
1285 }
1286 
1287 }
1288