1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2002-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 *
44 * $Id: ExternalXid.java,v 1.1 2004/11/26 01:51:01 tanderson Exp $
45 *
46 * Date Author Changes
47 * 24/01/2002 jima Created
48 */
49 package org.exolab.jms.tranlog;
50
51 import java.io.Externalizable;
52 import java.io.IOException;
53 import java.io.ObjectInput;
54 import java.io.ObjectOutput;
55
56 import javax.transaction.xa.Xid;
57
58
59 /***
60 * This class maps an external XID that is set in the transaction manager.
61 * It needs to do this so that it can use it internally.
62 *
63 * @version $Revision: 1.1 $ $Date: 2004/11/26 01:51:01 $
64 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a>
65 * @see javax.transaction.xa.Xid
66 */
67 public final class ExternalXid
68 implements Xid, Externalizable {
69
70 /***
71 * This is the unique id used to identify the version of the class
72 * for the purpose of Serialization
73 */
74 static final long serialVersionUID = 1;
75
76 /***
77 * Efficient mapping from 4 bit value to lower case hexadecimal digit.
78 * gobbled from Tyrex imple
79 */
80 protected final static char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7',
81 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
82
83 /***
84 * The format identifier of the distributed transaction identifier
85 */
86 private int _formatId;
87
88 /***
89 * The array of bytes corresponding to the global transaction identifier
90 * part of the XID.
91 */
92 private byte[] _global;
93
94 /***
95 * The array of bytes corresponding to the branch qualifier
96 * part of the XID.
97 */
98 private byte[] _branch;
99
100 /***
101 * Cache a trnasient instance of the stringified version of the xid
102 */
103 private transient String _string = null;
104
105
106 /***
107 * Default constructor for Serialization
108 */
109 public ExternalXid() {
110 }
111
112 /***
113 * Create an instance of this class using the specified XID. This
114 * will always create a new instance and copy the format id, global
115 * transaction id and branch qualifier id to the new instance
116 *
117 * @param xid - the xid to use
118 */
119 public ExternalXid(Xid xid) {
120 this(xid.getFormatId(), xid.getGlobalTransactionId(),
121 xid.getBranchQualifier());
122 }
123
124 /***
125 * Create an insrance of this class using the specified format id,
126 * global transaction id and the branch qualifier.
127 *
128 * @param formatId - the format identifier
129 * @param global - the global transaction identifier
130 * @param branch - the branch qualifier
131 */
132 public ExternalXid(int formatId, byte[] global, byte[] branch) {
133 _formatId = formatId;
134
135
136 if ((global == null) ||
137 (global.length == 0)) {
138 _global = new byte[0];
139 } else {
140 _global = new byte[global.length];
141 System.arraycopy(global, 0, _global, 0, global.length);
142 }
143
144
145 if ((branch == null) ||
146 (branch.length == 0)) {
147 _branch = new byte[0];
148 } else {
149 _branch = new byte[branch.length];
150 System.arraycopy(branch, 0, _branch, 0, branch.length);
151 }
152 }
153
154
155 public int getFormatId() {
156 return _formatId;
157 }
158
159
160 public byte[] getGlobalTransactionId() {
161 return _global;
162 }
163
164
165 public byte[] getBranchQualifier() {
166 return _branch;
167 }
168
169 /***
170 * Returns the global transaction identifier in the form of
171 * exid://formatId.global.branch
172 *
173 * @return String
174 */
175 public String toString() {
176
177 if (_string == null) {
178 StringBuffer buffer = new StringBuffer("xid://");
179 buffer.append(HEX_DIGITS[(int) ((_formatId >> 28) & 0x0F)]);
180 buffer.append(HEX_DIGITS[(int) ((_formatId >> 24) & 0x0F)]);
181 buffer.append(HEX_DIGITS[(int) ((_formatId >> 20) & 0x0F)]);
182 buffer.append(HEX_DIGITS[(int) ((_formatId >> 16) & 0x0F)]);
183 buffer.append(HEX_DIGITS[(int) ((_formatId >> 12) & 0x0F)]);
184 buffer.append(HEX_DIGITS[(int) ((_formatId >> 8) & 0x0F)]);
185 buffer.append(HEX_DIGITS[(int) ((_formatId >> 4) & 0x0F)]);
186 buffer.append(HEX_DIGITS[(int) (_formatId & 0x0F)]);
187 buffer.append('-');
188 if (_global != null && _global.length > 0) {
189 for (int i = _global.length; i-- > 0;) {
190 buffer.append(HEX_DIGITS[(_global[i] & 0xF0) >> 4]);
191 buffer.append(HEX_DIGITS[(_global[i] & 0x0F)]);
192 }
193 }
194 buffer.append('-');
195 if (_branch != null && _branch.length > 0) {
196 for (int i = _branch.length; i-- > 0;) {
197 buffer.append(HEX_DIGITS[(_branch[i] & 0xF0) >> 4]);
198 buffer.append(HEX_DIGITS[(_branch[i] & 0x0F)]);
199 }
200 }
201 _string = buffer.toString();
202 }
203
204 return _string;
205 }
206
207
208 public int hashCode() {
209 return toString().hashCode();
210 }
211
212
213 public boolean equals(Object obj) {
214
215 if (obj == this) {
216 return true;
217 }
218
219 if (obj instanceof ExternalXid) {
220
221 Xid xid = (Xid) obj;
222
223 if (xid.getFormatId() != _formatId) {
224 return false;
225 }
226
227
228 byte[] global = xid.getGlobalTransactionId();
229 if ((global == null) ||
230 (global.length == 0)) {
231 if ((_global != null) ||
232 (_global.length != 0)) {
233 return false;
234 }
235 } else {
236 if (global.length != _global.length) {
237 return false;
238 }
239
240 for (int index = 0; index < global.length; index++) {
241 if (global[index] != _global[index]) {
242 return false;
243 }
244 }
245 }
246
247
248 byte[] branch = xid.getBranchQualifier();
249 if ((branch == null) ||
250 (branch.length == 0)) {
251 if ((_branch != null) ||
252 (_branch.length != 0)) {
253 return false;
254 }
255 } else {
256 if (branch.length != _branch.length) {
257 return false;
258 }
259
260 for (int index = 0; index < branch.length; index++) {
261 if (branch[index] != _branch[index]) {
262 return false;
263 }
264 }
265 }
266 return true;
267 }
268
269 return false;
270 }
271
272
273 public void writeExternal(ObjectOutput stream)
274 throws IOException {
275 stream.writeLong(serialVersionUID);
276 stream.writeInt(_formatId);
277
278 stream.writeInt(_global.length);
279 stream.write(_global);
280
281 stream.writeInt(_branch.length);
282 stream.write(_branch);
283
284 }
285
286
287 public void readExternal(ObjectInput stream)
288 throws IOException, ClassNotFoundException {
289 long version = stream.readLong();
290
291 if (version == serialVersionUID) {
292 _formatId = stream.readInt();
293
294 _global = new byte[stream.readInt()];
295 stream.read(_global);
296
297 _branch = new byte[stream.readInt()];
298 stream.read(_branch);
299
300 } else {
301 throw new IOException("No support for ExternalXid " +
302 "with version " + version);
303 }
304 }
305 }