diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/MacAddressUserId.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/MacAddressUserId.java index 760a4b80..6bc1d227 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/MacAddressUserId.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/MacAddressUserId.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,19 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.vault.authentication; import java.io.IOException; +import java.lang.reflect.Method; import java.net.InetAddress; import java.net.NetworkInterface; +import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -39,6 +42,10 @@ import org.springframework.util.StringUtils; */ public class MacAddressUserId implements AppIdUserIdMechanism { + // Compatibility with Java 1.7 and greater + private final static Method GET_INDEX = ReflectionUtils + .findMethod(NetworkInterface.class, "getIndex"); + private final Log log = LogFactory.getLog(MacAddressUserId.class); private final String networkInterfaceHint; @@ -86,8 +93,8 @@ public class MacAddressUserId implements AppIdUserIdMechanism { try { NetworkInterface networkInterface = null; - List interfaces = Collections.list(NetworkInterface - .getNetworkInterfaces()); + List interfaces = Collections + .list(NetworkInterface.getNetworkInterfaces()); if (StringUtils.hasText(networkInterfaceHint)) { @@ -112,6 +119,12 @@ public class MacAddressUserId implements AppIdUserIdMechanism { InetAddress localHost = InetAddress.getLocalHost(); networkInterface = NetworkInterface.getByInetAddress(localHost); + if (networkInterface == null + || networkInterface.getHardwareAddress() == null) { + + networkInterface = getNetworkInterfaceWithHardwareAddress(interfaces); + } + if (networkInterface == null) { throw new IllegalStateException(String.format( "Cannot determine NetworkInterface for %s", localHost)); @@ -120,9 +133,9 @@ public class MacAddressUserId implements AppIdUserIdMechanism { byte[] mac = networkInterface.getHardwareAddress(); if (mac == null) { - throw new IllegalStateException(String.format( - "Network interface %s has no hardware address", - networkInterface.getName())); + throw new IllegalStateException( + String.format("Network interface %s has no hardware address", + networkInterface.getName())); } return Sha256.toSha256(Sha256.toHexString(mac)); @@ -132,7 +145,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism { } } - private NetworkInterface getNetworkInterface(Number hint, + private static NetworkInterface getNetworkInterface(Number hint, List interfaces) { if (interfaces.size() > hint.intValue() && hint.intValue() >= 0) { @@ -142,7 +155,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism { return null; } - private NetworkInterface getNetworkInterface(String hint, + private static NetworkInterface getNetworkInterface(String hint, List interfaces) { for (NetworkInterface anInterface : interfaces) { @@ -154,4 +167,46 @@ public class MacAddressUserId implements AppIdUserIdMechanism { return null; } + + private static NetworkInterface getNetworkInterfaceWithHardwareAddress( + List interfaces) throws IOException { + + List networkInterfacesToUse = interfaces; + + if (GET_INDEX != null) { + networkInterfacesToUse = new ArrayList(interfaces); + Collections.sort(networkInterfacesToUse, + NetworkInterfaceIndexComparator.INSTANCE); + } + + for (NetworkInterface anInterface : networkInterfacesToUse) { + byte[] hardwareAddress = anInterface.getHardwareAddress(); + if (hardwareAddress != null) { + return anInterface; + } + } + + return null; + } + + /** + * @since 1.0.1 + */ + enum NetworkInterfaceIndexComparator implements Comparator { + INSTANCE; + + @Override + public int compare(NetworkInterface o1, NetworkInterface o2) { + + try { + int left = (Integer) GET_INDEX.invoke(o1); + int right = (Integer) GET_INDEX.invoke(o2); + return (left < right) ? -1 : ((left == right) ? 0 : 1); + } + catch (Exception e) { + throw new IllegalStateException( + "Cannot retrieve index from NetworkInterface", e); + } + } + } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/MacAddressUserIdUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/MacAddressUserIdUnitTests.java index a8346da3..8c961786 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/MacAddressUserIdUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/MacAddressUserIdUnitTests.java @@ -17,18 +17,18 @@ package org.springframework.vault.authentication; import java.net.NetworkInterface; import java.net.SocketException; +import java.util.Collections; +import java.util.List; import java.util.regex.Pattern; import org.junit.Test; -import org.springframework.util.CollectionUtils; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assume.assumeTrue; /** * Unit tests for {@link MacAddressUserId}. - * + * * @author Mark Paluch */ public class MacAddressUserIdUnitTests { @@ -38,8 +38,8 @@ public class MacAddressUserIdUnitTests { String userId = new MacAddressUserId().createUserId(); - assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch( - Pattern.compile("[a-f]")); + assertThat(userId).matches(Pattern.compile("[0-9A-F]+")) + .doesNotMatch(Pattern.compile("[a-f]")); } @Test @@ -50,25 +50,25 @@ public class MacAddressUserIdUnitTests { String userId = new MacAddressUserId(index).createUserId(); - assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch( - Pattern.compile("[a-f]")); + assertThat(userId).matches(Pattern.compile("[0-9A-F]+")) + .doesNotMatch(Pattern.compile("[a-f]")); } /** * Obtain index for {@link NetworkInterface} with a HardwareAddress. - * + * * @return -1 if none, otherwise index. * @throws SocketException */ private int getValidNetworkInterfaceIndex() throws SocketException { - NetworkInterface[] networkInterfaces = CollectionUtils.toArray( - NetworkInterface.getNetworkInterfaces(), new NetworkInterface[0]); + List interfaces = Collections + .list(NetworkInterface.getNetworkInterfaces()); int index = -1; - for (int i = 0; i < networkInterfaces.length; i++) { - if (networkInterfaces[i].getHardwareAddress() != null) { + for (int i = 0; i < interfaces.size(); i++) { + if (interfaces.get(i).getHardwareAddress() != null) { index = i; break; }