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 }