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
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,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
getPreRelease(const char * szRelease)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
~SunVersion()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 */
operator >(const SunVersion & ver) const267 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
operator <(const SunVersion & ver) const305 bool SunVersion::operator < (const SunVersion& ver) const
306 {
307 return (! operator > (ver)) && (! operator == (ver));
308 }
309
operator ==(const SunVersion & ver) const310 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
SelfTest()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 char const * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.",
343 "10.2-2", "10_10.0", "10..10","10.10", "a.0.999",
344 "1.4b.1_01", "9.90.-99_09", "1.4.1_99-",
345 "1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A",
346 "1.4.1-1ea", "1.5.0_010", "1.5.0._01-", "1.5.0_01-eac"};
347 char const * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1",
348 "1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a",
349 "1.3.2", "1.4.0", "1.5.0_01-ea", "2.0.0"};
350
351 int num = sizeof (versions) / sizeof(char*);
352 int numBad = sizeof (badVersions) / sizeof(char*);
353 int numOrdered = sizeof (orderedVer) / sizeof(char*);
354 //parsing test (positive)
355 for (int i = 0; i < num; i++)
356 {
357 SunVersion ver(versions[i]);
358 if ( ! ver)
359 {
360 bRet = false;
361 break;
362 }
363 }
364 OSL_ENSURE(bRet, "SunVersion selftest failed");
365 //Parsing test (negative)
366 for ( int i = 0; i < numBad; i++)
367 {
368 SunVersion ver(badVersions[i]);
369 if (ver)
370 {
371 bRet = false;
372 break;
373 }
374 }
375 OSL_ENSURE(bRet, "SunVersion selftest failed");
376
377 // Ordering test
378 bRet = true;
379 int j = 0;
380 for (int i = 0; i < numOrdered; i ++)
381 {
382 SunVersion curVer(orderedVer[i]);
383 if ( ! curVer)
384 {
385 bRet = false;
386 break;
387 }
388 for (j = 0; j < numOrdered; j++)
389 {
390 SunVersion compVer(orderedVer[j]);
391 if (i < j)
392 {
393 if ( !(curVer < compVer))
394 {
395 bRet = false;
396 break;
397 }
398 }
399 else if ( i == j)
400 {
401 if (! (curVer == compVer
402 && ! (curVer > compVer)
403 && ! (curVer < compVer)))
404 {
405 bRet = false;
406 break;
407 }
408 }
409 else if (i > j)
410 {
411 if ( !(curVer > compVer))
412 {
413 bRet = false;
414 break;
415 }
416 }
417 }
418 if ( ! bRet)
419 break;
420 }
421 if (bRet)
422 JFW_TRACE2("[Java framework] sunjavaplugin: Testing class SunVersion succeeded.\n");
423 else
424 OSL_ENSURE(bRet, "[Java framework] sunjavaplugin: SunVersion self test failed.\n");
425 }
426 #endif
427
428 }
429