1 /***
2 *
3 * Copyright 2004 Protique Ltd
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.codehaus.activemq.util;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 import java.net.InetAddress;
24 import java.net.ServerSocket;
25
26 /***
27 * Generator for globally unique Strings
28 *
29 * @version $Revision: 1.1 $
30 */
31 public class IdGenerator {
32 private static final Log log = LogFactory.getLog(IdGenerator.class);
33 private static final String UNIQUE_STUB;
34 private static int instanceCount;
35 private static String hostName;
36 private String seed;
37 private long sequence;
38
39 static {
40 String stub = "";
41 boolean canAccessSystemProps = true;
42 try {
43 SecurityManager sm = System.getSecurityManager();
44 if (sm != null) {
45 sm.checkPropertiesAccess();
46 }
47 }
48 catch (SecurityException se) {
49 canAccessSystemProps = false;
50 }
51 if (canAccessSystemProps) {
52 try {
53 hostName = InetAddress.getLocalHost().getHostName();
54 ServerSocket ss = new ServerSocket(0);
55 stub = "ID:" + hostName + "-" + ss.getLocalPort() + "-" + System.currentTimeMillis() + "-";
56 Thread.sleep(100);
57 ss.close();
58 }
59 catch (Exception ioe) {
60 log.warn("could not generate unique stub", ioe);
61 }
62 }
63 else {
64 hostName = "localhost";
65 stub = "ID:" + hostName + "-1-" + System.currentTimeMillis() + "-";
66 }
67 UNIQUE_STUB = stub;
68 }
69
70 /***
71 * As we have to find the hostname as a side-affect of generating a unique stub, we allow it's easy retrevial here
72 *
73 * @return the local host name
74 */
75 public static String getHostName() {
76 return hostName;
77 }
78
79 /***
80 * Construct an IdGenerator
81 */
82 public IdGenerator() {
83 synchronized (UNIQUE_STUB) {
84 this.seed = UNIQUE_STUB + (instanceCount++) + ":";
85 }
86 }
87
88 /***
89 * Generate a unqiue id
90 *
91 * @return a unique id
92 */
93 public synchronized String generateId() {
94 return this.seed + (this.sequence++);
95 }
96
97 /***
98 * @return the unique seed used by this generator
99 */
100 public String getSeed() {
101 return seed;
102 }
103
104 /***
105 * From a generated id - return the seed (i.e. minus the count)
106 *
107 * @param id the generated identifer
108 * @return
109 */
110 public static String getSeedFromId(String id) {
111 String result = id;
112 if (id != null) {
113 int index = id.lastIndexOf(':');
114 if (index > 0 && (index + 1) < id.length()) {
115 result = id.substring(0, index + 1);
116 }
117 }
118 return result;
119 }
120
121 /***
122 * From a generated id - return the generator count
123 *
124 * @param id
125 * @return the count
126 */
127 public static long getCountFromId(String id) {
128 long result = -1;
129 if (id != null) {
130 int index = id.lastIndexOf(':');
131
132 if (index > 0 && (index + 1) < id.length()) {
133 String numStr = id.substring(index + 1, id.length());
134 result = Long.parseLong(numStr);
135 }
136 }
137 return result;
138 }
139
140 /***
141 * Does a proper compare on the ids
142 *
143 * @param id1
144 * @param id2
145 * @return
146 */
147
148 public static int compare(String id1, String id2) {
149 int result = -1;
150 String seed1 = IdGenerator.getSeedFromId(id1);
151 String seed2 = IdGenerator.getSeedFromId(id2);
152 if (seed1 != null && seed2 != null) {
153 result = seed1.compareTo(seed2);
154 if (result == 0) {
155 long count1 = IdGenerator.getCountFromId(id1);
156 long count2 = IdGenerator.getCountFromId(id2);
157 result = (int) (count1 - count2);
158 }
159 }
160 return result;
161
162 }
163 }