XidImpl.java
001 /* Licensed to the Apache Software Foundation (ASF) under one
002  * or more contributor license agreements.  See the NOTICE file
003  * distributed with this work for additional information
004  * regarding copyright ownership.  The ASF licenses this file
005  * to you under the Apache License, Version 2.0 (the
006  * "License"); you may not use this file except in compliance
007  * with 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,
012  * software distributed under the License is distributed on an
013  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
014  * KIND, either express or implied.  See the License for the
015  * specific language governing permissions and limitations
016  * under the License.
017  */
018 package org.apache.qpid.dtx;
019 
020 import org.slf4j.Logger;
021 import org.slf4j.LoggerFactory;
022 import org.apache.qpid.QpidException;
023 
024 import javax.transaction.xa.Xid;
025 
026 import java.io.*;
027 
028 /**
029  * Implements javax.transaction.dtx.Xid
030  */
031 public class XidImpl implements Xid
032 {
033     /**
034      * this session's logger
035      */
036     private static final Logger _logger = LoggerFactory.getLogger(XidImpl.class);
037 
038     /**
039      * the transaction branch identifier part of XID as an array of bytes
040      */
041     private byte[] _branchQualifier;
042 
043     /**
044      * the format identifier part of the XID.
045      */
046     private int _formatID;
047 
048     /**
049      * the global transaction identifier part of XID as an array of bytes.
050      */
051     private byte[] _globalTransactionID;
052 
053     //--- Constructors
054 
055     /**
056      * Create new Xid.
057      * this is an empty constructor.
058      */
059     public XidImpl()
060     {
061 
062     }
063 
064     /**
065      * Create a new XidImpl from an existing Xid.
066      <p> Usefull for casting external Xids
067      *
068      @param xid Foreign Xid.
069      */
070     public XidImpl(Xid xid)
071     {
072         _branchQualifier = xid.getBranchQualifier();
073         _formatID = xid.getFormatId();
074         _globalTransactionID = xid.getGlobalTransactionId();
075     }
076 
077     /**
078      * Create a new Xid.
079      *
080      @param branchQualifier     The transaction branch identifier part of XID as an array of bytes.
081      @param format              The format identifier part of the XID.
082      @param globalTransactionID The global transaction identifier part of XID as an array of bytes.
083      */
084     public XidImpl(byte[] branchQualifier, int format, byte[] globalTransactionID)
085     {
086         _branchQualifier = branchQualifier;
087         _formatID = format;
088         _globalTransactionID = globalTransactionID;
089     }
090 
091     /**
092      * Create a new Xid form its String form
093      * 4         1   1        g            b
094      * +---+---+---+---+---+---+---+-  -+---+---+-  -+---+
095      * |   format_id   | g | b |   txn-id   |   br-id    |
096      * +---+---+---+---+---+---+---+-  -+---+---+-  -+---+
097      * 0               4   5   6           6+g         6+g+b
098      * format_id: an implementation specific format identifier
099      <p/>
100      * gtrid_length: how many bytes of this form the transaction id
101      <p/>
102      * bqual_length: how many bytes of this form the branch id
103      <p/>
104      * data: a sequence of octets of at most 128 bytes containing the txn id and the
105      * branch id
106      <p/>
107      * Note - The sum of the two lengths must equal the length of the data field.
108      *
109      @param xid an XID STring Form
110      @throws QpidException If the string does not represent a valid Xid
111      */
112     public XidImpl(String xidthrows QpidException
113     {
114         if (_logger.isDebugEnabled())
115         {
116             _logger.debug("converting string " + xid + " into XidImpl");
117         }
118         try
119         {
120             DataInputStream input = new DataInputStream(new ByteArrayInputStream(xid.getBytes()));
121             _formatID = (intinput.readLong();
122             int g = input.readByte();
123             int b = input.readByte();
124             _globalTransactionID = new byte[g];
125             _branchQualifier = new byte[b];
126             if (input.read(_globalTransactionID, 0, g!= g)
127             {
128                 throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null);
129             }
130             if (input.read(_branchQualifier, 0, b!= b)
131             {
132                 throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null);
133             }
134         }
135         catch (IOException e)
136         {
137             throw new QpidException("cannot convert the string " + xid + " into an Xid", null, e);
138         }
139     }
140 
141     //---  Xid interface implementation
142 
143     /**
144      * Format identifier. O means the OSI CCR format.
145      *
146      @return Global transaction identifier.
147      */
148     public byte[] getGlobalTransactionId()
149     {
150         return _globalTransactionID;
151     }
152 
153     /**
154      * Obtain the transaction branch identifier part of XID as an array of bytes.
155      *
156      @return Branch identifier part of XID.
157      */
158     public byte[] getBranchQualifier()
159     {
160         return _branchQualifier;
161     }
162 
163     /**
164      * Obtain the format identifier part of the XID.
165      *
166      @return Format identifier. O means the OSI CCR format.
167      */
168     public int getFormatId()
169     {
170         return _formatID;
171     }
172 
173     //--- Object operations
174 
175     /**
176      * Indicates whether some other Xid is "equal to" this one.
177      <p> Two Xids are equal if and only if their three elementary parts are equal
178      *
179      @param o the object to compare this <code>XidImpl</code> against.
180      @return true if the <code>XidImpl</code> are equal, false otherwise.
181      */
182     public boolean equals(Object o)
183     {
184         if (this == o)
185         {
186             return true;
187         }
188         if (instanceof XidImpl)
189         {
190             XidImpl other = (XidImplo;
191             if (_formatID == other.getFormatId())
192             {
193                 if (_branchQualifier.length == other.getBranchQualifier().length)
194                 {
195                     for (int i = 0; i < _branchQualifier.length; i++)
196                     {
197                         if (_branchQualifier[i!= other.getBranchQualifier()[i])
198                         {
199                             return false;
200                         }
201                     }
202                     if (_globalTransactionID.length == other.getGlobalTransactionId().length)
203                     {
204                         for (int i = 0; i < _globalTransactionID.length; i++)
205                         {
206                             if (_globalTransactionID[i!= other.getGlobalTransactionId()[i])
207                             {
208                                 return false;
209                             }
210                         }
211                         // everithing is equal
212                         return true;
213                     }
214                 }
215             }
216         }
217         return false;
218     }
219 
220     //-- Static helper method
221     /**
222      * Convert an Xid into the AMQP String format.
223      
224      * 4         1   1        g            b
225      * +---+---+---+---+---+---+---+-  -+---+---+-  -+---+
226      * |   format_id   | g | b |   txn-id   |   br-id    |
227      * +---+---+---+---+---+---+---+-  -+---+---+-  -+---+
228      * 0               4   5   6           6+g         6+g+b
229      * format_id: an implementation specific format identifier
230      <p/>
231      * gtrid_length: how many bytes of this form the transaction id
232      <p/>
233      * bqual_length: how many bytes of this form the branch id
234      <p/>
235      * data: a sequence of octets of at most 128 bytes containing the txn id and the
236      * branch id
237      <p/>
238      * Note - The sum of the two lengths must equal the length of the data field.
239      *
240      @param xid an Xid to convert.
241      @return The String representation of this Xid
242      @throws QpidException In case of problem when converting this Xid into a string.
243      */
244     public static org.apache.qpid.transport.Xid convert(Xid xidthrows QpidException
245     {
246         return new org.apache.qpid.transport.Xid(xid.getFormatId(),
247                                                     xid.getGlobalTransactionId(),
248                                                     xid.getBranchQualifier());
249     }
250 }