All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hornetq.utils.UUIDGenerator Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
/* JUG Java Uuid Generator
 *
 * Copyright (c) 2002- Tatu Saloranta, [email protected]
 *
 * Licensed under the License specified in the file licenses/LICENSE.txt which is
 * included with the source code.
 * You may not use this file except in compliance with the License.
 *
 * 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.
 */

package org.hornetq.utils;

import java.lang.reflect.Method;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.hornetq.api.core.SimpleString;

public final class UUIDGenerator
{
   private static final UUIDGenerator sSingleton = new UUIDGenerator();

   // Windows has some fake adapters that will return the same HARDWARE ADDRESS on any computer. We need to ignore those
   private static final byte[][] BLACK_LIST = new byte[][]{{2, 0, 84, 85, 78, 1}};

   /**
    * Random-generator, used by various UUID-generation methods:
    */
   private Random mRnd = null;

   private final Object mTimerLock = new Object();

   private UUIDTimer mTimer = null;

   private byte[] address;

   /**
    * Constructor is private to enforce singleton access.
    */
   private UUIDGenerator()
   {
   }

   /**
    * Method used for accessing the singleton generator instance.
    */
   public static UUIDGenerator getInstance()
   {
      return UUIDGenerator.sSingleton;
   }

   /*
    * ///////////////////////////////////////////////////// // Configuration
    * /////////////////////////////////////////////////////
    */

   /**
    * Method for getting the shared random number generator used for generating
    * the UUIDs. This way the initialization cost is only taken once; access
    * need not be synchronized (or in cases where it has to, SecureRandom takes
    * care of it); it might even be good for getting really 'random' stuff to
    * get shared access...
    */
   public Random getRandomNumberGenerator()
   {
      /*
       * Could be synchronized, but since side effects are trivial (ie.
       * possibility of generating more than one SecureRandom, of which all but
       * one are dumped) let's not add synchronization overhead:
       */
      if (mRnd == null)
      {
         mRnd = new SecureRandom();
      }
      return mRnd;
   }

   public UUID generateTimeBasedUUID(final byte[] byteAddr)
   {
      byte[] contents = new byte[16];
      int pos = 10;
      for (int i = 0; i < 6; ++i)
      {
         contents[pos + i] = byteAddr[i];
      }

      synchronized (mTimerLock)
      {
         if (mTimer == null)
         {
            mTimer = new UUIDTimer(getRandomNumberGenerator());
         }

         mTimer.getTimestamp(contents);
      }

      return new UUID(UUID.TYPE_TIME_BASED, contents);
   }

   public byte[] generateDummyAddress()
   {
      Random rnd = getRandomNumberGenerator();
      byte[] dummy = new byte[6];
      rnd.nextBytes(dummy);
      /* Need to set the broadcast bit to indicate it's not a real
       * address.
       */
      dummy[0] |= (byte) 0x01;

      if (HornetQUtilLogger.LOGGER.isDebugEnabled())
      {
         HornetQUtilLogger.LOGGER.debug("using dummy address " + UUIDGenerator.asString(dummy));
      }
      return dummy;
   }

   /**
    * If running java 6 or above, returns {@link NetworkInterface#getHardwareAddress()}, else return {@code null}.
    * The first hardware address is returned when iterating all the NetworkInterfaces
    */
   public static byte[] getHardwareAddress()
   {
      Method getHardwareAddressMethod;
      Method isUpMethod;
      Method isLoopbackMethod;
      Method isVirtualMethod;
      try
      {
         getHardwareAddressMethod = NetworkInterface.class.getMethod("getHardwareAddress");
         isUpMethod = NetworkInterface.class.getMethod("isUp");
         isLoopbackMethod = NetworkInterface.class.getMethod("isLoopback");
         isVirtualMethod = NetworkInterface.class.getMethod("isVirtual");
         // check if we have enough security permissions to create and shutdown an executor
         ExecutorService executor = Executors.newFixedThreadPool(0);
         executor.shutdownNow();
      }
      catch (Throwable t)
      {
         // not on Java 6 or not enough security permission
         return null;
      }

      try
      {
         List ifaces = getAllNetworkInterfaces();

         if (ifaces.size() == 0)
         {
            return null;
         }

         byte[] address = findFirstMatchingHardwareAddress(ifaces,
                                                           getHardwareAddressMethod,
                                                           isUpMethod,
                                                           isLoopbackMethod,
                                                           isVirtualMethod);
         if (address != null)
         {
            if (HornetQUtilLogger.LOGGER.isDebugEnabled())
            {
               HornetQUtilLogger.LOGGER.debug("using hardware address " + UUIDGenerator.asString(address));
            }
            return address;
         }
         return null;
      }
      catch (Exception e)
      {
         return null;
      }
   }

   public SimpleString generateSimpleStringUUID()
   {
      return new SimpleString(generateStringUUID());
   }

   public UUID generateUUID()
   {
      byte[] address = getAddressBytes();

      UUID uid = generateTimeBasedUUID(address);

      return uid;
   }

   public String generateStringUUID()
   {
      byte[] address = getAddressBytes();

      if (address == null)
      {
         return java.util.UUID.randomUUID().toString();
      }
      else
      {
         return generateTimeBasedUUID(address).toString();
      }
   }

   public static byte[] getZeroPaddedSixBytes(final byte[] bytes)
   {
      if (bytes == null)
      {
         return null;
      }
      if (bytes.length > 0 && bytes.length <= 6)
      {
         if (bytes.length == 6)
         {
            return bytes;
         }
         else
         {
            // pad with zeroes to have a 6-byte array
            byte[] paddedAddress = new byte[6];
            System.arraycopy(bytes, 0, paddedAddress, 0, bytes.length);
            for (int i = bytes.length; i < 6; i++)
            {
               paddedAddress[i] = 0;
            }
            return paddedAddress;
         }
      }
      return null;
   }

   // Private -------------------------------------------------------

   private static boolean isBlackList(final byte[] address)
   {
      for (byte[] blackList : UUIDGenerator.BLACK_LIST)
      {
         if (Arrays.equals(address, blackList))
         {
            return true;
         }
      }
      return false;
   }

   private byte[] getAddressBytes()
   {
      if (address == null)
      {
         address = UUIDGenerator.getHardwareAddress();
         if (address == null)
         {
            address = generateDummyAddress();
         }
      }

      return address;
   }

   private static String asString(final byte[] bytes)
   {
      if (bytes == null)
      {
         return null;
      }

      StringBuilder s = new StringBuilder();
      for (int i = 0; i < bytes.length - 1; i++)
      {
         s.append(Integer.toHexString(bytes[i]));
         s.append(":");
      }
      s.append(bytes[bytes.length - 1]);
      return s.toString();
   }

   private static List getAllNetworkInterfaces()
   {
      Enumeration networkInterfaces;
      try
      {
         networkInterfaces = NetworkInterface.getNetworkInterfaces();

         List ifaces = new ArrayList();
         while (networkInterfaces.hasMoreElements())
         {
            ifaces.add(networkInterfaces.nextElement());
         }
         return ifaces;
      }
      catch (SocketException e)
      {
         return Collections.emptyList();
      }
   }

   private static byte[] findFirstMatchingHardwareAddress(List ifaces,
                                                          final Method getHardwareAddressMethod,
                                                          final Method isUpMethod,
                                                          final Method isLoopbackMethod,
                                                          final Method isVirtualMethod)
   {
      ExecutorService executor = Executors.newFixedThreadPool(ifaces.size());
      Collection> tasks = new ArrayList>(ifaces.size());

      for (final NetworkInterface networkInterface : ifaces)
      {
         tasks.add(new Callable()
         {
            public byte[] call() throws Exception
            {
               boolean up = (Boolean) isUpMethod.invoke(networkInterface);
               boolean loopback = (Boolean) isLoopbackMethod.invoke(networkInterface);
               boolean virtual = (Boolean) isVirtualMethod.invoke(networkInterface);

               if (loopback || virtual || !up)
               {
                  throw new Exception("not suitable interface");
               }

               Object res = getHardwareAddressMethod.invoke(networkInterface);
               if (res != null && res instanceof byte[])
               {

                  byte[] address = (byte[]) res;
                  byte[] paddedAddress = UUIDGenerator.getZeroPaddedSixBytes(address);

                  if (UUIDGenerator.isBlackList(address))
                  {
                     throw new Exception("black listed address");
                  }

                  if (paddedAddress != null)
                  {
                     return paddedAddress;
                  }
               }

               throw new Exception("invalid network interface");
            }
         });
      }
      try
      {
         // we wait 5 seconds to get the first matching hardware address. After that, we give up and return null
         byte[] address = executor.invokeAny(tasks, 5, TimeUnit.SECONDS);
         return address;
      }
      catch (Exception e)
      {
         return null;
      }
      finally
      {
         executor.shutdownNow();
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy