/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you 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.                                           *
 ****************************************************************/
package org.apache.james.dnsservice.library.netmatcher;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.james.dnsservice.api.DNSService;
import org.apache.james.dnsservice.library.inetnetwork.InetNetworkBuilder;
import org.apache.james.dnsservice.library.inetnetwork.model.InetNetwork;

/**
 * NetMatcher Class is used to check if an ipAddress match a network.
 * 
 * NetMatcher provides a means for checking whether
 * a particular IPv4 or IPv6 address or domain name is within a set of subnets.
 */
public class NetMatcher {
    
    /**
     * The DNS Service used to build InetNetworks.
     */
    private DNSService dnsServer;

    /**
     * The Set of InetNetwork to match against.
     */
    private Set<InetNetwork> networks;

    /**
     * Create a new instance of Netmatcher.
     * 
     * @param nets a String[] which holds all networks
     * @param dnsServer the DNSService which will be used in this class
     */
    public NetMatcher(final String[] nets, DNSService dnsServer) {
        this.dnsServer = dnsServer;
        initInetNetworks(nets);
    }

    /**
     * Create a new instance of Netmatcher.
     * 
     * @param nets a Collection which holds all networks
     * @param dnsServer the DNSService which will be used in this class
     */
    public NetMatcher(final Collection<String> nets, DNSService dnsServer) {
        this.dnsServer = dnsServer;
        initInetNetworks(nets);
    }

    /**
     * The given String may represent an IP address or a host name.
     * 
     * @param hostIP the ipAddress or host name to check
     * @see #matchInetNetwork(InetAddress)
     */
    public boolean matchInetNetwork(final String hostIP) {
        
        InetAddress ip = null;

        try {
            ip = dnsServer.getByName(hostIP);
        } catch (UnknownHostException uhe) {
            log("Cannot resolve address for " + hostIP + ": " + uhe.getMessage());
            return false;
        }

        return matchInetNetwork(ip);

    }

    /**
     * Return true if passed InetAddress match a network which 
     * was used to construct the Netmatcher.
     * 
     * @param an InetAddress
     * @return true if match the network
     */
    public boolean matchInetNetwork(final InetAddress ip) {
        
        boolean sameNet = false;

        for (Iterator<InetNetwork> iter = networks.iterator(); (!sameNet) && iter.hasNext();) {
            InetNetwork network = iter.next();
            sameNet = network.contains(ip);
        }
        
        return sameNet;
    
    }

    /**
     * @see InetNetwork#toString()
     */
    public String toString() {
        return networks.toString();
    }

    /**
     * Can be overwritten for logging
     * 
     * @param s  the String to log
     */
    protected void log(String s) {
    }
    
    /**
     * Init the class with the given networks.
     * 
     * @param nets a Collection which holds all networks
     */
    private void initInetNetworks(final Collection<String> nets) {
        initInetNetworks(nets.toArray(new String[]{}));
    }

    /**
     * Init the class with the given networks.
     * 
     * @param nets a String[] which holds all networks
     */
    private void initInetNetworks(final String[] nets) {

        networks = new HashSet<InetNetwork>();

        final InetNetworkBuilder inetNetwork = new InetNetworkBuilder(dnsServer);

        for (String net: nets) {
            try {
                InetNetwork inet = inetNetwork.getFromString(net);
                networks.add(inet);
            } catch (UnknownHostException uhe) {
                log("Cannot resolve address: " + uhe.getMessage());
            }
        }
        
    }

}

@@ -1352,23 +1352,26 @@
 va.util.
-HashSet
+Comparator
 ;%0Aimport
@@ -1408,16 +1408,48 @@
 va.util.
+SortedSet;%0Aimport java.util.Tree
 Set;%0A%0Aim
@@ -2070,16 +2070,22 @@
 private 
+Sorted
 Set%3CInet
@@ -3904,24 +3904,92 @@
  %7D%0A%0A    /**%0A
+     * Return a sorted representation of the inet networks.%0A     * %0A
      * @see 
@@ -4705,12 +4705,12 @@
 new 
-Hash
+Tree
 Set%3C
@@ -4722,16 +4722,203 @@
 etwork%3E(
+new Comparator%3CInetNetwork%3E() %7B%0A            public int compare(InetNetwork in1, InetNetwork in2) %7B%0A                return in1.toString().compareTo(in2.toString());%0A            %7D%0A        %7D
 );%0A%0A    

Use a SortedSet to ensure tests are successfull on all platforms (solaris,...) - we don't add many networks, so it should this should not give performance impact.