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
SunVersion(const rtl::OUString & usVer)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 }
SunVersion(const char * szVer)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 */
init(const char * szVersion)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
getPreRelease(const char * szRelease)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
~SunVersion()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 */
operator >(const SunVersion & ver) const266 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
operator <(const SunVersion & ver) const304 bool SunVersion::operator < (const SunVersion& ver) const
305 {
306 return (! operator > (ver)) && (! operator == (ver));
307 }
308
operator ==(const SunVersion & ver) const309 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
SelfTest()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