View Javadoc

1   /**
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.transaction.manager;
19  
20  import java.util.Random;
21  import javax.transaction.xa.Xid;
22  import java.net.InetAddress;
23  import java.net.UnknownHostException;
24  
25  /**
26   * Factory for transaction ids.
27   * The Xid is constructed of three parts:
28   * <ol><li>8 byte count (LSB first)</li>
29   * <li>4 byte system id</li>
30   * <li>2 byte entropy</li>
31   * <li>4 or 16 byte IP address of host</li>
32   * <ol>
33   * @version $Rev: 740842 $ $Date: 2009-02-04 14:51:48 -0500 (Wed, 04 Feb 2009) $
34   * todo Should have a way of setting baseId
35   */
36  public class XidFactoryImpl implements XidFactory {
37      private final byte[] baseId = new byte[Xid.MAXGTRIDSIZE];
38      private long count = 1;
39  
40      public XidFactoryImpl(byte[] tmId) {
41         System.arraycopy(tmId, 0, baseId, 8, tmId.length);
42      }
43  
44      public XidFactoryImpl() {
45          byte[] hostid;
46          try {
47              hostid = InetAddress.getLocalHost().getAddress();
48          } catch (UnknownHostException e) {
49              hostid = new byte[]{127, 0, 0, 1};
50          }
51          int uid = System.identityHashCode(this);
52          baseId[8] = (byte) uid;
53          baseId[9] = (byte) (uid >>> 8);
54          baseId[10] = (byte) (uid >>> 16);
55          baseId[11] = (byte) (uid >>> 24);
56  
57          byte[] entropy = new byte[2];
58          new Random().nextBytes(entropy);
59          baseId[12] = entropy[0];
60          baseId[13] = entropy[1];
61  
62          System.arraycopy(hostid, 0, baseId, 14, hostid.length);
63      }
64  
65      public Xid createXid() {
66          byte[] globalId = (byte[]) baseId.clone();
67          long id;
68          synchronized (this) {
69              id = count++;
70          }
71          globalId[0] = (byte) id;
72          globalId[1] = (byte) (id >>> 8);
73          globalId[2] = (byte) (id >>> 16);
74          globalId[3] = (byte) (id >>> 24);
75          globalId[4] = (byte) (id >>> 32);
76          globalId[5] = (byte) (id >>> 40);
77          globalId[6] = (byte) (id >>> 48);
78          globalId[7] = (byte) (id >>> 56);
79          return new XidImpl(globalId);
80      }
81  
82      public Xid createBranch(Xid globalId, int branch) {
83          byte[] branchId = (byte[]) baseId.clone();
84          branchId[0] = (byte) branch;
85          branchId[1] = (byte) (branch >>> 8);
86          branchId[2] = (byte) (branch >>> 16);
87          branchId[3] = (byte) (branch >>> 24);
88          return new XidImpl(globalId, branchId);
89      }
90  
91      public boolean matchesGlobalId(byte[] globalTransactionId) {
92          if (globalTransactionId.length != Xid.MAXGTRIDSIZE) {
93              return false;
94          }
95          for (int i = 8; i < globalTransactionId.length; i++) {
96              if (globalTransactionId[i] != baseId[i]) {
97                  return false;
98              }
99          }
100         return true;
101     }
102 
103     public boolean matchesBranchId(byte[] branchQualifier) {
104         if (branchQualifier.length != Xid.MAXBQUALSIZE) {
105             return false;
106         }
107         for (int i = 8; i < branchQualifier.length; i++) {
108             if (branchQualifier[i] != baseId[i]) {
109                 return false;
110             }
111         }
112         return true;
113     }
114 
115     public Xid recover(int formatId, byte[] globalTransactionid, byte[] branchQualifier) {
116         return new XidImpl(formatId, globalTransactionid, branchQualifier);
117     }
118 
119 }