001: package com.sun.portal.wsrp.common;
002:
003: import java.net.InetAddress;
004: import java.net.UnknownHostException;
005:
006: /*
007: * This class can be used to generate a WSRP handle or key. It should
008: * not be confused with javax.crypto.KeyGenerator.
009: */
010: public class KeyGenerator {
011: /*
012: * Most of the code in this class is ripped off from
013: * com/sun/server/session/SessionInformation.java used in
014: * JavaWebServer 2.0 to generate session Ids. Even the comments
015: * are preserved. :-) Something like this is so useful that I
016: * have no idea why this code isn't made public or available in
017: * the JDK.
018: */
019:
020: /* The counter used to generate session ids */
021: private static int mSessionIdCounter = 0;
022:
023: /* The template to use for forming session id's */
024: private static byte[] mSessionIdTemplate;
025:
026: /* The mapping from 5-bit value to character */
027: private static final char[] sBitChars = { 'A', 'B', 'C', 'D', 'E',
028: 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
029: 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
030: '3', '4', '5' };
031:
032: /* The mask for the second bytes */
033: private static final int[] sSecondByteMasks = { 0x0, 0x1, 0x3, 0x7,
034: 0x1f };
035:
036: public static String generateKey() {
037: return generateSessionId();
038: }
039:
040: static {
041: // The IP address of this host, default to the loopback address.
042: byte[] addrBytes = { 0x7f, 0x00, 0x00, 0x01 };
043:
044: try {
045: addrBytes = InetAddress.getLocalHost().getAddress();
046: } catch (UnknownHostException exc) {
047: }
048:
049: mSessionIdTemplate = new byte[14];
050: int pos = 8;
051:
052: // Put in the address bytes
053: System.arraycopy(addrBytes, 0, mSessionIdTemplate, pos, 4);
054: pos += 4;
055:
056: // Put in the port
057: // FIXME - get the port from somewhere
058: int port = 0;
059: mSessionIdTemplate[pos++] = (byte) ((port >> 8) & 0xff);
060: mSessionIdTemplate[pos++] = (byte) ((port) & 0xff);
061: }
062:
063: /**
064: * Returns a new unique integer
065: **/
066: static synchronized int generateSessionIdCount() {
067: return mSessionIdCounter++;
068: }
069:
070: /**
071: *
072: * Generates a new unique Session id. Subclasses may override this
073: * to provide their own session id generation mechanisms. One thing
074: * to keep in mind is that a session's swap file is taken directly
075: * from the session id, so the session id should be something that
076: * can be used as a file name. In particular, some OS's
077: * case-insensitive with regards to file names. Thus a good
078: * character set to use for session id's are the capital letters and
079: * numeric digits.
080: **/
081: static String generateSessionId() {
082: // Get the session id array
083: byte[] idBytes = new byte[mSessionIdTemplate.length];
084: System.arraycopy(mSessionIdTemplate, 0, idBytes, 0,
085: mSessionIdTemplate.length);
086: int pos = 0;
087:
088: // Get in the counter
089: int count = generateSessionIdCount();
090:
091: // Hash based on the current time and count
092: int hash = count;
093: long nowTime = System.currentTimeMillis();
094: hash = (hash * 39) + (int) ((nowTime >> 32) & 0xffffffff);
095: hash = (hash * 39) + (int) (nowTime & 0xffffffff);
096:
097: // Put in the hash
098: idBytes[pos++] = (byte) ((hash >> 24) & 0xff);
099: idBytes[pos++] = (byte) ((hash >> 16) & 0xff);
100: idBytes[pos++] = (byte) ((hash >> 8) & 0xff);
101: idBytes[pos++] = (byte) ((hash) & 0xff);
102:
103: // Put in the counter
104: idBytes[pos++] = (byte) ((count >> 24) & 0xff);
105: idBytes[pos++] = (byte) ((count >> 16) & 0xff);
106: idBytes[pos++] = (byte) ((count >> 8) & 0xff);
107: idBytes[pos++] = (byte) ((count) & 0xff);
108:
109: // Convert the byte array to a String
110: return convertSessionIdBytesToSessionId(idBytes);
111: }
112:
113: /**
114: *
115: * Converts the specified byte array to a String to be used for the
116: * session id. The conversion is performed breaking the byte array
117: * into groups of 5 bits, then taking each group (value 0-31) and
118: * converting to a character 'A'-'Z', '0'-'9'.
119: **/
120: static String convertSessionIdBytesToSessionId(byte[] pBytes) {
121: int numBits = pBytes.length * 8;
122: int numChars = numBits / 5;
123: if (numChars % 5 != 0)
124: numChars++;
125: char[] chars = new char[numChars];
126:
127: int byteNum = 0;
128: int bitNum = 0;
129: int pos = 0;
130: while (byteNum < pBytes.length) {
131: int val = 0;
132:
133: // Get from the byte
134: if (bitNum <= 3) {
135: val = (pBytes[byteNum] >> (3 - bitNum)) & 0x1f;
136: }
137: // Get from this byte and the next
138: else {
139: val = pBytes[byteNum] << (5 - (8 - bitNum));
140: if (byteNum + 1 < pBytes.length) {
141: int secondVal = pBytes[byteNum + 1] >> 8 - (5 - (8 - bitNum));
142: secondVal &= sSecondByteMasks[5 - (8 - bitNum)];
143: val |= secondVal;
144: }
145: val &= 0x1f;
146: }
147:
148: // Assign the character
149: chars[pos++] = sBitChars[val];
150:
151: // Increment to the next character
152: bitNum += 5;
153: if (bitNum >= 8) {
154: byteNum++;
155: bitNum -= 8;
156: }
157: }
158:
159: return new String(chars);
160: }
161: }
|