EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.iapi.services.info]

COVERAGE SUMMARY FOR SOURCE FILE [ProductVersionHolder.java]

nameclass, %method, %block, %line, %
ProductVersionHolder.java100% (1/1)77%  (20/26)67%  (358/535)66%  (92.4/140)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ProductVersionHolder100% (1/1)77%  (20/26)67%  (358/535)66%  (92.4/140)
ProductVersionHolder (): void 0%   (0/1)0%   (0/18)0%   (0/7)
ProductVersionHolder (String, String, String, int, int, int, int, String, Boo... 100% (1/1)100% (54/54)100% (19/19)
fullVersionString (int, int, int, boolean, String): String 100% (1/1)71%  (68/96)73%  (19.8/27)
getBuildNumber (): String 100% (1/1)100% (3/3)100% (1/1)
getBuildNumberAsInt (): int 100% (1/1)76%  (38/50)62%  (10/16)
getDrdaMaintVersion (): int 100% (1/1)100% (3/3)100% (1/1)
getFixPackVersion (): int 0%   (0/1)0%   (0/5)0%   (0/1)
getMaintVersion (): int 100% (1/1)100% (3/3)100% (1/1)
getMajorVersion (): int 100% (1/1)100% (3/3)100% (1/1)
getMinorVersion (): int 100% (1/1)100% (3/3)100% (1/1)
getProductName (): String 100% (1/1)100% (3/3)100% (1/1)
getProductTechnologyName (): String 100% (1/1)100% (3/3)100% (1/1)
getProductVendorName (): String 100% (1/1)100% (3/3)100% (1/1)
getProductVersionHolder (Properties): ProductVersionHolder 100% (1/1)100% (52/52)100% (10/10)
getProductVersionHolder (String, String, String, int, int, int, int, String, ... 100% (1/1)100% (15/15)100% (2/2)
getProductVersionHolderFromMyEnv (InputStream): ProductVersionHolder 100% (1/1)33%  (15/46)35%  (4.6/13)
getProductVersionHolderFromMyEnv (String): ProductVersionHolder 0%   (0/1)0%   (0/18)0%   (0/6)
getSimpleVersionString (): String 100% (1/1)100% (8/8)100% (1/1)
getVersionBuildString (boolean): String 100% (1/1)100% (16/16)100% (1/1)
isAlpha (): boolean 0%   (0/1)0%   (0/17)0%   (0/1)
isBeta (): boolean 100% (1/1)100% (4/4)100% (1/1)
loadProperties (String): Properties 0%   (0/1)0%   (0/32)0%   (0/9)
parseInt (String): int 100% (1/1)80%  (12/15)79%  (5.5/7)
run (): Object 0%   (0/1)0%   (0/5)0%   (0/1)
simpleVersionString (int, int, boolean): String 100% (1/1)72%  (21/29)75%  (6/8)
toString (): String 100% (1/1)100% (31/31)100% (7/7)

1/*
2 
3   Derby - Class org.apache.derby.iapi.services.info.ProductVersionHolder
4 
5   Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   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, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19*/
20 
21package org.apache.derby.iapi.services.info;
22 
23import java.io.InputStream;
24import java.io.IOException;
25import java.util.Properties;
26 
27 
28/**
29  Class to hold a cloudscape Product version.
30 
31  This class includes the following product version features.
32 
33  <OL>
34  <LI>Save the product version information this holds as a String. We call
35      the string a 'product version string'.
36  <LI>Construct a ProductVersionHolder from a valid 'product version string'.
37  <LI>Determine if two product versions are feature compatible. This means
38      products of these versions may interoperate with ***NO*** compatibility
39          problems.
40  <LI>Determine if two product versions are the same. This is a stronger
41      test than the test for feature compatibility.
42  </OL>
43 
44 
45 
46  Cloudscape 5.1 and older versions used the majorVersion, minorVersion, maintVersion versions
47  directly. That is a three part version number, majorVersion.minorVersion.maintVersion, e.g. 5.1.21.
48 
49  For Cloudscape 5.2 onwards a four part name is required.
50        majorVersion.minorVersion.fixPack.bugVersion e.g. 5.2.1.2
51 
52        This follows the IBM standard and allows us to state that a fix pack will be 5.2.3 without worrying
53        about how many maintence fixes there are between fix packs.
54 
55        We implement this using the existing format of ProductVersionHolder to reduce disruption to the
56        code, however we make the maintVersion encode the {fixPack.bugVersion}. Since the maintVersion
57        is represented by a int (2G values) we have plenty of room for encoding. If we assign a given
58        majorVersion.minorVersion.fixPack a 10 year life, then we about the maximum number of individual releases
59        it can have is 10 years * 365 days/year = 3650. Thus with the pre 5.2 scheme we would not expect a 
60        5.1.x to have an x > 3650 (approximately). Usually the rate of point releases has been much less than
61        one per day, 5.1.31 is released about 225 days after GA which makes around a point release every 7 days.
62        But in the encoding we need to be conservative. With fix packs the maximum is about 2 per year and fix
63        packs are only made to the current release, thus with a yearly minor release cycle we would imagine
64        only 2 fixpacks per major.minor. However like other IBM products or release cycle may be extended thus
65        we can expect up to a handful of fix packs.
66 
67        Thus we might imagine releases like
68 
69        5.2.0.12
70        5.2.0.234
71        5.2.1.34
72        5.2.4.2445
73 
74  but highly unlikey to have
75 
76        5.2.2.59321
77        5.2.23.1
78        
79 
80    The encoding number must continue to increase so that the
81        
82                encodedMaintB > encodedMaintA
83 
84                if (fixPackB > fixPackA) || ((fixPackB == fixPackA) && (bugB > bugA))
85 
86 
87        Selected encoding
88 
89        encodedMaint = (fixPack * 1,000,000) + (bugVersion);
90 
91        Handles many many fixpacks and upto one million bug fixes per fix pack and remains somewhat human readable.
92 
93        Special fix packs
94 
95        fixpack == 0 = alpha (version off main codeline)
96        fixpack == 1 = first release of major.minor (may be marked with beta)
97        fixpack == 2 = first fix pack (displayed as 1)
98     
99 
100        The drdaMaintVersion is sent in the Network Server PRDID. It never displays
101    but may be used by the client for version specific behaviour. It should be 
102        reset to 0 with each minor release.        
103 
104  The product version string has the form:
105  <PRE>
106  productVendorName - ProductName - majorVersion.minorVersion.maintVersion [beta] - (buildNumber)
107 
108  </PRE>
109 
110  */
111public final class ProductVersionHolder implements java.security.PrivilegedAction
112{
113 
114        //
115        //Used as an invalid value for numbers. This works because all
116        //the numbers in a product version must be non-negative.
117        private static final int BAD_NUMBER = -1;
118        private static final String ALPHA = "alpha";
119        private static final String BETA = "beta";
120 
121        private final static int        MAINT_ENCODING = 1000000;
122        
123        private String productVendorName;
124        private String productName;
125        private String productTechnologyName;
126        private int majorVersion = BAD_NUMBER;
127        private int minorVersion = BAD_NUMBER;
128        private int maintVersion = BAD_NUMBER;
129        private int drdaMaintVersion = BAD_NUMBER;
130        private String buildNumber = "????";
131        private Boolean isBeta;
132 
133        private ProductVersionHolder() {
134        }
135        
136        /**
137          Create a ProductVersionHolder
138 
139          <P>Please see the documentation for the varient of getProductVesionHolder
140          that takes the same parameters as this for a description of the parameters.
141          */
142        private ProductVersionHolder(String productVendorName,
143                                                                 String productName,
144                                                                 String productTechnologyName,
145                                                                 int majorVersion,
146                                                                 int minorVersion,
147                                                                 int maintVersion,
148                                                                 int drdaMaintVersion,
149                                                                 String buildNumber,
150                                                                 Boolean isBeta)
151        {
152                if (productVendorName != null)
153                        this.productVendorName = productVendorName.trim();
154                if (productName != null)
155                        this.productName = productName.trim();
156                if (productTechnologyName != null)
157                        this.productTechnologyName = productTechnologyName.trim();
158                this.majorVersion = majorVersion;
159                this.minorVersion = minorVersion;
160                this.maintVersion = maintVersion;
161                this.drdaMaintVersion = drdaMaintVersion;
162                this.buildNumber = buildNumber;
163                this.isBeta = isBeta;
164        }
165 
166        /**
167          Create a valid ProductVersionHolder. If any of the
168          parameters provided is invalid, this returns null.
169          @param productName The name of the product. productName.length()
170          must be greater than 0. The syntax for a product name is
171          'productGenus[:productSpecies]'. 
172          @param majorVersion The most significant portion of a 3 
173          part product version.  Must be non-negative.
174          @param minorVersion The second portion of a 3 part 
175          product version. Must be non-negative.
176          @param maintVersion The least significant portion of a 3 part
177          product version. Must be non-negative.
178          @param drdaMaintVersion The protocol modification number for minor release.
179          @param buildNumber The buildNumber for a product. 
180          @param isBeta true iff the product is beta.
181          @return A valid ProductVersionHolder of null if any of the parameters
182          provided are not valid.
183          */
184        public static ProductVersionHolder
185        getProductVersionHolder(
186                                                   String productVendorName,
187                                                   String productName,
188                                                   String productTechnologyName,
189                                                   int majorVersion,
190                                                   int minorVersion,
191                                                   int maintVersion,
192                                                   int drdaMaintVersion,
193                                                   String buildNumber,
194                                                   Boolean isBeta)
195        {
196                ProductVersionHolder pvh =
197                        new ProductVersionHolder(productVendorName,
198                                                                         productName,
199                                                                         productTechnologyName,
200                                                                         majorVersion,
201                                                                         minorVersion,
202                                                                         maintVersion,
203                                                                         drdaMaintVersion,
204                                                                         buildNumber,
205                                                                         isBeta);
206                return pvh;
207        }
208        
209        /**
210          Get a ProductVersionHolder for a product of a given genus,
211          that is available in the caller's environment. 
212          Even though this uses a priv bock, it may stil fail when
213          the jar the version is being fetched from, is different to the
214          one that loaded this class, AND the jars are in different security contexts.
215 
216          @param productGenus The genus for the product.
217          @return The ProductVersionHolder or null if
218          a product with the given genus is not available in the
219          caller's environment.
220          */
221        public static ProductVersionHolder
222        getProductVersionHolderFromMyEnv(String productGenus)
223        {
224 
225                ProductVersionHolder tempPVH = new ProductVersionHolder();
226 
227                tempPVH.productGenus = productGenus;
228                Properties p = (Properties) java.security.AccessController.doPrivileged(tempPVH);
229 
230                if (p == null)
231                        return null;
232 
233                return getProductVersionHolder(p);
234        }
235 
236 
237        /**
238                Load the version info from the already opened properties files.
239                We need to do this because if the jar files (e.g. db2jtools and db2j)
240                are in different security contexts (entries in the policy files) then
241                we cannot load the version information for one of them correctly.
242                This is because the this class will either have been loaded from
243                only one of the jars and hence can only access the resource in its own jar.
244                By making code specific to the jar open the resource we are guaranteed it will work.
245        */
246        public static ProductVersionHolder
247        getProductVersionHolderFromMyEnv(InputStream propertiesStream)
248        {
249 
250                if (propertiesStream == null)
251                        return null;
252 
253                Properties p = new Properties();
254                try {
255                        p.load(propertiesStream);
256                }
257                catch (IOException ioe) {
258 
259                        System.out.println("IOE " + ioe.getMessage());
260                        //
261                        //This case is a bit ugly. If we get an IOException, we return
262                        //null. Though this correctly reflects that the product is not
263                        //available for use, it may be confusing to users that we swallow
264                        //the IO error here.
265                        return null;
266                } finally {
267                        try {
268                                propertiesStream.close();
269                        } catch (IOException ioe2) {
270                        }
271                }
272 
273                return getProductVersionHolder(p);
274        }
275 
276        /**
277          Get a ProductVersionHolder based on the information in
278          the Properties object provided.
279 
280          @param p The properties object that holds the productVersion
281          information.
282          @return The ProductVersionHolder or null if
283          a product with the given genus is not available in the
284          caller's environment.
285          */
286        public static ProductVersionHolder
287        getProductVersionHolder(Properties p)
288        {
289                String pvn = p.getProperty(PropertyNames.PRODUCT_VENDOR_NAME);
290                String pn = p.getProperty(PropertyNames.PRODUCT_EXTERNAL_NAME);
291                String ptn = p.getProperty(PropertyNames.PRODUCT_TECHNOLOGY_NAME);
292                int v1 = parseInt(p.getProperty(PropertyNames.PRODUCT_MAJOR_VERSION));
293                int v2 = parseInt(p.getProperty(PropertyNames.PRODUCT_MINOR_VERSION));
294                int v3 = parseInt(p.getProperty(PropertyNames.PRODUCT_MAINT_VERSION));
295                int v4 = parseInt(p.getProperty(PropertyNames.PRODUCT_DRDA_MAINT_VERSION));
296                String bn = p.getProperty(PropertyNames.PRODUCT_BUILD_NUMBER);
297                Boolean isBeta =
298                        Boolean.valueOf(p.getProperty(PropertyNames.PRODUCT_BETA_VERSION));
299                return         getProductVersionHolder(pvn,pn,ptn,v1,v2,v3,v4,bn,isBeta);
300        }
301 
302 
303        /**
304          Return the product vendor name.
305          */
306        public String getProductVendorName()
307        {
308                return productVendorName;
309        }
310 
311 
312        /**
313          Return the external product name.
314          */
315        public String getProductName()
316        {
317                return productName;
318        }
319        public String getProductTechnologyName()
320        {
321                return productTechnologyName;
322        }
323 
324        /**
325          Return the major version number.
326          */
327        public int getMajorVersion() {return majorVersion;}
328        /**
329          Return the minor version number.
330          */
331        public int getMinorVersion() {return minorVersion;}
332        /**
333          Return the <B>encoded</B> maintainence version number.
334          */
335        public int getMaintVersion() {return maintVersion;}
336 
337        /** 
338                Return the drda protocol maintenance version for this minor release.
339                Starts at 0 for each minor release and only incremented 
340                when client behaviour changes based on the server version.
341        **/
342        public int getDrdaMaintVersion() {return drdaMaintVersion; }
343 
344        /**
345                Return the fix pack version from the maintence encoding.
346        */
347        public int getFixPackVersion() { return maintVersion / MAINT_ENCODING; }
348 
349 
350        /**
351          Return true if this is a beta product.
352          */
353        public boolean isBeta() {return isBeta.booleanValue();}
354        /**
355          Return true if this is a alpha product.
356          */
357        public boolean isAlpha() {
358                return           (majorVersion >= 5)
359                                && (minorVersion > 2)
360                                && ((maintVersion / MAINT_ENCODING) == 0);
361        }
362        /**
363          Return the build number for this product.
364          */
365        public String getBuildNumber() {return buildNumber;}
366 
367    /**
368     * Return the build number as an integer if possible,
369     * mapping from the SVN number.
370     * nnnnn -> returns nnnnn
371     * nnnnnM -> returns -nnnnn indicates a modified code base
372     * nnnnn:mmmmm -> returns -nnnnn
373     * anything else -> returns -1
374    */
375    public int getBuildNumberAsInt(){
376            if (buildNumber == null)
377                return -1;
378            boolean dubiousCode = false;
379            int offset = buildNumber.indexOf('M');
380            if (offset == -1)
381                offset = buildNumber.indexOf(':');
382            else
383                dubiousCode = true;
384            if (offset == -1)
385                    offset = buildNumber.length();
386        else
387            dubiousCode = true;
388            
389            try {
390                    int bnai = Integer.parseInt(buildNumber.substring(0, offset));
391                    if (dubiousCode)
392                        bnai = -bnai;
393                    return bnai;
394            } catch (NumberFormatException nfe) 
395             {
396                     return -1;
397            }
398    }
399 
400        /**
401          Parse a string containing a non-negative integer. Return
402          a negative integer is the String is invalid.
403 
404          @param s A string with a non-negative integer (a sequence
405          of decimal digits.)
406          @return the integer or a negative number if s is invalid.
407          */
408        private static int parseInt(String s)
409        {
410                //System.out.println("Parsing integer: "+s);                
411                int result = BAD_NUMBER;
412                try
413                        {
414                                if (s!=null)
415                                        result = Integer.parseInt(s);
416                        }
417                catch (NumberFormatException nfe)
418                        {}
419 
420                if (result < 0) result = BAD_NUMBER;
421                return result;
422        }
423 
424        /**
425          Return  a string representation of this ProductVersion. The
426          difference between this and createProductVersionString, is
427          that this method retruns a String when this ProductVersionHolder
428          holds invalid version information.
429         */
430        public String toString()
431        {
432                StringBuffer sb = new StringBuffer();
433                sb.append(getProductVendorName());
434                sb.append(" - ");
435                sb.append(getProductName());
436                sb.append(" - ");
437                sb.append(getVersionBuildString(true));
438                return sb.toString();
439        }
440 
441        /**
442                Return the feature version string, ie. major.minor. (e.g. 5.2)
443        */
444        public String getSimpleVersionString() {
445 
446                return ProductVersionHolder.simpleVersionString(majorVersion, minorVersion, isBeta());
447        }
448 
449        /**
450                Convert a major and minor number with beta status into a string.
451        */
452        public static String simpleVersionString(int major, int minor, boolean isBeta) {
453 
454                StringBuffer sb = new StringBuffer();
455 
456                sb.append(major);
457                sb.append('.');
458                sb.append(minor);
459                if (isBeta) {
460                        sb.append(' ');
461                        sb.append(BETA);
462                }
463 
464                return sb.toString();
465        }
466        public static String fullVersionString(int major, int minor, int maint, boolean isBeta, String build) {
467                StringBuffer sb = new StringBuffer();
468                sb.append(major);
469                sb.append('.');
470                sb.append(minor);
471                sb.append('.');
472 
473                String preRelease = null;
474                if (major == 5 && minor <= 2 && maint < MAINT_ENCODING)
475                {
476                        sb.append(maint);
477                        if (isBeta)
478                                preRelease = BETA;
479                }
480                else
481                {
482                        int fixPack = maint / MAINT_ENCODING;
483                        int bugVersion = maint % MAINT_ENCODING;
484                        sb.append(fixPack);
485                        sb.append('.');
486                        sb.append(bugVersion);
487 
488                        if (fixPack == 0)
489                        {
490                                preRelease = ALPHA;
491                        }
492                        else if (isBeta) {
493                                preRelease = BETA;
494                        }
495                }
496 
497        if (preRelease != null)
498        {
499                        sb.append(' ');
500            sb.append(preRelease);
501        }
502                if (build != null) {
503                        sb.append(" - (");
504 
505                        sb.append(build);
506                        sb.append(')');
507                }
508        return sb.toString();
509        }
510        /**
511                Returns a short-hand value for the product version string.
512                Used by Sysinfo.
513                Includes the optional <beta> designation
514        */
515    public String getVersionBuildString(boolean withBuild)
516    {
517                return ProductVersionHolder.fullVersionString(majorVersion, minorVersion, maintVersion, isBeta(),
518                        withBuild ? buildNumber : null);
519    }
520 
521        /*
522        ** Security related methods 
523        */
524        private String productGenus;
525        public final Object run() {
526 
527                // SECURITY PERMISSION - IP4
528                return loadProperties(this.productGenus);
529        }
530        // SECURITY PERMISSION - IP4
531        private Properties loadProperties(String productGenus) {
532                String resourceName = "/org/apache/derby/info/" + productGenus+".properties";
533                        
534                InputStream is = getClass().getResourceAsStream(resourceName);
535                if (is==null) {
536                        return null;
537                }
538 
539                Properties p = new Properties();
540                try {
541                        p.load(is);
542                        return p;
543                }
544                catch (IOException ioe) {
545                        //
546                        //This case is a bit ugly. If we get an IOException, we return
547                        //null. Though this correctly reflects that the product is not
548                        //available for use, it may be confusing to users that we swallow
549                        //the IO error here.
550                        return null;
551                }
552        }
553}

[all classes][org.apache.derby.iapi.services.info]
EMMA 2.0.5312 (C) Vladimir Roubtsov