View Javadoc
1   package org.argeo.transaction.simple;
2   
3   import java.io.Serializable;
4   import java.nio.ByteBuffer;
5   import java.util.Arrays;
6   import java.util.UUID;
7   
8   import javax.transaction.xa.Xid;
9   
10  /**
11   * Implementation of {@link Xid} based on {@link UUID}, using max significant
12   * bits as global transaction id, and least significant bits as branch
13   * qualifier.
14   */
15  public class UuidXid implements Xid, Serializable {
16  	private static final long serialVersionUID = -5380531989917886819L;
17  	public final static int FORMAT = (int) serialVersionUID;
18  
19  	private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
20  
21  	private final int format;
22  	private final byte[] globalTransactionId;
23  	private final byte[] branchQualifier;
24  	private final String uuid;
25  	private final int hashCode;
26  
27  	public UuidXid() {
28  		this(UUID.randomUUID());
29  	}
30  
31  	public UuidXid(UUID uuid) {
32  		this.format = FORMAT;
33  		this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
34  		this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
35  		this.uuid = uuid.toString();
36  		this.hashCode = uuid.hashCode();
37  	}
38  
39  	public UuidXid(Xid xid) {
40  		this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
41  				.getBranchQualifier());
42  	}
43  
44  	private UuidXid(int format, byte[] globalTransactionId,
45  			byte[] branchQualifier) {
46  		this.format = format;
47  		this.globalTransactionId = globalTransactionId;
48  		this.branchQualifier = branchQualifier;
49  		this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
50  				.toString();
51  		this.hashCode = uuid.hashCode();
52  	}
53  
54  	@Override
55  	public int getFormatId() {
56  		return format;
57  	}
58  
59  	@Override
60  	public byte[] getGlobalTransactionId() {
61  		return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
62  	}
63  
64  	@Override
65  	public byte[] getBranchQualifier() {
66  		return Arrays.copyOf(branchQualifier, branchQualifier.length);
67  	}
68  
69  	@Override
70  	public int hashCode() {
71  		return hashCode;
72  	}
73  
74  	@Override
75  	public boolean equals(Object obj) {
76  		if (this == obj)
77  			return true;
78  		if (obj instanceof UuidXid) {
79  			UuidXid that = (UuidXid) obj;
80  			return Arrays.equals(globalTransactionId, that.globalTransactionId)
81  					&& Arrays.equals(branchQualifier, that.branchQualifier);
82  		}
83  		if (obj instanceof Xid) {
84  			Xid that = (Xid) obj;
85  			return Arrays.equals(globalTransactionId,
86  					that.getGlobalTransactionId())
87  					&& Arrays
88  							.equals(branchQualifier, that.getBranchQualifier());
89  		}
90  		return uuid.equals(obj.toString());
91  	}
92  
93  	@Override
94  	protected Object clone() throws CloneNotSupportedException {
95  		return new UuidXid(format, globalTransactionId, branchQualifier);
96  	}
97  
98  	@Override
99  	public String toString() {
100 		return uuid;
101 	}
102 
103 	public UUID asUuid() {
104 		return bytesToUUID(globalTransactionId, branchQualifier);
105 	}
106 
107 	public static byte[] uuidToBytes(long bits) {
108 		ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
109 		buffer.putLong(0, bits);
110 		return buffer.array();
111 	}
112 
113 	public static UUID bytesToUUID(byte[] most, byte[] least) {
114 		if (most.length < BYTES_PER_LONG)
115 			most = Arrays.copyOf(most, BYTES_PER_LONG);
116 		if (least.length < BYTES_PER_LONG)
117 			least = Arrays.copyOf(least, BYTES_PER_LONG);
118 		ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
119 		buffer.put(most, 0, BYTES_PER_LONG);
120 		buffer.put(least, 0, BYTES_PER_LONG);
121 		buffer.flip();
122 		return new UUID(buffer.getLong(), buffer.getLong());
123 	}
124 
125 	// public static void main(String[] args) {
126 	// UUID uuid = UUID.randomUUID();
127 	// System.out.println(uuid);
128 	// uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
129 	// uuidToBytes(uuid.getLeastSignificantBits()));
130 	// System.out.println(uuid);
131 	// }
132 }