KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jotm > JavaXidImpl


1 /*
2  * @(#) JavaXidImpl.java
3  *
4  * JOTM: Java Open Transaction Manager
5  *
6  *
7  * This module was originally developed by
8  *
9  * - Bull S.A. as part of the JOnAS application server code released in
10  * July 1999 (www.bull.com)
11  *
12  * --------------------------------------------------------------------------
13  * The original code and portions created by Bull SA are
14  * Copyright (c) 1999 BULL SA
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are met:
19  *
20  * -Redistributions of source code must retain the above copyright notice, this
21  * list of conditions and the following disclaimer.
22  *
23  * -Redistributions in binary form must reproduce the above copyright notice,
24  * this list of conditions and the following disclaimer in the documentation
25  * and/or other materials provided with the distribution.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  *
39  * --------------------------------------------------------------------------
40  * $Id: JavaXidImpl.java,v 1.2 2005/04/22 17:49:37 tonyortiz Exp $
41  * --------------------------------------------------------------------------
42  */

43 package org.objectweb.jotm;
44
45 import java.io.Serializable JavaDoc;
46 import java.nio.ByteBuffer JavaDoc;
47 import java.security.SecureRandom JavaDoc;
48 import javax.transaction.xa.Xid JavaDoc;
49
50 /**
51  * Xid implementation for JTA
52  *
53  * XID has the following format as defined by X/Open Specification:
54  *
55  * XID
56  * long formatId format identifier
57  * long gtrid_length value 1-64
58  * long bqual_length value 1-64
59  * byte data [XIDDATASIZE] where XIDDATASIZE = 128
60  *
61  * The data field comprises at most two contiguous components:
62  * a global transaction identifier (gtrid) and a branch qualifier (bqual)
63  * which are defined as:
64  *
65  * byte gtrid [1-64] global transaction identfier
66  * byte bqual [1-64] branch qualifier
67  *
68  */

69 public class JavaXidImpl implements Xid, Serializable JavaDoc {
70
71     public static final int JOTM_FORMAT_ID = 0xBB14;
72
73     // these cells are gated by this.getClass()
74
private static SecureRandom JavaDoc rand = null; // (also used as first-time flag)
75
private final byte internalVersId = 1;
76     private static int count = 1;
77     private static long uuid0;
78     private static long uuid1;
79     private static boolean uuidsRecovered = false;
80     private static byte[] gtrid_base = null; // created by makeGtridBase()
81
private static String JavaDoc host, server;
82
83     private String JavaDoc fullString = "";
84     private String JavaDoc shortString = "";
85     
86     private boolean hashcodevalid = false;
87     private int myhashcode;
88
89     static String JavaDoc HexDigits[] = {
90         "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
91         "0a", "0b", "0c", "0d", "0e", "0f",
92         "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
93         "1a", "1b", "1c", "1d", "1e", "1f",
94         "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
95         "2a", "2b", "2c", "2d", "2e", "2f",
96         "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
97         "3a", "3b", "3c", "3d", "3e", "3f",
98         "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
99         "4a", "4b", "4c", "4d", "4e", "4f",
100         "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
101         "5a", "5b", "5c", "5d", "5e", "5f",
102         "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
103         "6a", "6b", "6c", "6d", "6e", "6f",
104         "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
105         "7a", "7b", "7c", "7d", "7e", "7f",
106         "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
107         "8a", "8b", "8c", "8d", "8e", "8f",
108         "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
109         "9a", "9b", "9c", "9d", "9e", "9f",
110         "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9",
111         "aa", "ab", "ac", "ad", "ae", "af",
112         "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9",
113         "ba", "bb", "bc", "bd", "be", "bf",
114         "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9",
115         "ca", "cb", "cc", "cd", "ce", "cf",
116         "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
117         "da", "db", "dc", "dd", "de", "df",
118         "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
119         "ea", "eb", "ec", "ed", "ee", "ef",
120         "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
121         "fa", "fb", "fc", "fd", "fe", "ff"
122     };
123
124     /**
125      * format id
126      * @serial
127      */

128     private int formatId;
129
130     /**
131      * gtrid length
132      * @serial
133      */

134     private int gtrid_length;
135
136     /**
137      * bqual length
138      * @serial
139      */

140     private int bqual_length;
141
142     /**
143      * global transaction id
144      * @serial
145      */

146     private byte[] gtrid;
147
148     /**
149      * branch qualifier
150      * @serial
151      */

152     private byte[] bqual;
153
154     // -------------------------------------------------------------------
155
// Constructors
156
// -------------------------------------------------------------------
157

158     /**
159      * Build an javax.transaction.xa.Xid from the org.objectweb.jotm.Xid
160      */

161     public JavaXidImpl(org.objectweb.jotm.Xid jotmXid ) {
162         if (TraceTm.jotm.isDebugEnabled()) {
163             TraceTm.jotm.debug("jotmXID= " + jotmXid);
164         }
165
166         formatId = jotmXid.getFormatId();
167         gtrid = jotmXid.getGlobalTransactionId();
168         gtrid_length = gtrid.length;
169         bqual = jotmXid.getBranchQualifier();
170         bqual_length = bqual.length;
171     }
172
173     // -------------------------------------------------------------------
174
// Xid implementation
175
// -------------------------------------------------------------------
176

177     /**
178      * Get the format id for that Xid
179      */

180     public int getFormatId() {
181         return formatId;
182     }
183
184     /**
185      * Get the Global Id for that Xid
186      */

187     public byte[] getGlobalTransactionId() {
188         return gtrid;
189     }
190
191     /**
192      * Get the Branch Qualifier for that Xid
193      */

194     public byte[] getBranchQualifier() {
195         return bqual;
196     }
197
198     // -------------------------------------------------------------------
199
// other methods
200
// -------------------------------------------------------------------
201

202     /**
203      * Hex Dump of byte
204      */

205     static final void byteToHex( byte inbyte, StringBuffer JavaDoc str_buff ) {
206
207         int myByte = 0xFF & inbyte;
208         
209         str_buff.append( HexDigits[myByte] );
210         return;
211     }
212
213     /**
214      * String form
215      * default toString() compresses Xid's
216      */

217     public String JavaDoc toString() {
218         return this.toString( false );
219     }
220
221     public String JavaDoc toString( boolean Full ) {
222
223         byte[] gtrid_local = null;
224         byte[] bqual_local = null;
225
226         if (Full && (fullString.length() != 0) ) {
227             return fullString;
228         } else if (!Full && (shortString.length() != 0) ) {
229             return shortString;
230         }
231
232         // Buffers need two hex characters per byte
233
StringBuffer JavaDoc str_buff_gtrid = new StringBuffer JavaDoc(MAXGTRIDSIZE * 2);
234         StringBuffer JavaDoc str_buff_bqual = new StringBuffer JavaDoc(MAXBQUALSIZE * 2);
235
236         gtrid_local = new byte[MAXGTRIDSIZE];
237         ByteBuffer JavaDoc aa = ByteBuffer.wrap(gtrid_local);
238        
239         System.arraycopy(gtrid, 0, gtrid_local, 0, gtrid_length);
240
241         for (int i=0; i < gtrid_length; i++) {
242             byteToHex(aa.get(), str_buff_gtrid );
243         }
244
245         bqual_local = new byte[MAXBQUALSIZE];
246         ByteBuffer JavaDoc bb = ByteBuffer.wrap(bqual_local);
247
248         if (bqual != null) {
249             System.arraycopy(bqual, 0, bqual_local, 0, bqual_length);
250
251             for (int i=0; i < bqual_length; i++) {
252                 byteToHex(bb.get(), str_buff_bqual);
253             }
254         }
255
256         if ((gtrid_length > 30) && !Full ) { // be prepared to reduce output string
257
int strlen = str_buff_gtrid.length();
258             str_buff_gtrid.replace( (strlen / 6), (strlen / 6) + 2, "...");
259             str_buff_gtrid.delete( (strlen / 6) + 3, strlen - 5);
260         }
261
262         if ((bqual_length > 30) && !Full ) { // be prepared to reduce output string
263
int strlen = str_buff_bqual.length();
264             str_buff_bqual.replace( (strlen / 6), (strlen / 6) + 2, "...");
265             str_buff_bqual.delete( (strlen / 6) + 3, strlen - 5);
266         }
267
268         if (Full) {
269             fullString = Long.toHexString(formatId) + ":" +
270                          Long.toHexString(gtrid_length) + ":" +
271                          Long.toHexString(bqual_length) + ":" +
272                          str_buff_gtrid.toString() + ":" +
273                          str_buff_bqual.toString();
274             return fullString;
275         }
276
277         shortString = Long.toHexString(formatId) + ":" +
278                             Long.toHexString(gtrid_length) + ":" +
279                             Long.toHexString(bqual_length) + ":" +
280                             str_buff_gtrid.toString() + ":" +
281                             str_buff_bqual.toString();
282         return shortString;
283     }
284
285     /*
286      * make a unique but recognizable gtrid.
287      *
288      * format:
289      * 1. internal version identifier - 1 byte
290      * 2. uuid - 16 bytes
291      * 3. host name - 16 bytes
292      * 4. server name - 15 bytes
293      * 5. timestamp - 8 bytes
294      * 6. [reserved for use by bqual - 8 bytes]
295      *
296      * Items 1 thru 4 are generated by makeGtridBase and comprise the recognizable
297      * portion of a gtrid or bqual. Together, these serve to make Xids generated on
298      * this system unique from those generated on other systems.
299      * Item 5 is generated by this routine and serves to make gtrids unique.
300      * Item 6 serves to distinguish different bquals belonging
301      * to the same Xid, and is generated elsewhere.
302      *
303      * Items 1 thru 4 are used to determine if we (JOTM) generated this gtrid/bqual.
304      */

305
306     private byte[] makeGtrid() {
307         makeGtridBase();
308         long uniqueTimeStamp;
309
310         synchronized( getClass() ) {
311             uniqueTimeStamp = System.currentTimeMillis() * 1024 + count;
312             count++;
313         }
314
315         ByteBuffer JavaDoc bb = ByteBuffer.allocate(gtrid_base.length+8);
316         bb.put(gtrid_base);
317         bb.putLong(uniqueTimeStamp);
318         return bb.array();
319     }
320
321     private void makeGtridBase() {
322         // acquire the configured uuid, host and server name.
323
// fabricate a uuid if one does not yet exist.
324
// and append a unique timestamp.
325

326         synchronized( getClass() ) {
327             if (rand == null) {
328                 rand = new SecureRandom JavaDoc();
329                 
330                 if (uuidsRecovered == false) { // first time or no journal
331
//uuid0 = Long.parseLong(System.getProperty("jotm.uuid.part1"),16);
332
//uuid1 = Long.parseLong(System.getProperty("jotm.uuid.part2"),16);
333
uuid0 = rand.nextLong();
334                     uuid1 = rand.nextLong();
335                     
336                     // We build the Inique ID Record in makeGtridBase
337
// Store the Unique ID Record using HOWL so it can manage for us.
338
// It will never have a DONE record written.
339
//
340
// The Unique ID record consists of two fields:
341
// 1. uuid0
342
// 2. uuid1
343
//
344
// The XA Unique ID record format:
345
// Unique ID record type1 (byte[3]) - 'RU1'
346
// Unique ID record stored uuido (long) - 8 bytes
347
// Unique ID record stored uuid1 (long) - 8 bytes
348
//
349

350                     byte [] UniqueID = new byte[3+8+8];
351                     byte [] [] UniqueIDRecord = new byte [1][3+8+8];
352
353                     String JavaDoc rt1 = "RU1";
354
355                     ByteBuffer JavaDoc rr1 = ByteBuffer.wrap(UniqueID);
356                     rr1.put(rt1.getBytes());
357                     rr1.putLong(uuid0);
358                     rr1.putLong(uuid1);
359
360                     UniqueIDRecord [0] = UniqueID;
361                 }
362
363                 host = "";
364                 server = "";
365                 // make host & server names fixed length, as defined above
366
host = (host+" ").substring(0,15);
367                 server = (server+" ").substring(0,14);
368                 gtrid_base = new byte[1+8+8+16+15];
369                 ByteBuffer JavaDoc bb = ByteBuffer.wrap(gtrid_base);
370                 bb.put(internalVersId);
371                 bb.putLong(uuid0);
372                 bb.putLong(uuid1);
373                 bb.put(host.getBytes());
374                 bb.put(server.getBytes());
375             }
376         }
377     }
378
379     // -------------------------------------------------------------------
380
// equals and hashCode
381
// -------------------------------------------------------------------
382

383     /**
384      * return true if objects are identical
385      */

386     public boolean equals( Object JavaDoc obj2 ) {
387         
388         JavaXidImpl xid2 = (JavaXidImpl) obj2;
389
390         if (formatId == xid2.getFormatId()
391             && java.util.Arrays.equals(bqual, xid2.getBranchQualifier())
392             && java.util.Arrays.equals(gtrid, xid2.getGlobalTransactionId())) {
393             return true;
394         } else {
395             return false;
396         }
397     }
398
399     /**
400      * return a hashcode value for this object
401      */

402     public int hashCode() {
403
404         int hc = 0;
405
406         if (hashcodevalid == false) {
407
408             for (int i = 0; i < gtrid.length; i++) {
409                 hc = hc * 37 + gtrid[i];
410             }
411
412             for (int i = 0; i < bqual.length; i++ ) {
413                 hc = hc * 37 + bqual[i];
414             }
415
416             myhashcode = hc;
417             hashcodevalid = true;
418         }
419         return myhashcode;
420     }
421 }
422
Popular Tags