Document and clean up UUID factory API and implementation.
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / ConcurrentUuidFactory.java
index 14f6d54adb0d25467ad58c732fdc4654704a367c..6debd83b803426453c9e56b1594b6793bcaf6dcb 100644 (file)
@@ -1,21 +1,12 @@
 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;
 
@@ -28,25 +19,34 @@ import java.util.UUID;
 public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory {
        private final static Logger logger = System.getLogger(ConcurrentUuidFactory.class.getName());
 
-       private Long nodeIdBase;
+       public ConcurrentUuidFactory(byte[] nodeId) {
+               this(nodeId, 0);
+       }
 
        public ConcurrentUuidFactory(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);
+               long nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId);
                setNodeIdSupplier(() -> nodeIdBase);
-               assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0];
        }
 
+       /**
+        * 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
         */
@@ -77,61 +77,4 @@ public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory {
                return secureRandom;
        }
 
-       /** Returns an SHA1 digest of one of the IP addresses. */
-       protected byte[] getIpBytes() {
-               Enumeration<NetworkInterface> 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