KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > services > info > ProductVersionHolder


1 /*
2
3    Derby - Class org.apache.derby.iapi.services.info.ProductVersionHolder
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20 */

21
22 package org.apache.derby.iapi.services.info;
23
24 import java.io.InputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.Properties JavaDoc;
27
28
29 /**
30   Class to hold a cloudscape Product version.
31
32   This class includes the following product version features.
33
34   <OL>
35   <LI>Save the product version information this holds as a String. We call
36       the string a 'product version string'.
37   <LI>Construct a ProductVersionHolder from a valid 'product version string'.
38   <LI>Determine if two product versions are feature compatible. This means
39       products of these versions may interoperate with ***NO*** compatibility
40       problems.
41   <LI>Determine if two product versions are the same. This is a stronger
42       test than the test for feature compatibility.
43   </OL>
44
45
46
47   Cloudscape 5.1 and older versions used the majorVersion, minorVersion, maintVersion versions
48   directly. That is a three part version number, majorVersion.minorVersion.maintVersion, e.g. 5.1.21.
49
50   For Cloudscape 5.2 onwards a four part name is required.
51     majorVersion.minorVersion.fixPack.bugVersion e.g. 5.2.1.2
52
53     This follows the IBM standard and allows us to state that a fix pack will be 5.2.3 without worrying
54     about how many maintence fixes there are between fix packs.
55
56     We implement this using the existing format of ProductVersionHolder to reduce disruption to the
57     code, however we make the maintVersion encode the {fixPack.bugVersion}. Since the maintVersion
58     is represented by a int (2G values) we have plenty of room for encoding. If we assign a given
59     majorVersion.minorVersion.fixPack a 10 year life, then we about the maximum number of individual releases
60     it can have is 10 years * 365 days/year = 3650. Thus with the pre 5.2 scheme we would not expect a
61     5.1.x to have an x > 3650 (approximately). Usually the rate of point releases has been much less than
62     one per day, 5.1.31 is released about 225 days after GA which makes around a point release every 7 days.
63     But in the encoding we need to be conservative. With fix packs the maximum is about 2 per year and fix
64     packs are only made to the current release, thus with a yearly minor release cycle we would imagine
65     only 2 fixpacks per major.minor. However like other IBM products or release cycle may be extended thus
66     we can expect up to a handful of fix packs.
67
68     Thus we might imagine releases like
69
70     5.2.0.12
71     5.2.0.234
72     5.2.1.34
73     5.2.4.2445
74
75   but highly unlikey to have
76
77     5.2.2.59321
78     5.2.23.1
79     
80
81     The encoding number must continue to increase so that the
82     
83         encodedMaintB > encodedMaintA
84
85         if (fixPackB > fixPackA) || ((fixPackB == fixPackA) && (bugB > bugA))
86
87
88     Selected encoding
89
90     encodedMaint = (fixPack * 1,000,000) + (bugVersion);
91
92     Handles many many fixpacks and upto one million bug fixes per fix pack and remains somewhat human readable.
93
94     Special fix packs
95
96     fixpack == 0 = alpha (version off main codeline)
97     fixpack == 1 = first release of major.minor (may be marked with beta)
98     fixpack == 2 = first fix pack (displayed as 1)
99      
100
101     The drdaMaintVersion is sent in the Network Server PRDID. It never displays
102     but may be used by the client for version specific behaviour. It should be
103     reset to 0 with each minor release.
104
105   The product version string has the form:
106   <PRE>
107   productVendorName - ProductName - majorVersion.minorVersion.maintVersion [beta] - (buildNumber)
108
109   </PRE>
110
111   */

112 public final class ProductVersionHolder implements java.security.PrivilegedAction JavaDoc
113 {
114
115     //
116
//Used as an invalid value for numbers. This works because all
117
//the numbers in a product version must be non-negative.
118
private static final int BAD_NUMBER = -1;
119     private static final String JavaDoc ALPHA = "alpha";
120     private static final String JavaDoc BETA = "beta";
121
122     private final static int MAINT_ENCODING = 1000000;
123     
124     private String JavaDoc productVendorName;
125     private String JavaDoc productName;
126     private String JavaDoc productTechnologyName;
127     private int majorVersion = BAD_NUMBER;
128     private int minorVersion = BAD_NUMBER;
129     private int maintVersion = BAD_NUMBER;
130     private int drdaMaintVersion = BAD_NUMBER;
131     private String JavaDoc buildNumber = "????";
132     private Boolean JavaDoc isBeta;
133
134     private ProductVersionHolder() {
135     }
136     
137     /**
138       Create a ProductVersionHolder
139
140       <P>Please see the documentation for the varient of getProductVesionHolder
141       that takes the same parameters as this for a description of the parameters.
142       */

143     private ProductVersionHolder(String JavaDoc productVendorName,
144                                  String JavaDoc productName,
145                                  String JavaDoc productTechnologyName,
146                                  int majorVersion,
147                                  int minorVersion,
148                                  int maintVersion,
149                                  int drdaMaintVersion,
150                                  String JavaDoc buildNumber,
151                                  Boolean JavaDoc isBeta)
152     {
153         if (productVendorName != null)
154             this.productVendorName = productVendorName.trim();
155         if (productName != null)
156             this.productName = productName.trim();
157         if (productTechnologyName != null)
158             this.productTechnologyName = productTechnologyName.trim();
159         this.majorVersion = majorVersion;
160         this.minorVersion = minorVersion;
161         this.maintVersion = maintVersion;
162         this.drdaMaintVersion = drdaMaintVersion;
163         this.buildNumber = buildNumber;
164         this.isBeta = isBeta;
165     }
166
167     /**
168       Create a valid ProductVersionHolder. If any of the
169       parameters provided is invalid, this returns null.
170       @param productName The name of the product. productName.length()
171       must be greater than 0. The syntax for a product name is
172       'productGenus[:productSpecies]'.
173       @param majorVersion The most significant portion of a 3
174       part product version. Must be non-negative.
175       @param minorVersion The second portion of a 3 part
176       product version. Must be non-negative.
177       @param maintVersion The least significant portion of a 3 part
178       product version. Must be non-negative.
179       @param drdaMaintVersion The protocol modification number for minor release.
180       @param buildNumber The buildNumber for a product.
181       @param isBeta true iff the product is beta.
182       @return A valid ProductVersionHolder of null if any of the parameters
183       provided are not valid.
184       */

185     public static ProductVersionHolder
186     getProductVersionHolder(
187                            String JavaDoc productVendorName,
188                            String JavaDoc productName,
189                            String JavaDoc productTechnologyName,
190                            int majorVersion,
191                            int minorVersion,
192                            int maintVersion,
193                            int drdaMaintVersion,
194                            String JavaDoc buildNumber,
195                            Boolean JavaDoc isBeta)
196     {
197         ProductVersionHolder pvh =
198             new ProductVersionHolder(productVendorName,
199                                      productName,
200                                      productTechnologyName,
201                                      majorVersion,
202                                      minorVersion,
203                                      maintVersion,
204                                      drdaMaintVersion,
205                                      buildNumber,
206                                      isBeta);
207         return pvh;
208     }
209     
210     /**
211       Get a ProductVersionHolder for a product of a given genus,
212       that is available in the caller's environment.
213       Even though this uses a priv bock, it may stil fail when
214       the jar the version is being fetched from, is different to the
215       one that loaded this class, AND the jars are in different security contexts.
216
217       @param productGenus The genus for the product.
218       @return The ProductVersionHolder or null if
219       a product with the given genus is not available in the
220       caller's environment.
221       */

222     public static ProductVersionHolder
223     getProductVersionHolderFromMyEnv(String JavaDoc productGenus)
224     {
225
226         ProductVersionHolder tempPVH = new ProductVersionHolder();
227
228         tempPVH.productGenus = productGenus;
229         Properties JavaDoc p = (Properties JavaDoc) java.security.AccessController.doPrivileged(tempPVH);
230
231         if (p == null)
232             return null;
233
234         return getProductVersionHolder(p);
235     }
236
237
238     /**
239         Load the version info from the already opened properties files.
240         We need to do this because if the jar files (e.g. db2jtools and db2j)
241         are in different security contexts (entries in the policy files) then
242         we cannot load the version information for one of them correctly.
243         This is because the this class will either have been loaded from
244         only one of the jars and hence can only access the resource in its own jar.
245         By making code specific to the jar open the resource we are guaranteed it will work.
246     */

247     public static ProductVersionHolder
248     getProductVersionHolderFromMyEnv(InputStream JavaDoc propertiesStream)
249     {
250
251         if (propertiesStream == null)
252             return null;
253
254         Properties JavaDoc p = new Properties JavaDoc();
255         try {
256             p.load(propertiesStream);
257         }
258         catch (IOException JavaDoc ioe) {
259
260             System.out.println("IOE " + ioe.getMessage());
261             //
262
//This case is a bit ugly. If we get an IOException, we return
263
//null. Though this correctly reflects that the product is not
264
//available for use, it may be confusing to users that we swallow
265
//the IO error here.
266
return null;
267         } finally {
268             try {
269                 propertiesStream.close();
270             } catch (IOException JavaDoc ioe2) {
271             }
272         }
273
274         return getProductVersionHolder(p);
275     }
276
277     /**
278       Get a ProductVersionHolder based on the information in
279       the Properties object provided.
280
281       @param p The properties object that holds the productVersion
282       information.
283       @return The ProductVersionHolder or null if
284       a product with the given genus is not available in the
285       caller's environment.
286       */

287     public static ProductVersionHolder
288     getProductVersionHolder(Properties JavaDoc p)
289     {
290         String JavaDoc pvn = p.getProperty(PropertyNames.PRODUCT_VENDOR_NAME);
291         String JavaDoc pn = p.getProperty(PropertyNames.PRODUCT_EXTERNAL_NAME);
292         String JavaDoc ptn = p.getProperty(PropertyNames.PRODUCT_TECHNOLOGY_NAME);
293         int v1 = parseInt(p.getProperty(PropertyNames.PRODUCT_MAJOR_VERSION));
294         int v2 = parseInt(p.getProperty(PropertyNames.PRODUCT_MINOR_VERSION));
295         int v3 = parseInt(p.getProperty(PropertyNames.PRODUCT_MAINT_VERSION));
296         int v4 = parseInt(p.getProperty(PropertyNames.PRODUCT_DRDA_MAINT_VERSION));
297         String JavaDoc bn = p.getProperty(PropertyNames.PRODUCT_BUILD_NUMBER);
298         Boolean JavaDoc isBeta =
299             Boolean.valueOf(p.getProperty(PropertyNames.PRODUCT_BETA_VERSION));
300         return getProductVersionHolder(pvn,pn,ptn,v1,v2,v3,v4,bn,isBeta);
301     }
302
303
304     /**
305       Return the product vendor name.
306       */

307     public String JavaDoc getProductVendorName()
308     {
309         return productVendorName;
310     }
311
312
313     /**
314       Return the external product name.
315       */

316     public String JavaDoc getProductName()
317     {
318         return productName;
319     }
320     public String JavaDoc getProductTechnologyName()
321     {
322         return productTechnologyName;
323     }
324
325     /**
326       Return the major version number.
327       */

328     public int getMajorVersion() {return majorVersion;}
329     /**
330       Return the minor version number.
331       */

332     public int getMinorVersion() {return minorVersion;}
333     /**
334       Return the <B>encoded</B> maintainence version number.
335       */

336     public int getMaintVersion() {return maintVersion;}
337
338     /**
339         Return the drda protocol maintenance version for this minor release.
340         Starts at 0 for each minor release and only incremented
341         when client behaviour changes based on the server version.
342     **/

343     public int getDrdaMaintVersion() {return drdaMaintVersion; }
344
345     /**
346         Return the fix pack version from the maintence encoding.
347     */

348     public int getFixPackVersion() { return maintVersion / MAINT_ENCODING; }
349
350
351     /**
352       Return true if this is a beta product.
353       */

354     public boolean isBeta() {return isBeta.booleanValue();}
355     /**
356       Return true if this is a alpha product.
357       */

358     public boolean isAlpha() {
359         return (majorVersion >= 5)
360                 && (minorVersion > 2)
361                 && ((maintVersion / MAINT_ENCODING) == 0);
362     }
363     /**
364       Return the build number for this product.
365       */

366     public String JavaDoc getBuildNumber() {return buildNumber;}
367
368     /**
369      * Return the build number as an integer if possible,
370      * mapping from the SVN number.
371      * nnnnn -> returns nnnnn
372      * nnnnnM -> returns -nnnnn indicates a modified code base
373      * nnnnn:mmmmm -> returns -nnnnn
374      * anything else -> returns -1
375     */

376     public int getBuildNumberAsInt(){
377         if (buildNumber == null)
378             return -1;
379         boolean dubiousCode = false;
380         int offset = buildNumber.indexOf('M');
381         if (offset == -1)
382             offset = buildNumber.indexOf(':');
383         else
384             dubiousCode = true;
385         if (offset == -1)
386             offset = buildNumber.length();
387         else
388             dubiousCode = true;
389         
390         try {
391             int bnai = Integer.parseInt(buildNumber.substring(0, offset));
392             if (dubiousCode)
393                 bnai = -bnai;
394             return bnai;
395         } catch (NumberFormatException JavaDoc nfe)
396         {
397             return -1;
398         }
399     }
400
401     /**
402       Parse a string containing a non-negative integer. Return
403       a negative integer is the String is invalid.
404
405       @param s A string with a non-negative integer (a sequence
406       of decimal digits.)
407       @return the integer or a negative number if s is invalid.
408       */

409     private static int parseInt(String JavaDoc s)
410     {
411         //System.out.println("Parsing integer: "+s);
412
int result = BAD_NUMBER;
413         try
414             {
415                 if (s!=null)
416                     result = Integer.parseInt(s);
417             }
418         catch (NumberFormatException JavaDoc nfe)
419             {}
420
421         if (result < 0) result = BAD_NUMBER;
422         return result;
423     }
424
425     /**
426       Return a string representation of this ProductVersion. The
427       difference between this and createProductVersionString, is
428       that this method retruns a String when this ProductVersionHolder
429       holds invalid version information.
430      */

431     public String JavaDoc toString()
432     {
433         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
434         sb.append(getProductVendorName());
435         sb.append(" - ");
436         sb.append(getProductName());
437         sb.append(" - ");
438         sb.append(getVersionBuildString(true));
439         return sb.toString();
440     }
441
442     /**
443         Return the feature version string, ie. major.minor. (e.g. 5.2)
444     */

445     public String JavaDoc getSimpleVersionString() {
446
447         return ProductVersionHolder.simpleVersionString(majorVersion, minorVersion, isBeta());
448     }
449
450     /**
451         Convert a major and minor number with beta status into a string.
452     */

453     public static String JavaDoc simpleVersionString(int major, int minor, boolean isBeta) {
454
455         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
456
457         sb.append(major);
458         sb.append('.');
459         sb.append(minor);
460         if (isBeta) {
461             sb.append(' ');
462             sb.append(BETA);
463         }
464
465         return sb.toString();
466     }
467     public static String JavaDoc fullVersionString(int major, int minor, int maint, boolean isBeta, String JavaDoc build) {
468         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
469         sb.append(major);
470         sb.append('.');
471         sb.append(minor);
472         sb.append('.');
473
474         String JavaDoc preRelease = null;
475         if (major == 5 && minor <= 2 && maint < MAINT_ENCODING)
476         {
477             sb.append(maint);
478             if (isBeta)
479                 preRelease = BETA;
480         }
481         else
482         {
483             int fixPack = maint / MAINT_ENCODING;
484             int bugVersion = maint % MAINT_ENCODING;
485             sb.append(fixPack);
486             sb.append('.');
487             sb.append(bugVersion);
488
489             if (fixPack == 0)
490             {
491                 preRelease = ALPHA;
492             }
493             else if (isBeta) {
494                 preRelease = BETA;
495             }
496         }
497
498         if (preRelease != null)
499         {
500             sb.append(' ');
501             sb.append(preRelease);
502         }
503         if (build != null) {
504             sb.append(" - (");
505
506             sb.append(build);
507             sb.append(')');
508         }
509         return sb.toString();
510     }
511     /**
512         Returns a short-hand value for the product version string.
513         Used by Sysinfo.
514         Includes the optional <beta> designation
515     */

516     public String JavaDoc getVersionBuildString(boolean withBuild)
517     {
518         return ProductVersionHolder.fullVersionString(majorVersion, minorVersion, maintVersion, isBeta(),
519             withBuild ? buildNumber : null);
520     }
521
522     /*
523     ** Security related methods
524     */

525     private String JavaDoc productGenus;
526     public final Object JavaDoc run() {
527
528         // SECURITY PERMISSION - IP4
529
return loadProperties(this.productGenus);
530     }
531     // SECURITY PERMISSION - IP4
532
private Properties JavaDoc loadProperties(String JavaDoc productGenus) {
533         String JavaDoc resourceName = "/org/apache/derby/info/" + productGenus+".properties";
534             
535         InputStream JavaDoc is = getClass().getResourceAsStream(resourceName);
536         if (is==null) {
537             return null;
538         }
539
540         Properties JavaDoc p = new Properties JavaDoc();
541         try {
542             p.load(is);
543             return p;
544         }
545         catch (IOException JavaDoc ioe) {
546             //
547
//This case is a bit ugly. If we get an IOException, we return
548
//null. Though this correctly reflects that the product is not
549
//available for use, it may be confusing to users that we swallow
550
//the IO error here.
551
return null;
552         }
553     }
554 }
555
Popular Tags