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_jvmfwk.hxx" 26 27 #include "sunversion.hxx" 28 #include "osl/thread.h" 29 #include "osl/process.h" 30 #include "osl/security.hxx" 31 #include <string.h> 32 #include <ctype.h> 33 #include "diagnostics.h" 34 using namespace rtl; 35 using namespace osl; 36 namespace jfw_plugin { //stoc_javadetect 37 38 39 //extern OUString ::Impl::usPathDelim(); 40 #define OUSTR( x ) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) 41 42 #if OSL_DEBUG_LEVEL >= 2 43 class SelfTest 44 { 45 public: 46 SelfTest(); 47 } test; 48 #endif 49 50 SunVersion::SunVersion(const rtl::OUString &usVer): 51 m_nUpdateSpecial(0), m_preRelease(Rel_NONE), 52 usVersion(usVer) 53 { 54 memset(m_arVersionParts, 0, sizeof(m_arVersionParts)); 55 rtl::OString sVersion= rtl::OUStringToOString(usVer, osl_getThreadTextEncoding()); 56 m_bValid = init(sVersion.getStr()); 57 } 58 SunVersion::SunVersion(const char * szVer): 59 m_nUpdateSpecial(0), m_preRelease(Rel_NONE) 60 { 61 memset(m_arVersionParts, 0, sizeof(m_arVersionParts)); 62 m_bValid = init(szVer); 63 usVersion= rtl::OUString(szVer,strlen(szVer),osl_getThreadTextEncoding()); 64 } 65 66 67 /**Format major.minor.maintainance_update 68 */ 69 bool SunVersion::init(const char *szVersion) 70 { 71 if ( ! szVersion || strlen(szVersion) == 0) 72 return false; 73 74 //first get the major,minor,maintainance 75 const char * pLast = szVersion; 76 const char * pCur = szVersion; 77 //pEnd point to the position after the last character 78 const char * pEnd = szVersion + strlen(szVersion); 79 // 0 = major, 1 = minor, 2 = maintainance, 3 = update 80 int nPart = 0; 81 // position within part beginning with 0 82 int nPartPos = 0; 83 char buf[128]; 84 85 //char must me a number 0 - 999 and no leading 86 while (1) 87 { 88 if (pCur < pEnd && isdigit(*pCur)) 89 { 90 if (pCur < pEnd) 91 pCur ++; 92 nPartPos ++; 93 } 94 //if correct separator then form integer 95 else if ( 96 ! (nPartPos == 0) // prevents: ".4.1", "..1", part must start with digit 97 && ( 98 //seperators after maintainance (1.4.1_01, 1.4.1-beta, or1.4.1 99 ((pCur == pEnd || *pCur == '_' || *pCur == '-') && (nPart == 2 )) 100 || 101 //separators between major-minor and minor-maintainance 102 (nPart < 2 && *pCur == '.') ) 103 && ( 104 //prevent 1.4.0. 1.4.0- 105 pCur + 1 == pEnd ? isdigit(*(pCur)) : 1) ) 106 { 107 int len = pCur - pLast; 108 if (len >= 127) 109 return false; 110 111 strncpy(buf, pLast, len); 112 buf[len] = 0; 113 pCur ++; 114 pLast = pCur; 115 116 m_arVersionParts[nPart] = atoi(buf); 117 nPart ++; 118 nPartPos = 0; 119 if (nPart == 3) 120 break; 121 122 //check next character 123 if (! ( (pCur < pEnd) 124 && ( (nPart < 3) && isdigit(*pCur)))) //(*pCur >= 48 && *pCur <=57)))) 125 return false; 126 } 127 else 128 { 129 return false; 130 } 131 } 132 if (pCur >= pEnd) 133 return true; 134 //We have now 1.4.1. This can be followed by _01, -beta, etc. 135 // _01 (update) According to docu must not be followed by any other 136 //characters, but on Solaris 9 we have a 1.4.1_01a!! 137 if (* (pCur - 1) == '_') 138 {// _01, _02 139 // update is the last part _01, _01a, part 0 is the digits parts and 1 the trailing alpha 140 while (1) 141 { 142 if (pCur <= pEnd) 143 { 144 if ( ! isdigit(*pCur)) 145 { 146 //1.4.1_01-, 1.4.1_01a, the numerical part may only be 2 chars. 147 int len = pCur - pLast; 148 if (len > 2) 149 return false; 150 //we've got the update: 01, 02 etc 151 strncpy(buf, pLast, len); 152 buf[len] = 0; 153 m_arVersionParts[nPart] = atoi(buf); 154 if (pCur == pEnd) 155 { 156 break; 157 } 158 if (*pCur == 'a' && (pCur + 1) == pEnd) 159 { 160 //check if it s followed by a simple "a" (not specified) 161 m_nUpdateSpecial = *pCur; 162 break; 163 } 164 else if (*pCur == '-' && pCur < pEnd) 165 { 166 //check 1.5.0_01-ea 167 PreRelease pr = getPreRelease(++pCur); 168 if (pr == Rel_NONE) 169 return false; 170 //just ignore -ea because its no official release 171 break; 172 } 173 else 174 { 175 return false; 176 } 177 } 178 if (pCur < pEnd) 179 pCur ++; 180 else 181 break; 182 } 183 } 184 } 185 // 1.4.1-ea 186 else if (*(pCur - 1) == '-') 187 { 188 m_preRelease = getPreRelease(pCur); 189 if (m_preRelease == Rel_NONE) 190 return false; 191 #if defined(FREEBSD) 192 if (m_preRelease == Rel_FreeBSD) 193 { 194 pCur++; //elemnate `p' 195 if (pCur < pEnd && isdigit(*pCur)) 196 pCur ++; 197 int len = pCur - pLast -1; //elemenate `p' 198 if (len >= 127) 199 return false; 200 strncpy(buf, (pLast+1), len); //elemenate `p' 201 buf[len] = 0; 202 m_nUpdateSpecial = atoi(buf)+100; //hack for FBSD #i56953# 203 return true; 204 } 205 #endif 206 } 207 else 208 { 209 return false; 210 } 211 return true; 212 } 213 214 SunVersion::PreRelease SunVersion::getPreRelease(const char *szRelease) 215 { 216 if (szRelease == NULL) 217 return Rel_NONE; 218 #ifdef OS2 219 // all prerelases codes are threated the same way (-ga1, -ga2, ...) 220 return Rel_OS2; 221 #endif 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