Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/misc/ExtensionInfo.java
38829 views
/*1* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.misc;2627import java.util.StringTokenizer;28import java.util.jar.Attributes;29import java.util.jar.Attributes.Name;30import java.util.ResourceBundle;31import java.util.MissingResourceException;32import java.text.MessageFormat;33import java.lang.Character.*;343536/**37* This class holds all necessary information to install or38* upgrade a extension on the user's disk39*40* @author Jerome Dochez41*/42public class ExtensionInfo {4344/**45* <p>46* public static values returned by the isCompatible method47* </p>48*/49public static final int COMPATIBLE = 0;50public static final int REQUIRE_SPECIFICATION_UPGRADE = 1;51public static final int REQUIRE_IMPLEMENTATION_UPGRADE = 2;52public static final int REQUIRE_VENDOR_SWITCH = 3;53public static final int INCOMPATIBLE = 4;5455/**56* <p>57* attributes fully describer an extension. The underlying described58* extension may be installed and requested.59* <p>60*/61public String title;62public String name;63public String specVersion;64public String specVendor;65public String implementationVersion;66public String vendor;67public String vendorId;68public String url;6970// For I18N support71private static final ResourceBundle rb =72ResourceBundle.getBundle("sun.misc.resources.Messages");737475/**76* <p>77* Create a new uninitialized extension information object78* </p>79*/80public ExtensionInfo() {81}8283/**84* <p>85* Create and initialize an extension information object.86* The initialization uses the attributes passed as being87* the content of a manifest file to load the extension88* information from.89* Since manifest file may contain information on several90* extension they may depend on, the extension key parameter91* is prepanded to the attribute name to make the key used92* to retrieve the attribute from the manifest file93* <p>94* @param extensionKey unique extension key in the manifest95* @param attr Attributes of a manifest file96*/97public ExtensionInfo(String extensionKey, Attributes attr)98throws NullPointerException99{100String s;101if (extensionKey!=null) {102s = extensionKey + "-";103} else {104s ="";105}106107String attrKey = s + Name.EXTENSION_NAME.toString();108name = attr.getValue(attrKey);109if (name != null)110name = name.trim();111112attrKey = s + Name.SPECIFICATION_TITLE.toString();113title = attr.getValue(attrKey);114if (title != null)115title = title.trim();116117attrKey = s + Name.SPECIFICATION_VERSION.toString();118specVersion = attr.getValue(attrKey);119if (specVersion != null)120specVersion = specVersion.trim();121122attrKey = s + Name.SPECIFICATION_VENDOR.toString();123specVendor = attr.getValue(attrKey);124if (specVendor != null)125specVendor = specVendor.trim();126127attrKey = s + Name.IMPLEMENTATION_VERSION.toString();128implementationVersion = attr.getValue(attrKey);129if (implementationVersion != null)130implementationVersion = implementationVersion.trim();131132attrKey = s + Name.IMPLEMENTATION_VENDOR.toString();133vendor = attr.getValue(attrKey);134if (vendor != null)135vendor = vendor.trim();136137attrKey = s + Name.IMPLEMENTATION_VENDOR_ID.toString();138vendorId = attr.getValue(attrKey);139if (vendorId != null)140vendorId = vendorId.trim();141142attrKey =s + Name.IMPLEMENTATION_URL.toString();143url = attr.getValue(attrKey);144if (url != null)145url = url.trim();146}147148/**149* <p>150* @return true if the extension described by this extension information151* is compatible with the extension described by the extension152* information passed as a parameter153* </p>154*155* @param the requested extension information to compare to156*/157public int isCompatibleWith(ExtensionInfo ei) {158159if (name == null || ei.name == null)160return INCOMPATIBLE;161if (name.compareTo(ei.name)==0) {162// is this true, if not spec version is specified, we consider163// the value as being "any".164if (specVersion == null || ei.specVersion == null)165return COMPATIBLE;166167int version = compareExtensionVersion(specVersion, ei.specVersion);168if (version<0) {169// this extension specification is "older"170if (vendorId != null && ei.vendorId !=null) {171if (vendorId.compareTo(ei.vendorId)!=0) {172return REQUIRE_VENDOR_SWITCH;173}174}175return REQUIRE_SPECIFICATION_UPGRADE;176} else {177// the extension spec is compatible, let's look at the178// implementation attributes179if (vendorId != null && ei.vendorId != null) {180// They care who provides the extension181if (vendorId.compareTo(ei.vendorId)!=0) {182// They want to use another vendor implementation183return REQUIRE_VENDOR_SWITCH;184} else {185// Vendor matches, let's see the implementation version186if (implementationVersion != null && ei.implementationVersion != null) {187// they care about the implementation version188version = compareExtensionVersion(implementationVersion, ei.implementationVersion);189if (version<0) {190// This extension is an older implementation191return REQUIRE_IMPLEMENTATION_UPGRADE;192}193}194}195}196// All othe cases, we consider the extensions to be compatible197return COMPATIBLE;198}199}200return INCOMPATIBLE;201}202203/**204* <p>205* helper method to print sensible information on the undelying described206* extension207* </p>208*/209public String toString() {210return "Extension : title(" + title + "), name(" + name + "), spec vendor(" +211specVendor + "), spec version(" + specVersion + "), impl vendor(" +212vendor + "), impl vendor id(" + vendorId + "), impl version(" +213implementationVersion + "), impl url(" + url + ")";214}215216/*217* <p>218* helper method to compare two versions.219* version are in the x.y.z.t pattern.220* </p>221* @param source version to compare to222* @param target version used to compare against223* @return < 0 if source < version224* > 0 if source > version225* = 0 if source = version226*/227private int compareExtensionVersion(String source, String target)228throws NumberFormatException229{230source = source.toLowerCase();231target = target.toLowerCase();232233return strictCompareExtensionVersion(source, target);234}235236237/*238* <p>239* helper method to compare two versions.240* version are in the x.y.z.t pattern.241* </p>242* @param source version to compare to243* @param target version used to compare against244* @return < 0 if source < version245* > 0 if source > version246* = 0 if source = version247*/248private int strictCompareExtensionVersion(String source, String target)249throws NumberFormatException250{251if (source.equals(target))252return 0;253254StringTokenizer stk = new StringTokenizer(source, ".,");255StringTokenizer ttk = new StringTokenizer(target, ".,");256257// Compare number258int n = 0, m = 0, result = 0;259260// Convert token into meaning number for comparision261if (stk.hasMoreTokens())262n = convertToken(stk.nextToken().toString());263264// Convert token into meaning number for comparision265if (ttk.hasMoreTokens())266m = convertToken(ttk.nextToken().toString());267268if (n > m)269return 1;270else if (m > n)271return -1;272else273{274// Look for index of "." in the string275int sIdx = source.indexOf(".");276int tIdx = target.indexOf(".");277278if (sIdx == -1)279sIdx = source.length() - 1;280281if (tIdx == -1)282tIdx = target.length() - 1;283284return strictCompareExtensionVersion(source.substring(sIdx + 1),285target.substring(tIdx + 1));286}287}288289private int convertToken(String token)290{291if (token == null || token.equals(""))292return 0;293294int charValue = 0;295int charVersion = 0;296int patchVersion = 0;297int strLength = token.length();298int endIndex = strLength;299char lastChar;300301Object[] args = {name};302MessageFormat mf = new MessageFormat(rb.getString("optpkg.versionerror"));303String versionError = mf.format(args);304305// Look for "-" for pre-release306int prIndex = token.indexOf("-");307308// Look for "_" for patch release309int patchIndex = token.indexOf("_");310311if (prIndex == -1 && patchIndex == -1)312{313// This is a FCS release314try {315return Integer.parseInt(token) * 100;316} catch (NumberFormatException e) {317System.out.println(versionError);318return 0;319}320}321else if (patchIndex != -1)322{323// This is a patch (update) release324int prversion;325try {326// Obtain the version327prversion = Integer.parseInt(token.substring(0, patchIndex));328329// Check to see if the patch version is in the n.n.n_nnl format (special release)330lastChar = token.charAt(strLength-1);331if (Character.isLetter(lastChar)) {332// letters a-z have values from 10-35333charValue = Character.getNumericValue(lastChar);334endIndex = strLength-1;335336// Obtain the patch version id337patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));338339if (charValue >= Character.getNumericValue('a') && charValue <= Character.getNumericValue('z')) {340// This is a special release341charVersion = (patchVersion * 100) + charValue;342} else {343// character is not a a-z letter, ignore344charVersion = 0;345System.out.println(versionError);346}347} else {348// This is a regular update release. Obtain the patch version id349patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));350}351} catch (NumberFormatException e) {352System.out.println(versionError);353return 0;354}355return prversion * 100 + (patchVersion + charVersion);356}357else358{359//This is a milestone release, either a early access, alpha, beta, or RC360361// Obtain the version362int mrversion;363try {364mrversion = Integer.parseInt(token.substring(0, prIndex));365} catch (NumberFormatException e) {366System.out.println(versionError);367return 0;368}369370// Obtain the patch version string, including the milestone + version371String prString = token.substring(prIndex + 1);372373// Milestone version374String msVersion = "";375int delta = 0;376377if (prString.indexOf("ea") != -1)378{379msVersion = prString.substring(2);380delta = 50;381}382else if (prString.indexOf("alpha") != -1)383{384msVersion = prString.substring(5);385delta = 40;386}387else if (prString.indexOf("beta") != -1)388{389msVersion = prString.substring(4);390delta = 30;391}392else if (prString.indexOf("rc") != -1)393{394msVersion = prString.substring(2);395delta = 20;396}397398if (msVersion == null || msVersion.equals(""))399{400// No version after the milestone, assume 0401return mrversion * 100 - delta ;402}403else404{405// Convert the milestone version406try {407return mrversion * 100 - delta + Integer.parseInt(msVersion);408} catch (NumberFormatException e) {409System.out.println(versionError);410return 0;411}412}413}414}415}416417418