/*
 * 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
/** * This class holds all necessary information to install or * upgrade a extension on the user's disk * * @author Jerome Dochez */
public class ExtensionInfo {

public static values returned by the isCompatible method

/** * <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;

attributes fully describer an extension. The underlying described extension may be installed and requested.

/** * <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");

Create a new uninitialized extension information object

/** * <p> * Create a new uninitialized extension information object * </p> */
public ExtensionInfo() { }

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

Params:
  • extensionKey – unique extension key in the manifest
  • attr – Attributes of a manifest file
/** * <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(); }

Params:
  • the – requested extension information to compare to
Returns:true if the extension described by this extension information is compatible with the extension described by the extension information passed as a parameter

/** * <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; }

helper method to print sensible information on the undelying described extension

/** * <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; } } } } }