QPID-6044 : [Java Broker] [AMQP 1.0] cache the valid host names for the local machine

git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1620593 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
index 6937d31..d8b81a2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
@@ -65,4 +65,7 @@
     Collection<Connection> getConnections();
 
     void start();
+
+    boolean isLocalMachine(final String host);
+
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index d1abded..c90215f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -21,6 +21,11 @@
 
 package org.apache.qpid.server.model.port;
 
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.security.AccessControlException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -29,6 +34,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.log4j.Logger;
 
@@ -54,6 +63,60 @@
 {
     private static final Logger LOGGER = Logger.getLogger(AbstractPort.class);
 
+    private static final Set<InetAddress> LOCAL_ADDRESSES = new CopyOnWriteArraySet<>();
+    private static final Set<String> LOCAL_ADDRESS_NAMES = new CopyOnWriteArraySet<>();
+    private static final Lock ADDRESS_LOCK = new ReentrantLock();
+    private static final AtomicBoolean ADDRESSES_COMPUTED = new AtomicBoolean();
+
+    static
+    {
+        Thread thread = new Thread(new Runnable()
+        {
+            public void run()
+            {
+                Lock lock = ADDRESS_LOCK;
+
+                lock.lock();
+                try
+                {
+                    for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces()))
+                    {
+                        for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses())
+                        {
+                            InetAddress address = inetAddress.getAddress();
+                            LOCAL_ADDRESSES.add(address);
+                            String hostAddress = address.getHostAddress();
+                            if (hostAddress != null)
+                            {
+                                LOCAL_ADDRESS_NAMES.add(hostAddress);
+                            }
+                            String hostName = address.getHostName();
+                            if (hostName != null)
+                            {
+                                LOCAL_ADDRESS_NAMES.add(hostName);
+                            }
+                            String canonicalHostName = address.getCanonicalHostName();
+                            if (canonicalHostName != null)
+                            {
+                                LOCAL_ADDRESS_NAMES.add(canonicalHostName);
+                            }
+                        }
+                    }
+                }
+                catch (SocketException e)
+                {
+                    // ignore
+                }
+                finally
+                {
+                    ADDRESSES_COMPUTED.set(true);
+                    lock.unlock();
+                }
+            }
+        }, "Network Address Resolver");
+        thread.start();
+    }
+
     private final Broker<?> _broker;
     private State _state = State.UNINITIALIZED;
 
@@ -335,7 +398,7 @@
                 Collection<Protocol> portProtocols = existingPort.getProtocols();
                 if (portProtocols != null)
                 {
-                    final ArrayList<Protocol> intersection = new ArrayList(portProtocols);
+                    final ArrayList<Protocol> intersection = new ArrayList<>(portProtocols);
                     intersection.retainAll(getProtocols());
                     if(!intersection.isEmpty())
                     {
@@ -345,4 +408,39 @@
             }
         }
     }
+
+    public boolean isLocalMachine(final String host)
+    {
+        while(!ADDRESSES_COMPUTED.get())
+        {
+            Lock lock = ADDRESS_LOCK;
+            lock.lock();
+            lock.unlock();
+        }
+
+        boolean isNetworkAddress = true;
+        if (!LOCAL_ADDRESS_NAMES.contains(host))
+        {
+            try
+            {
+                InetAddress inetAddress = InetAddress.getByName(host);
+                if (!LOCAL_ADDRESSES.contains(inetAddress))
+                {
+                    isNetworkAddress = false;
+                }
+                else
+                {
+                    LOCAL_ADDRESS_NAMES.add(host);
+                }
+            }
+            catch (UnknownHostException e)
+            {
+                // ignore
+                isNetworkAddress = false;
+            }
+        }
+        return isNetworkAddress;
+
+    }
+
 }
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
index 8edc097..f97a223 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
@@ -22,19 +22,13 @@
 
 import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
 
-import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
 import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
 import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -142,7 +136,7 @@
         }
 
         _vhost = ((AmqpPort)_port).getVirtualHost(host);
-        if(_vhost == null && isNetworkAddress(host))
+        if(_vhost == null && _port.isLocalMachine(host))
         {
             _vhost = ((AmqpPort)_port).getVirtualHost(_broker.getDefaultVirtualHost());
         }
@@ -163,56 +157,6 @@
             _subject.getPrivateCredentials().addAll(authSubject.getPrivateCredentials());
         }
     }
-
-    private boolean isNetworkAddress(final String host)
-    {
-
-        try
-        {
-            Set<InetAddress> addresses = new HashSet<>();
-
-            for(NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces()))
-            {
-                for(InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses())
-                {
-                    InetAddress address = inetAddress.getAddress();
-                    addresses.add(address);
-                    if(host.equals(address.getHostAddress()))
-                    {
-                        return true;
-                    }
-                    if(host.equals(address.getHostName()))
-                    {
-                        return true;
-                    }
-                    if(host.equals(address.getCanonicalHostName()))
-                    {
-                        return true;
-                    }
-                }
-            }
-
-            try
-            {
-                InetAddress inetAddress = InetAddress.getByName(host);
-                if(addresses.contains(inetAddress))
-                {
-                    return true;
-                }
-            }
-            catch (UnknownHostException e)
-            {
-                // ignore
-            }
-        }
-        catch (SocketException e)
-        {
-            // ignore
-        }
-
-        return false;
-    }
-
     public void remoteSessionCreation(SessionEndpoint endpoint)
     {
         if(!_closedOnOpen)