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