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 }