package io.fathom.auto.config;
import java.io.File;
import java.io.IOException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import com.google.common.io.Files;
public class MachineSignature {
private static final Logger log = LoggerFactory.getLogger(MachineSignature.class);
// We try to generate a key that will be the same even if multiple
// concurrent processes on the machine generate the same key
public String generateKey() {
List<String> material = Lists.newArrayList();
Enumeration<NetworkInterface> networkInterfaces;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
throw new IllegalStateException("Error listing network interfaces", e);
}
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
try {
byte[] hardwareAddress = networkInterface.getHardwareAddress();
if (hardwareAddress != null) {
material.add("mac:" + networkInterface.getName() + ":"
+ BaseEncoding.base16().encode(hardwareAddress));
} else {
log.warn("No hardware address for {}", networkInterface.getName());
}
} catch (SocketException e) {
throw new IllegalStateException("Unable to get hardware address for: " + networkInterface.getName(), e);
}
// List<InterfaceAddress> interfaceAddresses = networkInterface
// .getInterfaceAddresses();
// for (InterfaceAddress interfaceAddress : interfaceAddresses) {
// material.add("mac:" + interfaceAddress.)
// }
}
String hostname;
try {
hostname = Files.toString(new File("/etc/hostname"), Charsets.UTF_8);
} catch (IOException e) {
throw new IllegalStateException("Unable to read /etc/hostname", e);
}
hostname = hostname.trim();
material.add("hostname:" + hostname);
// TODO: Any more for the mix??
material.add(computeFileHash("/proc/cpuinfo"));
Collections.sort(material);
Hasher hasher = Hashing.md5().newHasher();
for (String s : material) {
hasher.putString(s);
hasher.putByte((byte) 0);
}
return hostname + "_" + hasher.hash().toString();
}
private String computeFileHash(String path) {
try {
byte[] contents = Files.toByteArray(new File(path));
String hash = Hashing.md5().hashBytes(contents).toString();
return "filehash:" + path + ":" + hash;
} catch (IOException e) {
throw new IllegalStateException("Unable to read file " + path, e);
}
}
}