diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java index cd106921ea..1b2f4a3271 100755 --- a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java +++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java @@ -57,20 +57,19 @@ public List getMacAddress() { if (this.macAddressList != null) { return this.macAddressList; } - this.macAddressList = new ArrayList<>(); + List list = new ArrayList<>(); List inetAddresses = this.getLocalAllInetAddress(); if (inetAddresses != null && !inetAddresses.isEmpty()) { // Get the Mac address of all network interfaces - List list = new ArrayList<>(); Set uniqueValues = new HashSet<>(); for (InetAddress inetAddress : inetAddresses) { - String macByInetAddress = this.getMacByInetAddress(inetAddress); - if (uniqueValues.add(macByInetAddress)) { + String macByInetAddress = this.getMacByInetAddress(inetAddress, false); + if (macByInetAddress != null && uniqueValues.add(macByInetAddress)) { list.add(macByInetAddress); } } - this.macAddressList = list; } + this.macAddressList = list; return this.macAddressList; } @@ -99,6 +98,10 @@ public List getLocalAllInetAddress() { } public String getMacByInetAddress(InetAddress inetAddr) { + return this.getMacByInetAddress(inetAddr, true); + } + + private String getMacByInetAddress(InetAddress inetAddr, boolean required) { byte[] mac; try { mac = NetworkInterface.getByInetAddress(inetAddr) @@ -108,6 +111,12 @@ public String getMacByInetAddress(InetAddress inetAddr) { "Failed to get mac address for inet address '%s'", inetAddr)); } + if (mac == null) { + if (required) { + throw new IllegalStateException("Network interface has no hardware address"); + } + return null; + } StringBuilder sb = new StringBuilder(); for (int i = 0; i < mac.length; i++) { diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java index 9dc69cbdb9..3e5a0ba4ea 100644 --- a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java +++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java @@ -18,10 +18,14 @@ package org.apache.hugegraph.unit.license; import java.net.InetAddress; -import java.net.UnknownHostException; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.regex.Pattern; +import org.junit.Assume; import org.junit.Test; import org.apache.hugegraph.license.MachineInfo; @@ -73,15 +77,89 @@ public void testGetLocalAllInetAddress() { } @Test - public void testGetMacByInetAddress() throws UnknownHostException { + public void testGetMacByInetAddress() throws Exception { List addressList = machineInfo.getLocalAllInetAddress(); for (InetAddress address : addressList) { - String mac = machineInfo.getMacByInetAddress(address); - Assert.assertTrue(MAC_PATTERN.matcher(mac).matches()); + byte[] hardwareAddress = NetworkInterface.getByInetAddress(address) + .getHardwareAddress(); + if (hardwareAddress == null) { + Throwable exception = Assert.assertThrows(RuntimeException.class, + () -> machineInfo.getMacByInetAddress(address)); + Assert.assertFalse(exception instanceof NullPointerException); + } else { + String mac = machineInfo.getMacByInetAddress(address); + Assert.assertTrue(MAC_PATTERN.matcher(mac).matches()); + } } InetAddress address = InetAddress.getByAddress(new byte[]{0, 0, 0, 0}); - Assert.assertThrows(RuntimeException.class, () -> { - machineInfo.getMacByInetAddress(address); - }); + Throwable exception = Assert.assertThrows(RuntimeException.class, + () -> machineInfo.getMacByInetAddress(address)); + Assert.assertFalse(exception instanceof NullPointerException); + } + + @Test + public void testGetMacAddressWithoutMac() throws SocketException { + InetAddress loopback = InetAddress.getLoopbackAddress(); + Assume.assumeTrue(NetworkInterface.getByInetAddress(loopback) + .getHardwareAddress() == null); + MachineInfo info = new MachineInfo() { + @Override + public List getLocalAllInetAddress() { + return Collections.singletonList(loopback); + } + }; + Throwable exception = Assert.assertThrows(RuntimeException.class, + () -> info.getMacByInetAddress(loopback)); + Assert.assertFalse(exception instanceof NullPointerException); + Assert.assertEquals("Network interface has no hardware address", exception.getMessage()); + List addresses = info.getMacAddress(); + Assert.assertTrue(addresses.isEmpty()); + Assert.assertSame(addresses, info.getMacAddress()); + } + + @Test + public void testGetMacAddressSkipsMissingAndDuplicateMac() throws SocketException { + InetAddress loopback = InetAddress.getLoopbackAddress(); + Assume.assumeTrue(NetworkInterface.getByInetAddress(loopback) + .getHardwareAddress() == null); + InetAddress addressWithMac = null; + for (InetAddress address : machineInfo.getLocalAllInetAddress()) { + if (NetworkInterface.getByInetAddress(address).getHardwareAddress() != null) { + addressWithMac = address; + break; + } + } + Assume.assumeNotNull(addressWithMac); + InetAddress address = addressWithMac; + MachineInfo info = new MachineInfo() { + @Override + public List getLocalAllInetAddress() { + return Arrays.asList(loopback, address, loopback, address); + } + }; + List addresses = info.getMacAddress(); + Assert.assertEquals(1, addresses.size()); + Assert.assertTrue(addresses.contains(machineInfo.getMacByInetAddress(address))); + Assert.assertSame(addresses, info.getMacAddress()); + } + + @Test + public void testGetMacAddressRetriesAfterLookupFailure() { + RuntimeException failure = new RuntimeException("Controlled interface enumeration failure"); + int[] attempts = {0}; + MachineInfo info = new MachineInfo() { + @Override + public List getLocalAllInetAddress() { + if (++attempts[0] == 1) { + throw failure; + } + return Collections.emptyList(); + } + }; + Assert.assertSame(failure, Assert.assertThrows(RuntimeException.class, info::getMacAddress)); + List addresses = info.getMacAddress(); + Assert.assertTrue(addresses.isEmpty()); + Assert.assertSame(addresses, info.getMacAddress()); + Assert.assertEquals(2, attempts[0]); } }