X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.api.uuid%2Fsrc%2Forg%2Fargeo%2Fapi%2Fuuid%2FConcurrentUuidFactory.java;h=f2bd43689772a24c87ba5ad81e53f1f0fe00ddb4;hb=ee0a9f240a5da3a1437dda5abe7a1c46c5a3a8e9;hp=14f6d54adb0d25467ad58c732fdc4654704a367c;hpb=475dc8545eb01b541c63be6a480fdd8d808e75a4;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java index 14f6d54ad..f2bd43689 100644 --- a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java +++ b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java @@ -1,21 +1,8 @@ package org.argeo.api.uuid; -import static java.lang.System.Logger.Level.DEBUG; -import static java.lang.System.Logger.Level.INFO; -import static java.lang.System.Logger.Level.WARNING; - -import java.lang.System.Logger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.security.DrbgParameters; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import java.util.BitSet; -import java.util.Enumeration; import java.util.Objects; import java.util.UUID; @@ -25,28 +12,42 @@ import java.util.UUID; * * @see https://datatracker.ietf.org/doc/html/rfc4122 */ -public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory { - private final static Logger logger = System.getLogger(ConcurrentUuidFactory.class.getName()); +public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory implements TypedUuidFactory { +// private final static Logger logger = System.getLogger(ConcurrentUuidFactory.class.getName()); + + public ConcurrentUuidFactory(long initialClockRange, byte[] nodeId) { + this(initialClockRange, nodeId, 0); + } - private Long nodeIdBase; + /** With a random node id. */ + public ConcurrentUuidFactory(long initialClockRange) { + this(initialClockRange, NodeIdSupplier.randomNodeId()); + } - public ConcurrentUuidFactory(byte[] nodeId, int offset) { + public ConcurrentUuidFactory(long initialClockRange, byte[] nodeId, int offset) { Objects.requireNonNull(nodeId); if (offset + 6 > nodeId.length) throw new IllegalArgumentException("Offset too big: " + offset); byte[] defaultNodeId = toNodeIdBytes(nodeId, offset); - nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); - setNodeIdSupplier(() -> nodeIdBase); - assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0]; + long nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); + setNodeIdSupplier(() -> nodeIdBase, initialClockRange); } + /** + * Empty constructor for use with component life cycle. A {@link NodeIdSupplier} + * must be set externally, otherwise time based UUID won't work. + */ public ConcurrentUuidFactory() { - byte[] defaultNodeId = getIpBytes(); - nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); - setNodeIdSupplier(() -> nodeIdBase); - assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0]; + super(); } +// public ConcurrentUuidFactory() { +// byte[] defaultNodeId = getIpBytes(); +// nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); +// setNodeIdSupplier(() -> nodeIdBase); +// assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0]; +// } + /* * DEFAULT */ @@ -60,78 +61,23 @@ public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory { } @Override - protected SecureRandom newSecureRandom() { + protected SecureRandom createSecureRandom() { SecureRandom secureRandom; try { secureRandom = SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(256, DrbgParameters.Capability.PR_AND_RESEED, "UUID".getBytes())); } catch (NoSuchAlgorithmException e) { try { - logger.log(DEBUG, "DRBG secure random not found, using strong"); +// logger.log(DEBUG, "DRBG secure random not found, using strong"); secureRandom = SecureRandom.getInstanceStrong(); } catch (NoSuchAlgorithmException e1) { - logger.log(WARNING, "No strong secure random was found, using default"); +// logger.log(WARNING, "No strong secure random was found, using default"); secureRandom = new SecureRandom(); } + } catch (java.lang.NoClassDefFoundError e) {// Android + secureRandom = new SecureRandom(); } return secureRandom; } - /** Returns an SHA1 digest of one of the IP addresses. */ - protected byte[] getIpBytes() { - Enumeration netInterfaces = null; - try { - netInterfaces = NetworkInterface.getNetworkInterfaces(); - } catch (SocketException e) { - throw new IllegalStateException(e); - } - if (netInterfaces == null) - throw new IllegalStateException("No interfaces"); - - InetAddress selectedIpv6 = null; - InetAddress selectedIpv4 = null; - netInterfaces: while (netInterfaces.hasMoreElements()) { - NetworkInterface netInterface = netInterfaces.nextElement(); - byte[] hardwareAddress = null; - try { - hardwareAddress = netInterface.getHardwareAddress(); - if (hardwareAddress != null) { - // first IPv6 - addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { - InetAddress ip = addr.getAddress(); - if (ip instanceof Inet6Address) { - Inet6Address ipv6 = (Inet6Address) ip; - if (ipv6.isAnyLocalAddress() || ipv6.isLinkLocalAddress() || ipv6.isLoopbackAddress()) - continue addr; - selectedIpv6 = ipv6; - break netInterfaces; - } - - } - // then IPv4 - addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { - InetAddress ip = addr.getAddress(); - if (ip instanceof Inet4Address) { - Inet4Address ipv4 = (Inet4Address) ip; - if (ipv4.isAnyLocalAddress() || ipv4.isLinkLocalAddress() || ipv4.isLoopbackAddress()) - continue addr; - selectedIpv4 = ipv4; - } - - } - } - } catch (SocketException e) { - throw new IllegalStateException(e); - } - } - InetAddress selectedIp = selectedIpv6 != null ? selectedIpv6 : selectedIpv4; - if (selectedIp == null) - throw new IllegalStateException("No IP address found"); - byte[] digest = sha1(selectedIp.getAddress()); - logger.log(INFO, "Use IP " + selectedIp + " hashed as " + toHexString(digest) + " as node id"); - byte[] nodeId = toNodeIdBytes(digest, 0); - // marks that this is not based on MAC address - forceToNoMacAddress(nodeId, 0); - return nodeId; - } } \ No newline at end of file