/** * Alipay.com Inc. * Copyright (c) 2004-2012 All Rights Reserved. */ package com.alipay.zdal.datasource.tm; import javax.transaction.xa.Xid; /** * This object encapsulates the ID of a transaction. * This implementation is immutable and always serializable at runtime. * * @see TransactionImpl * @version $Revision: 57208 $ */ public class XidImpl implements Xid, java.io.Serializable { static final long serialVersionUID = -4175838107150528488L; // Constants ----------------------------------------------------- public static final int JBOSS_FORMAT_ID = 0x0101; // Static variable ----------------------------------------------- private static boolean trulyGlobalIdsEnabled = false; // Attributes ---------------------------------------------------- /** * Format id of this instance. * A JBoss-generated Xids has JBOSS_FORMAT_ID in this field. */ private final int formatId; /** * Global transaction id of this instance. * The coding of this class depends on the fact that this variable is * initialized in the constructor and never modified. References to * this array are never given away, instead a clone is delivered. */ private final byte[] globalId; /** * Branch qualifier of this instance. * This identifies the branch of a transaction. */ private final byte[] branchId; /** * Hash code of this instance. This is really a sequence number. */ private final int hash; /** * Local id of this instance. This field uniquely identifies a * transaction within a given JBoss server. */ private final long localId; /** * Global id of this instance. This field uniquely identifies a * transaction in a distributed environment. */ private final GlobalId trulyGlobalId; // Static -------------------------------------------------------- /** * Setter for class variable trulyGlobalIdsEnabled. */ public static void setTrulyGlobalIdsEnabled(boolean newValue) { trulyGlobalIdsEnabled = newValue; } /** * Getter for class variable trulyGlobalIdsEnabled. */ public static boolean getTrulyGlobalIdsEnabled() { return trulyGlobalIdsEnabled; } /** * Return a string that describes any Xid instance. */ static String toString(Xid id) { if (id == null) return "[NULL Xid]"; String s = id.getClass().getName(); s = s.substring(s.lastIndexOf('.') + 1); s = s + "[FormatId=" + id.getFormatId() + ", GlobalId=" + new String(id.getGlobalTransactionId()).trim() + ", BranchQual=" + new String(id.getBranchQualifier()).trim() + ((id instanceof XidImpl) ? ", localId=" + ((XidImpl) id).localId : "") + "]"; return s; } // Constructors -------------------------------------------------- /** * Create a new instance. */ public XidImpl(int formatId, byte[] globalId, byte[] branchId, int hash, long localId) { this.formatId = formatId; this.globalId = globalId; this.branchId = branchId; this.hash = hash; this.localId = localId; this.trulyGlobalId = (trulyGlobalIdsEnabled) ? new GlobalId(formatId, globalId) : null; } /** * Create a new instance with JBOSS_FORMAT_ID. */ XidImpl(byte[] globalId, byte[] branchId, int hash, long localId) { this.formatId = JBOSS_FORMAT_ID; this.globalId = globalId; this.branchId = branchId; this.hash = hash; this.localId = localId; this.trulyGlobalId = (trulyGlobalIdsEnabled) ? new GlobalId(JBOSS_FORMAT_ID, globalId, hash) : null; } /** * Create a new branch of an existing global transaction ID. * * @param xidImpl The transaction ID to create a new branch of. * @param branchId The ID of the new branch. * */ public XidImpl(final XidImpl xidImpl, final byte[] branchId) { this.formatId = xidImpl.formatId; this.globalId = xidImpl.globalId; // reuse array, we never modify it this.branchId = branchId; this.hash = xidImpl.hash; this.localId = xidImpl.localId; this.trulyGlobalId = (trulyGlobalIdsEnabled) ? xidImpl.trulyGlobalId : null; } // Public -------------------------------------------------------- // Xid implementation -------------------------------------------- /** * Return the global transaction id of this transaction. */ public byte[] getGlobalTransactionId() { return (byte[]) globalId.clone(); } /** * Return the branch qualifier of this transaction. */ public byte[] getBranchQualifier() { if (branchId.length == 0) return branchId; // Zero length arrays are immutable. else return (byte[]) branchId.clone(); } /** * Return the format identifier of this transaction. * * The format identifier augments the global id and specifies * how the global id and branch qualifier should be interpreted. */ public int getFormatId() { // The id we return here should be different from all other transaction // implementations. // Known IDs are: // -1: Sometimes used to denote a null transaction id. // 0: OSI TP (javadoc states OSI CCR, but that is a bit misleading // as OSI CCR doesn't even have ACID properties. But OSI CCR and // OSI TP do have the same id format.) // 1: Was used by early betas of jBoss. // 0x0101: The JBOSS_FORMAT_ID we use here. // 0xBB14: Used by JONAS. // 0xBB20: Used by JONAS. return formatId; } /** * Compare for equality. * * Instances are considered equal if they are both instances of XidImpl, * and if they have the same format id, the same global transaction id * and the same transaction branch qualifier. */ public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof XidImpl) { XidImpl other = (XidImpl) obj; if (formatId != other.formatId || globalId.length != other.globalId.length || branchId.length != other.branchId.length) return false; for (int i = 0; i < globalId.length; ++i) if (globalId[i] != other.globalId[i]) return false; for (int i = 0; i < branchId.length; ++i) if (branchId[i] != other.branchId[i]) return false; return true; } return false; } public int hashCode() { return hash; } public String toString() { return toString(this); } // Methods specific to JBoss Xid implementation ------------------ /** * Return the local id that identifies this transaction * within the JBoss server. */ public long getLocalIdValue() { return localId; } /** * Return a LocalId instance that identifies this transaction * within the JBoss server. */ public LocalId getLocalId() { return new LocalId(localId); } /** * Return a GlobalId instance that identifies this transaction * in a distributed environment. */ public GlobalId getTrulyGlobalId() { return trulyGlobalId; } /** * Compare for same transaction. * * Instances represent the same transaction if they have the same * format id and global transaction id. */ public boolean sameTransaction(XidImpl other) { if (other == this) return true; if (formatId != other.formatId || globalId.length != other.globalId.length) return false; for (int i = 0; i < globalId.length; ++i) if (globalId[i] != other.globalId[i]) return false; return true; } // Package protected --------------------------------------------- /** * Return the global transaction id of this transaction. * Unlike the {@link #getGlobalTransactionId()} method, this one * returns a reference to the global id byte array that may <em>not</em> * be changed. */ byte[] getInternalGlobalTransactionId() { return globalId; } // Protected ----------------------------------------------------- // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- }