/* Util.java Purpose: Description: History: Mar 20, 2012 Created by pao Copyright (C) 2011 Potix Corporation. All Rights Reserved. */ package org.zkoss.zats.mimic.impl; import java.io.Closeable; import java.math.BigInteger; import java.util.Random; import java.util.logging.Logger; import org.zkoss.Version; import org.zkoss.zats.ZatsException; /** * Utilities for implementation. * @author pao */ public class Util { private static Logger logger = Logger.getLogger(Util.class.getName()); private static BigInteger zkVersion; // current zk version static { // load current zk version try { String version = Version.class.getField("UID").get(null).toString(); zkVersion = Util.parseVersion(version); if(zkVersion == null) { throw new Exception("failed to parse ZK version string: " + version); } } catch (Throwable e) { throw new ZatsException("cannot load zk", e); } } public static BigInteger getZKVersion() { return zkVersion; } public static boolean isZKVersion(int primaryVer){ byte[] ver = zkVersion.toByteArray(); if(ver!=null && ver.length>=3){ return ver[0]==primaryVer; } return false; } public static boolean hasClass(String className){ try{ try{ Util.class.getClassLoader().loadClass(className); return true; }catch(ClassNotFoundException x){ return false; } }catch(Throwable x){ logger.warning(x.getMessage()); } return false; } /** * check the given version range is match current ZK version or not. * it accepts wildcard "*". e.g * or 5.0.* or 6.*.* */ public static boolean checkVersion(String startVersion, String endVersion){ // check version // If current isn't between start and end version, ignore this register. BigInteger start = "*".equals(startVersion.trim()) ? BigInteger.ZERO : Util.parseVersion(startVersion.replaceAll("[*]", "0")); BigInteger end = "*".equals(endVersion.trim()) ? BigInteger .valueOf(Long.MAX_VALUE) : Util.parseVersion(endVersion.replaceAll("[*]", String.valueOf(Byte.MAX_VALUE))); if (start == null || end == null) throw new IllegalArgumentException("wrong version format"); if (zkVersion.compareTo(start) < 0 || zkVersion.compareTo(end) > 0) return false; return true; } /** * close resource without any exception. * @param r resource. If null, do nothing. */ public static void close(Closeable r) { try { r.close(); } catch (Throwable e) { } } /** * parse ZK version to uniform number for compare. * the method design for normal version string, but it will still parse as long as possible. * @param version ZK version string. * @return uniform number or null if failed to parse. */ public static BigInteger parseVersion(final String version) { if (version == null || version.length() <= 0) return null; // check version and show some warning if (!version.matches("^\\s*\\d+(?:\\.\\d+)*\\s*$")) { logger.warning("not a normal ZK version: <" + version + ">"); } // parse string into byte array byte[] raw = new byte[4]; // String[] tokens = version.trim().split("[^\\d\\w]+"); // it remain combined digital and char. terms int length = Math.min(raw.length, tokens.length); for (int i = 0; i < length; ++i) { try { raw[i] = Byte.parseByte(tokens[i]); } catch (NumberFormatException e) { logger.warning("unrecognized part when parsing version: <" + tokens[i] + ">"); } } // major version term must be existed if (raw[0] <= 0) { return null; } // create extended BigInteger // Because raw data is big-endian, major number is most significant. return new BigInteger(raw) { private static final long serialVersionUID = 2712388085709130462L; public String toString() { return version; } }; } public static String generateRandomString() { return "zats-" + Integer.toHexString(System.identityHashCode(Util.class)) + new BigInteger(64, new Random()).abs().toString(36); } }