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 if( ! strcmp(szRelease,"ea")) 219 return Rel_EA; 220 else if( ! strcmp(szRelease,"ea1")) 221 return Rel_EA1; 222 else if( ! strcmp(szRelease,"ea2")) 223 return Rel_EA2; 224 else if( ! strcmp(szRelease,"ea3")) 225 return Rel_EA3; 226 else if ( ! strcmp(szRelease,"beta")) 227 return Rel_BETA; 228 else if ( ! strcmp(szRelease,"beta1")) 229 return Rel_BETA1; 230 else if ( ! strcmp(szRelease,"beta2")) 231 return Rel_BETA2; 232 else if ( ! strcmp(szRelease,"beta3")) 233 return Rel_BETA3; 234 else if (! strcmp(szRelease, "rc")) 235 return Rel_RC; 236 else if (! strcmp(szRelease, "rc1")) 237 return Rel_RC1; 238 else if (! strcmp(szRelease, "rc2")) 239 return Rel_RC2; 240 else if (! strcmp(szRelease, "rc3")) 241 return Rel_RC3; 242 #if defined (FREEBSD) 243 else if (! strncmp(szRelease, "p", 1)) 244 return Rel_FreeBSD; 245 #endif 246 else 247 return Rel_NONE; 248 } 249 250 SunVersion::~SunVersion() 251 { 252 253 } 254 255 /* Examples: 256 a) 1.0 < 1.1 257 b) 1.0 < 1.0.0 258 c) 1.0 < 1.0_00 259 260 returns false if both values are equal 261 */ 262 bool SunVersion::operator > (const SunVersion& ver) const 263 { 264 if( &ver == this) 265 return false; 266 267 //compare major.minor.maintainance 268 for( int i= 0; i < 4; i ++) 269 { 270 // 1.4 > 1.3 271 if(m_arVersionParts[i] > ver.m_arVersionParts[i]) 272 { 273 return true; 274 } 275 else if (m_arVersionParts[i] < ver.m_arVersionParts[i]) 276 { 277 return false; 278 } 279 } 280 //major.minor.maintainance_update are equal. test for a trailing char 281 if (m_nUpdateSpecial > ver.m_nUpdateSpecial) 282 { 283 return true; 284 } 285 286 //Until here the versions are equal 287 //compare pre -release values 288 if ((m_preRelease == Rel_NONE && ver.m_preRelease == Rel_NONE) 289 || 290 (m_preRelease != Rel_NONE && ver.m_preRelease == Rel_NONE)) 291 return false; 292 else if (m_preRelease == Rel_NONE && ver.m_preRelease != Rel_NONE) 293 return true; 294 else if (m_preRelease > ver.m_preRelease) 295 return true; 296 297 return false; 298 } 299 300 bool SunVersion::operator < (const SunVersion& ver) const 301 { 302 return (! operator > (ver)) && (! operator == (ver)); 303 } 304 305 bool SunVersion::operator == (const SunVersion& ver) const 306 { 307 bool bRet= true; 308 for(int i= 0; i < 4; i++) 309 { 310 if( m_arVersionParts[i] != ver.m_arVersionParts[i]) 311 { 312 bRet= false; 313 break; 314 } 315 } 316 bRet = m_nUpdateSpecial == ver.m_nUpdateSpecial && bRet; 317 bRet = m_preRelease == ver.m_preRelease && bRet; 318 return bRet; 319 } 320 321 SunVersion::operator bool() 322 { 323 return m_bValid; 324 } 325 326 #if OSL_DEBUG_LEVEL >= 2 327 SelfTest::SelfTest() 328 { 329 bool bRet = true; 330 331 char const * versions[] = {"1.4.0", "1.4.1", "1.0.0", "10.0.0", "10.10.0", 332 "10.2.2", "10.10.0", "10.10.10", "111.0.999", 333 "1.4.1_01", "9.90.99_09", "1.4.1_99", 334 "1.4.1_00a", 335 "1.4.1-ea", "1.4.1-beta", "1.4.1-rc1", 336 "1.5.0_01-ea", "1.5.0_01-rc2"}; 337 char const * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.", 338 "10.2-2", "10_10.0", "10..10","10.10", "a.0.999", 339 "1.4b.1_01", "9.90.-99_09", "1.4.1_99-", 340 "1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A", 341 "1.4.1-1ea", "1.5.0_010", "1.5.0._01-", "1.5.0_01-eac"}; 342 char const * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1", 343 "1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a", 344 "1.3.2", "1.4.0", "1.5.0_01-ea", "2.0.0"}; 345 346 int num = sizeof (versions) / sizeof(char*); 347 int numBad = sizeof (badVersions) / sizeof(char*); 348 int numOrdered = sizeof (orderedVer) / sizeof(char*); 349 //parsing test (positive) 350 for (int i = 0; i < num; i++) 351 { 352 SunVersion ver(versions[i]); 353 if ( ! ver) 354 { 355 bRet = false; 356 break; 357 } 358 } 359 OSL_ENSURE(bRet, "SunVersion selftest failed"); 360 //Parsing test (negative) 361 for ( int i = 0; i < numBad; i++) 362 { 363 SunVersion ver(badVersions[i]); 364 if (ver) 365 { 366 bRet = false; 367 break; 368 } 369 } 370 OSL_ENSURE(bRet, "SunVersion selftest failed"); 371 372 // Ordering test 373 bRet = true; 374 int j = 0; 375 for (int i = 0; i < numOrdered; i ++) 376 { 377 SunVersion curVer(orderedVer[i]); 378 if ( ! curVer) 379 { 380 bRet = false; 381 break; 382 } 383 for (j = 0; j < numOrdered; j++) 384 { 385 SunVersion compVer(orderedVer[j]); 386 if (i < j) 387 { 388 if ( !(curVer < compVer)) 389 { 390 bRet = false; 391 break; 392 } 393 } 394 else if ( i == j) 395 { 396 if (! (curVer == compVer 397 && ! (curVer > compVer) 398 && ! (curVer < compVer))) 399 { 400 bRet = false; 401 break; 402 } 403 } 404 else if (i > j) 405 { 406 if ( !(curVer > compVer)) 407 { 408 bRet = false; 409 break; 410 } 411 } 412 } 413 if ( ! bRet) 414 break; 415 } 416 if (bRet) 417 JFW_TRACE2("[Java framework] sunjavaplugin: Testing class SunVersion succeeded.\n"); 418 else 419 OSL_ENSURE(bRet, "[Java framework] sunjavaplugin: SunVersion self test failed.\n"); 420 } 421 #endif 422 423 } 424