com.fasterxml.jackson.databind.deser.std.UUIDDeserializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.Arrays;
import java.util.UUID;
import com.fasterxml.jackson.core.Base64Variants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
public class UUIDDeserializer
extends FromStringDeserializer
{
private static final long serialVersionUID = 1L;
final static int[] HEX_DIGITS = new int[127];
static {
Arrays.fill(HEX_DIGITS, -1);
for (int i = 0; i < 10; ++i) {
HEX_DIGITS['0' + i] = i;
}
for (int i = 0; i < 6; ++i) {
HEX_DIGITS['a' + i] = 10 + i;
HEX_DIGITS['A' + i] = 10 + i;
}
}
public final static UUIDDeserializer instance = new UUIDDeserializer();
public UUIDDeserializer() { super(UUID.class); }
@Override
protected UUID _deserialize(String id, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Adapted from java-uuid-generator (https://github.com/cowtowncoder/java-uuid-generator)
// which is 5x faster than UUID.fromString(value), as oper "ManualReadPerfWithUUID"
if (id.length() != 36) {
/* 14-Sep-2013, tatu: One trick we do allow, Base64-encoding, since we know
* length it must have...
*/
if (id.length() == 24) {
byte[] stuff = Base64Variants.getDefaultVariant().decode(id);
return _fromBytes(stuff, ctxt);
}
_badFormat(id);
}
// verify hyphens first:
if ((id.charAt(8) != '-') || (id.charAt(13) != '-')
|| (id.charAt(18) != '-') || (id.charAt(23) != '-')) {
_badFormat(id);
}
long l1 = intFromChars(id, 0);
l1 <<= 32;
long l2 = ((long) shortFromChars(id, 9)) << 16;
l2 |= shortFromChars(id, 14);
long hi = l1 + l2;
int i1 = (shortFromChars(id, 19) << 16) | shortFromChars(id, 24);
l1 = i1;
l1 <<= 32;
l2 = intFromChars(id, 28);
l2 = (l2 << 32) >>> 32; // sign removal, Java-style. Ugh.
long lo = l1 | l2;
return new UUID(hi, lo);
}
@Override
protected UUID _deserializeEmbedded(Object ob, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (ob instanceof byte[]) {
return _fromBytes((byte[]) ob, ctxt);
}
super._deserializeEmbedded(ob, ctxt);
return null; // never gets here
}
private void _badFormat(String uuidStr) {
throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
}
static int intFromChars(String str, int index) {
return (byteFromChars(str, index) << 24)
+(byteFromChars(str, index+2) << 16)
+(byteFromChars(str, index+4) << 8)
+ byteFromChars(str, index+6);
}
static int shortFromChars(String str, int index) {
return (byteFromChars(str, index) << 8) + byteFromChars(str, index+2);
}
static int byteFromChars(String str, int index)
{
final char c1 = str.charAt(index);
final char c2 = str.charAt(index+1);
if (c1 <= 127 && c2 <= 127) {
int hex = (HEX_DIGITS[c1] << 4) | HEX_DIGITS[c2];
if (hex >= 0) {
return hex;
}
}
if (c1 > 127 || HEX_DIGITS[c1] < 0) {
return _badChar(str, index, c1);
}
return _badChar(str, index+1, c2);
}
static int _badChar(String uuidStr, int index, char c) {
throw new NumberFormatException("Non-hex character '"+c+"', not valid character for a UUID String"
+"' (value 0x"+Integer.toHexString(c)+") for UUID String \""+uuidStr+"\"");
}
private UUID _fromBytes(byte[] bytes, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (bytes.length != 16) {
ctxt.mappingException("Can only construct UUIDs from byte[16]; got "+bytes.length+" bytes");
}
return new UUID(_long(bytes, 0), _long(bytes, 8));
}
private static long _long(byte[] b, int offset)
{
long l1 = ((long) _int(b, offset)) << 32;
long l2 = _int(b, offset+4);
// faster to just do it than check if it has sign
l2 = (l2 << 32) >>> 32; // to get rid of sign
return l1 | l2;
}
private static int _int(byte[] b, int offset)
{
return (b[offset] << 24)
| ((b[offset+1] & 0xFF) << 16)
| ((b[offset+2] & 0xFF) << 8)
| (b[offset+3] & 0xFF)
;
}
}