001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.tm;
023:
024: import javax.transaction.xa.Xid;
025:
026: /**
027: * This object encapsulates the ID of a transaction.
028: * This implementation is immutable and always serializable at runtime.
029: *
030: * @see TransactionImpl
031: * @author <a href="mailto:rickard.oberg@telkel.com">Rickard �berg</a>
032: * @author <a href="mailto:osh@sparre.dk">Ole Husgaard</a>
033: * @author <a href="reverbel@ime.usp.br">Francisco Reverbel</a>
034: * @version $Revision: 57208 $
035: */
036: public class XidImpl implements Xid, java.io.Serializable {
037: static final long serialVersionUID = -4175838107150528488L;
038: // Constants -----------------------------------------------------
039:
040: public static final int JBOSS_FORMAT_ID = 0x0101;
041:
042: // Static variable -----------------------------------------------
043:
044: private static boolean trulyGlobalIdsEnabled = false;
045:
046: // Attributes ----------------------------------------------------
047:
048: /**
049: * Format id of this instance.
050: * A JBoss-generated Xids has JBOSS_FORMAT_ID in this field.
051: */
052: private final int formatId;
053:
054: /**
055: * Global transaction id of this instance.
056: * The coding of this class depends on the fact that this variable is
057: * initialized in the constructor and never modified. References to
058: * this array are never given away, instead a clone is delivered.
059: */
060: private final byte[] globalId;
061:
062: /**
063: * Branch qualifier of this instance.
064: * This identifies the branch of a transaction.
065: */
066: private final byte[] branchId;
067:
068: /**
069: * Hash code of this instance. This is really a sequence number.
070: */
071: private final int hash;
072:
073: /**
074: * Local id of this instance. This field uniquely identifies a
075: * transaction within a given JBoss server.
076: */
077: private final long localId;
078:
079: /**
080: * Global id of this instance. This field uniquely identifies a
081: * transaction in a distributed environment.
082: */
083: private final GlobalId trulyGlobalId;
084:
085: // Static --------------------------------------------------------
086:
087: /**
088: * Setter for class variable trulyGlobalIdsEnabled.
089: */
090: public static void setTrulyGlobalIdsEnabled(boolean newValue) {
091: trulyGlobalIdsEnabled = newValue;
092: }
093:
094: /**
095: * Getter for class variable trulyGlobalIdsEnabled.
096: */
097: public static boolean getTrulyGlobalIdsEnabled() {
098: return trulyGlobalIdsEnabled;
099: }
100:
101: /**
102: * Return a string that describes any Xid instance.
103: */
104: static String toString(Xid id) {
105: if (id == null)
106: return "[NULL Xid]";
107:
108: String s = id.getClass().getName();
109: s = s.substring(s.lastIndexOf('.') + 1);
110: s = s
111: + "[FormatId="
112: + id.getFormatId()
113: + ", GlobalId="
114: + new String(id.getGlobalTransactionId()).trim()
115: + ", BranchQual="
116: + new String(id.getBranchQualifier()).trim()
117: + ((id instanceof XidImpl) ? ", localId="
118: + ((XidImpl) id).localId : "") + "]";
119:
120: return s;
121: }
122:
123: // Constructors --------------------------------------------------
124:
125: /**
126: * Create a new instance.
127: */
128: public XidImpl(int formatId, byte[] globalId, byte[] branchId,
129: int hash, long localId) {
130: this .formatId = formatId;
131: this .globalId = globalId;
132: this .branchId = branchId;
133: this .hash = hash;
134: this .localId = localId;
135: this .trulyGlobalId = (trulyGlobalIdsEnabled) ? new GlobalId(
136: formatId, globalId) : null;
137: }
138:
139: /**
140: * Create a new instance with JBOSS_FORMAT_ID.
141: */
142: XidImpl(byte[] globalId, byte[] branchId, int hash, long localId) {
143: this .formatId = JBOSS_FORMAT_ID;
144: this .globalId = globalId;
145: this .branchId = branchId;
146: this .hash = hash;
147: this .localId = localId;
148: this .trulyGlobalId = (trulyGlobalIdsEnabled) ? new GlobalId(
149: JBOSS_FORMAT_ID, globalId, hash) : null;
150: }
151:
152: /**
153: * Create a new branch of an existing global transaction ID.
154: *
155: * @param xidImpl The transaction ID to create a new branch of.
156: * @param branchId The ID of the new branch.
157: *
158: */
159: public XidImpl(final XidImpl xidImpl, final byte[] branchId) {
160: this .formatId = xidImpl.formatId;
161: this .globalId = xidImpl.globalId; // reuse array, we never modify it
162: this .branchId = branchId;
163: this .hash = xidImpl.hash;
164: this .localId = xidImpl.localId;
165: this .trulyGlobalId = (trulyGlobalIdsEnabled) ? xidImpl.trulyGlobalId
166: : null;
167: }
168:
169: // Public --------------------------------------------------------
170:
171: // Xid implementation --------------------------------------------
172:
173: /**
174: * Return the global transaction id of this transaction.
175: */
176: public byte[] getGlobalTransactionId() {
177: return (byte[]) globalId.clone();
178: }
179:
180: /**
181: * Return the branch qualifier of this transaction.
182: */
183: public byte[] getBranchQualifier() {
184: if (branchId.length == 0)
185: return branchId; // Zero length arrays are immutable.
186: else
187: return (byte[]) branchId.clone();
188: }
189:
190: /**
191: * Return the format identifier of this transaction.
192: *
193: * The format identifier augments the global id and specifies
194: * how the global id and branch qualifier should be interpreted.
195: */
196: public int getFormatId() {
197: // The id we return here should be different from all other transaction
198: // implementations.
199: // Known IDs are:
200: // -1: Sometimes used to denote a null transaction id.
201: // 0: OSI TP (javadoc states OSI CCR, but that is a bit misleading
202: // as OSI CCR doesn't even have ACID properties. But OSI CCR and
203: // OSI TP do have the same id format.)
204: // 1: Was used by early betas of jBoss.
205: // 0x0101: The JBOSS_FORMAT_ID we use here.
206: // 0xBB14: Used by JONAS.
207: // 0xBB20: Used by JONAS.
208:
209: return formatId;
210: }
211:
212: /**
213: * Compare for equality.
214: *
215: * Instances are considered equal if they are both instances of XidImpl,
216: * and if they have the same format id, the same global transaction id
217: * and the same transaction branch qualifier.
218: */
219: public boolean equals(Object obj) {
220: if (obj == this )
221: return true;
222: if (obj instanceof XidImpl) {
223: XidImpl other = (XidImpl) obj;
224:
225: if (formatId != other.formatId
226: || globalId.length != other.globalId.length
227: || branchId.length != other.branchId.length)
228: return false;
229:
230: for (int i = 0; i < globalId.length; ++i)
231: if (globalId[i] != other.globalId[i])
232: return false;
233:
234: for (int i = 0; i < branchId.length; ++i)
235: if (branchId[i] != other.branchId[i])
236: return false;
237:
238: return true;
239: }
240: return false;
241: }
242:
243: public int hashCode() {
244: return hash;
245: }
246:
247: public String toString() {
248: return toString(this );
249: }
250:
251: // Methods specific to JBoss Xid implementation ------------------
252:
253: /**
254: * Return the local id that identifies this transaction
255: * within the JBoss server.
256: */
257: public long getLocalIdValue() {
258: return localId;
259: }
260:
261: /**
262: * Return a LocalId instance that identifies this transaction
263: * within the JBoss server.
264: */
265: public LocalId getLocalId() {
266: return new LocalId(localId);
267: }
268:
269: /**
270: * Return a GlobalId instance that identifies this transaction
271: * in a distributed environment.
272: */
273: public GlobalId getTrulyGlobalId() {
274: return trulyGlobalId;
275: }
276:
277: /**
278: * Compare for same transaction.
279: *
280: * Instances represent the same transaction if they have the same
281: * format id and global transaction id.
282: */
283: public boolean sameTransaction(XidImpl other) {
284: if (other == this )
285: return true;
286: if (formatId != other.formatId
287: || globalId.length != other.globalId.length)
288: return false;
289:
290: for (int i = 0; i < globalId.length; ++i)
291: if (globalId[i] != other.globalId[i])
292: return false;
293:
294: return true;
295: }
296:
297: // Package protected ---------------------------------------------
298:
299: /**
300: * Return the global transaction id of this transaction.
301: * Unlike the {@link #getGlobalTransactionId()} method, this one
302: * returns a reference to the global id byte array that may <em>not</em>
303: * be changed.
304: */
305: byte[] getInternalGlobalTransactionId() {
306: return globalId;
307: }
308:
309: // Protected -----------------------------------------------------
310:
311: // Private -------------------------------------------------------
312:
313: // Inner classes -------------------------------------------------
314: }
|