All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.common.core.ComponentInfo Maven / Gradle / Ivy

There is a newer version: 5.1.4
Show newest version
/*
 * Copyright (c) 2013 Snowflake Computing Inc. All right reserved.
 */
package net.snowflake.common.core;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.InputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.jar.Attributes;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

/**
 * Component information, like version, SVN rev, etc is available through this class.
 *
 * 

It works by interrogating the class passed to the initialize() method. Current implementation * retrieves the version information from the jar that the passed in class had been loaded from, if * any. * *

* * @author ppovinec */ public class ComponentInfo { /** Supported version format pattern */ public static final String VERSION_FORMAT_PATTERN = "[0-9]+(\\.[0-9]+)(\\.[0-9]+)(\\.[0-9a-zA-Z_-]+)?"; /** The delimiter between the numbers in the version number */ private static final String VERSION_DELIMITER = "\\."; /** * Version info - purely a data class. All fields set to -1 if the value could not be determined. */ public static class Version implements Comparable { private final int majorVersion; private final int minorVersion; private final int patchVersion; private String buildId; public Version() { this.majorVersion = 0; this.minorVersion = 0; this.patchVersion = 0; this.buildId = null; } public Version(int majorVersion, int minorVersion, int patchVersion, String buildId) { this.majorVersion = majorVersion; this.minorVersion = minorVersion; this.patchVersion = patchVersion; this.buildId = buildId; } public Version(String version) { // only initialize if version has correct format if (version != null && version.matches(VERSION_FORMAT_PATTERN)) { List versionDecomposed = Arrays.asList(version.split(VERSION_DELIMITER, -1)); if (versionDecomposed.size() >= 3) { this.majorVersion = Integer.parseInt(versionDecomposed.get(0)); this.minorVersion = Integer.parseInt(versionDecomposed.get(1)); this.patchVersion = Integer.parseInt(versionDecomposed.get(2)); return; } } this.majorVersion = 0; this.minorVersion = 0; this.patchVersion = 0; } /** * Reverse engineer a Version from a version-rank. WARNING: Keep this consistent with * getVersionRank * * @param versionRank - the version rank * @return - the corresponding version */ public static final Version fromRank(long versionRank) { return new Version( (int) (versionRank >> 32), // majorVersion (int) ((versionRank >> 16) & Short.MAX_VALUE), // minorVersion (int) (versionRank & Short.MAX_VALUE), // patchVersion "" // buildId ); } /** * Generate an absolute version ranking allowing to compare two versions * * @return version rank */ @JsonIgnore public long getVersionRank() { return (((long) this.majorVersion) << 32) | (((long) this.minorVersion) << 16) | ((long) this.patchVersion); } public int getMajorVersion() { return majorVersion; } public int getMinorVersion() { return minorVersion; } public int getPatchVersion() { return patchVersion; } public String getBuildId() { return buildId; } /** * Backward compatibility, extract svn revision from build id * * @return SVN revision */ @JsonIgnore public int getSvnRevisionObsolete() { try { return (buildId != null) ? Integer.parseInt(this.buildId) : -1; } catch (NumberFormatException ex) { return 0; } } /** * Return the GS version number as a string so that it can be displayed by the UI * * @param showBuildNumber true if we should add the build number (internal) * @return version of that GS instance as a string */ public String getVersionAsString(boolean showBuildNumber) { return getVersionAsString(showBuildNumber, true); } public String getVersionAsString(boolean showBuildNumber, boolean includePatchVersion) { String versionStr; if (majorVersion == -1) { versionStr = "Dev"; } else { versionStr = ((majorVersion > -1) ? majorVersion : 0) + "." + ((minorVersion > -1) ? minorVersion : 0); if (includePatchVersion) { versionStr += "." + ((patchVersion > -1) ? patchVersion : 0); } if (majorVersion == 0) { versionStr += " (Beta)"; } } if (showBuildNumber && buildId != null) { versionStr += " b" + buildId; } return versionStr; } /** * This is to be able to de-serialize old export files * * @param svnRevision svn revision number */ public void setSvnRevision(int svnRevision) { this.buildId = String.valueOf(svnRevision); } @Override public int compareTo(Version other) { if (this == other) { return 0; } return Comparator.comparingInt(Version::getMajorVersion) .thenComparingInt(Version::getMinorVersion) .thenComparingInt(Version::getPatchVersion) // (spelley) // this isn't a true numeric sort but whatever. We're moving to // git buildIds anyways. So long as 2 String-but-numeric buildIds // have the same number of chars/digits this will correctly // compare them. I did this just to be able to test GS job retry // on a test deployment .thenComparing(Version::getBuildId, Comparator.nullsLast(Comparator.naturalOrder())) .compare(this, other); } @Override public String toString() { return "majorVersion=" + majorVersion + ", minorVersion=" + minorVersion + ", patchVersion=" + patchVersion + ", buildId=" + buildId; } @Override public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof Version)) { return false; } final Version version = (Version) o; return majorVersion == version.majorVersion && minorVersion == version.minorVersion && patchVersion == version.patchVersion && Objects.equals(buildId, version.buildId); } @Override public int hashCode() { return Objects.hash(majorVersion, minorVersion, patchVersion, buildId); } } private static Version theVersion; private static boolean initialized = false; /** * Get the version info part of the ComponentInfo. * *

* * @return version info * @throws IllegalStateException if the ComponentInfo has not been initialized */ public static Version getVersion() { if (!initialized) { throw new IllegalStateException("ComponentInfo not initialized"); } return theVersion; } /** * Initialize the ComponentInfo by retrieving all the necessary information from the available * sources. * *

* * @throws Exception if unable to complete the initialization */ public static void initialize() throws Exception { initialize(net.snowflake.common.core.ComponentInfo.class); } /** * Initialize the ComponentInfo by retrieving all the necessary information from the available * sources. * *

* * @param klass that should be interrogated * @throws Exception if unable to complete the initialization */ public static void initialize(Class klass) throws Exception { String implVersion; String buildId; // Get the URI of the source of the passed in class. URI jarURI = klass.getProtectionDomain().getCodeSource().getLocation().toURI(); // If this class is not loaded from a jar, assume we are in dev, and all // versions are returned as -1. if (!jarURI.toString().endsWith(".jar")) { theVersion = new Version(-1, -1, -1, null); initialized = true; return; } // Open the jar as a stream and read its manifest. InputStream is = null; try { is = jarURI.toURL().openStream(); if (is == null) { throw new RuntimeException("Couldn't open jar:" + jarURI); } JarInputStream jarStream = new JarInputStream(is); Manifest mf = jarStream.getManifest(); if (mf == null) { throw new IllegalStateException("Couldn't find manifest in:" + jarURI.toURL()); } // Parse the manifest to retrieve implementation version and SVN version. Attributes mainAttribs = mf.getMainAttributes(); implVersion = mainAttribs.getValue("Snowflake-Version"); buildId = mainAttribs.getValue("Snowflake-BuildId"); } catch (Exception ex) { // Simply rethrow... throw ex; } finally { if (is != null) { is.close(); } } // Parse implementation version as major.minor. Anything that doesn't // conform is silently translated to -1.-1 (this is mostly to workaround // the version strings like 1.0-SNAPSHOT in dev. int major = -1; int minor = -1; int patch = -1; if (implVersion != null) { try { String[] majorMinorPatch = implVersion.split("\\."); if (majorMinorPatch != null && majorMinorPatch.length >= 2) { major = Integer.parseInt(majorMinorPatch[0]); minor = Integer.parseInt(majorMinorPatch[1]); if (majorMinorPatch.length >= 3) patch = Integer.parseInt(majorMinorPatch[2]); else patch = 0; } } catch (Exception ex) { // Swallow. Will use default of -1. } } // Only Version in ComponentInfo now, so we're done with the initialization. theVersion = new Version(major, minor, patch, buildId); initialized = true; } /** * Initialize the ComponentInfo by explicitly passing it a {@link Version}. * * @param version that should be stored */ public static void initialize(final Version version) { theVersion = version; initialized = version != null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy