/*
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.bigdata.util.config;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Level;
/**
* Utility class that provides a set of static convenience methods
* related to processing information about the current node's Network
* Interface Card(s) (NICs) and associated IP address(es) and hostname.
* Although useful in general, the methods in this utility class may
* be particularly useful when employed from within a Jini configuration
* file.
* <p>
* This class cannot be instantiated.
*/
public class NicUtil {
private static final org.apache.log4j.Logger utilLogger =
LogUtil.getLog4jLogger( NicUtil.class );
private static final java.util.logging.Logger jiniConfigLogger =
java.util.logging.Logger.getLogger("net.jini.config");
private static final java.util.logging.Level WARNING =
java.util.logging.Level.WARNING;
private static final java.util.logging.Level INFO =
java.util.logging.Level.INFO;
private static final java.util.logging.Level CONFIG =
java.util.logging.Level.CONFIG;
// This class cannot be instantiated.
private NicUtil() {
throw new AssertionError
("com.bigdata.util.NicUtil cannot be instantiated");
}
/**
* Method that searches for and returns the network interface having
* the specified <code>name</code>.
*
* @param name <code>String</code> referencing the name of the
* network interface to return (for example, typical
* values for this parameter might be, "eth0", "eth1",
* "hme01", "lo", etc., depending on how the underlying
* platform is configured).
*
* @return an instance of <code>NetworkInterface</code> that represents
* the network interface corresponding to the given
* <code>name</code>, or <code>null</code> if there is no
* network interface with that name value.
*
* @throws SocketException if there is an error in the underlying
* I/O subsystem and/or protocol.
*
* @throws NullPointerException if <code>null</code> is input for
* <code>name</code>.
*/
public static NetworkInterface getNetworkInterface(String name)
throws SocketException
{
NetworkInterface nic = NetworkInterface.getByName(name);
if (nic == null) {
// try by IP address
InetAddress targetIp = null;
try {
targetIp = InetAddress.getByName(name);
nic = NetworkInterface.getByInetAddress(targetIp);
} catch (UnknownHostException uhe) {
// ignore, return null
}
}
return nic;
}
/**
* Method that returns a <code>Map</code> in which the key component
* of each element is one of the addresses of one of the network
* interface cards (nics) installed on the current node, and the
* corresponding value component is the name of the associated
* nic to which that address is assigned.
*
* @return a <code>Map</code> of key-value pairs in which the key
* is an instance of <code>InetAddress</code> referencing
* the address of one of the network interface cards installed
* on the current node, and the corresponding value is a
* <code>String</code> referencing the name of the associated
* network interface to which the address is assigned.
*
* @throws SocketException if there is an error in the underlying
* I/O subsystem and/or protocol.
*/
public static Map<InetAddress, String> getInetAddressMap()
throws SocketException
{
Map<InetAddress, String> retMap = new HashMap<InetAddress, String>();
//get all nics on the current node
Enumeration<NetworkInterface> nics =
NetworkInterface.getNetworkInterfaces();
while( nics.hasMoreElements() ) {
NetworkInterface curNic = nics.nextElement();
Enumeration<InetAddress> curNicAddrs = curNic.getInetAddresses();
String curNicName = curNic.getName();
while( curNicAddrs.hasMoreElements() ) {
retMap.put( curNicAddrs.nextElement(), curNicName );
}
}
return retMap;
}
/**
* Method that searches for and returns an array whose elements
* are all the network interface(s) that correspond to the specified
* <code>name</code>.
*
* @param name <code>String</code> referencing the name to which
* the desired network interface(s) correspond.
*
* @return an array whose elements are each instances of
* <code>NetworkInterface[]</code>, in which each such
* instance corresponds to the given <code>name</code>,
* or <code>null</code> if there is no network interface
* corresponding to that name value.
*
* Note that if the value given for the <code>name</code>
* parameter is the <code>String</code> "all", then this
* method will return an array containing all of the
* network interfaces installed on the current node,
* regardless of each interface's name.
*
* @throws SocketException if there is an error in the underlying
* I/O subsystem and/or protocol.
*
* @throws NullPointerException if <code>null</code> is input for
* <code>name</code>.
*/
public static NetworkInterface[] getNetworkInterfaceArray(String name)
throws SocketException
{
NetworkInterface [] nics = null;
if (name.equals("all")) {
Enumeration en = NetworkInterface.getNetworkInterfaces();
List nicList = (en != null) ?
Collections.list(en) : Collections.EMPTY_LIST;
nics = (NetworkInterface[])(nicList.toArray
(new NetworkInterface[nicList.size()]) );
} else {
nics = new NetworkInterface[1];
nics[0] = NetworkInterface.getByName(name);
if (nics[0] == null) {
// try to lookup by IP address
InetAddress targetIp = null;
try {
targetIp = InetAddress.getByName(name);
nics[0] = NetworkInterface.getByInetAddress(targetIp);
} catch (UnknownHostException uhe) {
// ignore, return null
}
}
}
return nics;
}
/**
* Returns the instance of <code>InetAddress</code> that represents
* the i-th IP address assigned to the network interface having the
* given <code>name</code> (where i is specified by the value of the
* <code>index</code> parameter).
* <p>
* If this method fails to retrieve the desired value for the
* given network interface <code>name</code> -- either because of
* a system error, or because a network interface with that name
* doesn't exist -- then this method provides the following
* <i>optional</i> fallback strategies, which will be executed in
* the order documented below:
*
* <p><ul>
* <li> if the <code>host</code> parameter is non-<code>null</code>
* <li> return the <code>InetAddress</code> for the given
* <code>host</code> name (or IP address string value)
* </ul></p>
*
* If the previous <code>fallback</code> strategy fails, then
*
* <p><ul>
* <li> if the <code>localHost</code> parameter is <code>true</code>
* <li> return the <code>InetAddress</code> for system local host
* </ul></p>
*
* Thus, although this method gives priority to the network interface
* <code>name</code>, if one wishes to force this method to return
* the <code>InetAddress</code> for a given host name rather than for
* a network interface, then <code>null</code> (or a name value known
* to not exist on the system) should be input for the <code>name</code>
* parameter. Similarly, if one wishes to force this method to return
* the <code>InetAddress</code> of the local host, then <code>null</code>
* should be input for both the <code>name</code> parameter and the
* <code>host</code> parameter.
* <p>
* If each of the strategies described above fail, then this method
* returns <code>null</code>.
*
* @param name <code>String</code> referencing the name of the
* network interface to query for the desired address.
*
* @param index non-negative <code>int</code> value that indicates
* which IP address, from the list of IP address(es)
* assigned to the network interface, should be
* used when retrieving the <code>InetAddress</code>
* to return. Note that 0 is typically input for
* this value.
*
* @param host <code>String</code> referencing the name of the
* host whose <code>InetAddress</code> should be
* returned if failure occurs for the <code>name</code>
* parameter.
*
* @param localHost if <code>true</code>, then upon failure to retrieve
* a valid value for the given <code>name</code> and
* the given <code>host</code> (in that order),
* attempt to return the <code>InetAddress</code> of
* the local host.
*
* @return the instance of <code>InetAddress</code> that represents
* the <code>index</code>-th IP address assigned to the
* network interface having the given <code>name</code>,
* or the given <code>host</code> name, or the local host.
*
* @throws NullPointerException if <code>null</code> is input for
* both <code>name</code> and <code>host</code>, and
* <code>localHost</code> is <code>false</code>.
*
* @throws IllegalArgumentException if the value input for
* <code>index</code> is negtive.
*
* @throws IndexOutOfBoundsException if the value input for
* <code>index</code> is out of range; that is if the value
* input is greater than or equal to the number of IP
* address(es) assigned to the corresponding network interface.
*/
public static InetAddress getInetAddress(String name,
int index,
String host,
boolean localHost)
{
// Validate input parameters
if( (name == null) && (host == null) && (localHost == false) ) {
throw new NullPointerException("name cannot be null");
}
if(index < 0) throw new IllegalArgumentException
("index cannot be negative");
// Primary retrieval attempt
NetworkInterface nic = null;
try {
nic = getNetworkInterface(name);
} catch(Exception e) {/* swallow and try fallback */}
if(nic != null) {
List<InterfaceAddress> interfaceAddrs =
nic.getInterfaceAddresses();
if(interfaceAddrs.size() == 0) return null;
int inet4AddrIndex = 0;
for(int i=0; i<interfaceAddrs.size();i++) {
InetAddress inetAddr = (interfaceAddrs.get(i)).getAddress();
if(inetAddr instanceof Inet4Address) {
if(index == inet4AddrIndex) {
Inet4Address inet4Addr = (Inet4Address)inetAddr;
String hostAddr = inet4Addr.getHostAddress();
String hostName = inet4Addr.getCanonicalHostName();
jiniConfigLogger.log(CONFIG,
"Inet4: address = "+hostAddr
+", name = "+hostName);
utilLogger.log(Level.TRACE,
"Inet4: address = "+hostAddr
+", name = "+hostName);
return inetAddr;
} else {
inet4AddrIndex = inet4AddrIndex+1;//next index
}
}
}
}
InetAddress fallback = null;
// Nic-based retrieval failed. Try host name?
if(host != null) {
try {
fallback = InetAddress.getByName(host);
} catch(Exception e) {/* swallow and try fallback */}
if(fallback != null) {
jiniConfigLogger.log(CONFIG, "fallback host = "+fallback);
utilLogger.log(Level.TRACE, "fallback host = "+fallback);
return fallback;
}
}
// Host-based retrieval failed. Try local host?
if(localHost) {
try {
fallback = InetAddress.getLocalHost();
} catch(Exception e) {/* swallow and return null */}
jiniConfigLogger.log(CONFIG, "fallback local host = "+fallback);
utilLogger.log(Level.TRACE, "fallback local host = "+fallback);
}
return fallback;
}
/**
* Method that returns the <i>Media Access Control (MAC)</i> address
* assigned to the network interface having the given <code>name</code>;
* returning the address as a <code>String</code> in a human-readable
* format that consists of six groups of two hexadecimal digits,
* separated by colons (:); e.g., <code>01:23:45:67:89:ab</code>.
* <p>
* If this method fails to retrieve the desired MAC address for the given
* network interface <code>name</code> -- either because of a system
* error, or because a network interface with the given <code>name</code>
* does not exist -- then <code>null</code> is returned.
*
* @param name <code>String</code> referencing the name of the
* network interface whose MAC address should be
* returned.
*
* @return a <code>String</code>, in human-readable format, whose value
* is constructed from the MAC address assigned to the network
* interface having the given <code>name</code>; or
* <code>null</code> if the MAC address of the desired network
* interface cannot be retrieved.
*
* @throws SocketException if there is an error in the underlying
* I/O subsystem and/or protocol.
*
* @throws NullPointerException if <code>null</code> is input for
* <code>name</code>.
*/
public static String getMacAddress(String name) throws SocketException {
String macAddr = null;
NetworkInterface nic = NicUtil.getNetworkInterface(name);
byte[] hwAddr = nic.getHardwareAddress();
if( (hwAddr != null) && (hwAddr.length > 0) ) {
StringBuffer strBuf = new StringBuffer();
for(int i=0; i<hwAddr.length; i++) {
String subStr = String.format("%02X", hwAddr[i]);
if(i == 0) {
strBuf.append(subStr);
} else {
strBuf.append(":"+subStr);
}
}
macAddr = strBuf.toString();
}
return macAddr;
}
// /**
// * Three-argument version of <code>getInetAddress</code> that retrieves
// * the desired interface name from the given <code>Configuration</code>
// * parameter.
// */
// public static InetAddress getInetAddress(Configuration config,
// String componentName,
// String nicNameEntry)
// {
// String nicName = "NoNetworkInterfaceName";
// try {
// nicName = (String)Config.getNonNullEntry(config,
// componentName,
// nicNameEntry,
// String.class,
// "eth0");
// } catch(ConfigurationException e) {
// jiniConfigLogger.log(WARNING, e
// +" - [componentName="+componentName
// +", nicNameEntry="+nicNameEntry+"]");
// utilLogger.log(Level.WARN, e
// +" - [componentName="+componentName
// +", nicNameEntry="+nicNameEntry+"]");
// e.printStackTrace();
// return null;
// }
// return ( getInetAddress(nicName, 0, null, false) );
// }
// What follows are a number of versions of the getIpAddress method
// provided for convenience.
/**
* Returns the <code>String</code> value of the 0-th IP address assigned
* to the network interface or host having the given <code>name</code>,
* or <code>null</code> if that IP address cannot be retrieved.
*/
public static String getIpAddress(String name) {
InetAddress inetAddr = getInetAddress(name, 0, name, false);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name, int index) {
InetAddress inetAddr = getInetAddress(name, index, name, false);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name, String host) {
InetAddress inetAddr = getInetAddress(name, 0, host, false);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name, int index, String host) {
InetAddress inetAddr = getInetAddress(name, index, host, false);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name,
int index,
String host,
boolean localHost)
{
InetAddress inetAddr = getInetAddress(name, index, host, localHost);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name, boolean localHost) {
InetAddress inetAddr = getInetAddress(name, 0, name, localHost);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddress(String name,
int index,
boolean localHost)
{
InetAddress inetAddr = getInetAddress(name, index, name, localHost);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddressByHost(String host) {
InetAddress inetAddr = getInetAddress(null, 0, host, false);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddressByHost(String host, boolean localHost) {
InetAddress inetAddr = getInetAddress(null, 0, host, localHost);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
public static String getIpAddressByLocalHost() {
InetAddress inetAddr = getInetAddress(null, 0, null, true);
if(inetAddr != null) return inetAddr.getHostAddress();
return null;
}
/**
* Special-purpose convenience method that returns a
* <code>String</code> value representing the ip address of
* the current node.
* <p>
* If a non-<code>null</code> value is input for the
* <code>systemPropertyName</code> parameter, then this
* method first determines if a system property with
* name equivalent to the given value has been set and,
* if it has, returns the ip address of the nic whose name
* is equivalent to that system property value; or
* <code>null</code> if there is no nic with the desired
* name installed on the node.
* <p>
* If there is no system property whose name is the value
* of the <code>systemPropertyName</code> parameter, and
* if the value "default" is input for the
* <code>defaultNic</code> parameter, then this method
* will return the IPV4 based address of the first reachable
* nic that can be found on the node; otherwise, if a
* non-<code>null</code> value not equal to "default" is
* input for the the <code>defaultNic</code> parameter,
* then this method returns the ip address of the nic
* corresponding to that given name; or <code>null</code>
* if there is no such nic name installed on the node.
* <p>
* If, on the other hand, <code>null</code> is input for
* the <code>systemPropertyName</code> parameter, then
* this method will attempt to find the desired ip address
* using only the value of the <code>defaultNic</code>,
* and applying the same search criteria as described
* above.
* <p>
* Note that in all cases, if <code>true</code> is input
* for the <code>loopOk</code> parameter, then upon failing
* to find a valid ip address using the specified search
* mechanism, this method will return the <i>loop back</i>
* address; otherwise, <code>null</code> is returned.
* <p>
* This method can be called from within a configuration
* as well as from within program control.
*
* @param systemPropertyName <code>String</code> value containing
* the name of a system property whose
* value is the network interface name
* whose ip address should be returned.
* May be <code>null</code>.
*
* @param defaultNic <code>String</code> value containing
* the name of the network interface
* whose ip address should be returned
* if <code>null</code> is input for the
* <code>systemPropertyName</code> parameter,
* or if there is no system property with
* name equivalent the value of the
* <code>systemPropertyName</code> parameter.
*
* @param loopbackOk if <code>true</code>, then return the
* <i>loop back</i> address upon failure
* to find a valid ip address using the
* search criteria specified through the
* <code>systemPropertyName</code> and
* <code>defaultNic</code> parameters.
*
* @return a <code>String</code> representing an ip address associated
* with the current node; where the value that is returned is
* determined according to the criteria described above.
*/
public static String getIpAddress(String systemPropertyName,
String defaultNic,
boolean loopbackOk)
throws SocketException, IOException
{
if(systemPropertyName != null) {//system property takes precedence
String nicName = System.getProperty(systemPropertyName);
boolean propSet = true;
if(nicName == null) {
propSet = false;
} else {
// handle ant script case where the system property
// may not have been set on the command line, but
// was still set to "${<systemPropertyName>}" using
// ant <sysproperty> tag
String rawProp = "${" + systemPropertyName + "}";
if( rawProp.equals(nicName) ) propSet = false;
}
if(propSet) {
return getIpAddress(nicName, 0, loopbackOk);
} else {//system property not set, try default and/or fallback
if(defaultNic != null) {
if( defaultNic.equals("default") ) {
return getDefaultIpv4Address(loopbackOk);
} else {
return getIpAddress(defaultNic, 0, loopbackOk);
}
} else {
return null;
}
}
} else {//no system property name provided, try default
if(defaultNic != null) {
if( defaultNic.equals("default") ) {
return getDefaultIpv4Address(loopbackOk);
} else {
return getIpAddress(defaultNic, 0, loopbackOk);
}
} else {
return getIpAddress(null, loopbackOk);
}
}
}
/**
* Examines each address associated with each network interface
* card (nic) installed on the current node, and returns the
* <code>String</code> value of the first such address that is
* determined to be both <i>reachable</i> and an address type
* that represents an <i>IPv4</i> address.
*
* This method will always first examine addresses that are
* <i>not</i> the <i>loopback</i> address (<i>local host</i>);
* returning a loopback adddress only if <code>true</code>
* is input for the <code>loopbackOk</code> parameter, and
* none of the non-loopback addresses satisfy this method's
* search criteria.
*
* If this method fails to find any address that satisfies the
* above criteria, then this method returns <code>null</code>.
*
* @param loopbackOk if <code>true</code>, then upon failure
* find an non-<i>loopback</i> address that
* satisfies this method's search criteria
* (an IPv4 type address and reachable), the
* first loopback address that is found to be
* reachable is returned.
*
* If <code>false</code> is input for this
* parameter, then this method will examine
* only those addresses that do <i>not</i>
* correspond to the corresponding nic's
* loopback address.
*
* @return a <code>String</code> value representing the first
* network interface address installed on the current
* node that is determined to be both <i>reachable</i>
* and an IPv4 type address; where the return value
* corresponds to a <i>loopback</i> address only if
* <code>true</code> is input for the <code>loopbackOk</code>
* parameter, and no non-loopback address satisfying
* the desired criteria can be found. If this method
* fails to find any address that satisfies the desired
* criteria, then <code>null</code> is returned.
*
* @throws SocketException if there is an error in the underlying
* I/O subsystem and/or protocol while retrieving the
* the network interfaces currently installed on the
* node.
*
* @throws IOException if a network error occurs while determining
* if a candidate return address is <i>reachable</i>.
*/
public static String getDefaultIpv4Address(final boolean loopbackOk)
throws SocketException, IOException
{
/*
* Note: I've commented out the inetAddr.isReachable() lines. Their
* return value was not being used, the method call was imposing
* significant latency on this method, and the possible IOException was
* not being trapped through the standard invocation code paths, e.g.,
* NicUtil.getInetAddress/3.
*
* One thing to note is that the method getDefaultIpv4Address where
* isReachable is called was created as a convenience; specifically, to
* allow one to use NicUtil with Windows, where the NIC name(s) can't
* necessarily be known a priori. It also turned out to then be
* convenient to use that method in the config files used by the tests;
* where dealing with multiple NICs is generally not an issue.
*
* But it was always intended that in a real system deployment, the NICs
* would be known and explicitly specified in the config files used in
* that real deployment, rather than running all network traffic through
* the single, default NIC. Thus, if the latency of the call is a
* concern, you might shorten the timeout that's currently baked into
* the call to isReachable; and test the return value, executing a
* continue when that value is false.
*
* Note: For a timeout of 500ms or less, isReachable(timeout) will
* return false under Windows. Therefore I have added a static cache for
* the loopback address so we do not suffer either lookup failures or
* large latencies on lookup.
*/
final int timeout = 3000;
// first consider the non-loopback addresses.
{
{ // test the cache
final String cached = nonLoopbackCache.get();
if (cached != null)
return cached;
}
// get all nics on the current node
final Enumeration<NetworkInterface> nics =
NetworkInterface.getNetworkInterfaces();
while( nics.hasMoreElements() ) {
final NetworkInterface curNic = nics.nextElement();
final List<InterfaceAddress> interfaceAddrs =
curNic.getInterfaceAddresses();
for(InterfaceAddress interfaceAddr : interfaceAddrs) {
final InetAddress inetAddr = interfaceAddr.getAddress();
final boolean isIpv4 = inetAddr instanceof Inet4Address;
final boolean isLoopbackAddress = inetAddr.isLoopbackAddress();
if(isIpv4) {
if(isLoopbackAddress) continue;
final boolean isReachable = inetAddr.isReachable(timeout);
if (!isReachable) continue;
final Inet4Address inet4Addr = (Inet4Address)inetAddr;
final String retVal = inet4Addr.getHostAddress();
jiniConfigLogger.log
(CONFIG, "default IPv4 address: "+retVal);
utilLogger.log
(Level.TRACE, "default IPv4 address: "+retVal);
// update the cache
nonLoopbackCache.set(retVal);
return retVal;
}
}
}
}
if(!loopbackOk) return null;
// now examine the loopback addresses.
{
{// test the cache
final String cached = loopbackCache.get();
if (cached != null)
return cached;
}
// get all nics on the current node
final Enumeration<NetworkInterface> nics =
NetworkInterface.getNetworkInterfaces();
while( nics.hasMoreElements() ) {
final NetworkInterface curNic = nics.nextElement();
final List<InterfaceAddress> interfaceAddrs =
curNic.getInterfaceAddresses();
for(InterfaceAddress interfaceAddr : interfaceAddrs) {
final InetAddress inetAddr = interfaceAddr.getAddress();
final boolean isIpv4 = inetAddr instanceof Inet4Address;
final boolean isLoopbackAddress = inetAddr.isLoopbackAddress();
if(isIpv4) {
if(!isLoopbackAddress) continue;
final boolean isReachable = inetAddr.isReachable(timeout);
if (!isReachable) continue;
final Inet4Address inet4Addr = (Inet4Address)inetAddr;
final String retVal = inet4Addr.getHostAddress();
jiniConfigLogger.log
(CONFIG, "default IPv4 address: "+retVal);
utilLogger.log
(Level.TRACE, "default IPv4 address: "+retVal);
// update the cache
loopbackCache.set(retVal);
return retVal;
}
}
}
}
return null;
}
static private long cacheTimeout = 60 * 1000;// ms
/**
* A simple cache with an expiration time and refresh on read.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
*/
private static class AddrCache<T> {
private volatile T cache = null;
private volatile long timestamp = 0L;
/**
* Return the address from the cache iff one exists in the cache and the
* cache has not expired. If the cache is expired, then it is cleared
* and <code>null</code> is returned. If the cache is empty, then
* <code>null</code> is returned. If the cache is not expired and has an
* address, then the cache age is touched to defer expiration.
*
* @return The address if found in the cache.
*/
synchronized T get() {
final long now = System.currentTimeMillis();
if (cache != null) {
final boolean expired = (now - timestamp) > cacheTimeout;
if (expired) {
cache = null;
return null;
}
timestamp = now;
return cache;
}
return null;
}
/**
* Sets the cached value.
*/
synchronized void set(final T addr) {
cache = addr;
timestamp = System.currentTimeMillis();
}
}
private static AddrCache<String> loopbackCache = new AddrCache<String>();
private static AddrCache<String> nonLoopbackCache = new AddrCache<String>();
public static String getDefaultIpv4Address()
throws SocketException, IOException
{
return getDefaultIpv4Address(false);//localhost NOT ok
}
/**
* Intended for use by scripts.
*/
public static void main(String[] args) {
String ipAddress = "NIC_DOES_NOT_EXIST";
try {
if(args.length == 0) {
ipAddress = getIpAddressByLocalHost();
} else {
if( args[0].equals("getIpAddressByLocalHost") ) {
ipAddress = getIpAddressByLocalHost();
} else if( args[0].equals("getIpAddress") ) {
if(args.length == 2) {
String tmpIpAddress = NicUtil.getIpAddress(args[1]);
if(tmpIpAddress != null) ipAddress = tmpIpAddress;
} else if(args.length == 3) {
String tmpIpAddress =
NicUtil.getIpAddress(args[1],0,args[2],false);
if(tmpIpAddress != null) ipAddress = tmpIpAddress;
}
} else {
ipAddress = "NIC_UTIL_FAILURE";
System.out.println("NicUtil Failure: unexpected number of "
+"arguments ("+args.length+")");
}
}
} catch(Throwable t) {
ipAddress = "NIC_UTIL_FAILURE";
t.printStackTrace();
}
System.out.println(ipAddress);
}
}