/**
   * 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 loopback address.
   * @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 {
    // If null or the empty string is supplied, the loopback address
    // is returned. Note that this is permitted without a security check.
    if (hostname == null || hostname.length() == 0) return loopback;

    SecurityManager s = System.getSecurityManager();
    if (s != null) s.checkConnect(hostname, -1);

    // 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 result = new InetAddress(null, null);
    lookup(hostname, result, false);
    return result;
  }
  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 && hostname.length() != 0) {
      try {
        localhost = new InetAddress(null, null);
        lookup(hostname, localhost, false);
      } catch (Exception ex) {
      }
    } else throw new UnknownHostException();

    if (localhost == null) localhost = new InetAddress(loopbackAddress, "localhost");
  }
  /**
   * 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) return hostName;

    // Lookup hostname and set field.
    lookup(null, this, false);

    return hostName;
  }