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.io.Serializable;
021    import java.util.Arrays;
022    import javax.transaction.xa.Xid;
023    
024    /**
025     * Unique id for a transaction.
026     *
027     * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
028     */
029    public class XidImpl implements Xid, Serializable {
030        private static int FORMAT_ID = 0x4765526f;  // Gero
031        private final int formatId;
032        private final byte[] globalId;
033        private final byte[] branchId;
034        private int hash;   //apparently never used by our code, so don't compute it.
035    
036        /**
037         * Constructor taking a global id (for the main transaction)
038         * @param globalId the global transaction id
039         */
040        public XidImpl(byte[] globalId) {
041            this.formatId = FORMAT_ID;
042            this.globalId = globalId;
043            //this.hash = hash(0, globalId);
044            branchId = new byte[Xid.MAXBQUALSIZE];
045        }
046    
047        /**
048         * Constructor for a branch id
049         * @param global the xid of the global transaction this branch belongs to
050         * @param branch the branch id
051         */
052        public XidImpl(Xid global, byte[] branch) {
053            this.formatId = FORMAT_ID;
054            //int hash;
055            if (global instanceof XidImpl) {
056                globalId = ((XidImpl) global).globalId;
057                //hash = ((XidImpl) global).hash;
058            } else {
059                globalId = global.getGlobalTransactionId();
060                //hash = hash(0, globalId);
061            }
062            branchId = branch;
063            //this.hash = hash(hash, branchId);
064        }
065    
066        public XidImpl(int formatId, byte[] globalId, byte[] branchId) {
067            this.formatId = formatId;
068            this.globalId = globalId;
069            this.branchId = branchId;
070        }
071    
072        private int hash(int hash, byte[] id) {
073            for (int i = 0; i < id.length; i++) {
074                hash = (hash * 37) + id[i];
075            }
076            return hash;
077        }
078    
079        public int getFormatId() {
080            return formatId;
081        }
082    
083        public byte[] getGlobalTransactionId() {
084            return (byte[]) globalId.clone();
085        }
086    
087        public byte[] getBranchQualifier() {
088            return (byte[]) branchId.clone();
089        }
090    
091        public boolean equals(Object obj) {
092            if (obj instanceof XidImpl == false) {
093                return false;
094            }
095            XidImpl other = (XidImpl) obj;
096            return formatId == other.formatId
097                    && Arrays.equals(globalId, other.globalId)
098                    && Arrays.equals(branchId, other.branchId);
099        }
100    
101        public int hashCode() {
102            if (hash == 0) {
103                hash = hash(hash(0, globalId), branchId);
104            }
105            return hash;
106        }
107    
108        public String toString() {
109            StringBuffer s = new StringBuffer();
110            s.append("[globalId=");
111            for (int i = 0; i < globalId.length; i++) {
112                s.append(Integer.toHexString(globalId[i]));
113            }
114            s.append(",branchId=");
115            for (int i = 0; i < branchId.length; i++) {
116                s.append(Integer.toHexString(branchId[i]));
117            }
118            s.append("]");
119            return s.toString();
120        }
121    }