001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.transaction.manager;
019
020 import java.util.Random;
021 import javax.transaction.xa.Xid;
022 import java.net.InetAddress;
023 import java.net.UnknownHostException;
024
025 /**
026 * Factory for transaction ids.
027 * The Xid is constructed of three parts:
028 * <ol><li>8 byte count (LSB first)</li>
029 * <li>4 byte system id</li>
030 * <li>2 byte entropy</li>
031 * <li>4 or 16 byte IP address of host</li>
032 * <ol>
033 * @version $Rev: 740842 $ $Date: 2009-02-04 14:51:48 -0500 (Wed, 04 Feb 2009) $
034 * todo Should have a way of setting baseId
035 */
036 public class XidFactoryImpl implements XidFactory {
037 private final byte[] baseId = new byte[Xid.MAXGTRIDSIZE];
038 private long count = 1;
039
040 public XidFactoryImpl(byte[] tmId) {
041 System.arraycopy(tmId, 0, baseId, 8, tmId.length);
042 }
043
044 public XidFactoryImpl() {
045 byte[] hostid;
046 try {
047 hostid = InetAddress.getLocalHost().getAddress();
048 } catch (UnknownHostException e) {
049 hostid = new byte[]{127, 0, 0, 1};
050 }
051 int uid = System.identityHashCode(this);
052 baseId[8] = (byte) uid;
053 baseId[9] = (byte) (uid >>> 8);
054 baseId[10] = (byte) (uid >>> 16);
055 baseId[11] = (byte) (uid >>> 24);
056
057 byte[] entropy = new byte[2];
058 new Random().nextBytes(entropy);
059 baseId[12] = entropy[0];
060 baseId[13] = entropy[1];
061
062 System.arraycopy(hostid, 0, baseId, 14, hostid.length);
063 }
064
065 public Xid createXid() {
066 byte[] globalId = (byte[]) baseId.clone();
067 long id;
068 synchronized (this) {
069 id = count++;
070 }
071 globalId[0] = (byte) id;
072 globalId[1] = (byte) (id >>> 8);
073 globalId[2] = (byte) (id >>> 16);
074 globalId[3] = (byte) (id >>> 24);
075 globalId[4] = (byte) (id >>> 32);
076 globalId[5] = (byte) (id >>> 40);
077 globalId[6] = (byte) (id >>> 48);
078 globalId[7] = (byte) (id >>> 56);
079 return new XidImpl(globalId);
080 }
081
082 public Xid createBranch(Xid globalId, int branch) {
083 byte[] branchId = (byte[]) baseId.clone();
084 branchId[0] = (byte) branch;
085 branchId[1] = (byte) (branch >>> 8);
086 branchId[2] = (byte) (branch >>> 16);
087 branchId[3] = (byte) (branch >>> 24);
088 return new XidImpl(globalId, branchId);
089 }
090
091 public boolean matchesGlobalId(byte[] globalTransactionId) {
092 if (globalTransactionId.length != Xid.MAXGTRIDSIZE) {
093 return false;
094 }
095 for (int i = 8; i < globalTransactionId.length; i++) {
096 if (globalTransactionId[i] != baseId[i]) {
097 return false;
098 }
099 }
100 return true;
101 }
102
103 public boolean matchesBranchId(byte[] branchQualifier) {
104 if (branchQualifier.length != Xid.MAXBQUALSIZE) {
105 return false;
106 }
107 for (int i = 8; i < branchQualifier.length; i++) {
108 if (branchQualifier[i] != baseId[i]) {
109 return false;
110 }
111 }
112 return true;
113 }
114
115 public Xid recover(int formatId, byte[] globalTransactionid, byte[] branchQualifier) {
116 return new XidImpl(formatId, globalTransactionid, branchQualifier);
117 }
118
119 }