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 #if OSL_DEBUG_LEVEL > 0
31 #include <stdio.h>
32 #endif
33 #include <string.h>
34 
35 #include "boost/scoped_array.hpp"
36 #include "osl/diagnose.h"
37 #include "rtl/ustring.hxx"
38 #include "rtl/ustrbuf.hxx"
39 #include "osl/module.hxx"
40 #include "osl/mutex.hxx"
41 #include "osl/thread.hxx"
42 #include "osl/file.hxx"
43 #include "rtl/instance.hxx"
44 #include "osl/getglobalmutex.hxx"
45 #include <setjmp.h>
46 #include <signal.h>
47 #include <stack>
48 
49 #include "jni.h"
50 #include "rtl/byteseq.hxx"
51 #include "jvmfwk/vendorplugin.h"
52 #include "util.hxx"
53 #include "sunversion.hxx"
54 #include "vendorlist.hxx"
55 #include "diagnostics.h"
56 
57 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
58 #define SUN_MICRO "Sun Microsystems Inc."
59 
60 using namespace osl;
61 using namespace rtl;
62 using namespace std;
63 using namespace jfw_plugin;
64 
65 namespace {
66 
67 struct PluginMutex: public ::rtl::Static<osl::Mutex, PluginMutex> {};
68 
69 #if defined UNX
70 OString getPluginJarPath(
71     const OUString & sVendor,
72     const OUString& sLocation,
73     const OUString& sVersion)
74 {
75     OString ret;
76     OUString sName1(RTL_CONSTASCII_USTRINGPARAM("javaplugin.jar"));
77     OUString sName2(RTL_CONSTASCII_USTRINGPARAM("plugin.jar"));
78     OUString sPath;
79     if (sVendor.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SUN_MICRO))))
80     {
81         SunVersion ver142("1.4.2-ea");
82         SunVersion ver150("1.5.0-ea");
83         SunVersion ver(sVersion);
84         OSL_ASSERT(ver142 && ver150 && ver);
85 
86         OUString sName;
87         if (ver < ver142)
88         {
89             sName = sName1;
90         }
91         else if (ver < ver150)
92         {//this will cause ea, beta etc. to have plugin.jar in path.
93             //but this does not harm. 1.5.0-beta < 1.5.0
94             sName = sName2;
95         }
96         if (sName.getLength())
97         {
98             sName = sLocation + OUSTR("/lib/") + sName;
99             OSL_VERIFY(
100                 osl_getSystemPathFromFileURL(sName.pData, & sPath.pData)
101                 == osl_File_E_None);
102         }
103     }
104     else
105     {
106         char sep[] =  {SAL_PATHSEPARATOR, 0};
107         OUString sName(sLocation + OUSTR("/lib/") + sName1);
108         OUString sPath1;
109         OUString sPath2;
110         if (osl_getSystemPathFromFileURL(sName.pData, & sPath1.pData)
111             == osl_File_E_None)
112         {
113             sName = sLocation + OUSTR("/lib/") + sName2;
114             if (osl_getSystemPathFromFileURL(sName.pData, & sPath2.pData)
115                 == osl_File_E_None)
116             {
117                 sPath = sPath1 + OUString::createFromAscii(sep) + sPath2;
118             }
119         }
120         OSL_ASSERT(sPath.getLength());
121     }
122     ret = rtl::OUStringToOString(sPath, osl_getThreadTextEncoding());
123 
124     return ret;
125 }
126 #endif // UNX
127 
128 
129 JavaInfo* createJavaInfo(const rtl::Reference<VendorBase> & info)
130 {
131     JavaInfo* pInfo = (JavaInfo*) rtl_allocateMemory(sizeof(JavaInfo));
132     if (pInfo == NULL)
133         return NULL;
134     rtl::OUString sVendor = info->getVendor();
135     pInfo->sVendor = sVendor.pData;
136     rtl_uString_acquire(sVendor.pData);
137     rtl::OUString sHome = info->getHome();
138     pInfo->sLocation = sHome.pData;
139     rtl_uString_acquire(pInfo->sLocation);
140     rtl::OUString sVersion = info->getVersion();
141     pInfo->sVersion = sVersion.pData;
142     rtl_uString_acquire(pInfo->sVersion);
143     pInfo->nFeatures = info->supportsAccessibility() ? 1 : 0;
144     pInfo->nRequirements = info->needsRestart() ? JFW_REQUIRE_NEEDRESTART : 0;
145     rtl::OUStringBuffer buf(1024);
146     buf.append(info->getRuntimeLibrary());
147     if (info->getLibraryPaths().getLength() > 0)
148     {
149         buf.appendAscii("\n");
150         buf.append(info->getLibraryPaths());
151         buf.appendAscii("\n");
152     }
153 
154     rtl::OUString sVendorData = buf.makeStringAndClear();
155     rtl::ByteSequence byteSeq( (sal_Int8*) sVendorData.pData->buffer,
156                                sVendorData.getLength() * sizeof(sal_Unicode));
157     pInfo->arVendorData = byteSeq.get();
158     rtl_byte_sequence_acquire(pInfo->arVendorData);
159 
160     return pInfo;
161 }
162 
163 rtl::OUString getRuntimeLib(const rtl::ByteSequence & data)
164 {
165     const sal_Unicode* chars = (sal_Unicode*) data.getConstArray();
166     sal_Int32 len = data.getLength();
167     rtl::OUString sData(chars, len / 2);
168     //the runtime lib is on the first line
169     sal_Int32 index = 0;
170     rtl::OUString aToken = sData.getToken( 0, '\n', index);
171 
172     return aToken;
173 }
174 
175 jmp_buf jmp_jvm_abort;
176 sig_atomic_t g_bInGetJavaVM = 0;
177 
178 extern "C" void JNICALL abort_handler()
179 {
180     // If we are within JNI_CreateJavaVM then we jump back into getJavaVM
181     if( g_bInGetJavaVM != 0 )
182     {
183         fprintf( stderr, "JavaVM: JNI_CreateJavaVM called _exit, caught by abort_handler in javavm.cxx\n");
184         longjmp( jmp_jvm_abort, 0);
185     }
186 }
187 
188 }
189 
190 extern "C"
191 javaPluginError jfw_plugin_getAllJavaInfos(
192     rtl_uString *sVendor,
193     rtl_uString *sMinVersion,
194     rtl_uString *sMaxVersion,
195     rtl_uString  * *arExcludeList,
196     sal_Int32  nLenList,
197     JavaInfo*** parJavaInfo,
198     sal_Int32 *nLenInfoList)
199 {
200     OSL_ASSERT(sVendor);
201     OSL_ASSERT(sMinVersion);
202     OSL_ASSERT(sMaxVersion);
203     OSL_ASSERT(parJavaInfo);
204     OSL_ASSERT(parJavaInfo);
205     OSL_ASSERT(nLenInfoList);
206     if (!sVendor || !sMinVersion || !sMaxVersion || !parJavaInfo || !nLenInfoList)
207         return JFW_PLUGIN_E_INVALID_ARG;
208 
209     //nLenlist contains the number of element in arExcludeList.
210     //If no exclude list is provided then nLenList must be 0
211     OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
212     if (arExcludeList == NULL && nLenList > 0)
213         return JFW_PLUGIN_E_INVALID_ARG;
214 
215     OUString ouVendor(sVendor);
216     OUString ouMinVer(sMinVersion);
217     OUString ouMaxVer(sMaxVersion);
218 
219     OSL_ASSERT(ouVendor.getLength() > 0);
220     if (ouVendor.getLength() == 0)
221         return JFW_PLUGIN_E_INVALID_ARG;
222 
223     JavaInfo** arInfo = NULL;
224 
225     //Find all JREs
226     vector<rtl::Reference<VendorBase> > vecInfos =
227         getAllJREInfos();
228     vector<rtl::Reference<VendorBase> > vecVerifiedInfos;
229 
230     typedef vector<rtl::Reference<VendorBase> >::iterator it;
231     for (it i= vecInfos.begin(); i != vecInfos.end(); i++)
232     {
233         const rtl::Reference<VendorBase>& cur = *i;
234 
235         if (ouVendor.equals(cur->getVendor()) == sal_False)
236             continue;
237 
238         if (ouMinVer.getLength() > 0)
239         {
240             try
241             {
242                 if (cur->compareVersions(sMinVersion) == -1)
243                     continue;
244             }
245             catch (MalformedVersionException&)
246             {
247                 //The minVersion was not recognized as valid for this vendor.
248                 JFW_ENSURE(
249                     0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
250                     + ouMinVer + OUSTR(" for vendor: ") + cur->getVendor()
251                     + OUSTR(" .Check minimum Version.") );
252                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
253             }
254         }
255 
256         if (ouMaxVer.getLength() > 0)
257         {
258             try
259             {
260                 if (cur->compareVersions(sMaxVersion) == 1)
261                     continue;
262             }
263             catch (MalformedVersionException&)
264             {
265                 //The maxVersion was not recognized as valid for this vendor.
266                 JFW_ENSURE(
267                     0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
268                     + ouMaxVer + OUSTR(" for vendor: ") + cur->getVendor()
269                     + OUSTR(" .Check maximum Version.") );
270                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
271             }
272         }
273 
274         if (arExcludeList > 0)
275         {
276             bool bExclude = false;
277             for (int j = 0; j < nLenList; j++)
278             {
279                 rtl::OUString sExVer(arExcludeList[j]);
280                 try
281                 {
282                     if (cur->compareVersions(sExVer) == 0)
283                     {
284                         bExclude = true;
285                         break;
286                     }
287                 }
288                 catch (MalformedVersionException&)
289                 {
290                     //The excluded version was not recognized as valid for this vendor.
291                     JFW_ENSURE(
292                         0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
293                         + sExVer + OUSTR(" for vendor: ") + cur->getVendor()
294                         + OUSTR(" .Check excluded versions.") );
295                     return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
296                 }
297             }
298             if (bExclude == true)
299                 continue;
300         }
301         vecVerifiedInfos.push_back(*i);
302     }
303     //Now vecVerifiedInfos contains all those JREs which meet the version requirements
304     //Transfer them into the array that is passed out.
305     arInfo = (JavaInfo**) rtl_allocateMemory(vecVerifiedInfos.size() * sizeof (JavaInfo*));
306     int j = 0;
307     typedef vector<rtl::Reference<VendorBase> >::const_iterator cit;
308     for (cit ii = vecVerifiedInfos.begin(); ii != vecVerifiedInfos.end(); ii++, j++)
309     {
310         arInfo[j] = createJavaInfo(*ii);
311     }
312     *nLenInfoList = vecVerifiedInfos.size();
313 
314 
315     *parJavaInfo = arInfo;
316     return JFW_PLUGIN_E_NONE;
317 }
318 
319 extern "C"
320 javaPluginError jfw_plugin_getJavaInfoByPath(
321     rtl_uString *path,
322     rtl_uString *sVendor,
323     rtl_uString *sMinVersion,
324     rtl_uString *sMaxVersion,
325     rtl_uString  *  *arExcludeList,
326     sal_Int32  nLenList,
327     JavaInfo ** ppInfo)
328 {
329     javaPluginError errcode = JFW_PLUGIN_E_NONE;
330 
331     OSL_ASSERT(path);
332     OSL_ASSERT(sVendor);
333     OSL_ASSERT(sMinVersion);
334     OSL_ASSERT(sMaxVersion);
335     if (!path || !sVendor || !sMinVersion || !sMaxVersion || !ppInfo)
336         return JFW_PLUGIN_E_INVALID_ARG;
337     OUString ouPath(path);
338     OSL_ASSERT(ouPath.getLength() > 0);
339     if (ouPath.getLength() == 0)
340         return JFW_PLUGIN_E_INVALID_ARG;
341 
342     //nLenlist contains the number of element in arExcludeList.
343     //If no exclude list is provided then nLenList must be 0
344     OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
345     if (arExcludeList == NULL && nLenList > 0)
346         return JFW_PLUGIN_E_INVALID_ARG;
347 
348     OUString ouVendor(sVendor);
349     OUString ouMinVer(sMinVersion);
350     OUString ouMaxVer(sMaxVersion);
351 
352     OSL_ASSERT(ouVendor.getLength() > 0);
353     if (ouVendor.getLength() == 0)
354         return JFW_PLUGIN_E_INVALID_ARG;
355 
356     rtl::Reference<VendorBase> aVendorInfo = getJREInfoByPath(ouPath);
357     if (aVendorInfo.is() == sal_False)
358         return JFW_PLUGIN_E_NO_JRE;
359 
360     //Check if the detected JRE matches the version requirements
361     if (ouVendor.equals(aVendorInfo->getVendor()) == sal_False)
362         return JFW_PLUGIN_E_NO_JRE;
363 
364     if (ouMinVer.getLength() > 0)
365     {
366         int nRes = 0;
367         try
368         {
369             nRes = aVendorInfo->compareVersions(ouMinVer);
370         }
371         catch (MalformedVersionException&)
372         {
373             //The minVersion was not recognized as valid for this vendor.
374             JFW_ENSURE(
375                 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
376                 + ouMinVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
377                 + OUSTR(" .Check minimum Version.") );
378             return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
379         }
380         if (nRes < 0)
381             return JFW_PLUGIN_E_FAILED_VERSION;
382     }
383 
384     if (ouMaxVer.getLength() > 0)
385     {
386         int nRes = 0;
387         try
388         {
389             nRes = aVendorInfo->compareVersions(ouMaxVer);
390         }
391         catch (MalformedVersionException&)
392         {
393             //The maxVersion was not recognized as valid for this vendor.
394             JFW_ENSURE(
395                 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
396                 + ouMaxVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
397                 + OUSTR(" .Check maximum Version.") );
398             return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
399         }
400         if (nRes > 0)
401             return JFW_PLUGIN_E_FAILED_VERSION;
402     }
403 
404     if (arExcludeList > 0)
405     {
406         for (int i = 0; i < nLenList; i++)
407         {
408             rtl::OUString sExVer(arExcludeList[i]);
409             int nRes = 0;
410             try
411             {
412                 nRes = aVendorInfo->compareVersions(sExVer);
413             }
414             catch (MalformedVersionException&)
415             {
416                 //The excluded version was not recognized as valid for this vendor.
417                 JFW_ENSURE(
418                     0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
419                     + sExVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
420                     + OUSTR(" .Check excluded versions.") );
421                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
422             }
423             if (nRes == 0)
424                 return JFW_PLUGIN_E_FAILED_VERSION;
425         }
426     }
427     *ppInfo = createJavaInfo(aVendorInfo);
428 
429     return errcode;
430 }
431 
432 /** starts a Java Virtual Machine.
433     <p>
434     The function shall ensure, that the VM does not abort the process
435     during instantiation.
436     </p>
437  */
438 extern "C"
439 javaPluginError jfw_plugin_startJavaVirtualMachine(
440     const JavaInfo *pInfo,
441     const JavaVMOption* arOptions,
442     sal_Int32 cOptions,
443     JavaVM ** ppVm,
444     JNIEnv ** ppEnv)
445 {
446     // unless guard is volatile the following warning occurs on gcc:
447     // warning: variable 't' might be clobbered by `longjmp' or `vfork'
448     volatile osl::MutexGuard guard(PluginMutex::get());
449     // unless errcode is volatile the following warning occurs on gcc:
450     // warning: variable 'errcode' might be clobbered by `longjmp' or `vfork'
451     volatile javaPluginError errcode = JFW_PLUGIN_E_NONE;
452     if ( pInfo == NULL || ppVm == NULL || ppEnv == NULL)
453         return JFW_PLUGIN_E_INVALID_ARG;
454     //Check if the Vendor (pInfo->sVendor) is supported by this plugin
455     if ( ! isVendorSupported(pInfo->sVendor))
456         return JFW_PLUGIN_E_WRONG_VENDOR;
457     rtl::OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
458     JFW_TRACE2(OUSTR("[Java framework] Using Java runtime library: ")
459               + sRuntimeLib + OUSTR(".\n"));
460     // On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because
461     // libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded
462     // witd RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
463     oslModule moduleRt = 0;
464 #if defined(LINUX)
465     if ((moduleRt = osl_loadModule(sRuntimeLib.pData,
466                                    SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_NOW)) == 0 )
467 #else
468     if ((moduleRt = osl_loadModule(sRuntimeLib.pData, SAL_LOADMODULE_DEFAULT)) == 0)
469 #endif
470      {
471          JFW_ENSURE(0, OUSTR("[Java framework]sunjavaplugin" SAL_DLLEXTENSION
472                              " could not load Java runtime library: \n")
473                     + sRuntimeLib + OUSTR("\n"));
474          JFW_TRACE0(OUSTR("[Java framework]sunjavaplugin" SAL_DLLEXTENSION
475                              " could not load Java runtime library: \n")
476                     + sRuntimeLib +  OUSTR("\n"));
477          return JFW_PLUGIN_E_VM_CREATION_FAILED;
478      }
479 
480 #ifdef UNX
481     //Setting the JAVA_HOME is needed for awt
482     rtl::OUString javaHome(RTL_CONSTASCII_USTRINGPARAM("JAVA_HOME="));
483     rtl::OUString sPathLocation;
484     osl_getSystemPathFromFileURL(pInfo->sLocation, & sPathLocation.pData);
485     javaHome += sPathLocation;
486     rtl::OString osJavaHome = rtl::OUStringToOString(
487         javaHome, osl_getThreadTextEncoding());
488     putenv(strdup(osJavaHome.getStr()));
489 #endif
490 
491     typedef jint JNICALL JNI_InitArgs_Type(void *);
492     typedef jint JNICALL JNI_CreateVM_Type(JavaVM **, JNIEnv **, void *);
493     rtl::OUString sSymbolCreateJava(
494             RTL_CONSTASCII_USTRINGPARAM("JNI_CreateJavaVM"));
495 
496     JNI_CreateVM_Type * pCreateJavaVM = (JNI_CreateVM_Type *) osl_getFunctionSymbol(
497         moduleRt, sSymbolCreateJava.pData);
498     if (!pCreateJavaVM)
499     {
500         OSL_ASSERT(0);
501         rtl::OString sLib = rtl::OUStringToOString(
502             sRuntimeLib, osl_getThreadTextEncoding());
503         rtl::OString sSymbol = rtl::OUStringToOString(
504             sSymbolCreateJava, osl_getThreadTextEncoding());
505         fprintf(stderr,"[Java framework]sunjavaplugin"SAL_DLLEXTENSION
506                 "Java runtime library: %s does not export symbol %s !\n",
507                 sLib.getStr(), sSymbol.getStr());
508         return JFW_PLUGIN_E_VM_CREATION_FAILED;
509     }
510 
511     // Some testing with Java 1.4 showed that JavaVMOption.optionString has to
512     // be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
513     JavaVMInitArgs vm_args;
514 
515     boost::scoped_array<JavaVMOption> sarOptions(
516         new JavaVMOption[cOptions + 1]);
517     JavaVMOption * options = sarOptions.get();
518 
519     // We set an abort handler which is called when the VM calls _exit during
520     // JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain
521     // all some directories of the Java installation. This is necessary for
522     // all versions below 1.5.1
523     options[0].optionString= (char *) "abort";
524     options[0].extraInfo= (void* )(sal_IntPtr)abort_handler;
525     rtl::OString sClassPathProp("-Djava.class.path=");
526     rtl::OString sClassPathOption;
527     for (int i = 0; i < cOptions; i++)
528     {
529 #ifdef UNX
530     // Until java 1.5 we need to put a plugin.jar or javaplugin.jar (<1.4.2)
531     // in the class path in order to have applet support.
532         rtl::OString sClassPath = arOptions[i].optionString;
533         if (sClassPath.match(sClassPathProp, 0) == sal_True)
534         {
535             char sep[] =  {SAL_PATHSEPARATOR, 0};
536             OString sAddPath = getPluginJarPath(pInfo->sVendor, pInfo->sLocation,pInfo->sVersion);
537             if (sAddPath.getLength())
538                 sClassPathOption = sClassPath + rtl::OString(sep) + sAddPath;
539             else
540                 sClassPathOption = sClassPath;
541             options[i+1].optionString = (char *) sClassPathOption.getStr();
542             options[i+1].extraInfo = arOptions[i].extraInfo;
543         }
544         else
545         {
546 #endif
547             options[i+1].optionString = arOptions[i].optionString;
548             options[i+1].extraInfo = arOptions[i].extraInfo;
549 #ifdef UNX
550         }
551 #endif
552 #if OSL_DEBUG_LEVEL >= 2
553         JFW_TRACE2(OString("VM option: ") + OString(options[i+1].optionString) +
554                    OString("\n"));
555 #endif
556     }
557 
558 #ifdef MACOSX
559     vm_args.version= JNI_VERSION_1_4; // issue 88987
560 #else
561     vm_args.version= JNI_VERSION_1_2;
562 #endif
563     vm_args.options= options;
564     vm_args.nOptions= cOptions + 1;
565     vm_args.ignoreUnrecognized= JNI_TRUE;
566 
567     /* We set a global flag which is used by the abort handler in order to
568        determine whether it is  should use longjmp to get back into this function.
569        That is, the abort handler determines if it is on the same stack as this function
570        and then jumps back into this function.
571     */
572     g_bInGetJavaVM = 1;
573     jint err;
574     JavaVM * pJavaVM = 0;
575     memset( jmp_jvm_abort, 0, sizeof(jmp_jvm_abort));
576     int jmpval= setjmp( jmp_jvm_abort );
577     /* If jmpval is not "0" then this point was reached by a longjmp in the
578        abort_handler, which was called indirectly by JNI_CreateVM.
579     */
580     if( jmpval == 0)
581     {
582         //returns negative number on failure
583         err= pCreateJavaVM(&pJavaVM, ppEnv, &vm_args);
584         g_bInGetJavaVM = 0;
585     }
586     else
587         // set err to a positive number, so as or recognize that an abort (longjmp)
588         //occurred
589         err= 1;
590 
591     if(err != 0)
592     {
593         rtl::OUString message;
594         if( err < 0)
595         {
596             fprintf(stderr,"[Java framework] sunjavaplugin"SAL_DLLEXTENSION
597                     "Can not create Java Virtual Machine\n");
598             errcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
599         }
600         else if( err > 0)
601         {
602             fprintf(stderr,"[Java framework] sunjavaplugin"SAL_DLLEXTENSION
603                     "Can not create JavaVirtualMachine, abort handler was called.\n");
604             errcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
605         }
606     }
607     else
608     {
609         *ppVm = pJavaVM;
610         JFW_TRACE2("[Java framework] sunjavaplugin"SAL_DLLEXTENSION " has created a VM.\n");
611     }
612 
613 
614    return errcode;
615 }
616 
617 extern "C"
618 javaPluginError jfw_plugin_existJRE(const JavaInfo *pInfo, sal_Bool *exist)
619 {
620     javaPluginError ret = JFW_PLUGIN_E_NONE;
621     if (!pInfo || !exist)
622         return JFW_PLUGIN_E_INVALID_ARG;
623     ::rtl::OUString sLocation(pInfo->sLocation);
624 
625     if (sLocation.getLength() == 0)
626         return JFW_PLUGIN_E_INVALID_ARG;
627     ::osl::DirectoryItem item;
628     ::osl::File::RC rc_item = ::osl::DirectoryItem::get(sLocation, item);
629     if (::osl::File::E_None == rc_item)
630     {
631         *exist = sal_True;
632     }
633     else if (::osl::File::E_NOENT == rc_item)
634     {
635         *exist = sal_False;
636     }
637     else
638     {
639         ret = JFW_PLUGIN_E_ERROR;
640     }
641 #ifdef MACOSX
642     //We can have the situation that the JavaVM runtime library is not
643     //contained within JAVA_HOME. Then the check for JAVA_HOME would return
644     //true although the runtime library may not be loadable.
645     if (ret == JFW_PLUGIN_E_NONE && *exist == sal_True)
646     {
647         rtl::OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
648         JFW_TRACE2(OUSTR("[Java framework] Checking existence of Java runtime library.\n"));
649 
650         ::osl::DirectoryItem itemRt;
651         ::osl::File::RC rc_itemRt = ::osl::DirectoryItem::get(sRuntimeLib, itemRt);
652         if (::osl::File::E_None == rc_itemRt)
653         {
654             *exist = sal_True;
655             JFW_TRACE2(OUSTR("[Java framework] Java runtime library exist: ")
656               + sRuntimeLib + OUSTR("\n"));
657 
658         }
659         else if (::osl::File::E_NOENT == rc_itemRt)
660         {
661             *exist = sal_False;
662             JFW_TRACE2(OUSTR("[Java framework] Java runtime library does not exist: ")
663                        + sRuntimeLib + OUSTR("\n"));
664         }
665         else
666         {
667             ret = JFW_PLUGIN_E_ERROR;
668             JFW_TRACE2(OUSTR("[Java framework] Error while looking for Java runtime library: ")
669                        + sRuntimeLib + OUSTR(" \n"));
670         }
671     }
672 #endif
673     return ret;
674 }
675 
676 
677