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    package org.apache.activemq.command;
018    
019    import java.util.Arrays;
020    import javax.transaction.xa.Xid;
021    import org.apache.activemq.util.HexSupport;
022    
023    /**
024     * @openwire:marshaller code="112"
025     * @version $Revision: 1.6 $
026     */
027    public class XATransactionId extends TransactionId implements Xid, Comparable {
028    
029        public static final byte DATA_STRUCTURE_TYPE = CommandTypes.ACTIVEMQ_XA_TRANSACTION_ID;
030    
031        private int formatId;
032        private byte[] branchQualifier;
033        private byte[] globalTransactionId;
034    
035        private transient int hash;
036        private transient String transactionKey;
037    
038        public XATransactionId() {
039        }
040    
041        public XATransactionId(Xid xid) {
042            this.formatId = xid.getFormatId();
043            this.globalTransactionId = xid.getGlobalTransactionId();
044            this.branchQualifier = xid.getBranchQualifier();
045        }
046    
047        public byte getDataStructureType() {
048            return DATA_STRUCTURE_TYPE;
049        }
050    
051        public synchronized String getTransactionKey() {
052            if (transactionKey == null) {
053                transactionKey = "XID:" + formatId + ":" + HexSupport.toHexFromBytes(globalTransactionId) + ":"
054                                 + HexSupport.toHexFromBytes(branchQualifier);
055            }
056            return transactionKey;
057        }
058    
059        public String toString() {
060            return getTransactionKey();
061        }
062    
063        public boolean isXATransaction() {
064            return true;
065        }
066    
067        public boolean isLocalTransaction() {
068            return false;
069        }
070    
071        /**
072         * @openwire:property version=1
073         */
074        public int getFormatId() {
075            return formatId;
076        }
077    
078        /**
079         * @openwire:property version=1
080         */
081        public byte[] getGlobalTransactionId() {
082            return globalTransactionId;
083        }
084    
085        /**
086         * @openwire:property version=1
087         */
088        public byte[] getBranchQualifier() {
089            return branchQualifier;
090        }
091    
092        public void setBranchQualifier(byte[] branchQualifier) {
093            this.branchQualifier = branchQualifier;
094            this.hash = 0;
095        }
096    
097        public void setFormatId(int formatId) {
098            this.formatId = formatId;
099            this.hash = 0;
100        }
101    
102        public void setGlobalTransactionId(byte[] globalTransactionId) {
103            this.globalTransactionId = globalTransactionId;
104            this.hash = 0;
105        }
106    
107        public int hashCode() {
108            if (hash == 0) {
109                hash = formatId;
110                hash = hash(globalTransactionId, hash);
111                hash = hash(branchQualifier, hash);
112                if (hash == 0) {
113                    hash = 0xaceace;
114                }
115            }
116            return hash;
117        }
118    
119        private static int hash(byte[] bytes, int hash) {
120            int size = bytes.length;
121            for (int i = 0; i < size; i++) {
122                hash ^= bytes[i] << ((i % 4) * 8);
123            }
124            return hash;
125        }
126    
127        public boolean equals(Object o) {
128            if (o == null || o.getClass() != XATransactionId.class) {
129                return false;
130            }
131            XATransactionId xid = (XATransactionId)o;
132            return xid.formatId == formatId && Arrays.equals(xid.globalTransactionId, globalTransactionId)
133                   && Arrays.equals(xid.branchQualifier, branchQualifier);
134        }
135    
136        public int compareTo(Object o) {
137            if (o == null || o.getClass() != XATransactionId.class) {
138                return -1;
139            }
140            XATransactionId xid = (XATransactionId)o;
141            return getTransactionKey().compareTo(xid.getTransactionKey());
142        }
143    
144    }