OSDN Git Service

2006-09-20 Gary Benson <gbenson@redhat.com>
authorgary <gary@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 20 Sep 2006 07:55:26 +0000 (07:55 +0000)
committergary <gary@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 20 Sep 2006 07:55:26 +0000 (07:55 +0000)
* java/net/InetAddress.java: Mostly merged with Classpath.
* java/net/VMInetAddress.java: New file.
* sources.am, Makefile.in: Rebuilt.

* java/net/natVMNetworkInterfacePosix.cc
(getInterfaces): Create InetAddress objects using
InetAddress.getByAddress.
* gnu/java/net/natPlainSocketImplPosix.cc
(accept, getOption): Likewise.
* gnu/java/net/natPlainDatagramSocketImplPosix.cc
(peekData, receive, getLocalAddress): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117075 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/Makefile.in
libjava/gnu/java/net/natPlainDatagramSocketImplPosix.cc
libjava/gnu/java/net/natPlainSocketImplPosix.cc
libjava/java/net/InetAddress.java
libjava/java/net/VMInetAddress.java [new file with mode: 0644]
libjava/java/net/natVMNetworkInterfacePosix.cc
libjava/sources.am

index 222fc79..0afedde 100644 (file)
@@ -1,3 +1,17 @@
+2006-09-20  Gary Benson  <gbenson@redhat.com>
+
+       * java/net/InetAddress.java: Mostly merged with Classpath.
+       * java/net/VMInetAddress.java: New file.
+       * sources.am, Makefile.in: Rebuilt.
+
+       * java/net/natVMNetworkInterfacePosix.cc
+       (getInterfaces): Create InetAddress objects using
+       InetAddress.getByAddress.
+       * gnu/java/net/natPlainSocketImplPosix.cc
+       (accept, getOption): Likewise.
+       * gnu/java/net/natPlainDatagramSocketImplPosix.cc
+       (peekData, receive, getLocalAddress): Likewise.
+
 2006-09-19  Keith Seitz  <keiths@redhat.com>
 
        * testsuite/libjava.jvmti/jvmti.exp: New file.
index cffe726..e81560c 100644 (file)
@@ -4136,6 +4136,7 @@ classpath/java/net/NoRouteToHostException.java \
 classpath/java/net/PasswordAuthentication.java \
 classpath/java/net/PortUnreachableException.java \
 classpath/java/net/ProtocolException.java \
+classpath/java/net/ResolverCache.java \
 classpath/java/net/ServerSocket.java \
 classpath/java/net/Socket.java \
 classpath/java/net/SocketAddress.java \
@@ -4156,6 +4157,7 @@ classpath/java/net/URLStreamHandler.java \
 classpath/java/net/URLStreamHandlerFactory.java \
 classpath/java/net/UnknownHostException.java \
 classpath/java/net/UnknownServiceException.java \
+java/net/VMInetAddress.java \
 java/net/VMNetworkInterface.java \
 java/net/VMURLConnection.java
 
index 0a744c5..f7ffaa8 100644 (file)
@@ -290,7 +290,7 @@ gnu::java::net::PlainDatagramSocketImpl::peekData (::java::net::DatagramPacket *
   else
     throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
 
-  p->setAddress (new ::java::net::InetAddress (raddr, NULL));
+  p->setAddress (::java::net::InetAddress::getByAddress (raddr));
   p->setPort (rport);
   p->length = (int) retlen;
   return rport;
@@ -430,7 +430,7 @@ gnu::java::net::PlainDatagramSocketImpl::receive (::java::net::DatagramPacket *p
   else
     throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
 
-  p->setAddress (new ::java::net::InetAddress (raddr, NULL));
+  p->setAddress (::java::net::InetAddress::getByAddress (raddr));
   p->setPort (rport);
   p->length = (jint) retlen;
   return;
@@ -564,7 +564,7 @@ getLocalAddress (int native_fd)
   else
     throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
 
-  return new ::java::net::InetAddress (laddr, NULL);
+  return ::java::net::InetAddress::getByAddress (laddr);
 }
 
 void
index 2dfc38c..e4572fa 100644 (file)
@@ -308,7 +308,7 @@ gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s)
 
   s->native_fd = new_socket;
   s->localport = localport;
-  s->address = new ::java::net::InetAddress (raddr, NULL);
+  s->address = ::java::net::InetAddress::getByAddress (raddr);
   s->port = rport;
   return;
 
@@ -808,7 +808,7 @@ gnu::java::net::PlainSocketImpl::getOption (jint optID)
           else
             throw new ::java::net::SocketException
               (JvNewStringUTF ("invalid family"));
-          localAddress = new ::java::net::InetAddress (laddr, NULL);
+          localAddress = ::java::net::InetAddress::getByAddress (laddr);
         }
 
       return localAddress;
index 995e897..bef9a6e 100644 (file)
@@ -1,5 +1,6 @@
 /* InetAddress.java -- Class to model an Internet address
-   Copyright (C) 1998, 1999, 2002, 2004, 2005  Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -38,8 +39,6 @@ exception statement from your version. */
 
 package java.net;
 
-import gnu.classpath.Configuration;
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -58,6 +57,7 @@ import java.io.Serializable;
  *
  * @author Aaron M. Renn (arenn@urbanophile.com)
  * @author Per Bothner
+ * @author Gary Benson (gbenson@redhat.com)
  *
  * @specnote This class is not final since JK 1.4
  */
@@ -69,23 +69,44 @@ public class InetAddress implements Serializable
    * Dummy InetAddress, used to bind socket to any (all) network interfaces.
    */
   static InetAddress ANY_IF;
-    
-  private static final byte[] loopbackAddress = { 127, 0, 0, 1 };
-
-  private static final InetAddress loopback 
-    = new Inet4Address(loopbackAddress, "localhost");
-
-  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 Inet4Address(zeros, "0.0.0.0");
+    byte[] addr;
+    try
+      {
+       addr = VMInetAddress.lookupInaddrAny();
+      }
+    catch (UnknownHostException e)
+      {
+       // Make one up and hope it works.
+       addr = new byte[] {0, 0, 0, 0};
+      }
+    try
+      {
+       ANY_IF = getByAddress(addr);
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
+    ANY_IF.hostName = ANY_IF.getHostName();
   }
+  
+  /**
+   * Stores static localhost address object.
+   */
+  static InetAddress LOCALHOST;
+  static
+  {
+    try
+      {
+       LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1});
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
+  }    
 
   /**
    * The Serialized Form specifies that an int 'address' is saved/restored.
@@ -105,29 +126,28 @@ public class InetAddress implements Serializable
   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.
+   * Needed for serialization.
    */
-  int family;
+  private int family;
 
   /**
-   * Initializes this object's addr instance variable from the passed in
-   * byte array.  Note that this constructor is protected and is called
-   * only by static methods in this class.
+   * Constructor.  Prior to the introduction of IPv6 support in 1.4,
+   * methods such as InetAddress.getByName() would return InetAddress
+   * objects.  From 1.4 such methods returned either Inet4Address or
+   * Inet6Address objects, but for compatibility Inet4Address objects
+   * are serialized as InetAddresses.  As such, there are only two
+   * places where it is appropriate to invoke this constructor: within
+   * subclasses constructors and within Inet4Address.writeReplace().
    *
    * @param ipaddr The IP number of this address as an array of bytes
    * @param hostname The hostname of this IP address.
+   * @param family The address family of this IP address.
    */
-  InetAddress(byte[] ipaddr, String hostname)
+  InetAddress(byte[] ipaddr, String hostname, int family)
   {
     addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
     hostName = hostname;
-    
-    if (ipaddr != null)
-      family = getFamily(ipaddr);
+    this.family = family;
   }
 
   /**
@@ -135,154 +155,263 @@ public class InetAddress implements Serializable
    * An address is multicast if the high four bits are "1110".  These are
    * also known as "Class D" addresses.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMulticastAddress();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if the InetAddress in a wildcard address
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @since 1.4
    */
   public boolean isAnyLocalAddress()
   {
-    // This is the IPv4 implementation.
-    // Any class derived from InetAddress should override this.
-    return equals(ANY_IF);
+    // This is inefficient, but certain methods on Win32 create
+    // InetAddress objects using "new InetAddress" rather than
+    // "InetAddress.getByAddress" so we provide a method body.
+    // This code is never executed on Posix systems.
+    try
+      {
+       return getByAddress(hostName, addr).isAnyLocalAddress();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if the InetAddress is a loopback address
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @since 1.4
    */
   public boolean isLoopbackAddress()
   {
-    // This is the IPv4 implementation.
-    // Any class derived from InetAddress should override this.
-    return (addr[0] & 0xff) == 0x7f;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isLoopbackAddress();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a link local address
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isLinkLocalAddress();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a site local address
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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] & 0xff) == 0x0a)
-      return true;
-
-    // 172.16.0.0/12
-    if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
-      return true;
-
-    // 192.168.0.0/16
-    if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
-      return true;
-
-    // XXX: Do we need to check more addresses here ?
-    return false;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isSiteLocalAddress();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a global multicast address
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMCGlobal();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a node local multicast address.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMCNodeLocal();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a link local multicast address.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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] & 0xff) == 0xe0
-           && (addr[1] & 0xff)  == 0x00
-           && (addr[2] & 0xff)  == 0x00);
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMCLinkLocal();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a site local multicast address.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMCSiteLocal();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
    * Utility routine to check if InetAddress is a organization local
    * multicast address.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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;
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).isMCOrgLocal();
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
   }
 
   /**
@@ -293,28 +422,42 @@ public class InetAddress implements Serializable
    */
   public String getHostName()
   {
-    if (hostName != null)
-      return hostName;
+    if (hostName == null)
+      hostName = getCanonicalHostName();
 
-    // Lookup hostname and set field.
-    lookup (null, this, false);
-    
     return hostName;
   }
 
   /**
    * Returns the canonical hostname represented by this InetAddress
+   */
+  String internalGetCanonicalHostName()
+  {
+    try
+      {
+       return ResolverCache.getHostByAddr(addr);
+      }
+    catch (UnknownHostException e)
+      {
+       return getHostAddress();
+      }
+  }
+
+  /**
+   * Returns the canonical hostname represented by this InetAddress
    * 
    * @since 1.4
    */
   public String getCanonicalHostName()
   {
+    String hostname = internalGetCanonicalHostName();
+
     SecurityManager sm = System.getSecurityManager();
     if (sm != null)
       {
         try
          {
-            sm.checkConnect(hostName, -1);
+            sm.checkConnect(hostname, -1);
          }
        catch (SecurityException e)
          {
@@ -322,16 +465,7 @@ public class InetAddress implements Serializable
          }
       }
 
-    // Try to find the FDQN now
-    InetAddress address;
-    byte[] ipaddr = getAddress();
-
-    if (ipaddr.length == 16)
-      address = new Inet6Address(getAddress(), null);
-    else
-      address = new Inet4Address(getAddress(), null);
-
-    return address.getHostName();
+    return hostname;
   }
 
   /**
@@ -346,91 +480,32 @@ public class InetAddress implements Serializable
     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".
+   * Returns the IP address of this object as a String.
    *
+   * <p>This method cannot be abstract for backward compatibility reasons. By
+   * default it always throws {@link UnsupportedOperationException} unless
+   * overridden.</p>
+   * 
    * @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());
-         }
+    // This method is masked on Posix systems, where all InetAddress
+    // objects are created using InetAddress.getByAddress() which 
+    // returns either Inet4Address or Inet6Address objects.  Certain
+    // native methods on Win32 use "new InetAddress" in which case
+    // this method will be visible.
+    try
+      {
+       return getByAddress(hostName, addr).getHostAddress();
       }
-    
-    for ( ; ; )
+    catch (UnknownHostException e)
       {
-        sb.append(addr[i] & 0xff);
-        i++;
-       
-        if (i == len)
-          break;
-       
-        sb.append('.');
+       throw new RuntimeException("should never happen", e);
       }
-
-    return sb.toString();
   }
 
   /**
@@ -555,33 +630,32 @@ public class InetAddress implements Serializable
   }
 
   /**
-   * If hostname is a valid numeric IP address, return the numeric address.
-   * Otherwise, return null.
-   *
-   * @param hostname the name of the host
-   */
-  private static native byte[] aton(String hostname);
-
-  /**
-   * Looks up all addresses of a given host.
+   * Returns an InetAddress object representing the IP address of
+   * the given literal IP address in dotted decimal format such as
+   * "127.0.0.1".  This is used by SocketPermission.setHostPort()
+   * to parse literal IP addresses without performing a DNS lookup.
    *
-   * @param hostname the host to lookup
-   * @param ipaddr the IP address to lookup
-   * @param all return all known addresses for one host
+   * @param literal The literal IP address to create the InetAddress
+   * object from
    *
-   * @return an array with all found addresses
+   * @return The address of the host as an InetAddress object, or
+   * null if the IP address is invalid.
    */
-  private static native InetAddress[] lookup (String hostname,
-                                             InetAddress ipaddr, boolean all);
-
-  /**
-   * Returns tha family type of an IP address.
-   *
-   * @param addr the IP address
-   *
-   * @return the family
-   */
-  private static native int getFamily (byte[] ipaddr);
+  static InetAddress getByLiteral(String literal)
+  {
+    byte[] address = VMInetAddress.aton(literal);
+    if (address == null)
+      return null;
+    
+    try
+      {
+       return getByAddress(address);
+      }
+    catch (UnknownHostException e)
+      {
+       throw new RuntimeException("should never happen", e);
+      }
+  }
 
   /**
    * Returns an InetAddress object representing the IP address of the given
@@ -604,25 +678,8 @@ public class InetAddress implements Serializable
   public static InetAddress getByName(String hostname)
     throws UnknownHostException
   {
-    // If null or the empty string is supplied, the loopback address
-    // is returned.
-    if (hostname == null || hostname.length() == 0)
-      return loopback;
-
-    // Assume that the host string is an IP address
-    byte[] address = aton(hostname);
-    if (address != null)
-      return getByAddress(address);
-
-    // Perform security check before resolving
-    SecurityManager s = System.getSecurityManager();
-    if (s != null)
-      s.checkConnect(hostname, -1);
-
-    // Try to resolve the host by DNS
-    InetAddress result = new InetAddress(null, null);
-    lookup (hostname, result, false);
-    return result;
+    InetAddress[] addresses = getAllByName(hostname);
+    return addresses[0];
   }
 
   /**
@@ -648,31 +705,29 @@ public class InetAddress implements Serializable
     // If null or the empty string is supplied, the loopback address
     // is returned.
     if (hostname == null || hostname.length() == 0)
-      return new InetAddress[] {loopback};
+      return new InetAddress[] {LOCALHOST};
 
     // Check if hostname is an IP address
-    byte[] address = aton (hostname);
+    InetAddress address = getByLiteral(hostname);
     if (address != null)
-      return new InetAddress[] {getByAddress(address)};
+      return new InetAddress[] {address};
 
     // Perform security check before resolving
-    SecurityManager s = System.getSecurityManager();
-    if (s != null)
-      s.checkConnect(hostname, -1);
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null)
+      sm.checkConnect(hostname, -1);
 
-    // Try to resolve the hostname by DNS
-    return lookup (hostname, null, true);
-  }
+    // Resolve the hostname
+    byte[][] iplist = ResolverCache.getHostByName(hostname);
+    if (iplist.length == 0)
+      throw new UnknownHostException(hostname);
 
-  /**
-   * 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();
+    InetAddress[] addresses = new InetAddress[iplist.length];
+    for (int i = 0; i < iplist.length; i++)
+      addresses[i] = getByAddress(hostname, iplist[i]);
+
+    return addresses;
+  }
 
   /**
    * Returns an InetAddress object representing the address of the current
@@ -685,62 +740,24 @@ public class InetAddress implements Serializable
    */
   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.isLoopbackAddress()))
-      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 (hostname == null || hostname.length() == 0)
-      throw new UnknownHostException();
-
+    String hostname = VMInetAddress.getLocalHostname();
     try
       {
-       // "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.
-       if (s != null)
-         {
-           // This is wrong, if the name returned from getLocalHostname()
-           // is not a fully qualified name.  FIXME.
-           s.checkConnect (hostname, -1);
-         }
-
-       localhost = new InetAddress (null, null);
-       lookup (hostname, localhost, false);
+       return getByName(hostname);
       }
-    catch (Exception ex)
+    catch (SecurityException e)
       {
-       UnknownHostException failure = new UnknownHostException(hostname);
-       failure.initCause(ex);
-       throw failure;
+       return LOCALHOST;
       }
   }
 
   /**
-   * Needed for serialization
+   * Inet4Address objects are serialized as InetAddress objects.
+   * This deserializes them back into Inet4Address objects.
    */
-  private void readResolve() throws ObjectStreamException
+  private Object readResolve() throws ObjectStreamException
   {
-    // FIXME: implement this
+    return new Inet4Address(addr, hostName);
   }
 
   private void readObject(ObjectInputStream ois)
@@ -752,13 +769,6 @@ public class InetAddress implements Serializable
 
     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
@@ -769,8 +779,35 @@ public class InetAddress implements Serializable
     int i = len - 4;
 
     for (; i < len; i++)
-      address = address << 8 | (((int) addr[i]) & 0xFF);
+      address = address << 8 | (addr[i] & 0xff);
 
     oos.defaultWriteObject();
   }
+
+  // The native methods remain here for now;
+  // methods in VMInetAddress map onto them.
+  static native byte[] aton(String hostname);
+  static native InetAddress[] lookup (String hostname,
+                                     InetAddress ipaddr, boolean all);
+  static native int getFamily (byte[] ipaddr);
+  static native String getLocalHostname();
+
+  // Some soon-to-be-removed native code synchronizes on this.
+  static InetAddress loopbackAddress = LOCALHOST;
+  
+  // Some soon-to-be-removed code uses this old and broken method.
+  InetAddress(byte[] ipaddr, String hostname)
+  {
+    addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
+    hostName = hostname;
+
+    if (ipaddr != null)
+      family = getFamily(ipaddr);
+  }
+
+  // Some soon-to-be-removed native code uses this old method.
+  private static InetAddress[] allocArray (int count)
+  {
+    return new InetAddress [count];
+  }  
 }
diff --git a/libjava/java/net/VMInetAddress.java b/libjava/java/net/VMInetAddress.java
new file mode 100644 (file)
index 0000000..b10cf25
--- /dev/null
@@ -0,0 +1,117 @@
+/* VMInetAddress.java -- Class to model an Internet address
+   Copyright (C) 2005  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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.Serializable;
+
+class VMInetAddress implements Serializable
+{
+  static
+  {
+    if (Configuration.INIT_LOAD_LIBRARY)
+      System.loadLibrary("javanet");
+  }
+
+  /**
+   * This 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.
+   */
+  public static String getLocalHostname()
+  {
+    return InetAddress.getLocalHostname();
+  }
+
+  /**
+   * Returns the value of the special address INADDR_ANY
+   */
+  public static byte[] lookupInaddrAny() throws UnknownHostException
+  {
+    return new byte[] {0, 0, 0, 0};
+  }
+
+  /**
+   * This method returns the hostname for a given IP address.  It will
+   * throw an UnknownHostException if the hostname cannot be determined.
+   *
+   * @param ip The IP address as a byte array
+   *
+   * @return The hostname
+   *
+   * @exception UnknownHostException If the reverse lookup fails
+   */
+  public static String getHostByAddr(byte[] ip) throws UnknownHostException
+  {
+    InetAddress addr = InetAddress.getByAddress(ip);
+    InetAddress.lookup(null, addr, false);
+    return addr.getHostName();
+  }
+
+  /**
+   * Returns a list of all IP addresses for a given hostname.  Will throw
+   * an UnknownHostException if the hostname cannot be resolved.
+   */
+  public static byte[][] getHostByName(String hostname)
+    throws UnknownHostException
+  {
+    InetAddress[] iaddrs = InetAddress.lookup(hostname, null, true);
+    byte[][] addrs = new byte[iaddrs.length][];
+    for (int i = 0; i < iaddrs.length; i++)
+      addrs[i] = iaddrs[i].getAddress();
+    return addrs;
+  }
+
+  /**
+   * Return the IP address represented by a literal address.
+   * Will return null if the literal address is not valid.
+   *
+   * @param address the name of the host
+   *
+   * @return The IP address as a byte array
+   */
+  public static byte[] aton(String address)
+  {
+    return InetAddress.aton(address);
+  }
+}
index 8238d9c..bfb11d2 100644 (file)
@@ -40,7 +40,7 @@ details.  */
 
 #include <gcj/cni.h>
 #include <jvm.h>
-#include <java/net/Inet4Address.h>
+#include <java/net/InetAddress.h>
 #include <java/net/NetworkInterface.h>
 #include <java/net/SocketException.h>
 #include <java/net/VMNetworkInterface.h>
@@ -148,8 +148,7 @@ java::net::VMNetworkInterface::getInterfaces ()
       jbyteArray baddr = JvNewByteArray (len);
       memcpy (elements (baddr), &(sa.sin_addr), len);
       jstring if_name = JvNewStringLatin1 (if_record->ifr_name);
-      Inet4Address* address =
-        new java::net::Inet4Address (baddr, JvNewStringLatin1 (""));
+      InetAddress* address = java::net::InetAddress::getByAddress (baddr);
       ht->add (new NetworkInterface (if_name, address));
       if_record++;
     }
index 56502e2..d7b18f4 100644 (file)
@@ -5223,6 +5223,7 @@ classpath/java/net/NoRouteToHostException.java \
 classpath/java/net/PasswordAuthentication.java \
 classpath/java/net/PortUnreachableException.java \
 classpath/java/net/ProtocolException.java \
+classpath/java/net/ResolverCache.java \
 classpath/java/net/ServerSocket.java \
 classpath/java/net/Socket.java \
 classpath/java/net/SocketAddress.java \
@@ -5243,6 +5244,7 @@ classpath/java/net/URLStreamHandler.java \
 classpath/java/net/URLStreamHandlerFactory.java \
 classpath/java/net/UnknownHostException.java \
 classpath/java/net/UnknownServiceException.java \
+java/net/VMInetAddress.java \
 java/net/VMNetworkInterface.java \
 java/net/VMURLConnection.java