001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. 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 package org.apache.camel.impl;
018
019 import java.net.ServerSocket;
020 import java.util.concurrent.atomic.AtomicLong;
021
022 import org.apache.camel.spi.UuidGenerator;
023 import org.apache.camel.util.InetAddressUtil;
024 import org.apache.camel.util.ObjectHelper;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027
028 /**
029 * {@link org.apache.camel.spi.UuidGenerator} which is a fast implementation based on
030 * how <a href="http://activemq.apache.org/>Apache ActiveMQ</a> generates its UUID.
031 * <p/>
032 * This implementation is not synchronized but it leverages API which may not be accessible
033 * in the cloud (such as Google App Engine).
034 */
035 public class ActiveMQUuidGenerator implements UuidGenerator {
036
037 private static final transient Logger LOG = LoggerFactory.getLogger(ActiveMQUuidGenerator.class);
038 private static final String UNIQUE_STUB;
039 private static int instanceCount;
040 private static String hostName;
041 private String seed;
042 private final AtomicLong sequence = new AtomicLong(1);
043 private final int length;
044
045 static {
046 String stub = "";
047 boolean canAccessSystemProps = true;
048 try {
049 SecurityManager sm = System.getSecurityManager();
050 if (sm != null) {
051 sm.checkPropertiesAccess();
052 }
053 } catch (SecurityException se) {
054 canAccessSystemProps = false;
055 }
056
057 if (canAccessSystemProps) {
058 try {
059 hostName = InetAddressUtil.getLocalHostName();
060 ServerSocket ss = new ServerSocket(0);
061 stub = "-" + ss.getLocalPort() + "-" + System.currentTimeMillis() + "-";
062 Thread.sleep(100);
063 ss.close();
064 } catch (Exception ioe) {
065 LOG.warn("Could not generate unique stub by using DNS and binding to local port, will fallback and use localhost as name", ioe);
066 }
067 }
068
069 // fallback to use localhost
070 if (hostName == null) {
071 hostName = "localhost";
072 }
073
074 if (ObjectHelper.isEmpty(stub)) {
075 stub = "-1-" + System.currentTimeMillis() + "-";
076 }
077 UNIQUE_STUB = stub;
078 }
079
080 public ActiveMQUuidGenerator(String prefix) {
081 synchronized (UNIQUE_STUB) {
082 this.seed = prefix + UNIQUE_STUB + (instanceCount++) + "-";
083 // let the ID be friendly for URL and file systems
084 this.seed = generateSanitizedId(this.seed);
085 this.length = seed.length() + ("" + Long.MAX_VALUE).length();
086 }
087 }
088
089 public ActiveMQUuidGenerator() {
090 this("ID-" + hostName);
091 }
092
093 /**
094 * As we have to find the hostname as a side-affect of generating a unique
095 * stub, we allow it's easy retrieval here
096 *
097 * @return the local host name
098 */
099 public static String getHostName() {
100 return hostName;
101 }
102
103 public String generateUuid() {
104 StringBuilder sb = new StringBuilder(length);
105 sb.append(seed);
106 sb.append(sequence.getAndIncrement());
107 return sb.toString();
108 }
109
110 /**
111 * Generate a unique ID - that is friendly for a URL or file system
112 *
113 * @return a unique id
114 */
115 public String generateSanitizedId() {
116 return generateSanitizedId(generateUuid());
117 }
118
119 /**
120 * Ensures that the id is friendly for a URL or file system
121 *
122 * @param id the unique id
123 * @return the id as file friendly id
124 */
125 public static String generateSanitizedId(String id) {
126 id = id.replace(':', '-');
127 id = id.replace('_', '-');
128 id = id.replace('.', '-');
129 id = id.replace('/', '-');
130 return id;
131 }
132 }