com.xsdn.main.util.Ip4Network.java Source code

Java tutorial

Introduction

Here is the source code for com.xsdn.main.util.Ip4Network.java

Source

/*
 * Copyright (c) 2015 NEC Corporation
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this
 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package com.xsdn.main.util;

import java.net.InetAddress;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;

import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;

/**
 * {@code Ip4Network} describes an IPv4 network.
 * IPv4 network is specified by an IPv4 address and prefix length.
 *
 * @since  Lithium
 */
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@XmlRootElement(name = "ipv4-network")
@XmlAccessorType(XmlAccessType.NONE)
public final class Ip4Network extends IpNetwork {
    /**
     * Version number for serialization.
     */
    private static final long serialVersionUID = -7431660855016600442L;

    /**
     * The number of octets in an IPv4 address.
     */
    public static final int SIZE = 4;

    /**
     * An IPv4 netmask which indicates all bits in an IPv4 address are set.
     */
    private static final int NETMASK_ALL = -1;

    /**
     * An integer value which represents an IPv4 network address.
     */
    private int address;

    /**
     * An integer value which represents a network mask.
     */
    private int netMask;

    /**
     * A byte array which represents an IPv4 network address.
     */
    private byte[] byteAddress;

    /**
     * A string representation of an IPv4 network address.
     * Note that this text does not contain prefix length.
     */
    private String networkAddress;

    /**
     * An {@link IpPrefix} instance which represents this IPv4 network.
     */
    private IpPrefix ipPrefix;

    /**
     * Return an IPv4 prefix length represented by the given byte array.
     *
     * <p>
     *   Note that this method returns 32 if all the bits in the given array
     *   are not set.
     * </p>
     *
     * @param bytes  A byte array which represents IPv4 network mask.
     * @return  The IPv4 prefix length represented by the given byte array.
     * @throws NullPointerException
     *    {@code bytes} is {@code null}.
     * @throws IllegalArgumentException
     *    The given byte array does not represent an IPv4 network mask.
     */
    public static int getPrefixLength(byte[] bytes) {
        // Verify the given network mask.
        int mask = NumberUtils.toInteger(bytes);
        if (mask == 0) {
            return Integer.SIZE;
        }

        int inv = ~mask;
        int p2 = inv + 1;
        if ((p2 & inv) != 0) {
            throw new IllegalArgumentException("Invalid IPv4 netmask: " + Integer.toHexString(mask));
        }

        return Integer.numberOfLeadingZeros(inv);
    }

    /**
     * Return an integer value which represents the IPv4 netmask specified by
     * the given prefix length.
     *
     * @param length  The IPv4 prefix length.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @return  An integer value.
     * @throws IllegalArgumentException
     *    The given prefix length is invalid.
     */
    public static int getNetMask(int length) {
        if (length < 0 || length > Integer.SIZE) {
            throw new IllegalArgumentException("Invalid prefix length: " + length);
        }

        int nzeroes = Integer.SIZE - length;
        return (NETMASK_ALL << nzeroes);
    }

    /**
     * Return an {@link InetAddress} instance which represents the IPv4 netmask
     * specified by the given prefix length.
     *
     * @param length  The IPv4 prefix length.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @return  An {@link InetAddress} instance.
     * @throws IllegalArgumentException
     *    The given prefix length is invalid.
     */
    public static InetAddress getInetMask(int length) {
        return getInetAddress(getNetMask(length));
    }

    /**
     * Create an IPv4 network address from the given IPv4 address and
     * prefix length.
     *
     * @param iaddr   An {@link InetAddress} instance.
     * @param length  The IPv4 prefix length.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @return  An {@link InetAddress} instance which represents the IPv4
     *          network address specified by the given pair of IPv4 address and
     *          prefix length.
     * @throws NullPointerException
     *    {@code iaddr} is {@code null}.
     * @throws IllegalArgumentException
     *    The given IPv4 address or prefix length is invalid.
     */
    public static InetAddress getNetworkAddress(InetAddress iaddr, int length) {
        int addr = NumberUtils.toInteger(iaddr.getAddress());
        int mask = getNetMask(length);
        return getInetAddress(addr & mask);
    }

    /**
     * Create an {@link InetAddress} instance which represents the IPv4 address
     * specified by the given integer value.
     *
     * @param addr  An integer value which represents the IPv4 address.
     * @return  An {@link InetAddress} instance.
     */
    public static InetAddress getInetAddress(int addr) {
        return getInetAddress(NumberUtils.toBytes(addr));
    }

    /**
     * Ensure that the given {@link IpNetwork} instance represents an
     * IPv4 address.
     *
     * @param ipn  An {@link IpNetwork} instance.
     * @return  {@code ipn} casted as {@link Ip4Network} if {@code ipn}
     *          represents an IPv4 address. Otherwise {@code null}.
     */
    public static Ip4Network toIp4Address(IpNetwork ipn) {
        return (ipn instanceof Ip4Network && ipn.isAddress()) ? (Ip4Network) ipn : null;
    }

    /**
     * Private constructor used for JAXB mapping.
     */
    @SuppressWarnings("unused")
    private Ip4Network() {
    }

    /**
     * Construct a new instance.
     *
     * <p>
     *   This constructor specifies 32 as CIDR prefix length.
     * </p>
     *
     * @param addr  An integer value which represents an IPv4 address.
     */
    public Ip4Network(int addr) {
        this(addr, Integer.SIZE);
    }

    /**
     * Construct a new instance.
     *
     * @param addr    An integer value which represents an IPv4 address.
     * @param prefix  Prefix length that specifies network range.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @throws IllegalArgumentException
     *    The given prefix length is invalid.
     */
    public Ip4Network(int addr, int prefix) {
        super(prefix);
        int mask = getNetMask(getPrefixLength());
        address = addr & mask;
        netMask = mask;
    }

    /**
     * Construct a new instance.
     *
     * <p>
     *   This constructor specifies 32 as CIDR prefix length.
     * </p>
     *
     * @param bytes  A byte array which represents an IPv4 address.
     * @throws NullPointerException
     *    {@code bytes} is {@code null}.
     * @throws IllegalArgumentException
     *    The given byte address does not represent an IPv4 address.
     */
    public Ip4Network(byte[] bytes) {
        this(bytes, Integer.SIZE);
    }

    /**
     * Construct a new instance.
     *
     * @param bytes  A byte array which represents an IPv4 address.
     * @param prefix  Prefix length that specifies network range.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @throws NullPointerException
     *    {@code bytes} is {@code null}.
     * @throws IllegalArgumentException
     *    The given prefix length is invalid.
     * @throws IllegalArgumentException
     *    The given byte address does not represent an IPv4 address.
     */
    public Ip4Network(byte[] bytes, int prefix) {
        super(prefix);
        int addr = NumberUtils.toInteger(bytes);
        int plen = getPrefixLength();
        int mask = getNetMask(plen);
        netMask = mask;
        if (plen == Integer.SIZE) {
            address = addr;
            byteAddress = bytes.clone();
        } else {
            address = addr & mask;
        }
    }

    /**
     * Construct a new instance.
     *
     * <p>
     *   This constructor specifies 32 as CIDR prefix length.
     * </p>
     *
     * @param iaddr  An {@link InetAddress} instance which represents an IPv4
     *               address.
     * @throws NullPointerException
     *    {@code iaddr} is {@code null}.
     * @throws IllegalArgumentException
     *    The given {@link InetAddress} instance does not represent an IPv4
     *    address.
     */
    public Ip4Network(InetAddress iaddr) {
        super(iaddr, Integer.SIZE);
    }

    /**
     * Construct a new instance.
     *
     * @param iaddr  An {@link InetAddress} instance which represents an IPv4
     *               address.
     * @param prefix  Prefix length that specifies network range.
     *                Note that zero means "no mask". So zero is treated as if
     *                the maximum prefix length is specified.
     * @throws NullPointerException
     *    {@code iaddr} is {@code null}.
     * @throws IllegalArgumentException
     *    The given prefix length is invalid.
     * @throws IllegalArgumentException
     *    The given {@link InetAddress} instance does not represent an IPv4
     *    address.
     */
    public Ip4Network(InetAddress iaddr, int prefix) {
        super(iaddr, prefix);
    }

    /**
     * Construct a new instance.
     *
     * @param cidr  A string representation of the IP network in CIDR notation.
     *              Note that zero prefix means "no mask". So zero prefix is
     *              treated as if the maximum prefix length is specified.
     * @throws NullPointerException
     *    {@code cidr} is {@code null}.
     * @throws IllegalArgumentException
     *    The given network address is invalid.
     */
    public Ip4Network(String cidr) {
        super(cidr);
    }

    /**
     * Return an integer value which represents the host address.
     *
     * @return  An integer value which represents the host address.
     */
    public int getAddress() {
        return address;
    }

    /**
     * Return an integer value which represents the network mask.
     *
     * @return  An integer value which represents the network mask.
     */
    public int getNetMask() {
        return netMask;
    }

    // IpNetwork

    /**
     * {@inheritDoc}
     */
    @Override
    public int getMaxPrefix() {
        return Integer.SIZE;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IpPrefix getIpPrefix() {
        IpPrefix ip = ipPrefix;
        if (ip == null) {
            StringBuilder builder = new StringBuilder();
            builder.append(getHostAddress()).append(CIDR_SEPARATOR).append(getPrefixLength());
            ip = new IpPrefix(new Ipv4Prefix(builder.toString()));
            ipPrefix = ip;
        }

        return ip;
    }

    /**
     * Return a MD-SAL IP address which represents this network address.
     *
     * @return  An {@link Ipv4} instance.
     */
    @Override
    public Ipv4 getMdAddress() {
        IpPrefix ipp = getIpPrefix();
        return new Ipv4Builder().setIpv4Address(ipp.getIpv4Prefix()).build();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getCidrText() {
        return getIpPrefix().getIpv4Prefix().getValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getHostAddress() {
        String addr = networkAddress;
        if (addr == null) {
            addr = getInetAddress().getHostAddress();
            networkAddress = addr;
        }

        return addr;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] getBytes() {
        byte[] bytes = byteAddress;
        if (bytes == null) {
            bytes = NumberUtils.toBytes(address);
            byteAddress = bytes;
        }

        return bytes.clone();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean contains(IpNetwork inw) {
        if (!inw.getClass().equals(Ip4Network.class)) {
            throw new IllegalArgumentException("Unexpected IpNetwork: " + inw);
        }

        Ip4Network ip4 = (Ip4Network) inw;
        return (address == (ip4.address & netMask));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    InetAddress init(InetAddress iaddr, int prefix) {
        int addr = NumberUtils.toInteger(iaddr.getAddress());
        int mask = getNetMask(prefix);
        int maskedAddr = addr & mask;
        address = maskedAddr;
        netMask = mask;
        return getInetAddress(maskedAddr);
    }

    // Object

    /**
     * Determine whether the given object is identical to this object.
     *
     * @param o  An object to be compared.
     * @return   {@code true} if identical. Otherwise {@code false}.
     */
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o == null || !Ip4Network.class.equals(o.getClass())) {
            return false;
        }

        Ip4Network ip4 = (Ip4Network) o;
        return (address == ip4.address && getPrefixLength() == ip4.getPrefixLength());
    }

    /**
     * Return the hash code of this object.
     *
     * @return  The hash code.
     */
    @Override
    public int hashCode() {
        return Ip4Network.class.getName().hashCode() * address;
    }
}