001: /*
002:
003: Derby - Class org.apache.derby.iapi.store.access.xa.XAXactId
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.store.access.xa;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026: import org.apache.derby.iapi.store.access.GlobalXact;
027:
028: import javax.transaction.xa.Xid;
029: import javax.transaction.xa.XAException;
030:
031: /**
032:
033: The XAXactId class is a specific implementation of the JTA Xid interface. It
034: is only used by the TransactionTable.restore() interface to return an array
035: of Xid's back to the caller, as part of serving the XAresource.restore()
036: interface.
037: <P>
038: It is NOT the object that is stored in the log. One reason for this is that
039: the Formattable and Xid interface's define two different return values for
040: the getFormatId() interface.
041:
042: **/
043:
044: public class XAXactId extends GlobalXact implements Xid {
045: /**************************************************************************
046: * Private Fields of the class
047: **************************************************************************
048: */
049: private static final char COLON = ':';
050:
051: /**************************************************************************
052: * Constructors for This class:
053: **************************************************************************
054: */
055:
056: /**
057: * initialize by making array copies of appropriate fields.
058: * <p>
059: **/
060: private void copy_init_xid(int format_id, byte[] global_id,
061: byte[] branch_id) {
062: this .format_id = format_id;
063: this .global_id = new byte[global_id.length];
064: System.arraycopy(global_id, 0, this .global_id, 0,
065: global_id.length);
066: this .branch_id = new byte[branch_id.length];
067: System.arraycopy(branch_id, 0, this .branch_id, 0,
068: branch_id.length);
069: }
070:
071: /**
072: * Construct from given pieces of an Xid. Makes copies of arrays.
073: * <p>
074: **/
075: public XAXactId(int format_id, byte[] global_id, byte[] branch_id) {
076: copy_init_xid(format_id, global_id, branch_id);
077: }
078:
079: /**
080: * Construct an Xid using an external Xid.
081: * <p>
082: * @exception XAException invalid external xid
083: */
084: public XAXactId(Xid xid) throws XAException {
085: if (xid == null)
086: throw new XAException(XAException.XAER_NOTA);
087:
088: copy_init_xid(xid.getFormatId(), xid.getGlobalTransactionId(),
089: xid.getBranchQualifier());
090: }
091:
092: public String toHexString() {
093: // the ascii representation of xid where xid is of
094: // format_id = f
095: // global_id = byte[N]
096: // branch_id = byte[M]
097: //
098: // :xx:yy:ffffffff:n...n:mmmm...m:
099: // where xx = N (up to 64 max)
100: // yy = M (up to 64 max)
101: // n..n = hex dump of global_id (0 to 128 bytes max)
102: // m..m = hex dump of branch_qualifier (0 to 128 bytes max)
103:
104: // 1+2+1+2+1+9+1+1+1
105: int maxLength = 20 + (global_id.length + branch_id.length) * 2;
106:
107: StringBuffer hexdump = new StringBuffer(maxLength);
108: hexdump.append(COLON)
109: .append(Integer.toString(global_id.length)).append(
110: COLON).append(
111: Integer.toString(branch_id.length)).append(
112: COLON).append(Integer.toString(format_id, 16))
113: .append(COLON).append(
114: org.apache.derby.iapi.util.StringUtil
115: .toHexString(global_id, 0,
116: global_id.length))
117: .append(COLON).append(
118: org.apache.derby.iapi.util.StringUtil
119: .toHexString(branch_id, 0,
120: branch_id.length))
121: .append(COLON);
122:
123: return hexdump.toString();
124:
125: }
126:
127: public XAXactId(String xactIdString) {
128: // extract it in pieces delimited by COLON
129: int start, end, length;
130:
131: // xx
132: start = 1;
133: end = xactIdString.indexOf(COLON, start);
134: if (SanityManager.DEBUG)
135: SanityManager.ASSERT(end != -1, "illegal string format");
136:
137: String xx = xactIdString.substring(start, end);
138: int N = Integer.parseInt(xx);
139:
140: if (SanityManager.DEBUG) {
141: SanityManager.ASSERT(N > 0 && N <= Xid.MAXGTRIDSIZE,
142: "illegal gtrid size");
143: }
144:
145: // yy
146: start = end + 1; // skip the COLON
147: end = xactIdString.indexOf(COLON, start);
148: if (SanityManager.DEBUG)
149: SanityManager.ASSERT(end != -1, "illegal string format");
150:
151: String yy = xactIdString.substring(start, end);
152: int M = Integer.parseInt(yy);
153:
154: if (SanityManager.DEBUG)
155: SanityManager.ASSERT(M > 0 && N <= Xid.MAXBQUALSIZE,
156: "illegal bqual size");
157:
158: // ffffffff
159: start = end + 1; // skip the COLON
160: end = xactIdString.indexOf(COLON, start);
161: if (SanityManager.DEBUG)
162: SanityManager.ASSERT(end != -1, "illegal string format");
163:
164: String f = xactIdString.substring(start, end);
165: format_id = Integer.parseInt(f, 16);
166:
167: // n...n
168: start = end + 1; // skip the COLON
169: end = xactIdString.indexOf(COLON, start);
170: if (SanityManager.DEBUG)
171: SanityManager.ASSERT(end != -1, "illegal string format");
172:
173: global_id = org.apache.derby.iapi.util.StringUtil
174: .fromHexString(xactIdString, start, (end - start));
175:
176: if (SanityManager.DEBUG)
177: SanityManager.ASSERT(global_id.length == N,
178: "inconsistent global_id length");
179:
180: // m...m
181: start = end + 1; // skip the COLON
182: end = xactIdString.indexOf(COLON, start);
183: if (SanityManager.DEBUG)
184: SanityManager.ASSERT(end != -1, "illegal string format");
185:
186: branch_id = org.apache.derby.iapi.util.StringUtil
187: .fromHexString(xactIdString, start, (end - start));
188:
189: if (SanityManager.DEBUG)
190: SanityManager.ASSERT(branch_id.length == M,
191: "inconsistent branch_id length, expect " + M
192: + " got " + branch_id.length);
193:
194: }
195:
196: /**************************************************************************
197: * Private/Protected methods of This class:
198: **************************************************************************
199: */
200:
201: /**************************************************************************
202: * Public Methods implementing the Xid interface:
203: **************************************************************************
204: */
205:
206: /**
207: * Obtain the format id part of the Xid.
208: * <p>
209: *
210: * @return Format identifier. O means the OSI CCR format.
211: **/
212: public int getFormatId() {
213: return (format_id);
214: }
215:
216: /**
217: * Obtain the global transaction identifier part of XID as an array of
218: * bytes.
219: * <p>
220: *
221: * @return A byte array containing the global transaction identifier.
222: **/
223: public byte[] getGlobalTransactionId() {
224: return (global_id);
225: }
226:
227: /**
228: * Obtain the transaction branch qualifier part of the Xid in a byte array.
229: * <p>
230: *
231: * @return A byte array containing the branch qualifier of the transaction.
232: **/
233: public byte[] getBranchQualifier() {
234: return (branch_id);
235: }
236:
237: public boolean equals(Object other) {
238: if (other == this )
239: return true;
240:
241: if (other == null)
242: return false;
243:
244: try {
245: if (other instanceof GlobalXact)
246: return super .equals(other);
247: // Just cast it and catch the exception rather than doing the type
248: // checking twice.
249: Xid other_xid = (Xid) other;
250:
251: return (java.util.Arrays.equals(other_xid
252: .getGlobalTransactionId(), this .global_id)
253: && java.util.Arrays.equals(other_xid
254: .getBranchQualifier(), this .branch_id) && other_xid
255: .getFormatId() == this .format_id);
256:
257: } catch (ClassCastException cce) {
258: // this class only knows how to compare with other Xids
259: if (SanityManager.DEBUG)
260: SanityManager.THROWASSERT("comparing XAXactId with "
261: + other.getClass().getName());
262:
263: return false;
264: }
265: }
266:
267: }
|