diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java index 099b2bb536e..6872e241f82 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.ClassHelper; import org.apache.dubbo.common.utils.StringUtils; +import java.io.IOException; import java.net.URL; import java.security.CodeSource; import java.util.Enumeration; @@ -28,12 +29,16 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Version */ public final class Version { private static final Logger logger = LoggerFactory.getLogger(Version.class); + + private static final Pattern PREFIX_DIGITS_PATTERN = Pattern.compile("^([0-9]*).*"); // Dubbo RPC protocol version, for compatibility, it must not be between 2.0.10 ~ 2.6.2 public static final String DEFAULT_DUBBO_PROTOCOL_VERSION = "2.0.2"; @@ -120,73 +125,47 @@ private static int parseInt(String version) { String[] vArr = version.split("\\."); int len = vArr.length; for (int i = 0; i < len; i++) { - v += Integer.parseInt(getDigital(vArr[i])) * Math.pow(10, (len - i - 1) * 2); + v += Integer.parseInt(getPrefixDigits(vArr[i])) * Math.pow(10, (len - i - 1) * 2); } return v; } - private static String getDigital(String v) { - int index = 0; - for (int i = 0; i < v.length(); i++) { - char c = v.charAt(i); - if (Character.isDigit(c)) { - if (i == v.length() - 1) { - index = i + 1; - } else { - index = i; - } - } else { - index = i; - break; - } - } - return v.substring(0, index); - } - - private static boolean hasResource(String path) { - try { - return Version.class.getClassLoader().getResource(path) != null; - } catch (Throwable t) { - return false; + /** + * get prefix digits from given version string + */ + private static String getPrefixDigits(String v) { + Matcher matcher = PREFIX_DIGITS_PATTERN.matcher(v); + if (matcher.find()) { + return matcher.group(1); } + return ""; } public static String getVersion(Class cls, String defaultVersion) { try { // find version info from MANIFEST.MF first String version = cls.getPackage().getImplementationVersion(); - if (StringUtils.isEmpty(version)) { - version = cls.getPackage().getSpecificationVersion(); + if (!StringUtils.isEmpty(version)) { + return version; } - if (StringUtils.isEmpty(version)) { - // guess version fro jar file name if nothing's found from MANIFEST.MF - CodeSource codeSource = cls.getProtectionDomain().getCodeSource(); - if (codeSource == null) { - logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion); - } else { - String file = codeSource.getLocation().getFile(); - if (file != null && file.length() > 0 && file.endsWith(".jar")) { - file = file.substring(0, file.length() - 4); - int i = file.lastIndexOf('/'); - if (i >= 0) { - file = file.substring(i + 1); - } - i = file.indexOf("-"); - if (i >= 0) { - file = file.substring(i + 1); - } - while (file.length() > 0 && !Character.isDigit(file.charAt(0))) { - i = file.indexOf("-"); - if (i >= 0) { - file = file.substring(i + 1); - } else { - break; - } - } - version = file; - } - } + + version = cls.getPackage().getSpecificationVersion(); + if (!StringUtils.isEmpty(version)) { + return version; + } + + // guess version fro jar file name if nothing's found from MANIFEST.MF + CodeSource codeSource = cls.getProtectionDomain().getCodeSource(); + if (codeSource == null) { + logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion); + return defaultVersion; + } + + String file = codeSource.getLocation().getFile(); + if (!StringUtils.isEmpty(file) && file.endsWith(".jar")) { + version = getFromFile(file); } + // return default version if no version info is found return StringUtils.isEmpty(version) ? defaultVersion : version; } catch (Throwable e) { @@ -196,6 +175,37 @@ public static String getVersion(Class cls, String defaultVersion) { } } + /** + * get version from file: path/to/group-module-x.y.z.jar, returns x.y.z + */ + private static String getFromFile(String file) { + // remove suffix ".jar": "path/to/group-module-x.y.z" + file = file.substring(0, file.length() - 4); + + // remove path: "group-module-x.y.z" + int i = file.lastIndexOf('/'); + if (i >= 0) { + file = file.substring(i + 1); + } + + // remove group: "module-x.y.z" + i = file.indexOf("-"); + if (i >= 0) { + file = file.substring(i + 1); + } + + // remove module: "x.y.z" + while (file.length() > 0 && !Character.isDigit(file.charAt(0))) { + i = file.indexOf("-"); + if (i >= 0) { + file = file.substring(i + 1); + } else { + break; + } + } + return file; + } + public static void checkDuplicate(Class cls, boolean failOnError) { checkDuplicate(cls.getName().replace('.', '/') + ".class", failOnError); } @@ -207,17 +217,7 @@ public static void checkDuplicate(Class cls) { public static void checkDuplicate(String path, boolean failOnError) { try { // search in caller's classloader - Enumeration urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path); - Set files = new HashSet(); - while (urls.hasMoreElements()) { - URL url = urls.nextElement(); - if (url != null) { - String file = url.getFile(); - if (file != null && file.length() > 0) { - files.add(file); - } - } - } + Set files = getResources(path); // duplicated jar is found if (files.size() > 1) { String error = "Duplicate class " + path + " in " + files.size() + " jar " + files; @@ -232,4 +232,22 @@ public static void checkDuplicate(String path, boolean failOnError) { } } + /** + * search resources in caller's classloader + */ + private static Set getResources(String path) throws IOException { + Enumeration urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path); + Set files = new HashSet(); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + if (url != null) { + String file = url.getFile(); + if (file != null && file.length() > 0) { + files.add(file); + } + } + } + return files; + } + }