001 /**
002 *
003 * Copyright 2004 Protique Ltd
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 **/
018 package org.activemq.util;
019
020 import org.apache.commons.logging.Log;
021 import org.apache.commons.logging.LogFactory;
022
023 import java.net.InetAddress;
024 import java.net.ServerSocket;
025
026 /**
027 * Generator for globally unique Strings
028 *
029 * @version $Revision: 1.1.1.1 $
030 */
031 public class IdGenerator {
032 private static final Log log = LogFactory.getLog(IdGenerator.class);
033 private static final String UNIQUE_STUB;
034 private static int instanceCount;
035 private static String hostName;
036 private String seed;
037 private long sequence;
038 private short shortSequence;
039
040 static {
041 String stub = "";
042 boolean canAccessSystemProps = true;
043 try {
044 SecurityManager sm = System.getSecurityManager();
045 if (sm != null) {
046 sm.checkPropertiesAccess();
047 }
048 }
049 catch (SecurityException se) {
050 canAccessSystemProps = false;
051 }
052 if (canAccessSystemProps) {
053 try {
054 hostName = InetAddress.getLocalHost().getHostName();
055 ServerSocket ss = new ServerSocket(0);
056 stub = "ID:" + hostName + "-" + ss.getLocalPort() + "-" + System.currentTimeMillis() + "-";
057 Thread.sleep(100);
058 ss.close();
059 }
060 catch (Exception ioe) {
061 log.warn("could not generate unique stub", ioe);
062 }
063 }
064 else {
065 hostName = "localhost";
066 stub = "ID:" + hostName + "-1-" + System.currentTimeMillis() + "-";
067 }
068 UNIQUE_STUB = stub;
069 }
070
071 /**
072 * As we have to find the hostname as a side-affect of generating a unique stub, we allow it's easy retrevial here
073 *
074 * @return the local host name
075 */
076 public static String getHostName() {
077 return hostName;
078 }
079
080 /**
081 * Construct an IdGenerator
082 */
083 public IdGenerator() {
084 synchronized (UNIQUE_STUB) {
085 this.seed = UNIQUE_STUB + (instanceCount++) + ":";
086 }
087 }
088
089 /**
090 * Construct an IdGenerator using the seed provided
091 * @param seed
092 */
093 public IdGenerator(String seed){
094 this.seed = seed;
095 }
096
097
098 /**
099 * Generate a unqiue id
100 *
101 * @return a unique id
102 */
103 public synchronized String generateId() {
104 return this.seed + (this.sequence++);
105 }
106
107 /**
108 * @return the unique seed used by this generator
109 */
110 public String getSeed() {
111 return seed;
112 }
113
114 /**
115 * @return the next sequence
116 */
117 public synchronized long getNextSequence(){
118 return this.sequence++;
119 }
120
121 /**
122 * @return the next short sequence
123 */
124 public synchronized short getNextShortSequence(){
125 //need to start with 1 for some wire protocols
126 return ++this.shortSequence;
127 }
128
129 /**
130 * From a generated id - return the seed (i.e. minus the count)
131 *
132 * @param id the generated identifer
133 * @return
134 */
135 public static String getSeedFromId(String id) {
136 String result = id;
137 if (id != null) {
138 int index = id.lastIndexOf(':');
139 if (index > 0 && (index + 1) < id.length()) {
140 result = id.substring(0, index + 1);
141 }
142 }
143 return result;
144 }
145
146 /**
147 * From a generated id - return the generator count
148 *
149 * @param id
150 * @return the count
151 */
152 public static long getCountFromId(String id) {
153 long result = -1;
154 if (id != null) {
155 int index = id.lastIndexOf(':');
156
157 if (index > 0 && (index + 1) < id.length()) {
158 String numStr = id.substring(index + 1, id.length());
159 result = Long.parseLong(numStr);
160 }
161 }
162 return result;
163 }
164
165 /**
166 * Does a proper compare on the ids
167 *
168 * @param id1
169 * @param id2
170 * @return
171 */
172
173 public static int compare(String id1, String id2) {
174 int result = -1;
175 String seed1 = IdGenerator.getSeedFromId(id1);
176 String seed2 = IdGenerator.getSeedFromId(id2);
177 if (seed1 != null && seed2 != null) {
178 result = seed1.compareTo(seed2);
179 if (result == 0) {
180 long count1 = IdGenerator.getCountFromId(id1);
181 long count2 = IdGenerator.getCountFromId(id2);
182 result = (int) (count1 - count2);
183 }
184 }
185 return result;
186
187 }
188 }