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 }