package com.jcdm.common.utils.uuid; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import com.jcdm.common.exception.UtilException; /** * æ供通用唯一识别ç (universally unique identifier)(UUID)实现 * * @author jc */ public final class UUID implements java.io.Serializable, Comparable<UUID> { private static final long serialVersionUID = -1185015143654744140L; /** * SecureRandom çš„å•ä¾‹ * */ private static class Holder { static final SecureRandom numberGenerator = getSecureRandom(); } /** æ¤UUID的最高64æœ‰æ•ˆä½ */ private final long mostSigBits; /** æ¤UUID的最低64æœ‰æ•ˆä½ */ private final long leastSigBits; /** * ç§æœ‰æž„é€ * * @param data æ•°æ® */ private UUID(byte[] data) { long msb = 0; long lsb = 0; assert data.length == 16 : "data must be 16 bytes in length"; for (int i = 0; i < 8; i++) { msb = (msb << 8) | (data[i] & 0xff); } for (int i = 8; i < 16; i++) { lsb = (lsb << 8) | (data[i] & 0xff); } this.mostSigBits = msb; this.leastSigBits = lsb; } /** * 使用指定的数æ®æž„é€ æ–°çš„ UUID。 * * @param mostSigBits 用于 {@code UUID} 的最高有效 64 ä½ * @param leastSigBits 用于 {@code UUID} 的最低有效 64 ä½ */ public UUID(long mostSigBits, long leastSigBits) { this.mostSigBits = mostSigBits; this.leastSigBits = leastSigBits; } /** * 获å–类型 4(伪éšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚。 * * @return éšæœºç”Ÿæˆçš„ {@code UUID} */ public static UUID fastUUID() { return randomUUID(false); } /** * 获å–类型 4(伪éšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚。 ä½¿ç”¨åŠ å¯†çš„å¼ºä¼ªéšæœºæ•°ç”Ÿæˆå™¨ç”Ÿæˆè¯¥ UUID。 * * @return éšæœºç”Ÿæˆçš„ {@code UUID} */ public static UUID randomUUID() { return randomUUID(true); } /** * 获å–类型 4(伪éšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚。 ä½¿ç”¨åŠ å¯†çš„å¼ºä¼ªéšæœºæ•°ç”Ÿæˆå™¨ç”Ÿæˆè¯¥ UUID。 * * @param isSecure 是å¦ä½¿ç”¨{@link SecureRandom}如果是å¯ä»¥èŽ·å¾—更安全的éšæœºç ,å¦åˆ™å¯ä»¥å¾—到更好的性能 * @return éšæœºç”Ÿæˆçš„ {@code UUID} */ public static UUID randomUUID(boolean isSecure) { final Random ng = isSecure ? Holder.numberGenerator : getRandom(); byte[] randomBytes = new byte[16]; ng.nextBytes(randomBytes); randomBytes[6] &= 0x0f; /* clear version */ randomBytes[6] |= 0x40; /* set to version 4 */ randomBytes[8] &= 0x3f; /* clear variant */ randomBytes[8] |= 0x80; /* set to IETF variant */ return new UUID(randomBytes); } /** * æ ¹æ®æŒ‡å®šçš„å—节数组获å–类型 3(基于å称的)UUID çš„é™æ€å·¥åŽ‚。 * * @param name ç”¨äºŽæž„é€ UUID çš„å—节数组。 * * @return æ ¹æ®æŒ‡å®šæ•°ç»„生æˆçš„ {@code UUID} */ public static UUID nameUUIDFromBytes(byte[] name) { MessageDigest md; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nsae) { throw new InternalError("MD5 not supported"); } byte[] md5Bytes = md.digest(name); md5Bytes[6] &= 0x0f; /* clear version */ md5Bytes[6] |= 0x30; /* set to version 3 */ md5Bytes[8] &= 0x3f; /* clear variant */ md5Bytes[8] |= 0x80; /* set to IETF variant */ return new UUID(md5Bytes); } /** * æ ¹æ® {@link #toString()} 方法ä¸æè¿°çš„å—ç¬¦ä¸²æ ‡å‡†è¡¨ç¤ºå½¢å¼åˆ›å»º{@code UUID}。 * * @param name 指定 {@code UUID} å—符串 * @return 具有指定值的 {@code UUID} * @throws IllegalArgumentException 如果 name 与 {@link #toString} ä¸æè¿°çš„å—符串表示形å¼ä¸ç¬¦æŠ›å‡ºæ¤å¼‚常 * */ public static UUID fromString(String name) { String[] components = name.split("-"); if (components.length != 5) { throw new IllegalArgumentException("Invalid UUID string: " + name); } for (int i = 0; i < 5; i++) { components[i] = "0x" + components[i]; } long mostSigBits = Long.decode(components[0]).longValue(); mostSigBits <<= 16; mostSigBits |= Long.decode(components[1]).longValue(); mostSigBits <<= 16; mostSigBits |= Long.decode(components[2]).longValue(); long leastSigBits = Long.decode(components[3]).longValue(); leastSigBits <<= 48; leastSigBits |= Long.decode(components[4]).longValue(); return new UUID(mostSigBits, leastSigBits); } /** * è¿”å›žæ¤ UUID çš„ 128 ä½å€¼ä¸çš„最低有效 64 ä½ã€‚ * * @return æ¤ UUID çš„ 128 ä½å€¼ä¸çš„最低有效 64 ä½ã€‚ */ public long getLeastSignificantBits() { return leastSigBits; } /** * è¿”å›žæ¤ UUID çš„ 128 ä½å€¼ä¸çš„最高有效 64 ä½ã€‚ * * @return æ¤ UUID çš„ 128 ä½å€¼ä¸æœ€é«˜æœ‰æ•ˆ 64 ä½ã€‚ */ public long getMostSignificantBits() { return mostSigBits; } /** * ä¸Žæ¤ {@code UUID} 相关è”的版本å·. 版本å·æè¿°æ¤ {@code UUID} 是如何生æˆçš„。 * <p> * 版本å·å…·æœ‰ä»¥ä¸‹å«æ„: * <ul> * <li>1 基于时间的 UUID * <li>2 DCE 安全 UUID * <li>3 基于å称的 UUID * <li>4 éšæœºç”Ÿæˆçš„ UUID * </ul> * * @return æ¤ {@code UUID} çš„ç‰ˆæœ¬å· */ public int version() { // Version is bits masked by 0x000000000000F000 in MS long return (int) ((mostSigBits >> 12) & 0x0f); } /** * ä¸Žæ¤ {@code UUID} 相关è”çš„å˜ä½“å·ã€‚å˜ä½“å·æè¿° {@code UUID} 的布局。 * <p> * å˜ä½“å·å…·æœ‰ä»¥ä¸‹å«æ„: * <ul> * <li>0 为 NCS å‘åŽå…¼å®¹ä¿ç•™ * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于æ¤ç±» * <li>6 ä¿ç•™ï¼Œå¾®è½¯å‘åŽå…¼å®¹ * <li>7 ä¿ç•™ä¾›ä»¥åŽå®šä¹‰ä½¿ç”¨ * </ul> * * @return æ¤ {@code UUID} 相关è”çš„å˜ä½“å· */ public int variant() { // This field is composed of a varying number of bits. // 0 - - Reserved for NCS backward compatibility // 1 0 - The IETF aka Leach-Salz variant (used by this class) // 1 1 0 Reserved, Microsoft backward compatibility // 1 1 1 Reserved for future definition. return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); } /** * ä¸Žæ¤ UUID 相关è”的时间戳值。 * * <p> * 60 ä½çš„æ—¶é—´æˆ³å€¼æ ¹æ®æ¤ {@code UUID} çš„ time_lowã€time_mid å’Œ time_hi å—æ®µæž„é€ ã€‚<br> * 所得到的时间戳以 100 毫微秒为å•ä½ï¼Œä»Ž UTC(通用å调时间) 1582 å¹´ 10 月 15 日零时开始。 * * <p> * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)ä¸æ‰æœ‰æ„义。<br> * å¦‚æžœæ¤ {@code UUID} ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则æ¤æ–¹æ³•æŠ›å‡º UnsupportedOperationException。 * * @throws UnsupportedOperationException å¦‚æžœæ¤ {@code UUID} ä¸æ˜¯ version 为 1 çš„ UUID。 */ public long timestamp() throws UnsupportedOperationException { checkTimeBase(); return (mostSigBits & 0x0FFFL) << 48// | ((mostSigBits >> 16) & 0x0FFFFL) << 32// | mostSigBits >>> 32; } /** * ä¸Žæ¤ UUID 相关è”的时钟åºåˆ—值。 * * <p> * 14 ä½çš„时钟åºåˆ—å€¼æ ¹æ®æ¤ UUID çš„ clock_seq å—æ®µæž„é€ ã€‚clock_seq å—段用于ä¿è¯åœ¨åŸºäºŽæ—¶é—´çš„ UUID ä¸çš„时间唯一性。 * <p> * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)ä¸æ‰æœ‰æ„义。 å¦‚æžœæ¤ UUID ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则æ¤æ–¹æ³•æŠ›å‡º * UnsupportedOperationException。 * * @return æ¤ {@code UUID} 的时钟åºåˆ— * * @throws UnsupportedOperationException å¦‚æžœæ¤ UUID çš„ version ä¸ä¸º 1 */ public int clockSequence() throws UnsupportedOperationException { checkTimeBase(); return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); } /** * ä¸Žæ¤ UUID 相关的节点值。 * * <p> * 48 ä½çš„èŠ‚ç‚¹å€¼æ ¹æ®æ¤ UUID çš„ node å—æ®µæž„é€ ã€‚æ¤å—段旨在用于ä¿å˜æœºå™¨çš„ IEEE 802 地å€ï¼Œè¯¥åœ°å€ç”¨äºŽç”Ÿæˆæ¤ UUID 以ä¿è¯ç©ºé—´å”¯ä¸€æ€§ã€‚ * <p> * 节点值仅在基于时间的 UUID(其 version 类型为 1)ä¸æ‰æœ‰æ„义。<br> * å¦‚æžœæ¤ UUID ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则æ¤æ–¹æ³•æŠ›å‡º UnsupportedOperationException。 * * @return æ¤ {@code UUID} 的节点值 * * @throws UnsupportedOperationException å¦‚æžœæ¤ UUID çš„ version ä¸ä¸º 1 */ public long node() throws UnsupportedOperationException { checkTimeBase(); return leastSigBits & 0x0000FFFFFFFFFFFFL; } /** * 返回æ¤{@code UUID} çš„å—符串表现形å¼ã€‚ * * <p> * UUID çš„å—符串表示形å¼ç”±æ¤ BNF æ述: * * <pre> * {@code * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> * time_low = 4*<hexOctet> * time_mid = 2*<hexOctet> * time_high_and_version = 2*<hexOctet> * variant_and_sequence = 2*<hexOctet> * node = 6*<hexOctet> * hexOctet = <hexDigit><hexDigit> * hexDigit = [0-9a-fA-F] * } * </pre> * * </blockquote> * * @return æ¤{@code UUID} çš„å—ç¬¦ä¸²è¡¨çŽ°å½¢å¼ * @see #toString(boolean) */ @Override public String toString() { return toString(false); } /** * 返回æ¤{@code UUID} çš„å—符串表现形å¼ã€‚ * * <p> * UUID çš„å—符串表示形å¼ç”±æ¤ BNF æ述: * * <pre> * {@code * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> * time_low = 4*<hexOctet> * time_mid = 2*<hexOctet> * time_high_and_version = 2*<hexOctet> * variant_and_sequence = 2*<hexOctet> * node = 6*<hexOctet> * hexOctet = <hexDigit><hexDigit> * hexDigit = [0-9a-fA-F] * } * </pre> * * </blockquote> * * @param isSimple 是å¦ç®€å•æ¨¡å¼ï¼Œç®€å•æ¨¡å¼ä¸ºä¸å¸¦'-'çš„UUIDå—符串 * @return æ¤{@code UUID} çš„å—ç¬¦ä¸²è¡¨çŽ°å½¢å¼ */ public String toString(boolean isSimple) { final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); // time_low builder.append(digits(mostSigBits >> 32, 8)); if (!isSimple) { builder.append('-'); } // time_mid builder.append(digits(mostSigBits >> 16, 4)); if (!isSimple) { builder.append('-'); } // time_high_and_version builder.append(digits(mostSigBits, 4)); if (!isSimple) { builder.append('-'); } // variant_and_sequence builder.append(digits(leastSigBits >> 48, 4)); if (!isSimple) { builder.append('-'); } // node builder.append(digits(leastSigBits, 12)); return builder.toString(); } /** * è¿”å›žæ¤ UUID 的哈希ç 。 * * @return UUID 的哈希ç 值。 */ @Override public int hashCode() { long hilo = mostSigBits ^ leastSigBits; return ((int) (hilo >> 32)) ^ (int) hilo; } /** * å°†æ¤å¯¹è±¡ä¸ŽæŒ‡å®šå¯¹è±¡æ¯”较。 * <p> * 当且仅当å‚æ•°ä¸ä¸º {@code null}ã€è€Œæ˜¯ä¸€ä¸ª UUID 对象ã€å…·æœ‰ä¸Žæ¤ UUID 相åŒçš„ varriantã€åŒ…å«ç›¸åŒçš„值(æ¯ä¸€ä½å‡ç›¸åŒï¼‰æ—¶ï¼Œç»“æžœæ‰ä¸º {@code true}。 * * @param obj è¦ä¸Žä¹‹æ¯”较的对象 * * @return 如果对象相åŒï¼Œåˆ™è¿”回 {@code true}ï¼›å¦åˆ™è¿”回 {@code false} */ @Override public boolean equals(Object obj) { if ((null == obj) || (obj.getClass() != UUID.class)) { return false; } UUID id = (UUID) obj; return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); } // Comparison Operations /** * å°†æ¤ UUID 与指定的 UUID 比较。 * * <p> * 如果两个 UUID ä¸åŒï¼Œä¸”第一个 UUID 的最高有效å—段大于第二个 UUID 的对应å—段,则第一个 UUID 大于第二个 UUID。 * * @param val ä¸Žæ¤ UUID 比较的 UUID * * @return åœ¨æ¤ UUID å°äºŽã€ç‰äºŽæˆ–大于 val 时,分别返回 -1ã€0 或 1。 * */ @Override public int compareTo(UUID val) { // The ordering is intentionally set up so that the UUIDs // can simply be numerically compared as two numbers return (this.mostSigBits < val.mostSigBits ? -1 : // (this.mostSigBits > val.mostSigBits ? 1 : // (this.leastSigBits < val.leastSigBits ? -1 : // (this.leastSigBits > val.leastSigBits ? 1 : // 0)))); } // ------------------------------------------------------------------------------------------------------------------- // Private method start /** * 返回指定数å—对应的hex值 * * @param val 值 * @param digits ä½ * @return 值 */ private static String digits(long val, int digits) { long hi = 1L << (digits * 4); return Long.toHexString(hi | (val & (hi - 1))).substring(1); } /** * 检查是å¦ä¸ºtime-based版本UUID */ private void checkTimeBase() { if (version() != 1) { throw new UnsupportedOperationException("Not a time-based UUID"); } } /** * 获å–{@link SecureRandom},类æä¾›åŠ å¯†çš„å¼ºéšæœºæ•°ç”Ÿæˆå™¨ (RNG) * * @return {@link SecureRandom} */ public static SecureRandom getSecureRandom() { try { return SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { throw new UtilException(e); } } /** * 获å–éšæœºæ•°ç”Ÿæˆå™¨å¯¹è±¡<br> * ThreadLocalRandom是JDK 7之åŽæ供并å‘产生éšæœºæ•°ï¼Œèƒ½å¤Ÿè§£å†³å¤šä¸ªçº¿ç¨‹å‘生的竞争争夺。 * * @return {@link ThreadLocalRandom} */ public static ThreadLocalRandom getRandom() { return ThreadLocalRandom.current(); } }