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