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 java.net.InetAddress;
025: import javax.transaction.xa.Xid;
026: import java.net.UnknownHostException;
027:
028: /**
029: * XidFactory.java
030: *
031: *
032: * Created: Sat Jun 15 19:01:18 2002
033: *
034: * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
035: * @version
036: *
037: * @jmx.mbean
038: */
039: public class XidFactory implements XidFactoryMBean {
040: /**
041: * The default value of baseGlobalId is the host name of this host,
042: * followed by a slash.
043: *
044: * This is used for building globally unique transaction identifiers.
045: * It would be safer to use the IP address, but a host name is better
046: * for humans to read and will do for now.
047: * This must be set individually if multiple jboss instances are
048: * running on the same machine.
049: */
050: private String baseGlobalId;
051:
052: /**
053: * The next transaction id to use on this host.
054: */
055: private long globalIdNumber = 0;
056:
057: /**
058: * The variable <code>pad</code> says whether the byte[] should be their
059: * maximum 64 byte length or the minimum.
060: * The max length is required for Oracle..
061: */
062: private boolean pad = false;
063:
064: /**
065: * The variable <code>noBranchQualifier</code> is the 1 or 64 byte zero
066: * array used for initial xids.
067: */
068: private byte[] noBranchQualifier = new byte[1]; // len > 0, per the XA spec
069:
070: /**
071: * This field stores the byte reprsentation of baseGlobalId
072: * to avoid the expensive getBytes() call on this String object
073: * when we create a new Xid, which we do VERY often!
074: */
075: private byte[] baseGlobalIdBytes;
076:
077: public XidFactory() {
078: try {
079: baseGlobalId = InetAddress.getLocalHost().getHostName();
080: // Ensure room for 14 digits of serial no.
081: if (baseGlobalId.length() > Xid.MAXGTRIDSIZE - 15)
082: baseGlobalId = baseGlobalId.substring(0,
083: Xid.MAXGTRIDSIZE - 15);
084: baseGlobalId = baseGlobalId + "/";
085: } catch (UnknownHostException e) {
086: baseGlobalId = "localhost/";
087: }
088: baseGlobalIdBytes = baseGlobalId.getBytes();
089: }
090:
091: /**
092: * mbean get-set pair for field BaseGlobalId
093: * Get the value of BaseGlobalId
094: * @return value of BaseGlobalId
095: *
096: * @jmx:managed-attribute
097: */
098: public String getBaseGlobalId() {
099: return baseGlobalId;
100: }
101:
102: /**
103: * Set the value of BaseGlobalId
104: * @param BaseGlobalId Value to assign to BaseGlobalId
105: *
106: * @jmx:managed-attribute
107: */
108: public void setBaseGlobalId(final String baseGlobalId) {
109: this .baseGlobalId = baseGlobalId;
110: baseGlobalIdBytes = baseGlobalId.getBytes();
111: }
112:
113: /**
114: * mbean get-set pair for field globalIdNumber
115: * Get the value of globalIdNumber
116: * @return value of globalIdNumber
117: *
118: * @jmx:managed-attribute
119: */
120: public synchronized long getGlobalIdNumber() {
121: return globalIdNumber;
122: }
123:
124: /**
125: * Set the value of globalIdNumber
126: * @param globalIdNumber Value to assign to globalIdNumber
127: *
128: * @jmx:managed-attribute
129: */
130: public synchronized void setGlobalIdNumber(final long globalIdNumber) {
131: this .globalIdNumber = globalIdNumber;
132: }
133:
134: /**
135: * mbean get-set pair for field pad
136: * Get the value of pad
137: * @return value of pad
138: *
139: * @jmx:managed-attribute
140: */
141: public boolean isPad() {
142: return pad;
143: }
144:
145: /**
146: * Set the value of pad
147: * @param pad Value to assign to pad
148: *
149: * @jmx:managed-attribute
150: */
151: public void setPad(boolean pad) {
152: this .pad = pad;
153: if (pad)
154: noBranchQualifier = new byte[Xid.MAXBQUALSIZE];
155: else
156: noBranchQualifier = new byte[1]; // length > 0, per the XA spec
157: }
158:
159: /**
160: * mbean get-set pair for field instance
161: * Get the value of instance
162: * @return value of instance
163: *
164: * @jmx:managed-attribute
165: */
166: public XidFactoryMBean getInstance() {
167: return this ;
168: }
169:
170: /**
171: * Describe <code>newXid</code> method here.
172: *
173: * @return a <code>XidImpl</code> value
174: * @jmx.managed-operation
175: */
176: public XidImpl newXid() {
177: long localId = getNextId();
178: String id = Long.toString(localId);
179: int len = pad ? Xid.MAXGTRIDSIZE : id.length()
180: + baseGlobalIdBytes.length;
181: byte[] globalId = new byte[len];
182: System.arraycopy(baseGlobalIdBytes, 0, globalId, 0,
183: baseGlobalIdBytes.length);
184: // this method is deprecated, but does exactly what we need in a very fast way
185: // the default conversion from String.getBytes() is way too expensive
186: id.getBytes(0, id.length(), globalId, baseGlobalIdBytes.length);
187: return new XidImpl(globalId, noBranchQualifier, (int) localId,
188: localId);
189: }
190:
191: /**
192: * Describe <code>newBranch</code> method here.
193: *
194: * @param xid a <code>XidImpl</code> value
195: * @param branchIdNum a <code>long</code> value
196: * @return a <code>XidImpl</code> value
197: * @jmx.managed-operation
198: */
199: public XidImpl newBranch(XidImpl xid, long branchIdNum) {
200: String id = Long.toString(branchIdNum);
201: int len = pad ? Xid.MAXBQUALSIZE : id.length();
202: byte[] branchId = new byte[len];
203: // this method is deprecated, but does exactly what we need in a very fast way
204: // the default conversion from String.getBytes() is way too expensive
205: id.getBytes(0, id.length(), branchId, 0);
206: return new XidImpl(xid, branchId);
207: }
208:
209: /**
210: * Extracts the local id contained in a global id.
211: *
212: * @param globalId a global id
213: * @return the local id extracted from the global id
214: * @jmx:managed-operation
215: */
216: public long extractLocalIdFrom(byte[] globalId) {
217: int i, start;
218: int len = globalId.length;
219:
220: for (i = 0; globalId[i++] != (byte) '/';)
221: ;
222: start = i;
223: while (i < len && globalId[i] != 0)
224: i++;
225: String globalIdNumber = new String(globalId, 0, start, i
226: - start);
227: return Long.parseLong(globalIdNumber);
228: }
229:
230: /**
231: * Describe <code>toString</code> method here.
232: *
233: * @param xid a <code>Xid</code> value
234: * @return a <code>String</code> value
235: * @jmx.managed-operation
236: */
237: public String toString(Xid xid) {
238: if (xid instanceof XidImpl)
239: return XidImpl.toString(xid);
240: else
241: return xid.toString();
242: }
243:
244: private synchronized long getNextId() {
245: return ++globalIdNumber;
246: }
247:
248: }
|