All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.martiansoftware.macnificent.MacAddress Maven / Gradle / Ivy

Go to download

Macnificent is a set of utility classes for working with MAC addresses in Java. In addition to a lightweight MacAddress class and parser, this includes IEEE OUI registry information and a formatter for MAC addresses that displays an abbreviated form of the device's manufacturer's name.

The newest version!
package com.martiansoftware.macnificent;

/*
 * Copyright (C) Martian Software, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 */

import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parses, encapsulates, formats, and represents a 6-byte MAC address.
 *
 * @author Marty Lamb
 */
public class MacAddress implements Comparable {

    /**
     * Length of a MAC address, in _bytes
     */
    public static final int ETH_ALEN = 6;

    /**
     * regex used to parse MAC addresses
     */
    private static final Pattern MACREGEX;
    
    /**
     * Multicast bit in first byte of MAC.
     */
    static final byte FLAG_MCAST = 0x01;

    /**
     * Local bit in first byte of MAC.
     */
    static final byte FLAG_LOCAL = 0x02;

    /**
     * Build the MACREGEX pattern.  Allow whitespace or any of '-' ':' '.' or '_'
     * to separate _bytes in the MAC.  MAC byte separation is not required.
     * Each byte of the MAC is captured in its own group.
     */
    static {
        StringBuilder buf = new StringBuilder("^\\s*");
        for (int i = 0; i < ETH_ALEN; ++i) {
            buf.append("([0-9a-fA-F]{2})"); // a MAC byte with a capturing group
            if (i == 0) {
                buf.append("([\\s-:._]?)");  // ignored chars that may separate MAC _bytes
            } else if (i < ETH_ALEN - 1) {
                buf.append("\\2"); // backreference for whatever the separator is (if any)
            }
        }
        buf.append("\\s*$");
        MACREGEX = Pattern.compile(buf.toString());
    }
            
    /**
     * The _bytes comprising this MacAddress.
     */
    private final byte[] _bytes = new byte[ETH_ALEN];

    /**
     * Creates a new MacAddress by copying the specified byte array (which must
     * contain ETH_ALEN _bytes)
     *
     * @param bytes the byte array representing the new MacAddress
     */
    public MacAddress(byte[] bytes) {
        if (bytes.length != ETH_ALEN) throw new IllegalArgumentException("MacAddress bytes array must contain exactly " + ETH_ALEN + " bytes.  Instead received " + bytes.length + " (" + hexString(bytes, bytes.length) + ")");
        System.arraycopy(bytes, 0, this._bytes, 0, ETH_ALEN);
    }

    /**
     * Creates a new MacAddress from a given NetworkInterface
     * @param ni the NetworkInterface for which the MacAddress is to be created
     * @throws java.net.SocketException if thrown by NetworkInterface.getHardwareAddress()
     */
    public MacAddress(NetworkInterface ni) throws java.net.SocketException {
        this(ni.getHardwareAddress());
    }
    
    /**
     * Creates a new MacAddress from the specified String.  The String must contain
     * ETH_ALEN hexadecimal-encoded _bytes, optionally separated by any whitespace
     * or any of '-', ':', '.', or '_'.  Whatever separator is used (if any)
     * must be used consistently within the String.  Leading and trailing
     * whitespace are ignored.
     *
     * For example, the following are valid MacAddress strings:
     * 
    *
  • 11:22:33:44:55:66
  • *
  • 1a-2b-3c-4d-5e-6f
  • *
  • FFFFFFFFFFFF
  • *
  • AA BB CC 11 22 33
  • *
* * The following are NOT valid MacAddress strings: *
    *
  • 11:22-33:44-55:66
  • *
  • 1a2b3c 4d5e6f
  • *
  • FFFFFFFFFFF (not long enough)
  • *
  • FFFFFFFFFFFFF (too long)
  • *
* @param s */ public MacAddress(String s) { Matcher m = MACREGEX.matcher(s); if (!m.matches()) throw new IllegalArgumentException("Invalid MacAddress string: \"" + s + "\""); int groupIndex; for (int i = 0; i < ETH_ALEN; ++i) { groupIndex = i + 1; if (i > 0) ++groupIndex; _bytes[i] = (byte) Integer.parseInt(m.group(groupIndex), 16); } } /** * Returns the internal byte array storing this MAC address. * NOTE: This is NOT a copy of the array. Modifying the array * returned may yield unexpected behavior (e.g., changing the hashCode). * * @return the internal byte array storing this MAC address. */ byte[] getInternalBytes() { return _bytes; } /** * Returns a copy of the internal byte array storing this MAC address. * * @return a copy of the internal byte array storing this MAC address. */ public byte[] getBytes() { return Arrays.copyOf(_bytes, ETH_ALEN); } /** * Indicates whether this MacAddress has its multicast bit set * @return true if this MacAddress has its multicast bit set */ public boolean isMulticast() { return (_bytes[0] & FLAG_MCAST) == FLAG_MCAST; } /** * Indicates whether this MacAddress has its local bit set * @return true if this MacAddress has its local bit set */ public boolean isLocal() { return (_bytes[0] & FLAG_LOCAL) == FLAG_LOCAL; } private String hexString(byte[] b, int len) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < len; ++i) { if (i != 0) buf.append(":"); buf.append(String.format("%02x", b[i])); } return buf.toString(); } @Override public String toString() { return hexString(_bytes, ETH_ALEN); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final MacAddress other = (MacAddress) obj; if (!Arrays.equals(this._bytes, other._bytes)) { return false; } return true; } @Override public int hashCode() { int hash = 5; hash = 97 * hash + Arrays.hashCode(this._bytes); return hash; } @Override public int compareTo(MacAddress o) { int r; for (int i = 0; i < ETH_ALEN; ++i) { r = _bytes[i] - o._bytes[i]; if (r != 0) return r; } return 0; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy