Kaydet (Commit) 43cc8abf authored tarafından Joachim Lingner's avatar Joachim Lingner

#i20052# plugin lib for java framework

üst c7d0bfee
#*************************************************************************
#
# $RCSfile: makefile.mk,v $
#
# $Revision: 1.1 $
#
# last change: $Author: jl $ $Date: 2004-04-19 15:37:36 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
#
# - GNU Lesser General Public License Version 2.1
# - Sun Industry Standards Source License Version 1.1
#
# Sun Microsystems Inc., October, 2000
#
# GNU Lesser General Public License Version 2.1
# =============================================
# Copyright 2000 by Sun Microsystems, Inc.
# 901 San Antonio Road, Palo Alto, CA 94303, USA
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 2.1, as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
#
# Sun Industry Standards Source License Version 1.1
# =================================================
# The contents of this file are subject to the Sun Industry Standards
# Source License Version 1.1 (the "License"); You may not use this file
# except in compliance with the License. You may obtain a copy of the
# License at http://www.openoffice.org/license.html.
#
# Software provided under this License is provided on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
# See the License for the specific provisions governing your rights and
# obligations concerning the Software.
#
# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
#
# Copyright: 2000 by Sun Microsystems, Inc.
#
# All Rights Reserved.
#
# Contributor(s): _______________________________________
#
#
#
#*************************************************************************
PRJ=..$/..$/..$/..
PRJNAME= jvmfwk
TARGET = plugin
ENABLE_EXCEPTIONS=TRUE
BOOTSTRAP_SERVICE=FALSE
LIBTARGET=NO
UNOCOMPONENT1=sunjavaplugin
# --- Settings -----------------------------------------------------
.INCLUDE : settings.mk
DLLPRE =
# ------------------------------------------------------------------
#.INCLUDE : ..$/cppumaker.mk
.IF "$(SOLAR_JAVA)"!=""
SLOFILES= \
$(SLO)$/sunjavaplugin.obj \
$(SLO)$/javainfo.obj \
$(SLO)$/sunversion.obj \
$(SLO)$/windows.obj
LIB1OBJFILES= \
$(SLO)$/sunjavaplugin.obj \
$(SLO)$/javainfo.obj \
$(SLO)$/sunversion.obj \
$(SLO)$/windows.obj
LIB1TARGET=$(SLB)$/$(UNOCOMPONENT1).lib
SHL1TARGET= $(UNOCOMPONENT1)
SHL1STDLIBS= \
$(CPPULIB) \
$(CPPUHELPER) \
$(SALLIB)
.IF "$(OS)" == "WNT"
SHL1STDLIBS += advapi32.lib
.ENDIF # WNT
SHL1VERSIONMAP = sunjavaplugin.map
SHL1DEPN=
SHL1IMPLIB= i$(UNOCOMPONENT1)
SHL1LIBS= $(LIB1TARGET)
SHL1DEF= $(MISC)$/$(SHL1TARGET).def
DEF1NAME= $(SHL1TARGET)
.ENDIF
# --- Targets ------------------------------------------------------
.INCLUDE : target.mk
/*************************************************************************
*
* $RCSfile: sunjavaplugin.cxx,v $
*
* $Revision: 1.1 $
*
* last change: $Author: jl $ $Date: 2004-04-19 15:36:12 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#if OSL_DEBUG_LEVEL > 0
#include <stdio.h>
#endif
#include "external/boost/scoped_array.hpp"
#include "osl/diagnose.h"
#include "rtl/ustring.hxx"
#include "osl/module.hxx"
#include "osl/mutex.hxx"
#include "osl/thread.hxx"
#include "rtl/instance.hxx"
#include "osl/getglobalmutex.hxx"
#include <setjmp.h>
#include <signal.h>
#include <stack>
#include "jni.h"
#include "rtl/byteseq.hxx"
#include "jvmfwk/vendorplugin.h"
#include "javainfo.hxx"
#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
namespace {
struct Init
{
osl::Mutex * operator()()
{
static osl::Mutex aInstance;
return &aInstance;
}
};
osl::Mutex * getPluginMutex()
{
return rtl_Instance< osl::Mutex, Init, ::osl::MutexGuard,
::osl::GetGlobalMutex >::create(
Init(), ::osl::GetGlobalMutex());
}
rtl::OUString getRuntimeLib(const rtl::ByteSequence & data)
{
const sal_Unicode* chars = (sal_Unicode*) data.getConstArray();
sal_Int32 len = data.getLength();
return rtl::OUString(chars, len / 2);
}
jmp_buf jmp_jvm_abort;
sig_atomic_t g_bInGetJavaVM = 0;
void abort_handler()
{
// If we are within JNI_CreateJavaVM then we jump back into getJavaVM
if( g_bInGetJavaVM != 0 )
{
fprintf( stderr, "JavaVM: JNI_CreateJavaVM called _exit, caught by abort_handler in javavm.cxx\n");
longjmp( jmp_jvm_abort, 0);
}
}
}
namespace cssu = com::sun::star::uno;
extern "C"
javaPluginError getAllJavaInfos( rtl_uString *sMinVersion,
rtl_uString *sMaxVersion,
rtl_uString * *arExcludeList,
sal_Int32 nLenList,
JavaInfo*** parJavaInfo,
sal_Int32 *nLenInfoList)
{
if (parJavaInfo == NULL || nLenInfoList == NULL)
return JFW_PLUGIN_E_INVALID_ARG;
JavaInfo** arInfo = NULL;
try
{
//check if we know all the required features
cssu::Sequence<rtl::OUString> seqExclude((rtl::OUString*)(rtl_uString**)arExcludeList, nLenList);
rtl::OUString sMin((rtl_uString*) sMinVersion);
std::vector<stoc_javadetect::JavaInfo> vec =
stoc_javadetect::JavaInfo::createAllInfo(sMin, seqExclude, 0);
arInfo = (JavaInfo**) rtl_allocateMemory(vec.size() * sizeof (JavaInfo*));
// JavaInfo * (_arInfo[] = (JavaInfo*(*)[])arInfo;
int j = 0;
rtl::OUString sVendor(OUSTR("Sun Microsystems Inc."));
typedef std::vector<stoc_javadetect::JavaInfo>::iterator cit;
for (cit i = vec.begin(); i != vec.end(); i++, j++)
{
arInfo[j] = (JavaInfo*) rtl_allocateMemory(sizeof JavaInfo);
JavaInfo* pInfo = arInfo[j];
pInfo->sVendor = sVendor.pData;
rtl_uString_acquire(sVendor.pData);
pInfo->sLocation = i->usJavaHome.pData;
rtl_uString_acquire(i->usJavaHome.pData);
pInfo->sVersion = i->getVersion().pData;
rtl_uString_acquire(pInfo->sVersion);
pInfo->nFeatures = i->supportsAccessibility() ? 1 : 0;
#ifdef UNX
pInfo->nRequirements = JFW_REQUIRE_NEEDRESTART;
#else
pInfo->nRequirements = 0x0l;
#endif
rtl::OUString sRuntimeLib = i->usRuntimeLib;
rtl::ByteSequence byteSeq( (sal_Int8*) sRuntimeLib.pData->buffer,
sRuntimeLib.getLength() * sizeof(sal_Unicode));
pInfo->arVendorData = byteSeq.get();
rtl_byte_sequence_acquire(pInfo->arVendorData);
}
*nLenInfoList = vec.size();
}
catch(stoc_javadetect::JavaInfo::MalformedVersionException&)
{
return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
}
*parJavaInfo = arInfo;
return JFW_PLUGIN_E_NONE;
}
extern "C"
javaPluginError getJavaInfoByPath(
rtl_uString *path,
rtl_uString *sMinVersion,
rtl_uString *sMaxVersion,
rtl_uString * *arExcludeList,
sal_Int32 nLenList,
JavaInfo ** ppInfo)
{
javaPluginError errcode = JFW_PLUGIN_E_NONE;
if (ppInfo == NULL)
return JFW_PLUGIN_E_INVALID_ARG;
try
{
rtl::OUString sPath((rtl_uString*)path);
stoc_javadetect::JavaInfo info(sPath);
//check if the version meets the requirements
const rtl::OUString& sVersion = info.getVersion();
rtl::OUString sTheMinVersion((rtl_uString*) sMinVersion);
if (sTheMinVersion.getLength() > 0)
{
int nRes =
stoc_javadetect::JavaInfo::compareVersions(
sVersion, sTheMinVersion);
if (nRes < 0)
return JFW_PLUGIN_E_FAILED_REQUIREMENTS;
}
rtl::OUString sTheMaxVersion((rtl_uString*) sMaxVersion);
if (sTheMaxVersion.getLength() > 0)
{
int nRes =
stoc_javadetect::JavaInfo::compareVersions(
sVersion, sTheMaxVersion);
if (nRes > 0)
return JFW_PLUGIN_E_FAILED_REQUIREMENTS;
}
if (arExcludeList > 0)
{
for (int i = 0; i < nLenList; i++)
{
rtl::OUString sExVer((rtl_uString*) arExcludeList[i]);
int nRes =
stoc_javadetect::JavaInfo::compareVersions(
sVersion, sExVer);
if (nRes == 0)
return JFW_PLUGIN_E_FAILED_REQUIREMENTS;
}
}
rtl::OUString sVendor(OUSTR("Sun Microsystems Inc."));
JavaInfo * pInfo = (JavaInfo*) rtl_allocateMemory(sizeof (JavaInfo));
pInfo->sVendor = sVendor.pData;
rtl_uString_acquire(sVendor.pData);
pInfo->sLocation = info.usJavaHome.pData;
rtl_uString_acquire(pInfo->sLocation);
pInfo->sVersion = info.getVersion().pData;
rtl_uString_acquire(pInfo->sVersion);
pInfo->nFeatures = info.supportsAccessibility() ? 1 : 0;
#ifdef UNX
pInfo->nRequirements = JFW_REQUIRE_NEEDRESTART;
#else
pInfo->nRequirements = 0l;
#endif
rtl::OUString sRuntimeLib = info.usRuntimeLib;
rtl::ByteSequence byteSeq( (sal_Int8*) sRuntimeLib.pData->buffer,
sRuntimeLib.getLength() * sizeof(sal_Unicode));
pInfo->arVendorData = byteSeq.get();
rtl_byte_sequence_acquire(pInfo->arVendorData);
*ppInfo = pInfo;
}
catch(stoc_javadetect::JavaInfo::InitException& )
{
errcode = JFW_PLUGIN_E_NO_JRE;
}
catch(stoc_javadetect::JavaInfo::MalformedVersionException& )
{
errcode = JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
}
catch(...)
{
errcode = JFW_PLUGIN_E_ERROR;
}
return errcode;
}
/** starts a Java Virtual Machine.
<p>
The function shall ensure, that the VM does not abort the process
during instantiation.
</p>
*/
extern "C"
javaPluginError startJavaVirtualMachine(
const JavaInfo *pInfo,
const JavaVMOption* arOptions,
sal_Int32 cOptions,
JavaVM ** ppVm,
JNIEnv ** ppEnv)
{
osl::MutexGuard guard(getPluginMutex());
javaPluginError errcode = JFW_PLUGIN_E_NONE;
if ( pInfo == NULL || ppVm == NULL || ppEnv == NULL)
return JFW_PLUGIN_E_INVALID_ARG;
// On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because
// libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded
// witd RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
rtl::OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
oslModule moduleRt =
osl_loadModule(sRuntimeLib.pData, SAL_LOADMODULE_DEFAULT);
#if defined(LINUX)
if ((moduleRt = osl_loadModule(sRuntimeLib.pData,
SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_NOW))
#else
if ((moduleRt = osl_loadModule(sRuntimeLib.pData, SAL_LOADMODULE_DEFAULT)) == 0)
#endif
{
OSL_ASSERT(0);
rtl::OString msg = rtl::OUStringToOString(
sRuntimeLib, osl_getThreadTextEncoding());
fprintf(stderr,"Could not load java runtime library : %s",
sRuntimeLib.getStr());
return JFW_PLUGIN_E_ERROR;
}
#ifdef UNX
rtl::OUString javaHome(RTL_CONSTASCII_USTRINGPARAM("JAVA_HOME="));
javaHome += pInfo->sLocation;
rtl::OString osJavaHome = rtl::OUStringToOString(
javaHome, osl_getThreadTextEncoding());
putenv(strdup(osJavaHome.getStr()));
#endif
typedef jint JNICALL JNI_InitArgs_Type(void *);
typedef jint JNICALL JNI_CreateVM_Type(JavaVM **, JNIEnv **, void *);
rtl::OUString sSymbolCreateJava(
RTL_CONSTASCII_USTRINGPARAM("JNI_CreateJavaVM"));
JNI_CreateVM_Type * pCreateJavaVM = (JNI_CreateVM_Type *) osl_getSymbol(
moduleRt, sSymbolCreateJava.pData);
if (!pCreateJavaVM)
{
OSL_ASSERT(0);
rtl::OString sLib = rtl::OUStringToOString(
sRuntimeLib, osl_getThreadTextEncoding());
rtl::OString sSymbol = rtl::OUStringToOString(
sSymbolCreateJava, osl_getThreadTextEncoding());
fprintf(stderr,"Java runtime library: %s does not export symbol %s !",
sLib.getStr(), sSymbol.getStr());
return JFW_PLUGIN_E_ERROR;
}
// The office sets a signal handler at startup. That causes a crash
// with java 1.3 under Solaris. To make it work, we set back the
// handler
#ifdef UNX
struct sigaction act;
act.sa_handler=SIG_DFL;
act.sa_flags= 0;
sigaction( SIGSEGV, &act, NULL);
sigaction( SIGPIPE, &act, NULL);
sigaction( SIGBUS, &act, NULL);
sigaction( SIGILL, &act, NULL);
sigaction( SIGFPE, &act, NULL);
#endif
// Some testing with Java 1.4 showed that JavaVMOption.optionString has to
// be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
JavaVMInitArgs vm_args;
boost::scoped_array<JavaVMOption> sarOptions(
new JavaVMOption[cOptions + 1]);
JavaVMOption * options = sarOptions.get();
// We set an abort handler which is called when the VM calls _exit during
// JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain
// all some directories of the Java installation. This is necessary for
// linux j2re1.3, 1.4 and Solaris j2re1.3. With a j2re1.4 on Solaris the
// LD_LIBRARY_PATH need not to be set anymore.
options[0].optionString= "abort";
options[0].extraInfo= (void* )abort_handler;
int index = 1;
for (int i = 0; i < cOptions; i++)
{
options[i+1].optionString = arOptions[i].optionString;
options[i+1].extraInfo = arOptions[i].extraInfo;
}
vm_args.version= JNI_VERSION_1_2;
vm_args.options= options;
vm_args.nOptions= cOptions + 1;
vm_args.ignoreUnrecognized= JNI_TRUE;
/* We set a global flag which is used by the abort handler in order to
determine whether it is should use longjmp to get back into this function.
That is, the abort handler determines if it is on the same stack as this function
and then jumps back into this function.
*/
g_bInGetJavaVM = 1;
jint err;
JavaVM * pJavaVM;
memset( jmp_jvm_abort, 0, sizeof(jmp_jvm_abort));
int jmpval= setjmp( jmp_jvm_abort );
/* If jmpval is not "0" then this point was reached by a longjmp in the
abort_handler, which was called indirectly by JNI_CreateVM.
*/
if( jmpval == 0)
{
//returns negative number on failure
err= pCreateJavaVM(&pJavaVM, ppEnv, &vm_args);
g_bInGetJavaVM = 0;
}
else
// set err to a positive number, so as or recognize that an abort (longjmp)
//occurred
err= 1;
if(err != 0)
{
rtl::OUString message;
if( err < 0)
{
fprintf(stderr,"Can not create Java Virtual Machine");
errcode = JFW_PLUGIN_E_ERROR;
}
else if( err > 0)
{
fprintf(stderr,"Can not create JavaVirtualMachine, abort handler was called");
errcode = JFW_PLUGIN_E_ERROR;
}
}
else
{
*ppVm = pJavaVM;
}
return errcode;
}
UDK_3_0_0 {
global:
getAllJavaInfos;
getJavaInfoByPath;
startJavaVirtualMachine;
local:
*;
};
/*************************************************************************
*
* $RCSfile: sunversion.cxx,v $
*
* $Revision: 1.1 $
*
* last change: $Author: jl $ $Date: 2004-04-19 15:36:26 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#include "sunversion.hxx"
#include "osl/thread.h"
#include "osl/process.h"
#include "osl/security.hxx"
#include <string.h>
#include <ctype.h>
using namespace rtl;
using namespace osl;
//using namespace JavaInfo;
using stoc_javadetect::SunVersion;
//using jvmaccess::JavaInfo::Impl;
namespace stoc_javadetect {
//extern OUString ::Impl::usPathDelim();
#define OUSTR( x ) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x ))
#ifdef SUNVERSION_SELFTEST
class SelfTest
{
public:
SelfTest();
} test;
#endif
SunVersion::SunVersion(): m_nUpdateSpecial(0),
m_preRelease(Rel_NONE),
m_bValid(false)
{
memset(m_arVersionParts, 0, sizeof(m_arVersionParts));
}
SunVersion::SunVersion(const rtl::OUString &usVer):
m_nUpdateSpecial(0), m_preRelease(Rel_NONE),
usVersion(usVer)
{
memset(m_arVersionParts, 0, sizeof(m_arVersionParts));
rtl::OString sVersion= rtl::OUStringToOString(usVer, osl_getThreadTextEncoding());
m_bValid = init(sVersion.getStr());
}
SunVersion::SunVersion(const char * szVer):
m_nUpdateSpecial(0), m_preRelease(Rel_NONE)
{
memset(m_arVersionParts, 0, sizeof(m_arVersionParts));
m_bValid = init(szVer);
usVersion= rtl::OUString(szVer,strlen(szVer),osl_getThreadTextEncoding());
}
/**Format major.minor.maintainance_update
*/
bool SunVersion::init(const char *szVersion)
{
if ( ! szVersion || strlen(szVersion) == 0)
return false;
//first get the major,minor,maintainance
const char * pLast = szVersion;
const char * pCur = szVersion;
//pEnd point to the position after the last character
const char * pEnd = szVersion + strlen(szVersion);
// 0 = major, 1 = minor, 2 = maintainance, 3 = update
int nPart = 0;
// position within part beginning with 0
int nPartPos = 0;
char buf[128];
//char must me a number 0 - 999 and no leading
char cCur = *pCur;
while (1)
{
if (pCur < pEnd && isdigit(*pCur))
{
if (pCur < pEnd)
pCur ++;
nPartPos ++;
}
//if correct separator then form integer
else if (
! (nPartPos == 0) // prevents: ".4.1", "..1", part must start with digit
&& (
//seperators after maintainance (1.4.1_01, 1.4.1-beta, or1.4.1
(pCur == pEnd || *pCur == '_' || *pCur == '-')
&& (nPart == 2 )
||
//separators between major-minor and minor-maintainance
(nPart < 2 && *pCur == '.') )
&& (
//prevent 1.4.0. 1.4.0-
pCur + 1 == pEnd ? isdigit(*(pCur)) : 1) )
{
int len = pCur - pLast;
if (len >= 127)
return false;
strncpy(buf, pLast, len);
buf[len] = 0;
pCur ++;
pLast = pCur;
m_arVersionParts[nPart] = atoi(buf);
nPart ++;
nPartPos = 0;
if (nPart == 3)
break;
//check next character
if (! ( (pCur < pEnd)
&& ( (nPart < 3) && isdigit(*pCur)))) //(*pCur >= 48 && *pCur <=57))))
return false;
}
else
{
return false;
}
}
if (pCur >= pEnd)
return true;
//We have now 1.4.1. This can be followed by _01, -beta, etc.
// _01 (update) According to docu must not be followed by any other
//characters, but on Solaris 9 we have a 1.4.1_01a!!
if (* (pCur - 1) == '_')
{// _01, _02
// update is the last part _01, _01a, part 0 is the digits parts and 1 the trailing alpha
int nUpdatePart = 0;
while (1)
{
if (pCur < pEnd && isdigit(*pCur))
{
if (pCur < pEnd)
pCur ++;
// nPartPos ++;
}
else if (nUpdatePart == 0 && (pCur == pEnd || isalpha(*pCur)))
{
int len = pCur - pLast;
if (len >= 127)
return false;
strncpy(buf, pLast, len);
buf[len] = 0;
m_arVersionParts[nPart] = atoi(buf);
nUpdatePart ++;
//_01a, only on character at last position
if (pCur < pEnd && isalpha(*pCur))
{
//this must be the last char
if (! (pCur + 1 == pEnd))
return false;
if (isupper(*pCur))
m_nUpdateSpecial = *pCur + 0x20; //make lowercase
else
m_nUpdateSpecial = *pCur;
}
break;
}
else
{
return false;
}
}
}
else if (*(pCur - 1) == '-')
{
if( ! strcmp(pCur,"ea"))
m_preRelease = Rel_EA;
else if( ! strcmp(pCur,"ea1"))
m_preRelease = Rel_EA1;
else if( ! strcmp(pCur,"ea2"))
m_preRelease = Rel_EA2;
else if ( ! strcmp(pCur,"beta"))
m_preRelease = Rel_BETA;
else if ( ! strcmp(pCur,"beta1"))
m_preRelease = Rel_BETA1;
else if ( ! strcmp(pCur,"beta2"))
m_preRelease = Rel_BETA2;
else if (! strcmp(pCur, "rc"))
m_preRelease = Rel_RC;
else if (! strcmp(pCur, "rc1"))
m_preRelease = Rel_RC1;
else if (! strcmp(pCur, "rc2"))
m_preRelease = Rel_RC2;
#if defined FREEBSD
// #i21615#: FreeBSD adds p[1-8] to their JDK port.
else if (! strcmp(pCur, "p8"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p7"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p6"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p5"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p4"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p3"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p2"))
m_preRelease = Rel_BETA;
else if (! strcmp(pCur, "p1"))
m_preRelease = Rel_BETA;
#endif
else
return false;
}
else
{
return false;
}
return true;
}
SunVersion::~SunVersion()
{
// delete[] strVersion;
}
/* Examples:
a) 1.0 < 1.1
b) 1.0 < 1.0.0
c) 1.0 < 1.0_00
returns false if both values are equal
*/
bool SunVersion::operator > (const SunVersion& ver) const
{
if( &ver == this)
return false;
bool ret= false;
bool bDone = false;
if (m_preRelease == ver.m_preRelease)
{
//compare major.minor.maintainance
for( int i= 0; i < 4; i ++)
{
// 1.4 > 1.3
if(m_arVersionParts[i] > ver.m_arVersionParts[i])
{
ret= true;
bDone = true;
break;
}
else if (m_arVersionParts[i] < ver.m_arVersionParts[i])
{
bDone = true;
break;
}
}
//major.minor.maintainance_update are equal. test for a trailing char
if (bDone == false
&& m_nUpdateSpecial > ver.m_nUpdateSpecial)
ret = true;
}
else if (m_preRelease == Rel_NONE && ver.m_preRelease > Rel_NONE)
{// a pre release is always minor to a relesase version:
// 1.3.1 > 1.4.0-beta
ret = true;
}
else if (m_preRelease > Rel_NONE && ver.m_preRelease == Rel_NONE)
{
ret = false;
}
else if(m_preRelease > ver.m_preRelease)
{
ret = true;
}
else
ret = false; // m_preRelease < ver.m_preRelease
return ret;
}
bool SunVersion::operator < (const SunVersion& ver) const
{
return (! operator > (ver)) && (! operator == (ver));
}
bool SunVersion::operator == (const SunVersion& ver) const
{
bool bRet= true;
for(int i= 0; i < 4; i++)
{
if( m_arVersionParts[i] != ver.m_arVersionParts[i])
{
bRet= false;
break;
}
}
bRet = m_nUpdateSpecial == ver.m_nUpdateSpecial && bRet;
bRet = m_preRelease == ver.m_preRelease && bRet;
return bRet;
}
SunVersion::operator bool()
{
return m_bValid;
}
SunVersion initVersion(const OUString& usJavaHomeArg)
{
OSL_ASSERT( usJavaHomeArg.getLength() > 0);
SunVersion ret;
//create the string to the java executable
#if defined WNT
OUString usJava(RTL_CONSTASCII_USTRINGPARAM
("java.exe"));
#else // WNT
OUString usJava(RTL_CONSTASCII_USTRINGPARAM
("java"));
#endif // WNT
usJava= usJavaHomeArg + OUSTR("/bin/") + usJava;
OUString usStartDir;
OUString argument(RTL_CONSTASCII_USTRINGPARAM("-version"));
oslProcess javaProcess= 0;
oslFileHandle fileOut= 0;
oslFileHandle fileErr= 0;
oslProcessError procErr =
osl_executeProcess_WithRedirectedIO( usJava.pData,//usExe.pData,
&argument.pData, //rtl_uString *strArguments[],
1, //sal_uInt32 nArguments,
osl_Process_HIDDEN, //oslProcessOption Options,
Security().getHandle(), //oslSecurity Security,
usStartDir.pData,//usStartDir.pData,//usWorkDir.pData, //rtl_uString *strWorkDir,
NULL, //rtl_uString *strEnvironment[],
0, // sal_uInt32 nEnvironmentVars,
&javaProcess, //oslProcess *pProcess,
NULL,//oslFileHandle *pChildInputWrite,
&fileOut,//oslFileHandle *pChildOutputRead,
&fileErr);//oslFileHandle *pChildErrorRead);
if( procErr == osl_Process_E_None)
{
const sal_Int32 BUF_SIZE= 512;
sal_Char buf[BUF_SIZE];
memset(buf, 0, BUF_SIZE);
sal_uInt64 read= 0;
TimeValue waitMax= {5 ,0};
if(osl_Process_E_None == osl_joinProcessWithTimeout(javaProcess, &waitMax))
{
//Read the output from stderr
if(osl_readFile(fileErr, &buf, BUF_SIZE, &read) == osl_File_E_None)
{
ret = getVersionFromBuf(buf, BUF_SIZE);
}
// If we have no version yet try stdout
if( ! ret)
{
if(osl_readFile(fileOut, &buf, BUF_SIZE - 1, &read) == osl_File_E_None)
{
ret = getVersionFromBuf(buf, BUF_SIZE - 1);
}
}
}
}
osl_closeFile(fileErr);
osl_closeFile(fileOut);
return ret;
}
/** java -version has an output that reads: java version "1.4.0" in the first line
@param arg
max size of buffer pBuf
*/
SunVersion getVersionFromBuf( const sal_Char *pBuf, sal_Int32 size)
{
// look for the string "version"
sal_Int32 i= rtl_str_indexOfStr_WithLength( (const sal_Char*) pBuf,
size,
RTL_CONSTASCII_STRINGPARAM(
"version"));
if(i == -1)
return SunVersion(pBuf);
sal_Char* pEnd= (sal_Char*)pBuf + size - 1;
pBuf += i + RTL_CONSTASCII_LENGTH("version");
// skip tabs an spaces
while (pBuf != pEnd && (*pBuf == '\t' || *pBuf == ' '))
++pBuf;
// next char " ? then move one forward
if (pBuf != pEnd && *pBuf == '"')
++pBuf;
// now we have the beginning of the version string.
// search for the end of the string indicated by white space or a character
// other than '.','_' or 0 ..9
sal_Char *pEndVer= (sal_Char*) pBuf;
while(pEndVer != pEnd &&
(*pEndVer != '\t'
&& *pEndVer != ' '
&& *pEndVer != '\n'
&& *pEndVer != '\"'))
pEndVer++;
// found the end, create the version string
sal_Int32 sizeVer= pEndVer - pBuf + 1;
char *szVersion= new char[sizeVer];
strncpy(szVersion, pBuf, sizeVer);
szVersion[sizeVer - 1]= 0;
SunVersion oVersion(szVersion);
delete[] szVersion;
return oVersion;
}
#ifdef SUNVERSION_SELFTEST
SelfTest::SelfTest()
{
bool bRet = true;
char * versions[] = {"1.4.0", "1.4.1", "1.0.0", "10.0.0", "10.10.0",
"10.2.2", "10.10.0", "10.10.10", "111.0.999",
"1.4.1_01", "9.90.99_09", "1.4.1_99",
"1.4.1_00a", "1.4.0_01z", "1.4.1_99A",
"1.4.1-ea", "1.4.1-beta", "1.4.1-rc1"};
char * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.",
"10.2-2", "10_10.0", "10..10","10.10", "a.0.999",
"1.4b.1_01", "9.90.-99_09", "1.4.1_99-",
"1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A",
"1.4.1-1ea"};
char * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1",
"1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a", "1.3.1_01b",
"1.3.2", "1.4.0", "2.0.0"};
size_t num = sizeof (versions) / sizeof(char*);
size_t numBad = sizeof (badVersions) / sizeof(char*);
size_t numOrdered = sizeof (orderedVer) / sizeof(char*);
//parsing test (positive)
for (int i = 0; i < num; i++)
{
SunVersion ver(versions[i]);
if ( ! ver)
{
bRet = false;
break;
}
}
OSL_ENSURE(bRet, "SunVersion selftest failed");
//Parsing test (negative)
for ( i = 0; i < numBad; i++)
{
SunVersion ver(badVersions[i]);
if (ver)
{
bRet = false;
break;
}
}
OSL_ENSURE(bRet, "SunVersion selftest failed");
// Ordering test
bRet = true;
int j = 0;
for (i = 0; i < numOrdered; i ++)
{
SunVersion curVer(orderedVer[i]);
if ( ! curVer)
{
bRet = false;
break;
}
for (j = 0; j < numOrdered; j++)
{
SunVersion compVer(orderedVer[j]);
if (i < j)
{
if ( !(curVer < compVer))
{
bRet = false;
break;
}
}
else if ( i == j)
{
if (! (curVer == compVer
&& ! (curVer > compVer)
&& ! (curVer < compVer)))
{
bRet = false;
break;
}
}
else if (i > j)
{
if ( !(curVer > compVer))
{
bRet = false;
break;
}
}
}
if ( ! bRet)
break;
}
OSL_ENSURE(bRet, "SunVersion self test failed");
}
#endif
}
/*************************************************************************
*
* $RCSfile: sunversion.hxx,v $
*
* $Revision: 1.1 $
*
* last change: $Author: jl $ $Date: 2004-04-19 15:36:59 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#if !defined INCLUDED_JVMACCESS_SUNVERSION_HXX
#define INCLUDED_JVMACCESS_SUNVERSION_HXX
#include "rtl/ustring.hxx"
namespace stoc_javadetect {
// Define SUNVERSION_SELFTEST to run a test when this lib is loaded
//#define SUNVERSION_SELFTEST
/* SunVersion is used to compare java versions based on a string, as taken
from the registry. The strings look like "1.3", "1.3.1", "1.3.1_02" etc.
Versions such as "1.4.1_01a" are allowed although this is not specified.
1.4.1_01 < 1.4.1_01a < 1.4.1_01b < 1.4.1_02
Pre - release versions, such as 1.4.1-ea, 1.4.1-beta, 1.4.1-rc are recognized,
but are treated as minor to release versions:
1.4.0 > 1.4.2-beta
Pre releases relate this way
1.4.1-ea < 1.4.1-beta < 1.4.1-rc1
An object acts as holder for the version string. That string may be present
even if the version could not be parsed. Then the version may not be compatible
to a SUN Java version.
An invalid object, that is, operator bool returns false, will always be
the lower version in a comparison. If two invalid objects are compared
then they are considered equal.
To test if the version is ok, that is this object can be compared to others,
use the bool conversion operator.
*/
class SunVersion
{
protected:
enum PreRelease
{
Rel_NONE,
Rel_EA,
Rel_EA1,
Rel_EA2,
Rel_BETA,
Rel_BETA1,
Rel_BETA2,
Rel_RC,
Rel_RC1,
Rel_RC2
};
//contains major,minor,micro,update
int m_arVersionParts[4];
// The update can be followed by a char, e.g. 1.4.1_01a
char m_nUpdateSpecial;
PreRelease m_preRelease;
public:
SunVersion();
SunVersion(const char * szVer);
SunVersion(const rtl::OUString& usVer);
~SunVersion();
bool operator > (const SunVersion& ver) const;
bool operator < (const SunVersion& ver) const;
bool operator == (const SunVersion& ver) const;
/** Test if the version is compatible tu SUN's versioning scheme
*/
operator bool ();
/** Will always contain a value if the object has been constructed with
a version string.
*/
rtl::OUString usVersion;
protected:
bool init(const char * szVer);
bool m_bValid;
};
/**
@param usJavaHome
File URL of the java installation directory.
*/
SunVersion initVersion(const rtl::OUString& usJavaHome);
SunVersion getVersionFromBuf(const sal_Char *pBuf, sal_Int32 sizeBuf);
}
#endif // INCLUDED_JVMACCESS_SUNVERSION_HXX
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment