/******************************************************************************* * Copyright (c) May 18, 2011 Zend Technologies Ltd. * 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 *******************************************************************************/ package org.zend.sdklib.internal.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.zend.sdklib.SdkException; import org.zend.sdklib.repository.IRepository; import org.zend.sdklib.repository.site.Application; import org.zend.sdklib.repository.site.Site; /** * Helps with version compare operations * * @author Roy, 2011 */ public class VersionsUtils { private final static String patternRange = "[\\(\\[]\\d{1,3}.\\d{1,3}(.\\d{1,3})?(.\\d{1,3})?(\\s)*,(\\s)*\\d{1,3}.\\d{1,3}(.\\d{1,3})?(.\\d{1,3})?[\\)\\]]"; private final static String patternVersion = "\\d{1,3}.\\d{1,3}(.\\d{1,3})?(.\\d{1,3})?"; /** * Tests that a version is in between a given range. * * <pre> * assertTrue(inBetween("5.1", "[5.0, 6.4]")); * assertTrue(inBetween("5.0", "[5.0, 6.4]")); * assertFalse(inBetween("5.0", "(5.0, 6.4]")); * assertFalse(inBetween("4.9", "[5.0, 6.4]")); * assertTrue(inBetween("6.4", "[5.0, 6.4]")); * assertFalse(inBetween("6.4", "[5.0, 6.4)")); * assertFalse(inBetween("7.0", "[5.0, 6.4]")); * </pre> * * @param currentVersion * @param range * @return */ public static boolean inBetween(String currentVersion, String range) { if (!range.matches(patternRange) || invalidVersion(currentVersion)) { throw new IllegalStateException( "Corrupted range or version specified in site, " + "consider contacting your site administrator"); } final Matcher matcher = Pattern.compile(patternVersion).matcher(range); boolean startInclusive = range.startsWith("["); boolean endInclusive = range.endsWith("]"); matcher.find(); String start = matcher.group(); matcher.find(); String end = matcher.group(); long s = normalizeVersion(start); long e = normalizeVersion(end); long c = normalizeVersion(currentVersion); return (s < c || (startInclusive && s == c)) && (e > c || (endInclusive && e == c)); } /** * Compare two given versions. * * <pre> * < 0 * </pre> * * ver1 is greater than ver2 * * <pre> * = 0 * </pre> * * ver1 is equal to ver2 * * <pre> * > 0 * </pre> * * ver1 is smaller than ver2 * * @param ver1 * @param ver2 * @return */ public static long versionCompare(String ver1, String ver2) { if (invalidVersion(ver1) || invalidVersion(ver2)) { throw new IllegalArgumentException("illegal format of version: " + ver1 + " or " + ver2); } return normalizeVersion(ver1) - normalizeVersion(ver2); } public static long normalizeVersion(String version) { if (invalidVersion(version)) { throw new IllegalArgumentException("illegal format of version: " + version); } final String[] split = version.split("\\."); long sum = 0; for (int i = 0; i < split.length; i++) { sum += Integer.valueOf(split[i]) * Math.pow(10, (9 - i * 3)); } return sum; } public static boolean invalidVersion(String currentVersion) { return !currentVersion.matches(patternVersion); } /** * @param applicationName * @param currentVersion * @return * @throws SdkException */ public static Application getApplicationUpdates(IRepository repository, String applicationName, String currentVersion) throws SdkException { final Site site = repository.getSite(); for (Application application : site.getApplication()) { if (application.getName().equalsIgnoreCase(applicationName) && validUpdate(currentVersion, application.getVersion(), application.getUpdateRange())) { return application; } } return null; } /** * There is an update if <br/> * 1. current version is smaller than new version on site <br/> * 2. current version is in between the range of the update<br/> * * @param currentVersion * @param newVersion * @param range * @return */ public static boolean validUpdate(String currentVersion, String newVersion, String range) { return versionCompare(newVersion, currentVersion) > 0 && inBetween(currentVersion, range); } /** * Returns the version part out of the package name * For example <pre>"quickstart-1.23.4.zpk"</pre> returns <pre>"1.23.4"</pre> * @param packageName * @return version */ public static final String getVersion(String packageName) { final Matcher m = Pattern.compile(patternVersion).matcher(packageName); final boolean find = m.find(); if (!find) { throw new IllegalArgumentException("package name should include a version number"); } return m.group(); } }