All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.activemq.artemis.utils.UUID Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.utils;

/**
 * UUID represents Universally Unique Identifiers (aka Global UID in Windows
 * world). UUIDs are usually generated via UUIDGenerator (or in case of 'Null
 * UUID', 16 zero bytes, via static method getNullUUID()), or received from
 * external systems.
 * 

* By default class caches the string presentations of UUIDs so that description * is only created the first time it's needed. For memory stingy applications * this caching can be turned off (note though that if uuid.toString() is never * called, desc is never calculated so only loss is the space allocated for the * desc pointer... which can of course be commented out to save memory). *

* Similarly, hash code is calculated when it's needed for the first time, and * from thereon that value is just returned. This means that using UUIDs as keys * should be reasonably efficient. *

* UUIDs can be compared for equality, serialized, cloned and even sorted. * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by * first ordering based on type (in the order of numeric values of types), * secondarily by time stamp (only for time-based time stamps), and finally by * straight numeric byte-by-byte comparison (from most to least significant * bytes). */ public final class UUID { private static final String kHexChars = "0123456789abcdefABCDEF"; public static final byte INDEX_CLOCK_HI = 6; public static final byte INDEX_CLOCK_MID = 4; public static final byte INDEX_CLOCK_LO = 0; public static final byte INDEX_TYPE = 6; // Clock seq. & variant are multiplexed... public static final byte INDEX_CLOCK_SEQUENCE = 8; public static final byte INDEX_VARIATION = 8; public static final byte TYPE_NULL = 0; public static final byte TYPE_TIME_BASED = 1; public static final byte TYPE_DCE = 2; // Not used public static final byte TYPE_NAME_BASED = 3; public static final byte TYPE_RANDOM_BASED = 4; /* * 'Standard' namespaces defined (suggested) by UUID specs: */ public static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8"; public static final String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8"; public static final String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8"; public static final String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8"; /* * By default let's cache desc, can be turned off. For hash code there's no * point in turning it off (since the int is already part of the instance * memory allocation); if you want to save those 4 bytes (or possibly bit * more if alignment is bad) just comment out hash caching. */ private static boolean sDescCaching = true; private final byte[] mId; // Both string presentation and hash value may be cached... private transient String mDesc = null; private transient int mHashCode = 0; /** * @param type UUID type * @param data 16 byte UUID contents */ public UUID(final int type, final byte[] data) { assert data.length == 16; mId = data; // Type is multiplexed with time_hi: mId[UUID.INDEX_TYPE] &= (byte) 0x0F; mId[UUID.INDEX_TYPE] |= (byte) (type << 4); // Variant masks first two bits of the clock_seq_hi: mId[UUID.INDEX_VARIATION] &= (byte) 0x3F; mId[UUID.INDEX_VARIATION] |= (byte) 0x80; } private UUID(final byte[] data) { assert data.length == 16; mId = data; } /** This is for conversions between two types of UUID */ public UUID(java.util.UUID uuid) { this(ByteUtil.doubleLongToBytes(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits())); } public byte[] asBytes() { return mId; } /** * Could use just the default hash code, but we can probably create a better * identity hash (ie. same contents generate same hash) manually, without * sacrificing speed too much. Although multiplications with modulos would * generate better hashing, let's use just shifts, and do 2 bytes at a time. *
* Of course, assuming UUIDs are randomized enough, even simpler approach * might be good enough? *
* Is this a good hash? ... one of these days I better read more about basic * hashing techniques I swear! */ private static final int[] kShifts = {3, 7, 17, 21, 29, 4, 9}; @Override public int hashCode() { if (mHashCode == 0) { // Let's handle first and last byte separately: int result = mId[0] & 0xFF; result |= result << 16; result |= result << 8; for (int i = 1; i < 15; i += 2) { int curr = (mId[i] & 0xFF) << 8 | mId[i + 1] & 0xFF; int shift = UUID.kShifts[i >> 1]; if (shift > 16) { result ^= curr << shift | curr >>> 32 - shift; } else { result ^= curr << shift; } } // and then the last byte: int last = mId[15] & 0xFF; result ^= last << 3; result ^= last << 13; result ^= last << 27; // Let's not accept hash 0 as it indicates 'not hashed yet': if (result == 0) { mHashCode = -1; } else { mHashCode = result; } } return mHashCode; } @Override public String toString() { /* * Could be synchronized, but there isn't much harm in just taking our * chances (ie. in the worst case we'll form the string more than once... * but result is the same) */ if (mDesc == null) { StringBuffer b = new StringBuffer(36); for (int i = 0; i < 16; ++i) { // Need to bypass hyphens: switch (i) { case 4: case 6: case 8: case 10: b.append('-'); break; default: // no-op } int hex = mId[i] & 0xFF; b.append(UUID.kHexChars.charAt(hex >> 4)); b.append(UUID.kHexChars.charAt(hex & 0x0f)); } if (!UUID.sDescCaching) { return b.toString(); } mDesc = b.toString(); } return mDesc; } /** * Creates a 128bit number from the String representation of {@link UUID}. * * @param uuid The UUID * @return byte array that can be used to recreate a UUID instance from the given String * representation */ public static byte[] stringToBytes(String uuid) { byte[] data = new byte[16]; int dataIdx = 0; try { for (int i = 0; i < uuid.length(); ) { while (uuid.charAt(i) == '-') { i++; } char c1 = uuid.charAt(i); char c2 = uuid.charAt(i + 1); i += 2; int c1Bytes = Character.digit(c1, 16); int c2Bytes = Character.digit(c2, 16); data[dataIdx++] = (byte) ((c1Bytes << 4) + c2Bytes); } } catch (RuntimeException e) { throw new IllegalArgumentException(e); } return data; } /** * Checking equality of UUIDs is easy; just compare the 128-bit number. */ @Override public boolean equals(final Object o) { if (!(o instanceof UUID)) { return false; } byte[] otherId = ((UUID) o).mId; byte[] thisId = mId; for (int i = 0; i < 16; ++i) { if (otherId[i] != thisId[i]) { return false; } } return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy