mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			769 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			769 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* InetAddress.java -- Class to model an Internet address
 | |
|    Copyright (C) 1998, 1999, 2002, 2004  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath 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; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | |
| 02111-1307 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package java.net;
 | |
| 
 | |
| import gnu.classpath.Configuration;
 | |
| import java.io.IOException;
 | |
| import java.io.ObjectInputStream;
 | |
| import java.io.ObjectOutputStream;
 | |
| import java.io.ObjectStreamException;
 | |
| import java.io.Serializable;
 | |
| 
 | |
| /**
 | |
|  * This class models an Internet address.  It does not have a public
 | |
|  * constructor.  Instead, new instances of this objects are created
 | |
|  * using the static methods getLocalHost(), getByName(), and
 | |
|  * getAllByName().
 | |
|  * <p>
 | |
|  * This class fulfills the function of the C style functions gethostname(),
 | |
|  * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
 | |
|  * into their corresponding numeric addresses and vice versa.
 | |
|  *
 | |
|  * @author Aaron M. Renn <arenn@urbanophile.com>
 | |
|  * @author Per Bothner
 | |
|  *
 | |
|  * @specnote This class is not final since JK 1.4
 | |
|  */
 | |
| public class InetAddress implements Serializable
 | |
| {
 | |
|   private static final long serialVersionUID = 3286316764910316507L;
 | |
| 
 | |
|   /**
 | |
|    * Dummy InetAddress, used to bind socket to any (all) network interfaces.
 | |
|    */
 | |
|   static InetAddress ANY_IF;
 | |
|     
 | |
|   private static final byte[] localhostAddress = { 127, 0, 0, 1 };
 | |
| 
 | |
|   private static InetAddress localhost = null;
 | |
| 
 | |
|   static
 | |
|   {
 | |
|     // load the shared library needed for name resolution
 | |
|     if (Configuration.INIT_LOAD_LIBRARY)
 | |
|       {
 | |
|         System.loadLibrary ("javanet");
 | |
|       }
 | |
|     
 | |
|     byte[] zeros = { 0, 0, 0, 0 };
 | |
|     ANY_IF = new InetAddress (zeros, "0.0.0.0");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * The Serialized Form specifies that an int 'address' is saved/restored.
 | |
|    * This class uses a byte array internally so we'll just do the conversion
 | |
|    * at serialization time and leave the rest of the algorithm as is.
 | |
|    */
 | |
|   private int address;
 | |
| 
 | |
|   /**
 | |
|    * An array of octets representing an IP address.
 | |
|    */
 | |
|   transient byte[] addr;
 | |
| 
 | |
|   /**
 | |
|    * The name of the host for this address.
 | |
|    */
 | |
|   String hostName;
 | |
| 
 | |
|   /**
 | |
|    * The field 'family' seems to be the AF_ value.
 | |
|    * FIXME: Much of the code in the other java.net classes does not make
 | |
|    * use of this family field.  A better implementation would be to make
 | |
|    * use of getaddrinfo() and have other methods just check the family
 | |
|    * field rather than examining the length of the address each time.
 | |
|    */
 | |
|   int family;
 | |
| 
 | |
|   /**
 | |
|    * Initializes this object's addr instance variable from the passed in
 | |
|    * int array.  Note that this constructor is protected and is called
 | |
|    * only by static methods in this class.
 | |
|    *
 | |
|    * @param ipaddr The IP number of this address as an array of bytes
 | |
|    */
 | |
|   InetAddress(byte[] address)
 | |
|   {
 | |
|     this (address, null);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Initializes this object's addr instance variable from the passed in
 | |
|    * int array.  Note that this constructor is protected and is called
 | |
|    * only by static methods in this class.
 | |
|    *
 | |
|    * @param ipaddr The IP number of this address as an array of bytes
 | |
|    * @param hostname The hostname of this IP address.
 | |
|    */
 | |
|   InetAddress(byte[] address, String hostname)
 | |
|   {
 | |
|     addr = address;
 | |
|     hostName = hostname;
 | |
|     
 | |
|     if (address != null)
 | |
|       family = getFamily (address);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if this address is a multicast address, false otherwise.
 | |
|    * An address is multicast if the high four bits are "1110".  These are
 | |
|    * also known as "Class D" addresses.
 | |
|    *
 | |
|    * @return true if mulitcast, false if not
 | |
|    *
 | |
|    * @since 1.1
 | |
|    */
 | |
|   public boolean isMulticastAddress()
 | |
|   {
 | |
|     // Mask against high order bits of 1110
 | |
|     if (addr.length == 4)
 | |
|       return (addr[0] & 0xF0) == 0xE0;
 | |
| 
 | |
|     // Mask against high order bits of 11111111
 | |
|     if (addr.length == 16)
 | |
|       return addr [0] == (byte) 0xFF;
 | |
|     
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if the InetAddress in a wildcard address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isAnyLocalAddress()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     return equals(ANY_IF);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if the InetAddress is a loopback address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isLoopbackAddress()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     return addr[0] == 0x7F;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if InetAddress is a link local address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isLinkLocalAddress()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // XXX: This seems to not exist with IPv4 addresses
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if InetAddress is a site local address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isSiteLocalAddress()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // 10.0.0.0/8
 | |
|     if (addr[0] == 0x0A)
 | |
|       return true;
 | |
| 
 | |
|     // XXX: Suns JDK 1.4.1 (on Linux) seems to have a bug here:
 | |
|     // it says 172.16.0.0 - 172.255.255.255 are site local addresses
 | |
|     // 172.16.0.0/12
 | |
|     if (addr[0] == 0xAC && (addr[1] & 0xF0) == 0x01)
 | |
|       return true;
 | |
| 
 | |
|     // 192.168.0.0/16
 | |
|     if (addr[0] == 0xC0 && addr[1] == 0xA8)
 | |
|       return true;
 | |
| 
 | |
|     // XXX: Do we need to check more addresses here ?
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if InetAddress is a global multicast address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isMCGlobal()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // XXX: This seems to not exist with IPv4 addresses
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility reoutine to check if InetAddress is a node local multicast address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isMCNodeLocal()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // XXX: This seems to not exist with IPv4 addresses
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility reoutine to check if InetAddress is a link local multicast address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isMCLinkLocal()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     if (! isMulticastAddress())
 | |
|       return false;
 | |
| 
 | |
|     return (addr[0] == 0xE0 && addr[1] == 0x00 && addr[2] == 0x00);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility routine to check if InetAddress is a site local multicast address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isMCSiteLocal()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // XXX: This seems to not exist with IPv4 addresses
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Utility reoutine to check if InetAddress is a organization local
 | |
|    * multicast address
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean isMCOrgLocal()
 | |
|   {
 | |
|     // This is the IPv4 implementation.
 | |
|     // Any class derived from InetAddress should override this.
 | |
|     // XXX: This seems to not exist with IPv4 addresses
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the hostname for this address.  This will return the IP address
 | |
|    * as a String if there is no hostname available for this address
 | |
|    *
 | |
|    * @return The hostname for this address
 | |
|    */
 | |
|   public String getHostName()
 | |
|   {
 | |
|     if (hostName == null)
 | |
|       lookup (null, this, false);
 | |
| 
 | |
|     return hostName;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the canonical hostname represented by this InetAddress
 | |
|    * 
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public String getCanonicalHostName()
 | |
|   {
 | |
|     SecurityManager sm = System.getSecurityManager();
 | |
|     if (sm != null)
 | |
|       {
 | |
|         try
 | |
| 	  {
 | |
|             sm.checkConnect (hostName, -1);
 | |
| 	  }
 | |
| 	catch (SecurityException e)
 | |
| 	  {
 | |
| 	    return getHostAddress();
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
|     // Try to find the FDQN now
 | |
|     InetAddress address = new InetAddress (getAddress(), null);
 | |
|     return address.getHostName();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the IP address of this object as a byte array.
 | |
|    *
 | |
|    * @return IP address
 | |
|    */
 | |
|   public byte[] getAddress()
 | |
|   {
 | |
|     // An experiment shows that JDK1.2 returns a different byte array each
 | |
|     // time.  This makes sense, in terms of security.
 | |
|     return (byte[]) addr.clone();
 | |
|   }
 | |
| 
 | |
|   /* Helper function due to a CNI limitation.  */
 | |
|   private static InetAddress[] allocArray (int count)
 | |
|   {
 | |
|     return new InetAddress [count];
 | |
|   }
 | |
| 
 | |
|   /* Helper function due to a CNI limitation.  */
 | |
|   private static SecurityException checkConnect (String hostname)
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     
 | |
|     if (s == null)
 | |
|       return null;
 | |
|     
 | |
|     try
 | |
|       {
 | |
| 	s.checkConnect (hostname, -1);
 | |
| 	return null;
 | |
|       }
 | |
|     catch (SecurityException ex)
 | |
|       {
 | |
| 	return ex;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the IP address of this object as a String.  The address is in
 | |
|    * the dotted octet notation, for example, "127.0.0.1".
 | |
|    *
 | |
|    * @return The IP address of this object in String form
 | |
|    *
 | |
|    * @since 1.0.2
 | |
|    */
 | |
|   public String getHostAddress()
 | |
|   {
 | |
|     StringBuffer sb = new StringBuffer(40);
 | |
| 
 | |
|     int len = addr.length;
 | |
|     int i = 0;
 | |
|     
 | |
|     if (len == 16)
 | |
|       { // An IPv6 address.
 | |
| 	for ( ; ; i += 2)
 | |
| 	  {
 | |
| 	    if (i >= 16)
 | |
| 	      return sb.toString();
 | |
| 	    
 | |
| 	    int x = ((addr [i] & 0xFF) << 8) | (addr [i + 1] & 0xFF);
 | |
| 	    boolean empty = sb.length() == 0;
 | |
| 	    
 | |
| 	    if (empty)
 | |
| 	      {
 | |
| 		if (i == 10 && x == 0xFFFF)
 | |
| 		  { // IPv4-mapped IPv6 address.
 | |
| 		    sb.append (":FFFF:");
 | |
| 		    break;  // Continue as IPv4 address;
 | |
| 		  }
 | |
| 		else if (i == 12)
 | |
| 		  { // IPv4-compatible IPv6 address.
 | |
| 		    sb.append (':');
 | |
| 		    break;  // Continue as IPv4 address.
 | |
| 		  }
 | |
| 		else if (i > 0)
 | |
| 		  sb.append ("::");
 | |
| 	      }
 | |
| 	    else
 | |
| 	      sb.append (':');
 | |
| 	    
 | |
| 	    if (x != 0 || i >= 14)
 | |
| 	      sb.append (Integer.toHexString (x).toUpperCase());
 | |
| 	  }
 | |
|       }
 | |
|     
 | |
|     for ( ; ; )
 | |
|       {
 | |
|         sb.append (addr [i] & 0xff);
 | |
| 	i++;
 | |
| 	
 | |
| 	if (i == len)
 | |
| 	  break;
 | |
| 	
 | |
| 	sb.append ('.');
 | |
|       }
 | |
| 
 | |
|     return sb.toString();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a hash value for this address.  Useful for creating hash
 | |
|    * tables.  Overrides Object.hashCode()
 | |
|    *
 | |
|    * @return A hash value for this address.
 | |
|    */
 | |
|   public int hashCode()
 | |
|   {
 | |
|     // There hashing algorithm is not specified, but a simple experiment
 | |
|     // shows that it is equal to the address, as a 32-bit big-endian integer.
 | |
|     int hash = 0;
 | |
|     int len = addr.length;
 | |
|     int i = len > 4 ? len - 4 : 0;
 | |
| 
 | |
|     for (; i < len; i++)
 | |
|       hash = (hash << 8) | (addr[i] & 0xFF);
 | |
| 
 | |
|     return hash;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Tests this address for equality against another InetAddress.  The two
 | |
|    * addresses are considered equal if they contain the exact same octets.
 | |
|    * This implementation overrides Object.equals()
 | |
|    *
 | |
|    * @param obj The address to test for equality
 | |
|    *
 | |
|    * @return true if the passed in object's address is equal to this one's,
 | |
|    * false otherwise
 | |
|    */
 | |
|   public boolean equals(Object obj)
 | |
|   {
 | |
|     if (! (obj instanceof InetAddress))
 | |
|       return false;
 | |
| 
 | |
|     // "The Java Class Libraries" 2nd edition says "If a machine has
 | |
|     // multiple names instances of InetAddress for different name of
 | |
|     // that same machine are not equal.  This is because they have
 | |
|     // different host names."  This violates the description in the
 | |
|     // JDK 1.2 API documentation.  A little experimentation
 | |
|     // shows that the latter is correct.
 | |
|     byte[] addr2 = ((InetAddress) obj).addr;
 | |
| 
 | |
|     if (addr.length != addr2.length)
 | |
|       return false;
 | |
| 
 | |
|     for (int i = 0; i < addr.length; i++)
 | |
|       if (addr[i] != addr2[i])
 | |
| 	return false;
 | |
| 
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Converts this address to a String.  This string contains the IP in
 | |
|    * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
 | |
|    * to getHostAddress() and overrides Object.toString()
 | |
|    *
 | |
|    * @return This address in String form
 | |
|    */
 | |
|   public String toString()
 | |
|   {
 | |
|     String host;
 | |
|     String address = getHostAddress();
 | |
| 
 | |
|     if (hostName != null)
 | |
|       host = hostName;
 | |
|     else
 | |
|       host = address;
 | |
| 
 | |
|     return host + "/" + address;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns an InetAddress object given the raw IP address.
 | |
|    *
 | |
|    * The argument is in network byte order: the highest order byte of the
 | |
|    * address is in getAddress()[0].
 | |
|    *
 | |
|    * @param addr The IP address to create the InetAddress object from
 | |
|    *
 | |
|    * @exception UnknownHostException If IP address has illegal length
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public static InetAddress getByAddress(byte[] addr)
 | |
|     throws UnknownHostException
 | |
|   {
 | |
|     return getByAddress(null, addr);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates an InetAddress based on the provided host name and IP address.
 | |
|    * No name service is checked for the validity of the address.
 | |
|    *
 | |
|    * @param host The hostname of the InetAddress object to create
 | |
|    * @param addr The IP address to create the InetAddress object from
 | |
|    *
 | |
|    * @exception UnknownHostException If IP address is of illegal length
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public static InetAddress getByAddress(String host, byte[] addr)
 | |
|     throws UnknownHostException
 | |
|   {
 | |
|     if (addr.length == 4)
 | |
|       return new Inet4Address(addr, host);
 | |
| 
 | |
|     if (addr.length == 16)
 | |
|       return new Inet6Address(addr, host);
 | |
| 
 | |
|     throw new UnknownHostException("IP address has illegal length");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * If host is a valid numeric IP address, return the numeric address.
 | |
|    * Otherwise, return null.
 | |
|    */
 | |
|   private static native byte[] aton (String host);
 | |
| 
 | |
|   private static native InetAddress[] lookup (String hostname,
 | |
| 		                              InetAddress addr, boolean all);
 | |
| 
 | |
|   private static native int getFamily (byte[] address);
 | |
| 
 | |
|   /**
 | |
|    * Returns an InetAddress object representing the IP address of the given
 | |
|    * hostname.  This name can be either a hostname such as "www.urbanophile.com"
 | |
|    * or an IP address in dotted decimal format such as "127.0.0.1".  If the
 | |
|    * hostname is null or "", the hostname of the local machine is supplied by
 | |
|    * default.  This method is equivalent to returning the first element in
 | |
|    * the InetAddress array returned from GetAllByName.
 | |
|    *
 | |
|    * @param hostname The name of the desired host, or null for the local machine.
 | |
|    *
 | |
|    * @return The address of the host as an InetAddress object.
 | |
|    *
 | |
|    * @exception UnknownHostException If no IP address for the host could
 | |
|    * be found
 | |
|    * @exception SecurityException If a security manager exists and its
 | |
|    * checkConnect method doesn't allow the operation
 | |
|    */
 | |
|   public static InetAddress getByName(String hostname)
 | |
|     throws UnknownHostException
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     if (s != null)
 | |
|       s.checkConnect(hostname, -1);
 | |
| 
 | |
|     // Default to current host if necessary
 | |
|     if (hostname == null || hostname.length() == 0)
 | |
|       return getLocalHost();
 | |
| 
 | |
|     // Assume that the host string is an IP address
 | |
|     byte[] address = aton(hostname);
 | |
|     if (address != null)
 | |
|       {
 | |
|         if (address.length == 4)
 | |
|           return new Inet4Address (address, null);
 | |
|         else if (address.length == 16)
 | |
|           {
 | |
| 	    if ((address [10] == 0xFF) && (address [11] == 0xFF))
 | |
| 	      {
 | |
| 		byte[] ip4addr = new byte [4];
 | |
| 		ip4addr [0] = address [12];
 | |
| 		ip4addr [1] = address [13];
 | |
| 		ip4addr [2] = address [14];
 | |
| 		ip4addr [3] = address [15];
 | |
| 		return new Inet4Address (ip4addr, null);
 | |
| 	      }
 | |
|             return new Inet6Address (address, null);
 | |
| 	  }
 | |
| 	else
 | |
|           throw new UnknownHostException ("Address has invalid length");
 | |
|       }
 | |
| 
 | |
|     // Try to resolve the host by DNS
 | |
|     InetAddress[] addresses = getAllByName(hostname);
 | |
|     return addresses[0];
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns an array of InetAddress objects representing all the host/ip
 | |
|    * addresses of a given host, given the host's name.  This name can be
 | |
|    * either a hostname such as "www.urbanophile.com" or an IP address in
 | |
|    * dotted decimal format such as "127.0.0.1".  If the value is null, the
 | |
|    * hostname of the local machine is supplied by default.
 | |
|    *
 | |
|    * @param hostname The name of the desired host, or null for the
 | |
|    * local machine.
 | |
|    *
 | |
|    * @return All addresses of the host as an array of InetAddress objects.
 | |
|    *
 | |
|    * @exception UnknownHostException If no IP address for the host could
 | |
|    * be found
 | |
|    * @exception SecurityException If a security manager exists and its
 | |
|    * checkConnect method doesn't allow the operation
 | |
|    */
 | |
|   public static InetAddress[] getAllByName(String hostname)
 | |
|     throws UnknownHostException
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     if (s != null)
 | |
|       s.checkConnect(hostname, -1);
 | |
| 
 | |
|     // Check if hostname is an IP address
 | |
|     byte[] address = aton (hostname);
 | |
|     if (address != null)
 | |
|       {
 | |
| 	InetAddress[] result = new InetAddress [1];
 | |
| 	result [0] = new InetAddress (address, null);
 | |
| 	return result;
 | |
|       }
 | |
| 
 | |
|     // Try to resolve the hostname by DNS
 | |
|     return lookup (hostname, null, true);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This native method looks up the hostname of the local machine
 | |
|    * we are on.  If the actual hostname cannot be determined, then the
 | |
|    * value "localhost" will be used.  This native method wrappers the
 | |
|    * "gethostname" function.
 | |
|    *
 | |
|    * @return The local hostname.
 | |
|    */
 | |
|   private static native String getLocalHostname();
 | |
| 
 | |
|   /**
 | |
|    * Returns an InetAddress object representing the address of the current
 | |
|    * host.
 | |
|    *
 | |
|    * @return The local host's address
 | |
|    *
 | |
|    * @exception UnknownHostException If no IP address for the host could
 | |
|    * be found
 | |
|    */
 | |
|   public static InetAddress getLocalHost() throws UnknownHostException
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     
 | |
|     // Experimentation shows that JDK1.2 does cache the result.
 | |
|     // However, if there is a security manager, and the cached result
 | |
|     // is other than "localhost", we need to check again.
 | |
|     if (localhost == null
 | |
| 	|| (s != null && localhost.addr != localhostAddress))
 | |
|       getLocalHost (s);
 | |
|     
 | |
|     return localhost;
 | |
|   }
 | |
| 
 | |
|   private static synchronized void getLocalHost (SecurityManager s)
 | |
|     throws UnknownHostException
 | |
|   {
 | |
|     // Check the localhost cache again, now that we've synchronized.
 | |
|     if (s == null && localhost != null)
 | |
|       return;
 | |
|     
 | |
|     String hostname = getLocalHostname();
 | |
|     
 | |
|     if (s != null)
 | |
|       {
 | |
| 	// "The Java Class Libraries" suggests that if the security
 | |
| 	// manager disallows getting the local host name, then
 | |
| 	// we use the loopback host.
 | |
| 	// However, the JDK 1.2 API claims to throw SecurityException,
 | |
| 	// which seems to suggest SecurityException is *not* caught.
 | |
| 	// In this case, experimentation shows that former is correct.
 | |
| 	try
 | |
| 	  {
 | |
| 	    // This is wrong, if the name returned from getLocalHostname()
 | |
| 	    // is not a fully qualified name.  FIXME.
 | |
| 	    s.checkConnect (hostname, -1);
 | |
| 	  }
 | |
| 	catch (SecurityException ex)
 | |
| 	  {
 | |
| 	    hostname = null;
 | |
| 	  }
 | |
|       }
 | |
|     
 | |
|     if (hostname != null)
 | |
|       {
 | |
| 	try
 | |
| 	  {
 | |
| 	    localhost = new InetAddress (null, null);
 | |
| 	    lookup (hostname, localhost, false);
 | |
| 	  }
 | |
| 	catch (Exception ex)
 | |
| 	  {
 | |
| 	  }
 | |
|       }
 | |
|     
 | |
|     if (localhost == null)
 | |
|       localhost = new InetAddress (localhostAddress, "localhost");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Needed for serialization
 | |
|    */
 | |
|   private void readResolve() throws ObjectStreamException
 | |
|   {
 | |
|     // FIXME: implement this
 | |
|   }
 | |
| 
 | |
|   private void readObject(ObjectInputStream ois)
 | |
|     throws IOException, ClassNotFoundException
 | |
|   {
 | |
|     ois.defaultReadObject();
 | |
|     addr = new byte[4];
 | |
|     addr[3] = (byte) address;
 | |
| 
 | |
|     for (int i = 2; i >= 0; --i)
 | |
|       addr[i] = (byte) (address >>= 8);
 | |
| 
 | |
|     // Ignore family from serialized data.  Since the saved address is 32 bits
 | |
|     // the deserialized object will have an IPv4 address i.e. AF_INET family.
 | |
|     // FIXME: An alternative is to call the aton method on the deserialized
 | |
|     // hostname to get a new address.  The Serialized Form doc is silent
 | |
|     // on how these fields are used.
 | |
|     family = getFamily (addr);
 | |
|   }
 | |
| 
 | |
|   private void writeObject(ObjectOutputStream oos) throws IOException
 | |
|   {
 | |
|     // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
 | |
|     // or a 16 byte IPv6 address.
 | |
|     int len = addr.length;
 | |
|     int i = len - 4;
 | |
| 
 | |
|     for (; i < len; i++)
 | |
|       address = address << 8 | (((int) addr[i]) & 0xFF);
 | |
| 
 | |
|     oos.defaultWriteObject();
 | |
|   }
 | |
| }
 |