1 | /* |
2 | |
3 | Derby - Class org.apache.derby.iapi.store.access.xa.XAXactId |
4 | |
5 | Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.iapi.store.access.xa; |
22 | |
23 | import org.apache.derby.iapi.services.sanity.SanityManager; |
24 | |
25 | import org.apache.derby.iapi.store.access.GlobalXact; |
26 | |
27 | import javax.transaction.xa.Xid; |
28 | import javax.transaction.xa.XAException; |
29 | |
30 | /** |
31 | |
32 | The XAXactId class is a specific implementation of the JTA Xid interface. It |
33 | is only used by the TransactionTable.restore() interface to return an array |
34 | of Xid's back to the caller, as part of serving the XAresource.restore() |
35 | interface. |
36 | <P> |
37 | It is NOT the object that is stored in the log. One reason for this is that |
38 | the Formattable and Xid interface's define two different return values for |
39 | the getFormatId() interface. |
40 | |
41 | **/ |
42 | |
43 | public class XAXactId extends GlobalXact implements Xid |
44 | { |
45 | /************************************************************************** |
46 | * Private Fields of the class |
47 | ************************************************************************** |
48 | */ |
49 | private static final char COLON = ':'; |
50 | |
51 | /************************************************************************** |
52 | * Constructors for This class: |
53 | ************************************************************************** |
54 | */ |
55 | |
56 | /** |
57 | * initialize by making array copies of appropriate fields. |
58 | * <p> |
59 | **/ |
60 | private void copy_init_xid( |
61 | int format_id, |
62 | byte[] global_id, |
63 | byte[] branch_id) |
64 | { |
65 | this.format_id = format_id; |
66 | this.global_id = new byte[global_id.length]; |
67 | System.arraycopy(global_id, 0, this.global_id, 0, global_id.length); |
68 | this.branch_id = new byte[branch_id.length]; |
69 | System.arraycopy(branch_id, 0, this.branch_id, 0, branch_id.length); |
70 | } |
71 | |
72 | /** |
73 | * Construct from given pieces of an Xid. Makes copies of arrays. |
74 | * <p> |
75 | **/ |
76 | public XAXactId( |
77 | int format_id, |
78 | byte[] global_id, |
79 | byte[] branch_id) |
80 | { |
81 | copy_init_xid(format_id, global_id, branch_id); |
82 | } |
83 | |
84 | /** |
85 | * Construct an Xid using an external Xid. |
86 | * <p> |
87 | * @exception XAException invalid external xid |
88 | */ |
89 | public XAXactId(Xid xid) throws XAException |
90 | { |
91 | if (xid == null) |
92 | throw new XAException(XAException.XAER_NOTA); |
93 | |
94 | copy_init_xid( |
95 | xid.getFormatId(), |
96 | xid.getGlobalTransactionId(), |
97 | xid.getBranchQualifier()); |
98 | } |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | public String toHexString() |
105 | { |
106 | // the ascii representation of xid where xid is of |
107 | // format_id = f |
108 | // global_id = byte[N] |
109 | // branch_id = byte[M] |
110 | // |
111 | // :xx:yy:ffffffff:n...n:mmmm...m: |
112 | // where xx = N (up to 64 max) |
113 | // yy = M (up to 64 max) |
114 | // n..n = hex dump of global_id (0 to 128 bytes max) |
115 | // m..m = hex dump of branch_qualifier (0 to 128 bytes max) |
116 | |
117 | // 1+2+1+2+1+9+1+1+1 |
118 | int maxLength = 20+(global_id.length+branch_id.length)*2; |
119 | |
120 | StringBuffer hexdump = new StringBuffer(maxLength); |
121 | hexdump.append(COLON). |
122 | append(Integer.toString(global_id.length)).append(COLON). |
123 | append(Integer.toString(branch_id.length)).append(COLON). |
124 | append(Integer.toString(format_id, 16)).append(COLON). |
125 | append(org.apache.derby.iapi.util.StringUtil.toHexString(global_id, 0, global_id.length)).append(COLON). |
126 | append(org.apache.derby.iapi.util.StringUtil.toHexString(branch_id, 0, branch_id.length)).append(COLON); |
127 | |
128 | return hexdump.toString(); |
129 | |
130 | } |
131 | |
132 | public XAXactId(String xactIdString) |
133 | { |
134 | // extract it in pieces delimited by COLON |
135 | int start, end, length; |
136 | |
137 | // xx |
138 | start = 1; |
139 | end = xactIdString.indexOf(COLON, start); |
140 | if (SanityManager.DEBUG) |
141 | SanityManager.ASSERT(end != -1, "illegal string format"); |
142 | |
143 | String xx = xactIdString.substring(start, end); |
144 | int N = Integer.parseInt(xx); |
145 | |
146 | if (SanityManager.DEBUG) |
147 | { |
148 | SanityManager.ASSERT(N > 0 && N <= Xid.MAXGTRIDSIZE, "illegal gtrid size"); |
149 | } |
150 | |
151 | // yy |
152 | start = end+1; // skip the COLON |
153 | end = xactIdString.indexOf(COLON, start); |
154 | if (SanityManager.DEBUG) |
155 | SanityManager.ASSERT(end != -1, "illegal string format"); |
156 | |
157 | String yy = xactIdString.substring(start,end); |
158 | int M = Integer.parseInt(yy); |
159 | |
160 | if (SanityManager.DEBUG) |
161 | SanityManager.ASSERT(M > 0 && N <= Xid.MAXBQUALSIZE, "illegal bqual size"); |
162 | |
163 | // ffffffff |
164 | start = end+1; // skip the COLON |
165 | end = xactIdString.indexOf(COLON, start); |
166 | if (SanityManager.DEBUG) |
167 | SanityManager.ASSERT(end != -1, "illegal string format"); |
168 | |
169 | String f = xactIdString.substring(start,end); |
170 | format_id = Integer.parseInt(f, 16); |
171 | |
172 | // n...n |
173 | start = end+1; // skip the COLON |
174 | end = xactIdString.indexOf(COLON, start); |
175 | if (SanityManager.DEBUG) |
176 | SanityManager.ASSERT(end != -1, "illegal string format"); |
177 | |
178 | global_id = org.apache.derby.iapi.util.StringUtil.fromHexString(xactIdString, start, (end-start)); |
179 | |
180 | if (SanityManager.DEBUG) |
181 | SanityManager.ASSERT(global_id.length == N, "inconsistent global_id length"); |
182 | |
183 | |
184 | // m...m |
185 | start = end+1; // skip the COLON |
186 | end = xactIdString.indexOf(COLON, start); |
187 | if (SanityManager.DEBUG) |
188 | SanityManager.ASSERT(end != -1, "illegal string format"); |
189 | |
190 | branch_id = org.apache.derby.iapi.util.StringUtil.fromHexString(xactIdString, start, (end-start)); |
191 | |
192 | if (SanityManager.DEBUG) |
193 | SanityManager.ASSERT(branch_id.length == M, |
194 | "inconsistent branch_id length, expect " + M + " got " + |
195 | branch_id.length); |
196 | |
197 | } |
198 | |
199 | |
200 | |
201 | /************************************************************************** |
202 | * Private/Protected methods of This class: |
203 | ************************************************************************** |
204 | */ |
205 | |
206 | /************************************************************************** |
207 | * Public Methods implementing the Xid interface: |
208 | ************************************************************************** |
209 | */ |
210 | |
211 | /** |
212 | * Obtain the format id part of the Xid. |
213 | * <p> |
214 | * |
215 | * @return Format identifier. O means the OSI CCR format. |
216 | **/ |
217 | public int getFormatId() |
218 | { |
219 | return(format_id); |
220 | } |
221 | |
222 | /** |
223 | * Obtain the global transaction identifier part of XID as an array of |
224 | * bytes. |
225 | * <p> |
226 | * |
227 | * @return A byte array containing the global transaction identifier. |
228 | **/ |
229 | public byte[] getGlobalTransactionId() |
230 | { |
231 | return(global_id); |
232 | } |
233 | |
234 | /** |
235 | * Obtain the transaction branch qualifier part of the Xid in a byte array. |
236 | * <p> |
237 | * |
238 | * @return A byte array containing the branch qualifier of the transaction. |
239 | **/ |
240 | public byte[] getBranchQualifier() |
241 | { |
242 | return(branch_id); |
243 | } |
244 | |
245 | |
246 | |
247 | public boolean equals(Object other) |
248 | { |
249 | if (other == this) |
250 | return true; |
251 | |
252 | if (other == null) |
253 | return false; |
254 | |
255 | try |
256 | { |
257 | if (other instanceof GlobalXact) |
258 | return super.equals(other); |
259 | // Just cast it and catch the exception rather than doing the type |
260 | // checking twice. |
261 | Xid other_xid = (Xid) other; |
262 | |
263 | return( |
264 | java.util.Arrays.equals( |
265 | other_xid.getGlobalTransactionId(), |
266 | this.global_id) && |
267 | java.util.Arrays.equals( |
268 | other_xid.getBranchQualifier(), |
269 | this.branch_id) && |
270 | other_xid.getFormatId() == this.format_id); |
271 | |
272 | } |
273 | catch(ClassCastException cce) |
274 | { |
275 | // this class only knows how to compare with other Xids |
276 | if (SanityManager.DEBUG) |
277 | SanityManager.THROWASSERT("comparing XAXactId with " + |
278 | other.getClass().getName()); |
279 | |
280 | return false; |
281 | } |
282 | } |
283 | |
284 | |
285 | } |
286 | |
287 | |
288 | |