/******************************************************************************* * Copyright (c) 2009 Vlad Dumitrescu and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Vlad Dumitrescu *******************************************************************************/ package com.ericsson.otp.erlang; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.eclipse.core.runtime.Assert; public final class RuntimeVersion implements Comparable<RuntimeVersion> { public static final int UNUSED = -1; private static final char[] minorMap = new char[] { 'A', 'B', 'C' }; private final int major; private final int minor; private int micro; public RuntimeVersion(final RuntimeVersion other) { major = other.major; minor = other.minor; micro = other.micro; } public RuntimeVersion(final int major, final int minor, final int micro) { Assert.isTrue(major >= UNUSED); Assert.isTrue(minor >= UNUSED); Assert.isTrue(micro >= UNUSED); this.major = major; this.minor = minor; this.micro = micro; } public RuntimeVersion(final int major, final int minor) { this(major, minor, UNUSED); } public RuntimeVersion(final int major) { this(major, UNUSED, UNUSED); } public RuntimeVersion(final String version) { this(version, null); } public RuntimeVersion(final String version, final String aMicro) { if (version == null || version.length() == 0) { major = UNUSED; minor = UNUSED; micro = UNUSED; return; } Assert.isTrue(version.charAt(0) == 'R'); int i = 1; char c; do { c = version.charAt(i); if (c >= '0' && c <= '9') { i++; } } while (c >= '0' && c <= '9' && i < version.length()); final String substring = version.substring(1, i); major = Integer.parseInt(substring); if (i < version.length()) { c = version.charAt(i); minor = Arrays.binarySearch(minorMap, c); i++; if (major >= 13) { if (i < version.length()) { micro = Integer.parseInt(version.substring(i)); } else { micro = 0; } } else { if (aMicro != null) { micro = Integer.parseInt(aMicro); } else { final int n = version.indexOf('-'); if (n == -1) { micro = UNUSED; } else { micro = Integer.parseInt(version.substring(n + 1)); } } } } else { minor = UNUSED; micro = UNUSED; } Assert.isTrue(major >= UNUSED); Assert.isTrue(minor >= UNUSED); Assert.isTrue(micro >= UNUSED); } @Override public String toString() { if (major == UNUSED) { return ""; } String result = "R" + Integer.toString(major); if (minor != UNUSED) { result += minorMap[minor]; if (micro != UNUSED) { String m = Integer.toString(micro); if (major < 13) { result += "-" + m; } else { if (micro != 0) { if (m.length() == 1) { m = "0" + m; } result += m; } } } } return result; } @Override public boolean equals(final Object v) { if (!(v instanceof RuntimeVersion)) { return false; } final RuntimeVersion other = (RuntimeVersion) v; return compareTo(other) == 0; } @Override public int compareTo(final RuntimeVersion o) { if (major == o.major) { if (minor == o.minor) { if (micro == o.micro) { return 0; } else { return micro - o.micro; } } else { return minor - o.minor; } } else { return major - o.major; } } public boolean isDefined() { return major != UNUSED; } public boolean isCompatible(final RuntimeVersion other) { return compareTo(other) >= 0; } public boolean isReleaseCompatible(final RuntimeVersion other) { return major == other.major && isCompatible(other); } public RuntimeVersion asMinor() { return new RuntimeVersion(major, minor); } public RuntimeVersion asMajor() { return new RuntimeVersion(major); } @Override public int hashCode() { return super.hashCode(); } public static String getRuntimeVersion(final String path) { if (path == null) { return null; } String result = null; final File boot = new File(path + "/bin/start.boot"); try { final FileInputStream is = new FileInputStream(boot); try { is.skip(14); readstring(is); result = readstring(is); } finally { is.close(); } } catch (final IOException e) { } return result; } public static String getMicroRuntimeVersion(final String path) { if (path == null) { return null; } String result = null; // now get micro version from kernel's minor version final File lib = new File(path + "/lib"); final File[] kernels = lib.listFiles(new FileFilter() { @Override public boolean accept(final File pathname) { try { boolean r = pathname.isDirectory(); r &= pathname.getName().startsWith("kernel-"); final String canonicalPath = pathname.getCanonicalPath() .toLowerCase(); final String absolutePath = pathname.getAbsolutePath() .toLowerCase(); r &= canonicalPath.equals(absolutePath); return r; } catch (final IOException e) { return false; } } }); if (kernels != null && kernels.length > 0) { final int[] krnls = new int[kernels.length]; for (int i = 0; i < kernels.length; i++) { final String k = kernels[i].getName(); try { int p = k.indexOf('.'); if (p < 0) { krnls[i] = 0; } else { p = k.indexOf('.', p + 1); if (p < 0) { krnls[i] = 0; } else { krnls[i] = Integer.parseInt(k.substring(p + 1)); } } } catch (final Exception e) { krnls[i] = 0; } } Arrays.sort(krnls); result = Integer.toString(krnls[krnls.length - 1]); } return result; } public static RuntimeVersion getVersion(final String homeDir) { final String label = RuntimeVersion.getRuntimeVersion(homeDir); final String micro = RuntimeVersion.getMicroRuntimeVersion(homeDir); return new RuntimeVersion(label, micro); } static String readstring(final InputStream is) { try { is.read(); byte[] b = new byte[2]; is.read(b); final int len = b[0] * 256 + b[1]; b = new byte[len]; is.read(b); final String s = new String(b); return s; } catch (final IOException e) { return null; } } public boolean isStable() { return minor > 0; } }