| /* |
| * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.misc; |
| |
| import java.util.StringTokenizer; |
| import java.util.jar.Attributes; |
| import java.util.jar.Attributes.Name; |
| import java.util.ResourceBundle; |
| import java.util.MissingResourceException; |
| import java.text.MessageFormat; |
| import java.lang.Character.*; |
| |
| |
| /** |
| * This class holds all necessary information to install or |
| * upgrade a extension on the user's disk |
| * |
| * @author Jerome Dochez |
| */ |
| public class ExtensionInfo { |
| |
| /** |
| * <p> |
| * public static values returned by the isCompatible method |
| * </p> |
| */ |
| public static final int COMPATIBLE = 0; |
| public static final int REQUIRE_SPECIFICATION_UPGRADE = 1; |
| public static final int REQUIRE_IMPLEMENTATION_UPGRADE = 2; |
| public static final int REQUIRE_VENDOR_SWITCH = 3; |
| public static final int INCOMPATIBLE = 4; |
| |
| /** |
| * <p> |
| * attributes fully describer an extension. The underlying described |
| * extension may be installed and requested. |
| * <p> |
| */ |
| public String title; |
| public String name; |
| public String specVersion; |
| public String specVendor; |
| public String implementationVersion; |
| public String vendor; |
| public String vendorId; |
| public String url; |
| |
| // For I18N support |
| private static final ResourceBundle rb = |
| ResourceBundle.getBundle("sun.misc.resources.Messages"); |
| |
| |
| /** |
| * <p> |
| * Create a new uninitialized extension information object |
| * </p> |
| */ |
| public ExtensionInfo() { |
| } |
| |
| /** |
| * <p> |
| * Create and initialize an extension information object. |
| * The initialization uses the attributes passed as being |
| * the content of a manifest file to load the extension |
| * information from. |
| * Since manifest file may contain information on several |
| * extension they may depend on, the extension key parameter |
| * is prepanded to the attribute name to make the key used |
| * to retrieve the attribute from the manifest file |
| * <p> |
| * @param extensionKey unique extension key in the manifest |
| * @param attr Attributes of a manifest file |
| */ |
| public ExtensionInfo(String extensionKey, Attributes attr) |
| throws NullPointerException |
| { |
| String s; |
| if (extensionKey!=null) { |
| s = extensionKey + "-"; |
| } else { |
| s =""; |
| } |
| |
| String attrKey = s + Name.EXTENSION_NAME.toString(); |
| name = attr.getValue(attrKey); |
| if (name != null) |
| name = name.trim(); |
| |
| attrKey = s + Name.SPECIFICATION_TITLE.toString(); |
| title = attr.getValue(attrKey); |
| if (title != null) |
| title = title.trim(); |
| |
| attrKey = s + Name.SPECIFICATION_VERSION.toString(); |
| specVersion = attr.getValue(attrKey); |
| if (specVersion != null) |
| specVersion = specVersion.trim(); |
| |
| attrKey = s + Name.SPECIFICATION_VENDOR.toString(); |
| specVendor = attr.getValue(attrKey); |
| if (specVendor != null) |
| specVendor = specVendor.trim(); |
| |
| attrKey = s + Name.IMPLEMENTATION_VERSION.toString(); |
| implementationVersion = attr.getValue(attrKey); |
| if (implementationVersion != null) |
| implementationVersion = implementationVersion.trim(); |
| |
| attrKey = s + Name.IMPLEMENTATION_VENDOR.toString(); |
| vendor = attr.getValue(attrKey); |
| if (vendor != null) |
| vendor = vendor.trim(); |
| |
| attrKey = s + Name.IMPLEMENTATION_VENDOR_ID.toString(); |
| vendorId = attr.getValue(attrKey); |
| if (vendorId != null) |
| vendorId = vendorId.trim(); |
| |
| attrKey =s + Name.IMPLEMENTATION_URL.toString(); |
| url = attr.getValue(attrKey); |
| if (url != null) |
| url = url.trim(); |
| } |
| |
| /** |
| * <p> |
| * @return true if the extension described by this extension information |
| * is compatible with the extension described by the extension |
| * information passed as a parameter |
| * </p> |
| * |
| * @param the requested extension information to compare to |
| */ |
| public int isCompatibleWith(ExtensionInfo ei) { |
| |
| if (name == null || ei.name == null) |
| return INCOMPATIBLE; |
| if (name.compareTo(ei.name)==0) { |
| // is this true, if not spec version is specified, we consider |
| // the value as being "any". |
| if (specVersion == null || ei.specVersion == null) |
| return COMPATIBLE; |
| |
| int version = compareExtensionVersion(specVersion, ei.specVersion); |
| if (version<0) { |
| // this extension specification is "older" |
| if (vendorId != null && ei.vendorId !=null) { |
| if (vendorId.compareTo(ei.vendorId)!=0) { |
| return REQUIRE_VENDOR_SWITCH; |
| } |
| } |
| return REQUIRE_SPECIFICATION_UPGRADE; |
| } else { |
| // the extension spec is compatible, let's look at the |
| // implementation attributes |
| if (vendorId != null && ei.vendorId != null) { |
| // They care who provides the extension |
| if (vendorId.compareTo(ei.vendorId)!=0) { |
| // They want to use another vendor implementation |
| return REQUIRE_VENDOR_SWITCH; |
| } else { |
| // Vendor matches, let's see the implementation version |
| if (implementationVersion != null && ei.implementationVersion != null) { |
| // they care about the implementation version |
| version = compareExtensionVersion(implementationVersion, ei.implementationVersion); |
| if (version<0) { |
| // This extension is an older implementation |
| return REQUIRE_IMPLEMENTATION_UPGRADE; |
| } |
| } |
| } |
| } |
| // All othe cases, we consider the extensions to be compatible |
| return COMPATIBLE; |
| } |
| } |
| return INCOMPATIBLE; |
| } |
| |
| /** |
| * <p> |
| * helper method to print sensible information on the undelying described |
| * extension |
| * </p> |
| */ |
| public String toString() { |
| return "Extension : title(" + title + "), name(" + name + "), spec vendor(" + |
| specVendor + "), spec version(" + specVersion + "), impl vendor(" + |
| vendor + "), impl vendor id(" + vendorId + "), impl version(" + |
| implementationVersion + "), impl url(" + url + ")"; |
| } |
| |
| /* |
| * <p> |
| * helper method to compare two versions. |
| * version are in the x.y.z.t pattern. |
| * </p> |
| * @param source version to compare to |
| * @param target version used to compare against |
| * @return < 0 if source < version |
| * > 0 if source > version |
| * = 0 if source = version |
| */ |
| private int compareExtensionVersion(String source, String target) |
| throws NumberFormatException |
| { |
| source = source.toLowerCase(); |
| target = target.toLowerCase(); |
| |
| return strictCompareExtensionVersion(source, target); |
| } |
| |
| |
| /* |
| * <p> |
| * helper method to compare two versions. |
| * version are in the x.y.z.t pattern. |
| * </p> |
| * @param source version to compare to |
| * @param target version used to compare against |
| * @return < 0 if source < version |
| * > 0 if source > version |
| * = 0 if source = version |
| */ |
| private int strictCompareExtensionVersion(String source, String target) |
| throws NumberFormatException |
| { |
| if (source.equals(target)) |
| return 0; |
| |
| StringTokenizer stk = new StringTokenizer(source, ".,"); |
| StringTokenizer ttk = new StringTokenizer(target, ".,"); |
| |
| // Compare number |
| int n = 0, m = 0, result = 0; |
| |
| // Convert token into meaning number for comparision |
| if (stk.hasMoreTokens()) |
| n = convertToken(stk.nextToken().toString()); |
| |
| // Convert token into meaning number for comparision |
| if (ttk.hasMoreTokens()) |
| m = convertToken(ttk.nextToken().toString()); |
| |
| if (n > m) |
| return 1; |
| else if (m > n) |
| return -1; |
| else |
| { |
| // Look for index of "." in the string |
| int sIdx = source.indexOf("."); |
| int tIdx = target.indexOf("."); |
| |
| if (sIdx == -1) |
| sIdx = source.length() - 1; |
| |
| if (tIdx == -1) |
| tIdx = target.length() - 1; |
| |
| return strictCompareExtensionVersion(source.substring(sIdx + 1), |
| target.substring(tIdx + 1)); |
| } |
| } |
| |
| private int convertToken(String token) |
| { |
| if (token == null || token.equals("")) |
| return 0; |
| |
| int charValue = 0; |
| int charVersion = 0; |
| int patchVersion = 0; |
| int strLength = token.length(); |
| int endIndex = strLength; |
| char lastChar; |
| |
| Object[] args = {name}; |
| MessageFormat mf = new MessageFormat(rb.getString("optpkg.versionerror")); |
| String versionError = mf.format(args); |
| |
| // Look for "-" for pre-release |
| int prIndex = token.indexOf("-"); |
| |
| // Look for "_" for patch release |
| int patchIndex = token.indexOf("_"); |
| |
| if (prIndex == -1 && patchIndex == -1) |
| { |
| // This is a FCS release |
| try { |
| return Integer.parseInt(token) * 100; |
| } catch (NumberFormatException e) { |
| System.out.println(versionError); |
| return 0; |
| } |
| } |
| else if (patchIndex != -1) |
| { |
| // This is a patch (update) release |
| int prversion; |
| try { |
| // Obtain the version |
| prversion = Integer.parseInt(token.substring(0, patchIndex)); |
| |
| // Check to see if the patch version is in the n.n.n_nnl format (special release) |
| lastChar = token.charAt(strLength-1); |
| if (Character.isLetter(lastChar)) { |
| // letters a-z have values from 10-35 |
| charValue = Character.getNumericValue(lastChar); |
| endIndex = strLength-1; |
| |
| // Obtain the patch version id |
| patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex)); |
| |
| if (charValue >= Character.getNumericValue('a') && charValue <= Character.getNumericValue('z')) { |
| // This is a special release |
| charVersion = (patchVersion * 100) + charValue; |
| } else { |
| // character is not a a-z letter, ignore |
| charVersion = 0; |
| System.out.println(versionError); |
| } |
| } else { |
| // This is a regular update release. Obtain the patch version id |
| patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex)); |
| } |
| } catch (NumberFormatException e) { |
| System.out.println(versionError); |
| return 0; |
| } |
| return prversion * 100 + (patchVersion + charVersion); |
| } |
| else |
| { |
| //This is a milestone release, either a early access, alpha, beta, or RC |
| |
| // Obtain the version |
| int mrversion; |
| try { |
| mrversion = Integer.parseInt(token.substring(0, prIndex)); |
| } catch (NumberFormatException e) { |
| System.out.println(versionError); |
| return 0; |
| } |
| |
| // Obtain the patch version string, including the milestone + version |
| String prString = token.substring(prIndex + 1); |
| |
| // Milestone version |
| String msVersion = ""; |
| int delta = 0; |
| |
| if (prString.indexOf("ea") != -1) |
| { |
| msVersion = prString.substring(2); |
| delta = 50; |
| } |
| else if (prString.indexOf("alpha") != -1) |
| { |
| msVersion = prString.substring(5); |
| delta = 40; |
| } |
| else if (prString.indexOf("beta") != -1) |
| { |
| msVersion = prString.substring(4); |
| delta = 30; |
| } |
| else if (prString.indexOf("rc") != -1) |
| { |
| msVersion = prString.substring(2); |
| delta = 20; |
| } |
| |
| if (msVersion == null || msVersion.equals("")) |
| { |
| // No version after the milestone, assume 0 |
| return mrversion * 100 - delta ; |
| } |
| else |
| { |
| // Convert the milestone version |
| try { |
| return mrversion * 100 - delta + Integer.parseInt(msVersion); |
| } catch (NumberFormatException e) { |
| System.out.println(versionError); |
| return 0; |
| } |
| } |
| } |
| } |
| } |