2022-09-20 15:40:53 +02:00

105 lines
3.7 KiB
Java

/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.core.util;
import lombok.extern.slf4j.Slf4j;
import java.net.NetworkInterface;
import java.rmi.server.UID;
import java.util.Enumeration;
@Slf4j
public class UIDProvider {
private static final String JVM_UID;
private static final String HARDWARE_UID;
static {
UID jvmUIDSource = new UID();
String asString = jvmUIDSource.toString();
//Format here: hexStringFromRandomNumber:hexStringFromSystemClock:hexStringOfUIDInstance
//The first two components here will be identical for all UID instances in a JVM, where as the 'hexStringOfUIDInstance'
// will vary (increment) between UID object instances. So we'll only be using the first two components here
int lastIdx = asString.lastIndexOf(":");
JVM_UID = asString.substring(0, lastIdx).replaceAll(":", "");
//Assumptions here:
//1. getNetworkInterfaces() returns at least one non-null element
// This is guaranteed by getNetworkInterfaces() Javadoc: "The {@code Enumeration} contains at least one element..."
//2. That the iteration order for network interfaces is consistent between JVM instances on the same hardware
// This appears to hold, but no formal guarantees seem to be available here
//3. That MAC addresses are 'unique enough' for our purposes
byte[] address = null;
boolean noInterfaces = false;
Enumeration<NetworkInterface> niEnumeration = null;
try {
niEnumeration = NetworkInterface.getNetworkInterfaces();
} catch (Exception e) {
noInterfaces = true;
}
if (niEnumeration != null) {
while (niEnumeration.hasMoreElements()) {
NetworkInterface ni = niEnumeration.nextElement();
byte[] addr;
try {
addr = ni.getHardwareAddress();
} catch (Exception e) {
continue;
}
if (addr == null || addr.length != 6)
continue; //May be null (if it can't be obtained) or not standard 6 byte MAC-48 representation
address = addr;
break;
}
}
if (address == null) {
log.warn("Could not generate hardware UID{}. Using fallback: JVM UID as hardware UID.",
(noInterfaces ? " (no interfaces)" : ""));
HARDWARE_UID = JVM_UID;
} else {
StringBuilder sb = new StringBuilder();
for (byte b : address) {
sb.append(String.format("%02x", b));
}
HARDWARE_UID = sb.toString();
}
}
private UIDProvider() {}
public static String getJVMUID() {
return JVM_UID;
}
public static String getHardwareUID() {
return HARDWARE_UID;
}
}