001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)ExchangeIdImpl.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.binding.proxy.util;
030:
031: import java.util.Enumeration;
032:
033: import java.net.NetworkInterface;
034: import java.net.InetAddress;
035:
036: import java.security.SecureRandom;
037:
038: /**
039: *
040: * This factory class is used to generate message exchange identifiers.
041: *
042: * This implementation uses time-based UUID's as its basis. Since the UUID itself is not
043: * really needed (and it's only in J2SE 5.0) we only return a string representation. The
044: * String representation is changed from the standard to be similar to contruct and easier
045: * to compare with other timestamp that might be available.
046: *
047: * @author Sun Microsystems, Inc
048: *
049: */
050:
051: public final class ExchangeIdImpl implements
052: com.sun.jbi.messaging.ExchangeIdGenerator {
053: /**
054: * Offset from 15-oct-1582 to 1-jan-1970 for timestamp correction.
055: */
056: long mLastTimestamp;
057: int mCounter;
058: int mSequence;
059: long mNode;
060: private final static long CLOCK_OFFSET = 0x01b21dd213814000L;
061: private final static int CLOCK_SCALE = 10000;
062:
063: /*
064: * The random number generator used by this class to create random
065: * based UUIDs.
066: */
067: private SecureRandom mRandom = new SecureRandom();
068:
069: /**
070: * Static factory to retrieve a type 1 (time based) UUID.
071: *
072: * The <code>UUID</code> is generated using a cryptographically strong
073: * pseudo random number generator.
074: *
075: * @return a randomly generated <tt>UUID</tt>.
076: */
077: public String nextId() {
078: long now = System.currentTimeMillis();
079: StringBuilder sb = new StringBuilder(40);
080: int counter;
081: long node;
082: int sequence;
083:
084: synchronized (this ) {
085: node = mNode;
086: sequence = mSequence;
087: if (mNode == 0 || now < mLastTimestamp) {
088: initialize();
089: node = mNode;
090: sequence = mSequence;
091: } else if (now == mLastTimestamp) {
092: //
093: // If we have generated the limit of UUID's per tick we have to wait.
094: //
095: if (mCounter == CLOCK_SCALE) {
096: mCounter &= 0xFF;
097: do {
098: try {
099: Thread.sleep(1L);
100: } catch (InterruptedException ie) {
101: }
102: now = System.currentTimeMillis();
103: } while (now == mLastTimestamp);
104: }
105: } else {
106: mCounter &= 0xff;
107: }
108: mLastTimestamp = now;
109: counter = ++mCounter;
110: }
111:
112: //
113: // Format up the identifier.
114: //
115: sb.append(node);
116: sb.append('-');
117: sb.append(sequence);
118: sb.append('-');
119: sb.append(now * CLOCK_SCALE + CLOCK_OFFSET + counter);
120: return (sb.toString());
121: }
122:
123: private void initialize() {
124: //
125: // For added entropy, add seeding material to the RNG. We use our set of network
126: // interface address as input.
127: //
128: if (mNode == 0) {
129: Enumeration eni;
130:
131: //
132: // Let the RNG seed itself.
133: //
134: mRandom.nextBytes(new byte[16]);
135:
136: //
137: // Now add the InetAddresses.
138: //
139: try {
140: eni = NetworkInterface.getNetworkInterfaces();
141: while (eni.hasMoreElements()) {
142: NetworkInterface ni = (NetworkInterface) eni
143: .nextElement();
144: Enumeration eia = ni.getInetAddresses();
145: while (eia.hasMoreElements()) {
146: InetAddress ia = (InetAddress) eia
147: .nextElement();
148: mRandom.setSeed(ia.getAddress());
149: }
150: }
151: } catch (java.net.SocketException sEx) {
152:
153: }
154: mNode = mRandom.nextLong() & 0xffffffffffffL;
155:
156: }
157:
158: mCounter = (mRandom.nextInt() & 0xff);
159: mSequence = (mRandom.nextInt() & 0xffff);
160: }
161: }
|