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 }