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_plugin.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,maintenance 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 = maintenance, 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 maintenance (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 //1.7.0_161, 1.8.0_162, it's as long as 3 chars in later Java version. 148 int len = pCur - pLast; 149 if (len > 3) 150 return false; 151 //we've got the update: 01, 02 etc 152 strncpy(buf, pLast, len); 153 buf[len] = 0; 154 m_arVersionParts[nPart] = atoi(buf); 155 if (pCur == pEnd) 156 { 157 break; 158 } 159 if (*pCur == 'a' && (pCur + 1) == pEnd) 160 { 161 //check if it s followed by a simple "a" (not specified) 162 m_nUpdateSpecial = *pCur; 163 break; 164 } 165 else if (*pCur == '-' && pCur < pEnd) 166 { 167 //check 1.5.0_01-ea 168 PreRelease pr = getPreRelease(++pCur); 169 if (pr == Rel_NONE) 170 return false; 171 //just ignore -ea because its no official release 172 break; 173 } 174 else 175 { 176 return false; 177 } 178 } 179 if (pCur < pEnd) 180 pCur ++; 181 else 182 break; 183 } 184 } 185 } 186 // 1.4.1-ea 187 else if (*(pCur - 1) == '-') 188 { 189 m_preRelease = getPreRelease(pCur); 190 if (m_preRelease == Rel_NONE) 191 return false; 192 #if defined(FREEBSD) 193 if (m_preRelease == Rel_FreeBSD) 194 { 195 pCur++; //elemnate `p' 196 if (pCur < pEnd && isdigit(*pCur)) 197 pCur ++; 198 int len = pCur - pLast -1; //elemenate `p' 199 if (len >= 127) 200 return false; 201 strncpy(buf, (pLast+1), len); //elemenate `p' 202 buf[len] = 0; 203 m_nUpdateSpecial = atoi(buf)+100; //hack for FBSD #i56953# 204 return true; 205 } 206 #endif 207 } 208 else 209 { 210 return false; 211 } 212 return true; 213 } 214 215 SunVersion::PreRelease SunVersion::getPreRelease(const char *szRelease) 216 { 217 if (szRelease == NULL) 218 return Rel_NONE; 219 #ifdef OS2 220 // all prerelases codes are threated the same way (-ga1, -ga2, ...) 221 return Rel_OS2; 222 #endif 223 if( ! strcmp(szRelease,"ea")) 224 return Rel_EA; 225 else if( ! strcmp(szRelease,"ea1")) 226 return Rel_EA1; 227 else if( ! strcmp(szRelease,"ea2")) 228 return Rel_EA2; 229 else if( ! strcmp(szRelease,"ea3")) 230 return Rel_EA3; 231 else if ( ! strcmp(szRelease,"beta")) 232 return Rel_BETA; 233 else if ( ! strcmp(szRelease,"beta1")) 234 return Rel_BETA1; 235 else if ( ! strcmp(szRelease,"beta2")) 236 return Rel_BETA2; 237 else if ( ! strcmp(szRelease,"beta3")) 238 return Rel_BETA3; 239 else if (! strcmp(szRelease, "rc")) 240 return Rel_RC; 241 else if (! strcmp(szRelease, "rc1")) 242 return Rel_RC1; 243 else if (! strcmp(szRelease, "rc2")) 244 return Rel_RC2; 245 else if (! strcmp(szRelease, "rc3")) 246 return Rel_RC3; 247 #if defined (FREEBSD) 248 else if (! strncmp(szRelease, "p", 1)) 249 return Rel_FreeBSD; 250 #endif 251 else 252 return Rel_NONE; 253 } 254 255 SunVersion::~SunVersion() 256 { 257 258 } 259 260 /* Examples: 261 a) 1.0 < 1.1 262 b) 1.0 < 1.0.0 263 c) 1.0 < 1.0_00 264 265 returns false if both values are equal 266 */ 267 bool SunVersion::operator > (const SunVersion& ver) const 268 { 269 if( &ver == this) 270 return false; 271 272 //compare major.minor.maintenance 273 for( int i= 0; i < 4; i ++) 274 { 275 // 1.4 > 1.3 276 if(m_arVersionParts[i] > ver.m_arVersionParts[i]) 277 { 278 return true; 279 } 280 else if (m_arVersionParts[i] < ver.m_arVersionParts[i]) 281 { 282 return false; 283 } 284 } 285 //major.minor.maintainance_update are equal. test for a trailing char 286 if (m_nUpdateSpecial > ver.m_nUpdateSpecial) 287 { 288 return true; 289 } 290 291 //Until here the versions are equal 292 //compare pre -release values 293 if ((m_preRelease == Rel_NONE && ver.m_preRelease == Rel_NONE) 294 || 295 (m_preRelease != Rel_NONE && ver.m_preRelease == Rel_NONE)) 296 return false; 297 else if (m_preRelease == Rel_NONE && ver.m_preRelease != Rel_NONE) 298 return true; 299 else if (m_preRelease > ver.m_preRelease) 300 return true; 301 302 return false; 303 } 304 305 bool SunVersion::operator < (const SunVersion& ver) const 306 { 307 return (! operator > (ver)) && (! operator == (ver)); 308 } 309 310 bool SunVersion::operator == (const SunVersion& ver) const 311 { 312 bool bRet= true; 313 for(int i= 0; i < 4; i++) 314 { 315 if( m_arVersionParts[i] != ver.m_arVersionParts[i]) 316 { 317 bRet= false; 318 break; 319 } 320 } 321 bRet = m_nUpdateSpecial == ver.m_nUpdateSpecial && bRet; 322 bRet = m_preRelease == ver.m_preRelease && bRet; 323 return bRet; 324 } 325 326 SunVersion::operator bool() 327 { 328 return m_bValid; 329 } 330 331 #if OSL_DEBUG_LEVEL >= 2 332 SelfTest::SelfTest() 333 { 334 bool bRet = true; 335 336 char const * versions[] = {"1.4.0", "1.4.1", "1.0.0", "10.0.0", "10.10.0", 337 "10.2.2", "10.10.0", "10.10.10", "111.0.999", 338 "1.4.1_01", "9.90.99_09", "1.4.1_99", 339 "1.4.1_00a", 340 "1.4.1-ea", "1.4.1-beta", "1.4.1-rc1", 341 "1.5.0_01-ea", "1.5.0_01-rc2", 342 "1.7.0_161"}; 343 char const * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.", 344 "10.2-2", "10_10.0", "10..10","10.10", "a.0.999", 345 "1.4b.1_01", "9.90.-99_09", "1.4.1_99-", 346 "1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A", 347 // "1.5.0_010" is now valid 348 // "1.4.1-1ea", "1.5.0_010", "1.5.0._01-", "1.5.0_01-eac"}; 349 "1.4.1-1ea", "1.8.0_0100", "1.5.0._01-", "1.5.0_01-eac"}; 350 char const * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1", 351 "1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a", 352 "1.3.2", "1.4.0", "1.5.0_01-ea", "2.0.0"}; 353 354 int num = sizeof (versions) / sizeof(char*); 355 int numBad = sizeof (badVersions) / sizeof(char*); 356 int numOrdered = sizeof (orderedVer) / sizeof(char*); 357 //parsing test (positive) 358 for (int i = 0; i < num; i++) 359 { 360 SunVersion ver(versions[i]); 361 if ( ! ver) 362 { 363 bRet = false; 364 break; 365 } 366 } 367 OSL_ENSURE(bRet, "SunVersion selftest failed"); 368 //Parsing test (negative) 369 for ( int i = 0; i < numBad; i++) 370 { 371 SunVersion ver(badVersions[i]); 372 if (ver) 373 { 374 bRet = false; 375 break; 376 } 377 } 378 OSL_ENSURE(bRet, "SunVersion selftest failed"); 379 380 // Ordering test 381 bRet = true; 382 int j = 0; 383 for (int i = 0; i < numOrdered; i ++) 384 { 385 SunVersion curVer(orderedVer[i]); 386 if ( ! curVer) 387 { 388 bRet = false; 389 break; 390 } 391 for (j = 0; j < numOrdered; j++) 392 { 393 SunVersion compVer(orderedVer[j]); 394 if (i < j) 395 { 396 if ( !(curVer < compVer)) 397 { 398 bRet = false; 399 break; 400 } 401 } 402 else if ( i == j) 403 { 404 if (! (curVer == compVer 405 && ! (curVer > compVer) 406 && ! (curVer < compVer))) 407 { 408 bRet = false; 409 break; 410 } 411 } 412 else if (i > j) 413 { 414 if ( !(curVer > compVer)) 415 { 416 bRet = false; 417 break; 418 } 419 } 420 } 421 if ( ! bRet) 422 break; 423 } 424 if (bRet) 425 JFW_TRACE2("[Java framework] sunjavaplugin: Testing class SunVersion succeeded.\n"); 426 else 427 OSL_ENSURE(bRet, "[Java framework] sunjavaplugin: SunVersion self test failed.\n"); 428 } 429 #endif 430 431 } 432