/*
* 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 com.sun.jini.outrigger.snaplogstore;
import java.util.Arrays;
import java.io.Serializable;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;
/**
* In the backend <code>Uuid</code>s are represented using
* <code>byte[16]</code>s. This works fine is most places, but
* sometimes we need to use a <code>Uuid</code> as a key in a hash
* table. Arrays do not make good hash table keys so we wrap the array
* in one of these to provide suitable implementations of
* <code>hashCode</code> and <code>equals</code>.
* <p>
* This method also has utility methods for converting
* <code>Uuid</code>s to and from <code>byte[16]</code>s.
*/
class ByteArrayWrapper implements Serializable {
/** The 16 bytes being wrapped */
private byte[] uuid;
/** A 32 bit hash of uuid */
private int hash;
/**
* Create a new <code>ByteArrayWrapper</code> that
* wraps the provided array.
* @param v The array to wrap.
* @throws IllegalArgumentException if <code>v.length</code> is
* not 16.
*/
ByteArrayWrapper(byte v[]) {
uuid = v;
// Same hash Uuid uses
hash = hashFor(v);
}
public boolean equals(Object o) {
if (!(o instanceof ByteArrayWrapper))
return false;
if (o == null)
return false;
final byte[] ouuid = ((ByteArrayWrapper)o).uuid;
return Arrays.equals(uuid, ouuid);
}
public int hashCode() {
return hash;
}
/**
* Encode the passed <code>Uuid</code> in to a newly allocated
* <code>byte[16]</code> in big-endian byte order.
* @param uuid the <code>Uuid</code> to encode.
* @return A new <code>byte[16]</code> initialized to the
* same bit pattern as <code>uuid</code>.
* @throws NullPointerException if <code>uuid</code> is
* <code>null</code>.
*/
static byte[] toByteArray(Uuid uuid) {
final byte rslt[] = new byte[16];
long bits0 = uuid.getMostSignificantBits();
for (int i=7; i>=0; i--) {
rslt[i] = (byte)bits0;
bits0 = bits0 >>> 8;
}
long bits1 = uuid.getLeastSignificantBits();
for (int i=15; i>=8; i--) {
rslt[i] = (byte)bits1;
bits1 = bits1 >>> 8;
}
return rslt;
}
/**
* Create a new <code>Uuid</code> that matches the bit pattern
* in the passed <code>byte[]</code>. Assumes the bit pattern
* is in big-endian byte order.
* @param bits the <code>byte[]</code> with bit pattern
*
* @return A new <code>Uuid</code> that matches the
* passed <code>byte[]</code>.
* @throws NullPointerException if <code>uuid</code> is
* <code>null</code>.
* @throws IllegalArgumentException if <code>bits.length</code>
* is not 16.
*/
static Uuid toUuid(byte bits[]) {
if (bits.length != 16)
throw new IllegalArgumentException("uuid.length must be 16");
long bits0 = 0;
for (int i=0; i<7; i++) {
bits0 = bits0 | (bits[i] & 0xFF);
bits0 = bits0 << 8;
}
bits0 = bits0 | (bits[7] & 0xFF);
long bits1 = 0;
for (int i=8; i<15; i++) {
bits1 = bits1 | (bits[i] & 0xFF);
bits1 = bits1 << 8;
}
bits1 = bits1 | (bits[15] & 0xFF);
return UuidFactory.create(bits0, bits1);
}
/**
* Compute an equivalent hash to <code>Uuid</code>.
* @throws IllegalArgumentException if <code>uuid.length</code>
* is not 16.
*/
static int hashFor(byte uuid[]) {
if (uuid.length != 16)
throw new IllegalArgumentException("uuid.length must be 16");
return
((uuid[15] ^ uuid[11] ^ uuid[7] ^ uuid[3]) << 24) |
((uuid[14] ^ uuid[10] ^ uuid[6] ^ uuid[2]) << 16) |
((uuid[13] ^ uuid[9] ^ uuid[5] ^ uuid[1]) << 8) |
((uuid[12] ^ uuid[8] ^ uuid[4] ^ uuid[0]) << 0);
}
}