net.ripe.ipresource.IpResourceSet.java Source code

Java tutorial

Introduction

Here is the source code for net.ripe.ipresource.IpResourceSet.java

Source

/**
 * The BSD License
 *
 * Copyright (c) 2010-2012 RIPE NCC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *   - Neither the name of the RIPE NCC nor the names of its contributors may be
 *     used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package net.ripe.ipresource;

import org.apache.commons.lang3.Validate;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.SortedSet;
import java.util.TreeMap;

/**
 * A mutable set of IP resources. Resources can be ASNs, IPv4 addresses, IPv6
 * addresses, or ranges. Adjacent resources are merged. Single-sized ranges are
 * normalized into single resources.
 */
public class IpResourceSet implements Iterable<IpResource>, Serializable {

    public static final IpResourceSet IP_PRIVATE_USE_RESOURCES = IpResourceSet
            .parse("10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7");
    public static final IpResourceSet ASN_PRIVATE_USE_RESOURCES = IpResourceSet.parse("AS64512-AS65534");
    public static final IpResourceSet ALL_PRIVATE_USE_RESOURCES = IpResourceSet
            .parse("AS64512-AS65534,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7");

    private static final long serialVersionUID = 1L;

    /*
     * Resources keyed by their end-point. This allows fast lookup to find potentially overlapping resources:
     *
     * resourcesByEndPoint.ceilingEntry(resourceToLookup.getStart())
     */
    private NavigableMap<IpResource, IpResource> resourcesByEndPoint;

    public IpResourceSet() {
        this.resourcesByEndPoint = new TreeMap<IpResource, IpResource>();
    }

    public IpResourceSet(IpResourceSet resources) {
        this.resourcesByEndPoint = new TreeMap<IpResource, IpResource>(resources.resourcesByEndPoint);
    }

    public IpResourceSet(IpResource... resources) {
        this();
        for (IpResource resource : resources) {
            add(resource);
        }
    }

    public IpResourceSet(Collection<? extends IpResource> resources) {
        this();
        for (IpResource resource : resources) {
            add(resource);
        }
    }

    public void addAll(IpResourceSet ipResourceSet) {
        for (IpResource ipResource : ipResourceSet.resourcesByEndPoint.values()) {
            add(ipResource);
        }
    }

    public void add(IpResource resource) {
        Validate.notNull(resource, "resource is null");

        UniqueIpResource start = resource.getStart();
        if (!start.equals(start.getType().getMinimum())) {
            start = start.predecessor();
        }

        IpResource resourceToAdd = normalize(resource);

        Iterator<IpResource> iterator = resourcesByEndPoint.tailMap(start, true).values().iterator();
        while (iterator.hasNext()) {
            IpResource potentialMatch = iterator.next();
            if (resourceToAdd.isMergeable(potentialMatch)) {
                iterator.remove();
                resourceToAdd = resourceToAdd.merge(potentialMatch);
            } else {
                break;
            }
        }

        IpResource normalized = normalize(resourceToAdd);
        resourcesByEndPoint.put(normalized.getEnd(), normalized);
    }

    public boolean isEmpty() {
        return resourcesByEndPoint.isEmpty();
    }

    public boolean contains(IpResource resource) {
        Entry<IpResource, IpResource> potentialMatch = resourcesByEndPoint.ceilingEntry(resource.getStart());
        return potentialMatch != null && potentialMatch.getValue().contains(resource);
    }

    public boolean contains(IpResourceSet other) {
        for (IpResource resource : other) {
            if (!contains(resource)) {
                return false;
            }
        }
        return true;
    }

    public boolean containsType(IpResourceType type) {
        for (IpResource resource : resourcesByEndPoint.values()) {
            if (type == resource.getType()) {
                return true;
            }
        }
        return false;
    }

    public static IpResourceSet parse(String s) {
        String[] resources = s.split(",");
        IpResourceSet result = new IpResourceSet();
        for (String r : resources) {
            String trimmed = r.trim();
            if (!trimmed.isEmpty()) {
                result.add(IpResource.parse(trimmed));
            }
        }
        return result;
    }

    public Iterator<IpResource> iterator() {
        return resourcesByEndPoint.values().iterator();
    }

    public boolean remove(IpResource resource) {
        boolean removed = false;

        Entry<IpResource, IpResource> potentialMatch = resourcesByEndPoint.ceilingEntry(resource.getStart());
        while (potentialMatch != null && potentialMatch.getValue().overlaps(resource)) {
            resourcesByEndPoint.remove(potentialMatch.getKey());
            removed = true;

            for (IpResource remains : potentialMatch.getValue().subtract(resource)) {
                add(remains);
            }

            potentialMatch = resourcesByEndPoint.ceilingEntry(resource.getStart());
        }

        return removed;
    }

    public void removeAll(IpResourceSet other) {
        for (IpResource resource : other) {
            remove(resource);
        }
    }

    public void retainAll(IpResourceSet other) {
        if (this.isEmpty()) {
            return;
        } else if (other.isEmpty()) {
            resourcesByEndPoint.clear();
            return;
        }

        NavigableMap<IpResource, IpResource> temp = new TreeMap<IpResource, IpResource>();
        Iterator<IpResource> thisIterator = this.iterator();
        Iterator<IpResource> thatIterator = other.iterator();
        IpResource thisResource = thisIterator.next();
        IpResource thatResource = thatIterator.next();
        while (thisResource != null && thatResource != null) {
            IpResource intersect = thisResource.intersect(thatResource);
            if (intersect != null) {
                temp.put(intersect.getEnd(), intersect);
            }
            int compareTo = thisResource.getEnd().compareTo(thatResource.getEnd());
            if (compareTo <= 0) {
                thisResource = thisIterator.hasNext() ? thisIterator.next() : null;
            }
            if (compareTo >= 0) {
                thatResource = thatIterator.hasNext() ? thatIterator.next() : null;
            }
        }
        this.resourcesByEndPoint = temp;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof IpResourceSet)) {
            return false;
        }
        IpResourceSet other = (IpResourceSet) obj;
        return resourcesByEndPoint.equals(other.resourcesByEndPoint);
    }

    @Override
    public int hashCode() {
        return resourcesByEndPoint.hashCode();
    }

    @Override
    public String toString() {
        String s = resourcesByEndPoint.values().toString();
        return s.substring(1, s.length() - 1);
    }

    private IpResource normalize(IpResource resource) {
        return resource.isUnique() ? resource.unique() : resource;
    }

    @SuppressWarnings("unchecked")
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gf = in.readFields();
        if (!gf.defaulted("resourcesByEndPoint")) {
            resourcesByEndPoint = (NavigableMap<IpResource, IpResource>) gf.get("resourcesByEndPoint", null);
        } else {
            SortedSet<IpResource> resources = (SortedSet<IpResource>) gf.get("resources", null);
            resourcesByEndPoint = new TreeMap<IpResource, IpResource>();
            for (IpResource resource : resources) {
                resourcesByEndPoint.put(resource.getEnd(), resource);
            }
        }
    }
}