001    /**
002     *
003     * Copyright 2003-2004 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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 javax.transaction.xa.Xid;
021    import java.net.InetAddress;
022    import java.net.UnknownHostException;
023    
024    /**
025     * Factory for transaction ids.
026     * The Xid is constructed of three parts:
027     * <ol><li>8 byte count (LSB first)</li>
028     * <li>4 byte system id</li>
029     * <li>4 or 16 byte IP address of host</li>
030     * <ol>
031     * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
032     * todo Should have a way of setting baseId
033     */
034    public class XidFactoryImpl implements XidFactory {
035        private final byte[] baseId = new byte[Xid.MAXGTRIDSIZE];
036        private long count = 1;
037    
038        public XidFactoryImpl(byte[] tmId) {
039           System.arraycopy(tmId, 0, baseId, 8, tmId.length);
040        }
041    
042        public XidFactoryImpl() {
043            byte[] hostid;
044            try {
045                hostid = InetAddress.getLocalHost().getAddress();
046            } catch (UnknownHostException e) {
047                hostid = new byte[]{127, 0, 0, 1};
048            }
049            int uid = System.identityHashCode(this);
050            baseId[8] = (byte) uid;
051            baseId[9] = (byte) (uid >>> 8);
052            baseId[10] = (byte) (uid >>> 16);
053            baseId[11] = (byte) (uid >>> 24);
054            System.arraycopy(hostid, 0, baseId, 12, hostid.length);
055        }
056    
057        public Xid createXid() {
058            byte[] globalId = (byte[]) baseId.clone();
059            long id;
060            synchronized (this) {
061                id = count++;
062            }
063            globalId[0] = (byte) id;
064            globalId[1] = (byte) (id >>> 8);
065            globalId[2] = (byte) (id >>> 16);
066            globalId[3] = (byte) (id >>> 24);
067            globalId[4] = (byte) (id >>> 32);
068            globalId[5] = (byte) (id >>> 40);
069            globalId[6] = (byte) (id >>> 48);
070            globalId[7] = (byte) (id >>> 56);
071            return new XidImpl(globalId);
072        }
073    
074        public Xid createBranch(Xid globalId, int branch) {
075            byte[] branchId = (byte[]) baseId.clone();
076            branchId[0] = (byte) branch;
077            branchId[1] = (byte) (branch >>> 8);
078            branchId[2] = (byte) (branch >>> 16);
079            branchId[3] = (byte) (branch >>> 24);
080            return new XidImpl(globalId, branchId);
081        }
082    
083        public boolean matchesGlobalId(byte[] globalTransactionId) {
084            if (globalTransactionId.length != Xid.MAXGTRIDSIZE) {
085                return false;
086            }
087            for (int i = 8; i < globalTransactionId.length; i++) {
088                if (globalTransactionId[i] != baseId[i]) {
089                    return false;
090                }
091            }
092            return true;
093        }
094    
095        public boolean matchesBranchId(byte[] branchQualifier) {
096            if (branchQualifier.length != Xid.MAXBQUALSIZE) {
097                return false;
098            }
099            for (int i = 8; i < branchQualifier.length; i++) {
100                if (branchQualifier[i] != baseId[i]) {
101                    return false;
102                }
103            }
104            return true;
105        }
106    
107        public Xid recover(int formatId, byte[] globalTransactionid, byte[] branchQualifier) {
108            return new XidImpl(formatId, globalTransactionid, branchQualifier);
109        }
110    
111    }