View Javadoc
1   package org.apache.commons.jcs.utils.net;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  import java.net.InetAddress;
26  import java.net.NetworkInterface;
27  import java.net.UnknownHostException;
28  import java.util.Enumeration;
29  
30  /**
31   * Simple utility for getting the local host name.
32   * <p>
33   * @author Aaron Smuts
34   */
35  public class HostNameUtil
36  {
37      /** The logger. */
38      private static final Log log = LogFactory.getLog( HostNameUtil.class );
39  
40      /**
41       * Gets the address for the local machine.
42       * <p>
43       * @return InetAddress.getLocalHost().getHostAddress()
44       * @throws UnknownHostException
45       */
46      public static String getLocalHostAddress() throws UnknownHostException
47      {
48          try
49          {
50              String hostAddress = getLocalHostLANAddress().getHostAddress();
51              if ( log.isDebugEnabled() )
52              {
53                  log.debug( "hostAddress = [" + hostAddress + "]" );
54              }
55              return hostAddress;
56          }
57          catch ( UnknownHostException e1 )
58          {
59              log.error( "Couldn't get localhost address", e1 );
60              throw e1;
61          }
62      }
63  
64      /**
65       * Returns an <code>InetAddress</code> object encapsulating what is most likely the machine's
66       * LAN IP address.
67       * <p>
68       * This method is intended for use as a replacement of JDK method
69       * <code>InetAddress.getLocalHost</code>, because that method is ambiguous on Linux systems.
70       * Linux systems enumerate the loopback network interface the same way as regular LAN network
71       * interfaces, but the JDK <code>InetAddress.getLocalHost</code> method does not specify the
72       * algorithm used to select the address returned under such circumstances, and will often return
73       * the loopback address, which is not valid for network communication. Details <a
74       * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>.
75       * <p>
76       * This method will scan all IP addresses on all network interfaces on the host machine to
77       * determine the IP address most likely to be the machine's LAN address. If the machine has
78       * multiple IP addresses, this method will prefer a site-local IP address (e.g. 192.168.x.x or
79       * 10.10.x.x, usually IPv4) if the machine has one (and will return the first site-local address
80       * if the machine has more than one), but if the machine does not hold a site-local address,
81       * this method will return simply the first non-loopback address found (IPv4 or IPv6).</p>
82       * <p>
83       * If this method cannot find a non-loopback address using this selection algorithm, it will
84       * fall back to calling and returning the result of JDK method
85       * <code>InetAddress.getLocalHost</code>.
86       * <p>
87       * <a href="http://issues.apache.org/jira/browse/JCS-40">JIR ISSUE JCS-40</a>
88       * <p>
89       * @return InetAddress
90       * @throws UnknownHostException If the LAN address of the machine cannot be found.
91       */
92      public static InetAddress getLocalHostLANAddress()
93          throws UnknownHostException
94      {
95          try
96          {
97              InetAddress candidateAddress = null;
98              // Iterate all NICs (network interface cards)...
99              for ( Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); )
100             {
101                 NetworkInterface iface = ifaces.nextElement();
102                 // Iterate all IP addresses assigned to each card...
103                 for ( Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); )
104                 {
105                     InetAddress inetAddr = inetAddrs.nextElement();
106                     if ( !inetAddr.isLoopbackAddress() )
107                     {
108                         if ( inetAddr.isSiteLocalAddress() )
109                         {
110                             // Found non-loopback site-local address. Return it immediately...
111                             return inetAddr;
112                         }
113                         else if ( candidateAddress == null )
114                         {
115                             // Found non-loopback address, but not necessarily site-local.
116                             // Store it as a candidate to be returned if site-local address is not subsequently found...
117                             candidateAddress = inetAddr;
118                             // Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates,
119                             // only the first. For subsequent iterations, candidate will be non-null.
120                         }
121                     }
122                 }
123             }
124             if ( candidateAddress != null )
125             {
126                 // We did not find a site-local address, but we found some other non-loopback address.
127                 // Server might have a non-site-local address assigned to its NIC (or it might be running
128                 // IPv6 which deprecates the "site-local" concept).
129                 // Return this non-loopback candidate address...
130                 return candidateAddress;
131             }
132             // At this point, we did not find a non-loopback address.
133             // Fall back to returning whatever InetAddress.getLocalHost() returns...
134             InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
135             if ( jdkSuppliedAddress == null )
136             {
137                 throw new UnknownHostException( "The JDK InetAddress.getLocalHost() method unexpectedly returned null." );
138             }
139             return jdkSuppliedAddress;
140         }
141         catch ( Exception e )
142         {
143             UnknownHostException unknownHostException = new UnknownHostException( "Failed to determine LAN address: "
144                 + e );
145             unknownHostException.initCause( e );
146             throw unknownHostException;
147         }
148     }
149 }