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