001: package org.apache.turbine.util;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.util.Random;
023:
024: /**
025: * This class generates a unique 10+ character id. This is good for
026: * authenticating users or tracking users around.
027: *
028: * <p>This code was borrowed from Apache
029: * JServ.JServServletManager.java. It is what Apache JServ uses to
030: * generate session ids for users. Unfortunately, it was not included
031: * in Apache JServ as a class, so I had to create one here in order to
032: * use it.
033: *
034: * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
035: * @author <a href="mailto:neeme@one.lv">Neeme Praks</a>
036: * @version $Id: GenerateUniqueId.java 534527 2007-05-02 16:10:59Z tv $
037: */
038: public class GenerateUniqueId {
039: /*
040: * Create a suitable string for session identification. Use
041: * synchronized count and time to ensure uniqueness. Use random
042: * string to ensure the timestamp cannot be guessed by programmed
043: * attack.
044: *
045: * Format of id is <6 chars random><3 chars time><1+ char count>
046: */
047: static private int session_count = 0;
048: static private long lastTimeVal = 0;
049: static private Random randomSource = new java.util.Random();
050:
051: // MAX_RADIX is 36
052:
053: /*
054: * We want to have a random string with a length of 6 characters.
055: * Since we encode it BASE 36, we've to modulo it with the
056: * following value:
057: */
058: public final static long maxRandomLen = 2176782336L; // 36 ** 6
059:
060: /*
061: * The session identifier must be unique within the typical
062: * lifespan of a Session; the value can roll over after that. 3
063: * characters: (this means a roll over after over a day, which is
064: * much larger than a typical lifespan)
065: */
066: public final static long maxSessionLifespanTics = 46656; // 36 ** 3
067:
068: /*
069: * Millisecons between different tics. So this means that the
070: * 3-character time string has a new value every 2 seconds:
071: */
072: public final static long ticDifference = 2000;
073:
074: /**
075: * Get the unique id.
076: *
077: * <p>NOTE: This must work together with
078: * get_jserv_session_balance() in jserv_balance.c
079: *
080: * @return A String with the new unique id.
081: */
082: static synchronized public String getIdentifier() {
083: StringBuffer sessionId = new StringBuffer();
084:
085: // Random value.
086: long n = randomSource.nextLong();
087: if (n < 0)
088: n = -n;
089: n %= maxRandomLen;
090:
091: // Add maxLen to pad the leading characters with '0'; remove
092: // first digit with substring.
093: n += maxRandomLen;
094: sessionId.append(Long.toString(n, Character.MAX_RADIX)
095: .substring(1));
096:
097: long timeVal = (System.currentTimeMillis() / ticDifference);
098:
099: // Cut.
100: timeVal %= maxSessionLifespanTics;
101:
102: // Padding, see above.
103: timeVal += maxSessionLifespanTics;
104:
105: sessionId.append(Long.toString(timeVal, Character.MAX_RADIX)
106: .substring(1));
107:
108: /*
109: * Make the string unique: append the session count since last
110: * time flip.
111: */
112:
113: // Count sessions only within tics. So the 'real' session
114: // count isn't exposed to the public.
115: if (lastTimeVal != timeVal) {
116: lastTimeVal = timeVal;
117: session_count = 0;
118: }
119: sessionId.append(Long.toString(++session_count,
120: Character.MAX_RADIX));
121:
122: return sessionId.toString();
123: }
124:
125: /**
126: * Get the unique id.
127: *
128: * @param jsIdent A String.
129: * @return A String with the new unique id.
130: */
131: synchronized public String getIdentifier(String jsIdent) {
132: if (jsIdent != null && jsIdent.length() > 0) {
133: return getIdentifier() + "." + jsIdent;
134: }
135: return getIdentifier();
136: }
137:
138: /**
139: * Simple test of the functionality.
140: *
141: * @param args A String[] with the command line arguments.
142: */
143: public static void main(String[] args) {
144: System.out.println(GenerateUniqueId.getIdentifier());
145: System.out.println(GenerateUniqueId.getIdentifier());
146: System.out.println(GenerateUniqueId.getIdentifier());
147: System.out.println(GenerateUniqueId.getIdentifier());
148: }
149: }
|