[jboss-cvs] JBoss Messaging SVN: r5765 - in trunk: tests/src/org/jboss/messaging/tests/unit/util and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jan 30 05:00:05 EST 2009


Author: jmesnil
Date: 2009-01-30 05:00:04 -0500 (Fri, 30 Jan 2009)
New Revision: 5765

Added:
   trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDGeneratorTest.java
Modified:
   trunk/src/main/org/jboss/messaging/util/UUIDGenerator.java
   trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDTest.java
Log:
JBMESSAGING-1494: UUIDGenerator does not use a different network address

* refactored the algorithm to chose the spatial part of the UUID:
  1. use the MAC address on Java 6
  2. use a non-loopback non-local-site InetAddress
  3. if both 1 and 2 fails (e.g. on java 5 or in a restricted environment), generate a random address

* the call to NetworkInterface.getHardwareAddress() is done by reflection so that the source remains 1.5 compatible.
* the choice of the address is done only the 1st time a UUID is generated

Modified: trunk/src/main/org/jboss/messaging/util/UUIDGenerator.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/UUIDGenerator.java	2009-01-29 22:27:33 UTC (rev 5764)
+++ trunk/src/main/org/jboss/messaging/util/UUIDGenerator.java	2009-01-30 10:00:04 UTC (rev 5765)
@@ -15,15 +15,22 @@
 
 package org.jboss.messaging.util;
 
+import java.lang.reflect.Method;
 import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.security.SecureRandom;
+import java.util.Enumeration;
 import java.util.Random;
 
+import org.jboss.messaging.core.logging.Logger;
+
 public final class UUIDGenerator
 {
    private final static UUIDGenerator sSingleton = new UUIDGenerator();
 
+   private static final Logger log = Logger.getLogger(UUIDGenerator.class);
+
    /**
     * Random-generator, used by various UUID-generation methods:
     */
@@ -31,6 +38,8 @@
 
    private final Object mTimerLock = new Object();
    private UUIDTimer mTimer = null;
+   private byte[] address;
+   
 
    /**
     * Constructor is private to enforce singleton access.
@@ -73,10 +82,9 @@
       return mRnd;
    }
 
-   public final UUID generateTimeBasedUUID(InetAddress addr)
+   public final UUID generateTimeBasedUUID(byte[] byteAddr)
    {
       byte[] contents = new byte[16];
-      byte[] byteAddr = addr.getAddress();
       int pos = 12;
       for (int i = 0; i < 4; ++i)
       {
@@ -96,77 +104,174 @@
       return new UUID(UUID.TYPE_TIME_BASED, contents);
    }
    
-   private InetAddress address;
+   public final 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 (log.isDebugEnabled())
+      {
+         log.debug("using dummy address " + asString(dummy));
+      }
+      return dummy;
+   }
+
+   /**
+    * If running java 6 or above, returns {@link NetworkInterface#getHardwareAddress()}, else return <code>null</code>.
+    * The first hardware address is returned when iterating all the NetworkInterfaces
+    */
+   public final static byte[] getHardwareAddress()
+   {
+      Method getHardwareAddressMethod;
+      try
+      {
+         getHardwareAddressMethod = NetworkInterface.class.getMethod("getHardwareAddress", null);
+      }
+      catch (Throwable t)
+      {
+         // not on Java 6 or not enough security permission
+         return null;
+      }
+      
+      try {
+         Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+         while (networkInterfaces.hasMoreElements())
+         {
+            NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
+            Object res = getHardwareAddressMethod.invoke(networkInterface, null);
+            if (res instanceof byte[])
+            {
+               byte[] address = (byte[])res;
+               if (log.isDebugEnabled())
+               {
+                  log.debug("using hardware address " + asString(address));
+               }
+               return address;
+            }
+         }
+      } catch (Throwable t)
+      {
+      }
+
+      return null;
+   }
    
-   private final InetAddress getAddress()
+   /**
+    * Browse all the network interfaces and their addresses until we find the 1st InetAddress which
+    * is neither a loopback address nor a site local address.
+    * Returns <code>null</code> if no such address is found.
+    */
+   public final static InetAddress getInetAddress()
    {
-      if (address == null)
-      {
-         address = null;
-         
          try
          {
-            address = InetAddress.getLocalHost();
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+            while (networkInterfaces.hasMoreElements())
+            {
+               NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
+               Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
+               while (inetAddresses.hasMoreElements())
+               {
+                  InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();
+                  if (!inetAddress.isLoopbackAddress()
+                      && !inetAddress.isSiteLocalAddress())
+                  {
+                     if (log.isDebugEnabled())
+                     {
+                        log.debug("using inet address " + inetAddress);
+                     }
+                     return inetAddress;
+                  }
+               }
+            }
          }
-         catch (UnknownHostException e)
-         {        
+         catch (SocketException e)
+         {
          }
-      }
-      return address;
+         return null;
    }
    
    public final SimpleString generateSimpleStringUUID()
    {
-      InetAddress localHost  = getAddress();
-      
-      SimpleString uid;
-      if (localHost == null)
+      byte[] address = getAddressBytes();
+      if (address == null)
       {
-         uid = new SimpleString(java.util.UUID.randomUUID().toString());
+         return new SimpleString(java.util.UUID.randomUUID().toString());
       }
       else
       {
          UUIDGenerator gen = UUIDGenerator.getInstance();
-         uid = new SimpleString(gen.generateTimeBasedUUID(localHost).toString());
+         return new SimpleString(gen.generateTimeBasedUUID(address).toString());
       }    
-      
-      return uid;
    }
    
-   public final SimpleString generateSimpleStringUUID2()
-   {
-      UUID uuid = generateUUID();
-      
-      SimpleString str = new SimpleString(uuid.asBytes());
-      
-      return str;
-   }
-   
    public final UUID generateUUID()
    {
-      InetAddress localHost  = getAddress();
+      byte[] address = getAddressBytes();
       
       UUIDGenerator gen = UUIDGenerator.getInstance();
-      UUID uid = gen.generateTimeBasedUUID(localHost);         
+      UUID uid = gen.generateTimeBasedUUID(address);         
       
       return uid;
    }
    
    public final String generateStringUUID()
    {
-      InetAddress localHost  = getAddress();
+      byte[] address = getAddressBytes();
       
-      String uid;
-      if (localHost == null)
+      if (address == null)
       {
-         uid = java.util.UUID.randomUUID().toString();
+         return java.util.UUID.randomUUID().toString();
       }
       else
       {
          UUIDGenerator gen = UUIDGenerator.getInstance();
-         uid = gen.generateTimeBasedUUID(localHost).toString();
+         return gen.generateTimeBasedUUID(address).toString();
       }    
+   }
+   
+   // Private -------------------------------------------------------
+   
+   private final byte[] getAddressBytes()
+   {
+      if (address == null)
+      {
+         address = getHardwareAddress();
+         if (address == null)
+         {
+            InetAddress addr = getInetAddress();
+            if (addr != null)
+            {
+               address = addr.getAddress();
+            }
+         }
+         if (address == null)
+         {
+            address = generateDummyAddress();
+         }
+      }
       
-      return uid;
+      return address;
    }
+   
+   private static final String asString(byte[] bytes)
+   {
+      if (bytes == null)
+      {
+         return null;
+      }
+      
+      String s = "";
+      for (int i = 0; i < bytes.length - 1; i++)
+      {
+         s += Integer.toHexString(bytes[i]) + ":";
+      }
+      s += bytes[bytes.length - 1];
+      return s;
+   }
 }

Added: trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDGeneratorTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDGeneratorTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDGeneratorTest.java	2009-01-30 10:00:04 UTC (rev 5765)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */ 
+
+package org.jboss.messaging.tests.unit.util;
+
+import java.net.InetAddress;
+
+import junit.framework.TestCase;
+
+import org.jboss.messaging.util.UUIDGenerator;
+
+/**
+ * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
+ *
+ * @version <tt>$Revision$</tt>
+ *
+ */
+public class UUIDGeneratorTest extends TestCase
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   public void testGetHardwareAddress() throws Exception
+   {
+      String javaVersion = System.getProperty("java.vm.version");
+      if (javaVersion.startsWith("1.5"))
+      {
+         assertNull(UUIDGenerator.getHardwareAddress());
+      } else if (javaVersion.startsWith("1.6"))
+      {
+         assertNotNull(UUIDGenerator.getHardwareAddress());
+      }
+   }
+   
+   public void testGetInetAddress() throws Exception
+   {
+      InetAddress address = UUIDGenerator.getInetAddress();
+      if (address != null)
+      {
+         assertFalse(address.isLoopbackAddress());
+         assertFalse(address.isSiteLocalAddress());
+      }
+   }
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDTest.java	2009-01-29 22:27:33 UTC (rev 5764)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/util/UUIDTest.java	2009-01-30 10:00:04 UTC (rev 5765)
@@ -22,7 +22,6 @@
 
 package org.jboss.messaging.tests.unit.util;
 
-import java.net.InetAddress;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -54,24 +53,22 @@
       Set<String> uuidsSet = new HashSet<String>();
       
       UUIDGenerator gen = UUIDGenerator.getInstance();
-      InetAddress addr = InetAddress.getLocalHost();
-      
       for (int i = 0; i < MANY_TIMES; i++)
       {
-         uuidsSet.add(gen.generateTimeBasedUUID(addr).toString());
+         uuidsSet.add(gen.generateStringUUID());
       }
       
       // we put them in a set to check duplicates
       assertEquals(MANY_TIMES, uuidsSet.size());
    }
-   
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
 
    protected int getTimes()
    {
-      return 1000;
+      return 100000;
    }
    
    // Private -------------------------------------------------------




More information about the jboss-cvs-commits mailing list