1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_jvmfwk.hxx" 30 31 #include "sunversion.hxx" 32 #include "osl/thread.h" 33 #include "osl/process.h" 34 #include "osl/security.hxx" 35 #include <string.h> 36 #include <ctype.h> 37 #include "diagnostics.h" 38 using namespace rtl; 39 using namespace osl; 40 namespace jfw_plugin { //stoc_javadetect 41 42 43 //extern OUString ::Impl::usPathDelim(); 44 #define OUSTR( x ) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) 45 46 #if OSL_DEBUG_LEVEL >= 2 47 class SelfTest 48 { 49 public: 50 SelfTest(); 51 } test; 52 #endif 53 54 SunVersion::SunVersion(const rtl::OUString &usVer): 55 m_nUpdateSpecial(0), m_preRelease(Rel_NONE), 56 usVersion(usVer) 57 { 58 memset(m_arVersionParts, 0, sizeof(m_arVersionParts)); 59 rtl::OString sVersion= rtl::OUStringToOString(usVer, osl_getThreadTextEncoding()); 60 m_bValid = init(sVersion.getStr()); 61 } 62 SunVersion::SunVersion(const char * szVer): 63 m_nUpdateSpecial(0), m_preRelease(Rel_NONE) 64 { 65 memset(m_arVersionParts, 0, sizeof(m_arVersionParts)); 66 m_bValid = init(szVer); 67 usVersion= rtl::OUString(szVer,strlen(szVer),osl_getThreadTextEncoding()); 68 } 69 70 71 /**Format major.minor.maintainance_update 72 */ 73 bool SunVersion::init(const char *szVersion) 74 { 75 if ( ! szVersion || strlen(szVersion) == 0) 76 return false; 77 78 //first get the major,minor,maintainance 79 const char * pLast = szVersion; 80 const char * pCur = szVersion; 81 //pEnd point to the position after the last character 82 const char * pEnd = szVersion + strlen(szVersion); 83 // 0 = major, 1 = minor, 2 = maintainance, 3 = update 84 int nPart = 0; 85 // position within part beginning with 0 86 int nPartPos = 0; 87 char buf[128]; 88 89 //char must me a number 0 - 999 and no leading 90 while (1) 91 { 92 if (pCur < pEnd && isdigit(*pCur)) 93 { 94 if (pCur < pEnd) 95 pCur ++; 96 nPartPos ++; 97 } 98 //if correct separator then form integer 99 else if ( 100 ! (nPartPos == 0) // prevents: ".4.1", "..1", part must start with digit 101 && ( 102 //seperators after maintainance (1.4.1_01, 1.4.1-beta, or1.4.1 103 ((pCur == pEnd || *pCur == '_' || *pCur == '-') && (nPart == 2 )) 104 || 105 //separators between major-minor and minor-maintainance 106 (nPart < 2 && *pCur == '.') ) 107 && ( 108 //prevent 1.4.0. 1.4.0- 109 pCur + 1 == pEnd ? isdigit(*(pCur)) : 1) ) 110 { 111 int len = pCur - pLast; 112 if (len >= 127) 113 return false; 114 115 strncpy(buf, pLast, len); 116 buf[len] = 0; 117 pCur ++; 118 pLast = pCur; 119 120 m_arVersionParts[nPart] = atoi(buf); 121 nPart ++; 122 nPartPos = 0; 123 if (nPart == 3) 124 break; 125 126 //check next character 127 if (! ( (pCur < pEnd) 128 && ( (nPart < 3) && isdigit(*pCur)))) //(*pCur >= 48 && *pCur <=57)))) 129 return false; 130 } 131 else 132 { 133 return false; 134 } 135 } 136 if (pCur >= pEnd) 137 return true; 138 //We have now 1.4.1. This can be followed by _01, -beta, etc. 139 // _01 (update) According to docu must not be followed by any other 140 //characters, but on Solaris 9 we have a 1.4.1_01a!! 141 if (* (pCur - 1) == '_') 142 {// _01, _02 143 // update is the last part _01, _01a, part 0 is the digits parts and 1 the trailing alpha 144 while (1) 145 { 146 if (pCur <= pEnd) 147 { 148 if ( ! isdigit(*pCur)) 149 { 150 //1.4.1_01-, 1.4.1_01a, the numerical part may only be 2 chars. 151 int len = pCur - pLast; 152 if (len > 2) 153 return false; 154 //we've got the update: 01, 02 etc 155 strncpy(buf, pLast, len); 156 buf[len] = 0; 157 m_arVersionParts[nPart] = atoi(buf); 158 if (pCur == pEnd) 159 { 160 break; 161 } 162 if (*pCur == 'a' && (pCur + 1) == pEnd) 163 { 164 //check if it s followed by a simple "a" (not specified) 165 m_nUpdateSpecial = *pCur; 166 break; 167 } 168 else if (*pCur == '-' && pCur < pEnd) 169 { 170 //check 1.5.0_01-ea 171 PreRelease pr = getPreRelease(++pCur); 172 if (pr == Rel_NONE) 173 return false; 174 //just ignore -ea because its no official release 175 break; 176 } 177 else 178 { 179 return false; 180 } 181 } 182 if (pCur < pEnd) 183 pCur ++; 184 else 185 break; 186 } 187 } 188 } 189 // 1.4.1-ea 190 else if (*(pCur - 1) == '-') 191 { 192 m_preRelease = getPreRelease(pCur); 193 if (m_preRelease == Rel_NONE) 194 return false; 195 #if defined(FREEBSD) 196 if (m_preRelease == Rel_FreeBSD) 197 { 198 pCur++; //elemnate `p' 199 if (pCur < pEnd && isdigit(*pCur)) 200 pCur ++; 201 int len = pCur - pLast -1; //elemenate `p' 202 if (len >= 127) 203 return false; 204 strncpy(buf, (pLast+1), len); //elemenate `p' 205 buf[len] = 0; 206 m_nUpdateSpecial = atoi(buf)+100; //hack for FBSD #i56953# 207 return true; 208 } 209 #endif 210 } 211 else 212 { 213 return false; 214 } 215 return true; 216 } 217 218 SunVersion::PreRelease SunVersion::getPreRelease(const char *szRelease) 219 { 220 if (szRelease == NULL) 221 return Rel_NONE; 222 if( ! strcmp(szRelease,"ea")) 223 return Rel_EA; 224 else if( ! strcmp(szRelease,"ea1")) 225 return Rel_EA1; 226 else if( ! strcmp(szRelease,"ea2")) 227 return Rel_EA2; 228 else if( ! strcmp(szRelease,"ea3")) 229 return Rel_EA3; 230 else if ( ! strcmp(szRelease,"beta")) 231 return Rel_BETA; 232 else if ( ! strcmp(szRelease,"beta1")) 233 return Rel_BETA1; 234 else if ( ! strcmp(szRelease,"beta2")) 235 return Rel_BETA2; 236 else if ( ! strcmp(szRelease,"beta3")) 237 return Rel_BETA3; 238 else if (! strcmp(szRelease, "rc")) 239 return Rel_RC; 240 else if (! strcmp(szRelease, "rc1")) 241 return Rel_RC1; 242 else if (! strcmp(szRelease, "rc2")) 243 return Rel_RC2; 244 else if (! strcmp(szRelease, "rc3")) 245 return Rel_RC3; 246 #if defined (FREEBSD) 247 else if (! strncmp(szRelease, "p", 1)) 248 return Rel_FreeBSD; 249 #endif 250 else 251 return Rel_NONE; 252 } 253 254 SunVersion::~SunVersion() 255 { 256 257 } 258 259 /* Examples: 260 a) 1.0 < 1.1 261 b) 1.0 < 1.0.0 262 c) 1.0 < 1.0_00 263 264 returns false if both values are equal 265 */ 266 bool SunVersion::operator > (const SunVersion& ver) const 267 { 268 if( &ver == this) 269 return false; 270 271 //compare major.minor.maintainance 272 for( int i= 0; i < 4; i ++) 273 { 274 // 1.4 > 1.3 275 if(m_arVersionParts[i] > ver.m_arVersionParts[i]) 276 { 277 return true; 278 } 279 else if (m_arVersionParts[i] < ver.m_arVersionParts[i]) 280 { 281 return false; 282 } 283 } 284 //major.minor.maintainance_update are equal. test for a trailing char 285 if (m_nUpdateSpecial > ver.m_nUpdateSpecial) 286 { 287 return true; 288 } 289 290 //Until here the versions are equal 291 //compare pre -release values 292 if ((m_preRelease == Rel_NONE && ver.m_preRelease == Rel_NONE) 293 || 294 (m_preRelease != Rel_NONE && ver.m_preRelease == Rel_NONE)) 295 return false; 296 else if (m_preRelease == Rel_NONE && ver.m_preRelease != Rel_NONE) 297 return true; 298 else if (m_preRelease > ver.m_preRelease) 299 return true; 300 301 return false; 302 } 303 304 bool SunVersion::operator < (const SunVersion& ver) const 305 { 306 return (! operator > (ver)) && (! operator == (ver)); 307 } 308 309 bool SunVersion::operator == (const SunVersion& ver) const 310 { 311 bool bRet= true; 312 for(int i= 0; i < 4; i++) 313 { 314 if( m_arVersionParts[i] != ver.m_arVersionParts[i]) 315 { 316 bRet= false; 317 break; 318 } 319 } 320 bRet = m_nUpdateSpecial == ver.m_nUpdateSpecial && bRet; 321 bRet = m_preRelease == ver.m_preRelease && bRet; 322 return bRet; 323 } 324 325 SunVersion::operator bool() 326 { 327 return m_bValid; 328 } 329 330 #if OSL_DEBUG_LEVEL >= 2 331 SelfTest::SelfTest() 332 { 333 bool bRet = true; 334 335 char const * versions[] = {"1.4.0", "1.4.1", "1.0.0", "10.0.0", "10.10.0", 336 "10.2.2", "10.10.0", "10.10.10", "111.0.999", 337 "1.4.1_01", "9.90.99_09", "1.4.1_99", 338 "1.4.1_00a", 339 "1.4.1-ea", "1.4.1-beta", "1.4.1-rc1", 340 "1.5.0_01-ea", "1.5.0_01-rc2"}; 341 char const * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.", 342 "10.2-2", "10_10.0", "10..10","10.10", "a.0.999", 343 "1.4b.1_01", "9.90.-99_09", "1.4.1_99-", 344 "1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A", 345 "1.4.1-1ea", "1.5.0_010", "1.5.0._01-", "1.5.0_01-eac"}; 346 char const * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1", 347 "1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a", 348 "1.3.2", "1.4.0", "1.5.0_01-ea", "2.0.0"}; 349 350 int num = sizeof (versions) / sizeof(char*); 351 int numBad = sizeof (badVersions) / sizeof(char*); 352 int numOrdered = sizeof (orderedVer) / sizeof(char*); 353 //parsing test (positive) 354 for (int i = 0; i < num; i++) 355 { 356 SunVersion ver(versions[i]); 357 if ( ! ver) 358 { 359 bRet = false; 360 break; 361 } 362 } 363 OSL_ENSURE(bRet, "SunVersion selftest failed"); 364 //Parsing test (negative) 365 for ( int i = 0; i < numBad; i++) 366 { 367 SunVersion ver(badVersions[i]); 368 if (ver) 369 { 370 bRet = false; 371 break; 372 } 373 } 374 OSL_ENSURE(bRet, "SunVersion selftest failed"); 375 376 // Ordering test 377 bRet = true; 378 int j = 0; 379 for (int i = 0; i < numOrdered; i ++) 380 { 381 SunVersion curVer(orderedVer[i]); 382 if ( ! curVer) 383 { 384 bRet = false; 385 break; 386 } 387 for (j = 0; j < numOrdered; j++) 388 { 389 SunVersion compVer(orderedVer[j]); 390 if (i < j) 391 { 392 if ( !(curVer < compVer)) 393 { 394 bRet = false; 395 break; 396 } 397 } 398 else if ( i == j) 399 { 400 if (! (curVer == compVer 401 && ! (curVer > compVer) 402 && ! (curVer < compVer))) 403 { 404 bRet = false; 405 break; 406 } 407 } 408 else if (i > j) 409 { 410 if ( !(curVer > compVer)) 411 { 412 bRet = false; 413 break; 414 } 415 } 416 } 417 if ( ! bRet) 418 break; 419 } 420 if (bRet) 421 JFW_TRACE2("[Java framework] sunjavaplugin: Testing class SunVersion succeeded.\n"); 422 else 423 OSL_ENSURE(bRet, "[Java framework] sunjavaplugin: SunVersion self test failed.\n"); 424 } 425 #endif 426 427 } 428