1 /*
   2  * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.misc;
  27 
  28 import java.util.StringTokenizer;
  29 import java.util.jar.Attributes;
  30 import java.util.jar.Attributes.Name;
  31 import java.util.ResourceBundle;
  32 import java.util.MissingResourceException;
  33 import java.text.MessageFormat;
  34 import java.lang.Character.*;
  35 
  36 
  37 /**
  38  * This class holds all necessary information to install or
  39  * upgrade a extension on the user's disk
  40  *
  41  * @deprecated this class will be removed in a future release.
  42  * @author  Jerome Dochez
  43  */
  44 @Deprecated
  45 public class ExtensionInfo {
  46 
  47     /**
  48      * <p>
  49      * public static values returned by the isCompatible method
  50      * </p>
  51      */
  52     public static final int COMPATIBLE = 0;
  53     public static final int REQUIRE_SPECIFICATION_UPGRADE = 1;
  54     public static final int REQUIRE_IMPLEMENTATION_UPGRADE = 2;
  55     public static final int REQUIRE_VENDOR_SWITCH = 3;
  56     public static final int INCOMPATIBLE = 4;
  57 
  58     /**
  59      * <p>
  60      * attributes fully describer an extension. The underlying described
  61      * extension may be installed and requested.
  62      * <p>
  63      */
  64     public String title;
  65     public String name;
  66     public String specVersion;
  67     public String specVendor;
  68     public String implementationVersion;
  69     public String vendor;
  70     public String vendorId;
  71     public String url;
  72 
  73     // For I18N support
  74     private static final ResourceBundle rb =
  75         ResourceBundle.getBundle("sun.misc.resources.Messages");
  76 
  77 
  78     /**
  79      * <p>
  80      * Create a new uninitialized extension information object
  81      * </p>
  82      */
  83     public ExtensionInfo() {
  84     }
  85 
  86     /**
  87      * <p>
  88      * Create and initialize an extension information object.
  89      * The initialization uses the attributes passed as being
  90      * the content of a manifest file to load the extension
  91      * information from.
  92      * Since manifest file may contain information on several
  93      * extension they may depend on, the extension key parameter
  94      * is prepanded to the attribute name to make the key used
  95      * to retrieve the attribute from the manifest file
  96      * <p>
  97      * @param extensionKey unique extension key in the manifest
  98      * @param attr Attributes of a manifest file
  99      */
 100     public ExtensionInfo(String extensionKey, Attributes attr)
 101         throws NullPointerException
 102     {
 103         String s;
 104         if (extensionKey!=null) {
 105             s = extensionKey + "-";
 106         } else {
 107             s ="";
 108         }
 109 
 110         String attrKey = s + Name.EXTENSION_NAME.toString();
 111         name = attr.getValue(attrKey);
 112         if (name != null)
 113             name = name.trim();
 114 
 115         attrKey = s + Name.SPECIFICATION_TITLE.toString();
 116         title = attr.getValue(attrKey);
 117         if (title != null)
 118             title = title.trim();
 119 
 120         attrKey = s + Name.SPECIFICATION_VERSION.toString();
 121         specVersion = attr.getValue(attrKey);
 122         if (specVersion != null)
 123             specVersion = specVersion.trim();
 124 
 125         attrKey = s + Name.SPECIFICATION_VENDOR.toString();
 126         specVendor = attr.getValue(attrKey);
 127         if (specVendor != null)
 128             specVendor = specVendor.trim();
 129 
 130         attrKey = s + Name.IMPLEMENTATION_VERSION.toString();
 131         implementationVersion = attr.getValue(attrKey);
 132         if (implementationVersion != null)
 133             implementationVersion = implementationVersion.trim();
 134 
 135         attrKey = s + Name.IMPLEMENTATION_VENDOR.toString();
 136         vendor = attr.getValue(attrKey);
 137         if (vendor != null)
 138             vendor = vendor.trim();
 139 
 140         attrKey = s + Name.IMPLEMENTATION_VENDOR_ID.toString();
 141         vendorId = attr.getValue(attrKey);
 142         if (vendorId != null)
 143             vendorId = vendorId.trim();
 144 
 145         attrKey =s + Name.IMPLEMENTATION_URL.toString();
 146         url = attr.getValue(attrKey);
 147         if (url != null)
 148             url = url.trim();
 149     }
 150 
 151     /**
 152      * <p>
 153      * @return true if the extension described by this extension information
 154      * is compatible with the extension described by the extension
 155      * information passed as a parameter
 156      * </p>
 157      *
 158      * @param the requested extension information to compare to
 159      */
 160     public int isCompatibleWith(ExtensionInfo ei) {
 161 
 162         if (name == null || ei.name == null)
 163             return INCOMPATIBLE;
 164         if (name.compareTo(ei.name)==0) {
 165             // is this true, if not spec version is specified, we consider
 166             // the value as being "any".
 167             if (specVersion == null || ei.specVersion == null)
 168                 return COMPATIBLE;
 169 
 170             int version = compareExtensionVersion(specVersion, ei.specVersion);
 171             if (version<0) {
 172                 // this extension specification is "older"
 173                 if (vendorId != null && ei.vendorId !=null) {
 174                     if (vendorId.compareTo(ei.vendorId)!=0) {
 175                         return REQUIRE_VENDOR_SWITCH;
 176                     }
 177                 }
 178                 return REQUIRE_SPECIFICATION_UPGRADE;
 179             } else {
 180                 // the extension spec is compatible, let's look at the
 181                 // implementation attributes
 182                 if (vendorId != null && ei.vendorId != null) {
 183                     // They care who provides the extension
 184                     if (vendorId.compareTo(ei.vendorId)!=0) {
 185                         // They want to use another vendor implementation
 186                         return REQUIRE_VENDOR_SWITCH;
 187                     } else {
 188                         // Vendor matches, let's see the implementation version
 189                         if (implementationVersion != null && ei.implementationVersion != null) {
 190                             // they care about the implementation version
 191                             version = compareExtensionVersion(implementationVersion, ei.implementationVersion);
 192                             if (version<0) {
 193                                 // This extension is an older implementation
 194                                 return REQUIRE_IMPLEMENTATION_UPGRADE;
 195                             }
 196                         }
 197                     }
 198                 }
 199                 // All othe cases, we consider the extensions to be compatible
 200                 return COMPATIBLE;
 201             }
 202         }
 203         return INCOMPATIBLE;
 204     }
 205 
 206     /**
 207      * <p>
 208      * helper method to print sensible information on the undelying described
 209      * extension
 210      * </p>
 211      */
 212     public String toString() {
 213         return "Extension : title(" + title + "), name(" + name + "), spec vendor(" +
 214             specVendor + "), spec version(" + specVersion + "), impl vendor(" +
 215             vendor + "), impl vendor id(" + vendorId + "), impl version(" +
 216             implementationVersion + "), impl url(" + url + ")";
 217     }
 218 
 219     /*
 220      * <p>
 221      * helper method to compare two versions.
 222      * version are in the x.y.z.t pattern.
 223      * </p>
 224      * @param source version to compare to
 225      * @param target version used to compare against
 226      * @return < 0 if source < version
 227      *         > 0 if source > version
 228      *         = 0 if source = version
 229      */
 230     private int compareExtensionVersion(String source, String target)
 231         throws NumberFormatException
 232     {
 233         source = source.toLowerCase();
 234         target = target.toLowerCase();
 235 
 236         return strictCompareExtensionVersion(source, target);
 237     }
 238 
 239 
 240     /*
 241      * <p>
 242      * helper method to compare two versions.
 243      * version are in the x.y.z.t pattern.
 244      * </p>
 245      * @param source version to compare to
 246      * @param target version used to compare against
 247      * @return < 0 if source < version
 248      *         > 0 if source > version
 249      *         = 0 if source = version
 250      */
 251     private int strictCompareExtensionVersion(String source, String target)
 252         throws NumberFormatException
 253     {
 254         if (source.equals(target))
 255             return 0;
 256 
 257         StringTokenizer stk = new StringTokenizer(source, ".,");
 258         StringTokenizer ttk = new StringTokenizer(target, ".,");
 259 
 260         // Compare number
 261         int n = 0, m = 0, result = 0;
 262 
 263         // Convert token into meaning number for comparision
 264         if (stk.hasMoreTokens())
 265             n = convertToken(stk.nextToken().toString());
 266 
 267         // Convert token into meaning number for comparision
 268         if (ttk.hasMoreTokens())
 269             m = convertToken(ttk.nextToken().toString());
 270 
 271         if (n > m)
 272             return 1;
 273         else if (m > n)
 274             return -1;
 275         else
 276         {
 277             // Look for index of "." in the string
 278             int sIdx = source.indexOf('.');
 279             int tIdx = target.indexOf('.');
 280 
 281             if (sIdx == -1)
 282                 sIdx = source.length() - 1;
 283 
 284             if (tIdx == -1)
 285                 tIdx = target.length() - 1;
 286 
 287             return strictCompareExtensionVersion(source.substring(sIdx + 1),
 288                                                  target.substring(tIdx + 1));
 289         }
 290     }
 291 
 292     private int convertToken(String token)
 293     {
 294         if (token == null || token.equals(""))
 295             return 0;
 296 
 297         int charValue = 0;
 298         int charVersion = 0;
 299         int patchVersion = 0;
 300         int strLength = token.length();
 301         int endIndex = strLength;
 302         char lastChar;
 303 
 304         Object[] args = {name};
 305         MessageFormat mf = new MessageFormat(rb.getString("optpkg.versionerror"));
 306         String versionError = mf.format(args);
 307 
 308         // Look for "-" for pre-release
 309         int prIndex = token.indexOf('-');
 310 
 311         // Look for "_" for patch release
 312         int patchIndex = token.indexOf('_');
 313 
 314         if (prIndex == -1 && patchIndex == -1)
 315         {
 316             // This is a FCS release
 317             try {
 318                 return Integer.parseInt(token) * 100;
 319             } catch (NumberFormatException e) {
 320                 System.out.println(versionError);
 321                 return 0;
 322             }
 323         }
 324         else if (patchIndex != -1)
 325         {
 326             // This is a patch (update) release
 327             int prversion;
 328             try {
 329                 // Obtain the version
 330                 prversion = Integer.parseInt(token.substring(0, patchIndex));
 331 
 332                 // Check to see if the patch version is in the n.n.n_nnl format (special release)
 333                 lastChar = token.charAt(strLength-1);
 334                 if (Character.isLetter(lastChar)) {
 335                     // letters a-z have values from 10-35
 336                     charValue = Character.getNumericValue(lastChar);
 337                     endIndex = strLength-1;
 338 
 339                     // Obtain the patch version id
 340                     patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));
 341 
 342                     if (charValue >= Character.getNumericValue('a') && charValue <= Character.getNumericValue('z')) {
 343                         // This is a special release
 344                         charVersion = (patchVersion * 100) + charValue;
 345                     } else {
 346                         // character is not a a-z letter, ignore
 347                         charVersion = 0;
 348                         System.out.println(versionError);
 349                     }
 350                 } else {
 351                     // This is a regular update release. Obtain the patch version id
 352                     patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));
 353                 }
 354             } catch (NumberFormatException e) {
 355                 System.out.println(versionError);
 356                 return 0;
 357             }
 358             return prversion * 100 + (patchVersion + charVersion);
 359         }
 360         else
 361         {
 362             //This is a milestone release, either a early access, alpha, beta, or RC
 363 
 364             // Obtain the version
 365             int mrversion;
 366             try {
 367                 mrversion = Integer.parseInt(token.substring(0, prIndex));
 368             } catch (NumberFormatException e) {
 369                 System.out.println(versionError);
 370                 return 0;
 371             }
 372 
 373             // Obtain the patch version string, including the milestone + version
 374             String prString = token.substring(prIndex + 1);
 375 
 376             // Milestone version
 377             String msVersion = "";
 378             int delta = 0;
 379 
 380             if (prString.indexOf("ea") != -1)
 381             {
 382                 msVersion = prString.substring(2);
 383                 delta = 50;
 384             }
 385             else if (prString.indexOf("alpha") != -1)
 386             {
 387                 msVersion = prString.substring(5);
 388                 delta = 40;
 389             }
 390             else if (prString.indexOf("beta") != -1)
 391             {
 392                 msVersion = prString.substring(4);
 393                 delta = 30;
 394             }
 395             else if (prString.indexOf("rc") != -1)
 396             {
 397                 msVersion = prString.substring(2);
 398                 delta = 20;
 399             }
 400 
 401             if (msVersion == null || msVersion.equals(""))
 402             {
 403                 // No version after the milestone, assume 0
 404                 return mrversion * 100 - delta ;
 405             }
 406             else
 407             {
 408                 // Convert the milestone version
 409                 try {
 410                     return mrversion * 100 - delta + Integer.parseInt(msVersion);
 411                 } catch (NumberFormatException e) {
 412                     System.out.println(versionError);
 413                     return 0;
 414                 }
 415             }
 416         }
 417     }
 418 }