xref: /trunk/main/jvmfwk/plugins/sunmajor/pluginlib/sunversion.cxx (revision 67f7bfb15893aaa2f3b1ee7ec6b966aaaad422fc)
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.maintenance_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                 //separators 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-maintenance
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 treated 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.maintenance_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