Address.java :  » Net » dnsjava » org » xbill » DNS » Java Open Source

Java Open Source » Net » dnsjava 
dnsjava » org » xbill » DNS » Address.java
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)

package org.xbill.DNS;

import java.net.*;
import java.net.Inet6Address;
import java.util.*;

/**
 * Routines dealing with IP addresses.  Includes functions similar to
 * those in the java.net.InetAddress class.
 *
 * @author Brian Wellington
 */

public final class Address {

public static final int IPv4 = 1;
public static final int IPv6 = 2;

private
Address() {}

private static byte []
parseV4(String s) {
  int numDigits;
  int currentOctet;
  byte [] values = new byte[4];
  int currentValue;
  int length = s.length();

  currentOctet = 0;
  currentValue = 0;
  numDigits = 0;
  for (int i = 0; i < length; i++) {
    char c = s.charAt(i);
    if (c >= '0' && c <= '9') {
      /* Can't have more than 3 digits per octet. */
      if (numDigits == 3)
        return null;
      /* Octets shouldn't start with 0, unless they are 0. */
      if (numDigits > 0 && currentValue == 0)
        return null;
      numDigits++;
      currentValue *= 10;
      currentValue += (c - '0');
      /* 255 is the maximum value for an octet. */
      if (currentValue > 255)
        return null;
    } else if (c == '.') {
      /* Can't have more than 3 dots. */
      if (currentOctet == 3)
        return null;
      /* Two consecutive dots are bad. */
      if (numDigits == 0)
        return null;
      values[currentOctet++] = (byte) currentValue;
      currentValue = 0;
      numDigits = 0;
    } else
      return null;
  }
  /* Must have 4 octets. */
  if (currentOctet != 3)
    return null;
  /* The fourth octet can't be empty. */
  if (numDigits == 0)
    return null;
  values[currentOctet] = (byte) currentValue;
  return values;
}

private static byte []
parseV6(String s) {
  boolean parsev4 = false;
  List l = new ArrayList();
  int range = -1;
  byte [] data = new byte[16];

  String [] tokens = s.split(":", -1);

  int first = 0;
  int last = tokens.length - 1;

  if (tokens[0].length() == 0) {
    // If the first two tokens are empty, it means the string
    // started with ::, which is fine.  If only the first is
    // empty, the string started with :, which is bad.
    if (last - first > 0 && tokens[1].length() == 0)
      first++;
    else
      return null;
  }

  if (tokens[last].length() == 0) {
    // If the last two tokens are empty, it means the string
    // ended with ::, which is fine.  If only the last is
    // empty, the string ended with :, which is bad.
    if (last - first > 0 && tokens[last - 1].length() == 0)
      last--;
    else
      return null;
  }

  if (last - first + 1 > 8)
    return null;

  int i, j;
  for (i = first, j = 0; i <= last; i++) {
    if (tokens[i].length() == 0) {
      if (range >= 0)
        return null;
      range = j;
      continue;
    }

    if (tokens[i].indexOf('.') >= 0) {
      parsev4 = true;
      // An IPv4 address must be the last component
      if (i < last)
        return null;
      // There can't have been more than 6 components.
      if (i > 6)
        return null;
      byte [] v4addr = Address.toByteArray(tokens[i], IPv4);
      if (v4addr == null)
        return null;
      for (int k = 0; k < 4; k++)
        data[j++] = v4addr[k];
      break;
    }

    try {
      for (int k = 0; k < tokens[i].length(); k++) {
        char c = tokens[i].charAt(k);
        if (Character.digit(c, 16) < 0)
          return null;
      }
      int x = Integer.parseInt(tokens[i], 16);
      if (x > 0xFFFF || x < 0)
        return null;
      data[j++] = (byte)(x >>> 8);
      data[j++] = (byte)(x & 0xFF);
    }
    catch (NumberFormatException e) {
      return null;
    }
  }

  if (j < 16 && range < 0)
    return null;

  if (range >= 0) {
    int empty = 16 - j;
    System.arraycopy(data, range, data, range + empty, j - range);
    for (i = range; i < range + empty; i++)
      data[i] = 0;
  }

  return data;
}

/**
 * Convert a string containing an IP address to an array of 4 or 16 integers.
 * @param s The address, in text format.
 * @param family The address family.
 * @return The address
 */
public static int []
toArray(String s, int family) {
  byte [] byteArray = toByteArray(s, family);
  if (byteArray == null)
    return null;
  int [] intArray = new int[byteArray.length];
  for (int i = 0; i < byteArray.length; i++)
    intArray[i] = byteArray[i] & 0xFF;
  return intArray;
}

/**
 * Convert a string containing an IPv4 address to an array of 4 integers.
 * @param s The address, in text format.
 * @return The address
 */
public static int []
toArray(String s) {
  return toArray(s, IPv4);
}

/**
 * Convert a string containing an IP address to an array of 4 or 16 bytes.
 * @param s The address, in text format.
 * @param family The address family.
 * @return The address
 */
public static byte []
toByteArray(String s, int family) {
  if (family == IPv4)
    return parseV4(s);
  else if (family == IPv6)
    return parseV6(s);
  else
    throw new IllegalArgumentException("unknown address family");
}

/**
 * Determines if a string contains a valid IP address.
 * @param s The string
 * @return Whether the string contains a valid IP address
 */
public static boolean
isDottedQuad(String s) {
  byte [] address = Address.toByteArray(s, IPv4);
  return (address != null);
}

/**
 * Converts a byte array containing an IPv4 address into a dotted quad string.
 * @param addr The array
 * @return The string representation
 */
public static String
toDottedQuad(byte [] addr) {
  return ((addr[0] & 0xFF) + "." + (addr[1] & 0xFF) + "." +
    (addr[2] & 0xFF) + "." + (addr[3] & 0xFF));
}

/**
 * Converts an int array containing an IPv4 address into a dotted quad string.
 * @param addr The array
 * @return The string representation
 */
public static String
toDottedQuad(int [] addr) {
  return (addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3]);
}

private static Record []
lookupHostName(String name) throws UnknownHostException {
  try {
    Record [] records = new Lookup(name).run();
    if (records == null)
      throw new UnknownHostException("unknown host");
    return records;
  }
  catch (TextParseException e) {
    throw new UnknownHostException("invalid name");
  }
}

private static InetAddress
addrFromRecord(String name, Record r) throws UnknownHostException {
  ARecord a = (ARecord) r;
  return InetAddress.getByAddress(name, a.getAddress().getAddress());
}

/**
 * Determines the IP address of a host
 * @param name The hostname to look up
 * @return The first matching IP address
 * @exception UnknownHostException The hostname does not have any addresses
 */
public static InetAddress
getByName(String name) throws UnknownHostException {
  try {
    return getByAddress(name);
  } catch (UnknownHostException e) {
    Record [] records = lookupHostName(name);
    return addrFromRecord(name, records[0]);
  }
}

/**
 * Determines all IP address of a host
 * @param name The hostname to look up
 * @return All matching IP addresses
 * @exception UnknownHostException The hostname does not have any addresses
 */
public static InetAddress []
getAllByName(String name) throws UnknownHostException {
  try {
    InetAddress addr = getByAddress(name);
    return new InetAddress[] {addr};
  } catch (UnknownHostException e) {
    Record [] records = lookupHostName(name);
    InetAddress [] addrs = new InetAddress[records.length];
    for (int i = 0; i < records.length; i++)
      addrs[i] = addrFromRecord(name, records[i]);
    return addrs;
  }
}

/**
 * Converts an address from its string representation to an IP address.
 * The address can be either IPv4 or IPv6.
 * @param addr The address, in string form
 * @return The IP addresses
 * @exception UnknownHostException The address is not a valid IP address.
 */
public static InetAddress
getByAddress(String addr) throws UnknownHostException {
  byte [] bytes;
  bytes = toByteArray(addr, IPv4);
  if (bytes != null)
    return InetAddress.getByAddress(bytes);
  bytes = toByteArray(addr, IPv6);
  if (bytes != null)
    return InetAddress.getByAddress(bytes);
  throw new UnknownHostException("Invalid address: " + addr);
}

/**
 * Converts an address from its string representation to an IP address in
 * a particular family.
 * @param addr The address, in string form
 * @param family The address family, either IPv4 or IPv6.
 * @return The IP addresses
 * @exception UnknownHostException The address is not a valid IP address in
 * the specified address family.
 */
public static InetAddress
getByAddress(String addr, int family) throws UnknownHostException {
  if (family != IPv4 && family != IPv6)
    throw new IllegalArgumentException("unknown address family");
  byte [] bytes;
  bytes = toByteArray(addr, family);
  if (bytes != null)
    return InetAddress.getByAddress(bytes);
  throw new UnknownHostException("Invalid address: " + addr);
}

/**
 * Determines the hostname for an address
 * @param addr The address to look up
 * @return The associated host name
 * @exception UnknownHostException There is no hostname for the address
 */
public static String
getHostName(InetAddress addr) throws UnknownHostException {
  Name name = ReverseMap.fromAddress(addr);
  Record [] records = new Lookup(name, Type.PTR).run();
  if (records == null)
    throw new UnknownHostException("unknown address");
  PTRRecord ptr = (PTRRecord) records[0];
  return ptr.getTarget().toString();
}

/**
 * Returns the family of an InetAddress.
 * @param address The supplied address.
 * @return The family, either IPv4 or IPv6.
 */
public static int
familyOf(InetAddress address) {
  if (address instanceof Inet4Address)
    return IPv4;
  if (address instanceof Inet6Address)
    return IPv6;
  throw new IllegalArgumentException("unknown address family");
}

/**
 * Returns the length of an address in a particular family.
 * @param family The address family, either IPv4 or IPv6.
 * @return The length of addresses in that family.
 */
public static int
addressLength(int family) {
  if (family == IPv4)
    return 4;
  if (family == IPv6)
    return 16;
  throw new IllegalArgumentException("unknown address family");
}

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.