EthernetAddress.java :  » Game » galatichero » biz » evot » util » Java Open Source

Java Open Source » Game » galatichero 
galatichero » biz » evot » util » EthernetAddress.java
/**
 * Copyright (C) 2001-2005 Connected Systems Inc. All rights reserved.
 * This software is the confidential and proprietary information of
 * Connected Systems Inc. ("Confidential Information").
 */
package biz.evot.util;

import java.io.Serializable;

/*
 * JUG Java Uuid Generator
 * 
 * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi
 * 
 * You can redistribute this work and/or modify it under the terms of LGPL
 * (Lesser General Public License), as published by Free Software Foundation
 * (http://www.fsf.org). No warranty is implied. See LICENSE for details about
 * licensing.
 */

/**
 * EthernetAddress encapsulates the 6-byte Mac address defined in IEEE 802.1
 * standard.
 */

public class EthernetAddress implements Serializable, Cloneable, Comparable {
  /**
   * 
   */
  private static final long serialVersionUID = -2063153337293131247L;

  private final static String kHexChars = "0123456789abcdefABCDEF";

  private final byte[] mAddress = new byte[6];

  /* *** Creation methods *** */

  /**
   * String constructor; given a 'standard' ethernet MAC address string (like
   * '00:C0:F0:3D:5B:7C'), constructs an EthernetAddress instance.
   * 
   * Note that string is case-insensitive, and also that leading zeroes may be
   * omitted. Thus '00:C0:F0:3D:5B:7C' and '0:c0:f0:3d:5b:7c' are equivalent,
   * and a 'null' address could be passed as ':::::' as well as
   * '00:00:00:00:00:00' (or any other intermediate combination).
   * 
   * @param addrStr
   *            String representation of the ethernet address
   */
  public EthernetAddress(String addrStr) throws NumberFormatException {
    byte[] addr = mAddress;
    int len = addrStr.length();

    /*
     * Ugh. Although the most logical format would be the 17-char one (12
     * hex digits separated by colons), apparently leading zeroes can be
     * omitted. Thus... Can't just check string length. :-/
     */
    for (int i = 0, j = 0; j < 6; ++j) {
      if (i >= len) {
        // Is valid if this would have been the last byte:
        if (j == 5) {
          addr[5] = (byte) 0;
          break;
        }
        throw new NumberFormatException("Incomplete ethernet address (missing one or more digits");
      }

      char c = addrStr.charAt(i);
      ++i;
      int value;

      // The whole number may be omitted (if it was zero):
      if (c == ':') {
        value = 0;
      } else {
        // No, got at least one digit?
        if (c >= '0' && c <= '9') {
          value = (c - '0');
        } else if (c >= 'a' && c <= 'f') {
          value = (c - 'a' + 10);
        } else if (c >= 'A' && c <= 'F') {
          value = (c - 'A' + 10);
        } else {
          throw new NumberFormatException("Non-hex character '" + c + "'");
        }

        // How about another one?
        if (i < len) {
          c = addrStr.charAt(i);
          ++i;
          if (c != ':') {
            value = (value << 4);
            if (c >= '0' && c <= '9') {
              value |= (c - '0');
            } else if (c >= 'a' && c <= 'f') {
              value |= (c - 'a' + 10);
            } else if (c >= 'A' && c <= 'F') {
              value |= (c - 'A' + 10);
            } else {
              throw new NumberFormatException("Non-hex character '" + c + "'");
            }
          }
        }
      }

      addr[j] = (byte) value;

      if (c != ':') {
        if (i < len) {
          if (addrStr.charAt(i) != ':') {
            throw new NumberFormatException("Expected ':', got ('" + addrStr.charAt(i) + "')");
          }
          ++i;
        } else if (j < 5) {
          throw new NumberFormatException("Incomplete ethernet address (missing one or more digits");
        }
      }
    }
  }

  /**
   * Binary constructor that constructs an instance given the 6 byte (48-bit)
   * address. Useful if an address is saved in binary format (for saving space
   * for example).
   */
  public EthernetAddress(byte[] addr) throws NumberFormatException {
    if (addr.length != 6) {
      throw new NumberFormatException("Ethernet address has to consist of 6 bytes");
    }
    for (int i = 0; i < 6; ++i) {
      mAddress[i] = addr[i];
    }
  }

  /**
   * Another binary constructor; constructs an instance from the given long
   * argument; the lowest 6 bytes contain the address.
   * 
   * @param addr
   *            long that contains the MAC address in 6 least significant
   *            bytes.
   */
  public EthernetAddress(long addr) {
    for (int i = 0; i < 6; ++i) {
      mAddress[5 - i] = (byte) addr;
      addr >>>= 8;
    }
  }

  /**
   * Package internal constructor for creating an 'empty' ethernet address
   */
  EthernetAddress() {
    byte z = (byte) 0;
    for (int i = 0; i < 6; ++i) {
      mAddress[i] = z;
    }
  }

  /**
   * Default cloning behaviour (bitwise copy) is just fine...
   */
  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      // shouldn't happen
      return null;
    }
  }

  /* *** Comparison methods *** */

  public boolean equals(Object o) {
    if (!(o instanceof EthernetAddress)) {
      return false;
    }
    byte[] otherAddress = ((EthernetAddress) o).mAddress;
    byte[] thisAddress = mAddress;
    for (int i = 0; i < 6; ++i) {
      if (otherAddress[i] != thisAddress[i]) {
        return false;
      }
    }
    return true;
  }

  /**
   * Method that compares this EthernetAddress to one passed in as argument.
   * Comparison is done simply by comparing individual address bytes in the
   * order.
   * 
   * @return -1 if this EthernetAddress should be sorted before the one passed
   *         in, 1 if after and 0 if they are equal.
   */
  public int compareTo(Object o) {
    byte[] thatA = ((EthernetAddress) o).mAddress;
    byte[] thisA = mAddress;

    for (int i = 0; i < 6; ++i) {
      int cmp = (((int) thisA[i]) & 0xFF) - (((int) thatA[i]) & 0xFF);
      if (cmp != 0) {
        return cmp;
      }
    }

    return 0;
  }

  /* *** Type conversion *** */

  /**
   * Returns the canonical string representation of this ethernet address.
   * Canonical means that all characters are lower-case and string length is
   * always 17 characters (ie. leading zeroes are not omitted).
   * 
   * @return Canonical string representation of this ethernet address.
   */
  public String toString() {
    /*
     * Let's not cache the output here (unlike with UUID), assuming this
     * won't be called as often:
     */
    StringBuffer b = new StringBuffer(17);
    byte[] addr = mAddress;

    for (int i = 0; i < 6; ++i) {
      if (i > 0) {
        b.append(":");
      }
      int hex = addr[i] & 0xFF;
      b.append(kHexChars.charAt(hex >> 4));
      b.append(kHexChars.charAt(hex & 0x0f));
    }
    return b.toString();
  }

  /**
   * Returns 6 byte byte array that contains the binary representation of this
   * ethernet address; byte 0 is the most significant byte (and so forth)
   * 
   * @return 6 byte byte array that contains the binary representation
   */
  public byte[] asByteArray() {
    byte[] result = new byte[6];

    toByteArray(result);

    return result;
  }

  /**
   * Synonym to 'asByteArray()'
   * 
   * @return 6 byte byte array that contains the binary representation
   */
  public byte[] toByteArray() {
    return asByteArray();
  }

  public void toByteArray(byte[] array) {
    toByteArray(array, 0);
  }

  public void toByteArray(byte[] array, int pos) {
    for (int i = 0; i < 6; ++i) {
      array[pos + i] = mAddress[i];
    }
  }

  public long toLong() {
    /*
     * Damn Java's having signed bytes sucks... they are NEVER what anyone
     * needs; and sign extension work-arounds are slow.
     */
    byte[] addr = mAddress;
    int hi = (((int) addr[0]) & 0xFF) << 8 | (((int) addr[1]) & 0xFF);
    int lo = ((int) addr[2]) & 0xFF;
    for (int i = 3; i < 6; ++i) {
      lo = (lo << 8) | (((int) addr[i]) & 0xFF);
    }

    return ((long) hi) << 32 | (((long) lo) & 0xFFFFFFFFL);
  }

  /**
   * Constructs a new EthernetAddress given the byte array that contains
   * binary representation of the address.
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor.
   * 
   * @param addr
   *            Binary representation of the ethernet address
   * 
   * @throws NumberFormatException
   *             if addr is invalid (less or more than 6 bytes in array)
   */
  public static EthernetAddress valueOf(byte[] addr) throws NumberFormatException {
    return new EthernetAddress(addr);
  }

  /**
   * Constructs a new EthernetAddress given the byte array that contains
   * binary representation of the address.
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor.
   * 
   * @param addr
   *            Binary representation of the ethernet address
   * 
   * @throws NumberFormatException
   *             if addr is invalid (less or more than 6 ints in array)
   */
  public static EthernetAddress valueOf(int[] addr) throws NumberFormatException {
    byte[] bAddr = new byte[addr.length];

    for (int i = 0; i < addr.length; ++i) {
      bAddr[i] = (byte) addr[i];
    }
    return new EthernetAddress(bAddr);
  }

  /**
   * Constructs a new EthernetAddress given a string representation of the
   * ethernet address.
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor.
   * 
   * @param addrStr
   *            String representation of the ethernet address
   * 
   * @throws NumberFormatException
   *             if addr representation is invalid
   */
  public static EthernetAddress valueOf(String addrStr) throws NumberFormatException {
    return new EthernetAddress(addrStr);
  }

  /**
   * Constructs a new EthernetAddress given the long int value (64-bit)
   * representation of the ethernet address (of which 48 LSB contain the
   * definition)
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor.
   * 
   * @param addr
   *            Long int representation of the ethernet address
   */
  public static EthernetAddress valueOf(long addr) {
    return new EthernetAddress(addr);
  }

  public static void main(String[] args) {
    System.out.println("EthernetAddress.main, test:");
    System.out.println("---------------------------");

    long rnd = 0;
    if (args == null || args.length == 0) {
      System.out.println("[no address passed, using a random address]");
      rnd = System.currentTimeMillis() ^ (long) (Math.random() * (double) 0x100000000L);
      args = new String[] { new EthernetAddress(rnd).toString() };
    }

    for (int i = 0; i < args.length; ++i) {
      String s = args[i];
      System.out.println("Address '" + s + "':");
      try {
        EthernetAddress a = EthernetAddress.valueOf(s);
        System.err.println("  Ok, comes out as '" + a.toString() + "'");

        // EthernetAddress <-> long
        System.err.print("  Converting to long, result = ");
        long l = a.toLong();
        System.err.println("" + Long.toHexString(l));
        System.err.print("  Creating address from long, are equal: ");
        EthernetAddress b = EthernetAddress.valueOf(l);
        if (b.equals(a)) {
          System.err.println("yes (OK)");
        } else {
          System.err.println("no (FAIL)");
          break;
        }

        // EthernetAddress <-> byte[]
        System.err.println("  Converting to byte array.");
        byte[] ba = a.asByteArray();
        System.err.print("  Creating address from byte[], are equal: ");
        b = EthernetAddress.valueOf(ba);
        if (b.equals(a)) {
          System.err.println("yes (OK)");
        } else {
          System.err.println("no (FAIL)");
          break;
        }
      } catch (NumberFormatException e) {
        System.out.println("  Fail: " + e.toString());
      }
    }
    System.out.println("---------------------------");
    System.out.println("Done.");
  }
}
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.