mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
23.01.2014 c7149b39417ba099ad2d6cd6b841bdc2e66d2cef
Migrate AddressMask class to opendj-core.
1 files deleted
1 files added
1 files renamed
4 files modified
573 ■■■■■ changed files
opendj-config-maven-plugin/src/main/resources/config/stylesheets/property-types/ip-address-mask.xsl 2 ●●● patch | view | raw | blame | history
opendj-config/src/main/java/org/forgerock/opendj/config/IPAddressMaskPropertyDefinition.java 10 ●●●● patch | view | raw | blame | history
opendj-config/src/main/java/org/forgerock/opendj/config/PropertyValueVisitor.java 2 ●●● patch | view | raw | blame | history
opendj-config/src/main/java/org/opends/server/types/package-info.java 35 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/AddressMask.java 262 ●●●● patch | view | raw | blame | history
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties 10 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/AddressMaskTestCase.java 252 ●●●●● patch | view | raw | blame | history
opendj-config-maven-plugin/src/main/resources/config/stylesheets/property-types/ip-address-mask.xsl
@@ -29,7 +29,7 @@
    Templates for processing IP address mask properties.
  -->
  <xsl:template match="adm:ip-address-mask" mode="java-value-imports">
    <import>org.opends.server.types.AddressMask</import>
    <import>org.forgerock.opendj.ldap.AddressMask</import>
  </xsl:template>
  <xsl:template match="adm:ip-address-mask" mode="java-value-type">
    <xsl:value-of select="'AddressMask'" />
opendj-config/src/main/java/org/forgerock/opendj/config/IPAddressMaskPropertyDefinition.java
@@ -22,17 +22,17 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions copyright 2014 ForgeRock AS.
 */
package org.forgerock.opendj.config;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.AddressMask;
import org.forgerock.util.Reject;
import java.util.EnumSet;
import org.opends.server.types.AddressMask;
/**
 * IP address mask property definition.
 */
@@ -100,8 +100,8 @@
        Reject.ifNull(value);
        try {
            return AddressMask.decode(value);
        } catch (ConfigException e) {
            return AddressMask.valueOf(value);
        } catch (LocalizedIllegalArgumentException e) {
            // TODO: it would be nice to throw the cause.
            throw PropertyException.illegalPropertyValueException(this, value);
        }
opendj-config/src/main/java/org/forgerock/opendj/config/PropertyValueVisitor.java
@@ -28,10 +28,10 @@
import java.net.InetAddress;
import org.forgerock.opendj.ldap.AddressMask;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.authorization.dseecompat.Aci;
import org.opends.server.types.AddressMask;
/**
 * A visitor of property values, in the style of the visitor design pattern.
opendj-config/src/main/java/org/opends/server/types/package-info.java
File was deleted
opendj-core/src/main/java/org/forgerock/opendj/ldap/AddressMask.java
File was renamed from opendj-config/src/main/java/org/opends/server/types/AddressMask.java
@@ -22,11 +22,11 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2011-2013 ForgeRock AS
 *      Portions copyright 2011-2014 ForgeRock AS
 */
package org.opends.server.types;
package org.forgerock.opendj.ldap;
import static com.forgerock.opendj.ldap.ProtocolMessages.*;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -34,13 +34,11 @@
import java.util.BitSet;
import java.util.Collection;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
/**
 * This class defines an address mask, which can be used to perform efficient
 * comparisons against IP addresses to determine whether a particular IP address
 * is in a given range.
 * An address mask can be used to perform efficient comparisons against IP
 * addresses to determine whether a particular IP address is in a given range.
 */
public final class AddressMask {
    /**
@@ -62,34 +60,20 @@
    private static final int IPV6MAXPREFIX = 128;
    /**
     * Decodes the provided string as an address mask.
     *
     * @param maskString
     *            The string to decode as an address mask.
     * @return AddressMask The address mask decoded from the provided string.
     * @throws ConfigException
     *             If the provided string cannot be decoded as an address mask.
     */
    public static AddressMask decode(final String maskString) throws ConfigException {
        return new AddressMask(maskString);
    }
    /**
     * Indicates whether provided address matches one of the address masks in
     * the provided collection.
     * Returns {@code true} if an address matches any of the provided address
     * masks.
     *
     * @param address
     *            The address to check.
     *            The address.
     * @param masks
     *            A collection of address masks to check.
     * @return <CODE>true</CODE> if the provided address matches one of the
     *         given address masks, or <CODE>false</CODE> if it does not.
     * @return {@code true} if an address matches any of the provided address
     *         masks.
     */
    public static boolean maskListContains(final InetAddress address, final Collection<AddressMask> masks) {
    public static boolean matchesAny(final Collection<AddressMask> masks, final InetAddress address) {
        if (address != null) {
            for (final AddressMask mask : masks) {
                if (mask.match(address)) {
                if (mask.matches(address)) {
                    return true;
                }
            }
@@ -97,6 +81,19 @@
        return false;
    }
    /**
     * Parses the provided string as an address mask.
     *
     * @param mask
     *            The address mask string to be parsed.
     * @return The parsed address mask.
     * @throws LocalizedIllegalArgumentException
     *             If the provided string cannot be decoded as an address mask.
     */
    public static AddressMask valueOf(final String mask) {
        return new AddressMask(mask);
    }
    // Array that holds each component of a hostname.
    private String[] hostName;
@@ -115,15 +112,7 @@
    // Bit array that holds wildcard info for above binary arrays.
    private final BitSet wildCard = new BitSet();
    /**
     * Address mask constructor.
     *
     * @param rule
     *            The rule string to process.
     * @throws ConfigException
     *             If the rule string is not valid.
     */
    private AddressMask(final String rule) throws ConfigException {
    private AddressMask(final String rule) {
        determineRuleType(rule);
        switch (ruleType) {
        case IPv6:
@@ -149,71 +138,13 @@
    }
    /**
     * Retrieves a string representation of this address mask.
     *
     * @return A string representation of this address mask.
     */
    @Override
    public String toString() {
        return ruleString;
    }
    /**
     * Try to determine what type of rule string this is. See RuleType above for
     * valid types.
     *
     * @param ruleString
     *            The rule string to be examined.
     * @throws ConfigException
     *             If the rule type cannot be determined from the rule string.
     */
    private void determineRuleType(final String ruleString) throws ConfigException {
        // Rule ending with '.' is invalid'
        if (ruleString.endsWith(".")) {
            final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(message);
        } else if (ruleString.startsWith(".")) {
            ruleType = RuleType.HOSTPATTERN;
        } else if (ruleString.startsWith("[") || (ruleString.indexOf(':') != -1)) {
            ruleType = RuleType.IPv6;
        } else {
            int wildCount = 0;
            final String[] s = ruleString.split("\\.", -1);
            /*
             * Try to figure out how many wildcards and if the rule is hostname
             * (can't begin with digit) or ipv4 address. Default to IPv4
             * ruletype.
             */
            ruleType = RuleType.HOST;
            for (final String value : s) {
                if (value.equals("*")) {
                    wildCount++;
                    continue;
                }
                // Looks like an ipv4 address
                if (Character.isDigit(value.charAt(0))) {
                    ruleType = RuleType.IPv4;
                    break;
                }
            }
            // All wildcards (*.*.*.*)
            if (wildCount == s.length) {
                ruleType = RuleType.ALLWILDCARD;
            }
        }
    }
    /**
     * Main match function that determines which rule-type match function to
     * use.
     * Returns {@code true} if this address mask matches the provided address.
     *
     * @param address
     *            The address to check.
     * @return <CODE>true</CODE>if one of the match functions found a match or
     *         <CODE>false</CODE>if not.
     *            The address.
     * @return {@code true} if this address mask matches the provided address.
     */
    private boolean match(final InetAddress address) {
    public boolean matches(final InetAddress address) {
        boolean ret = false;
        switch (ruleType) {
@@ -245,6 +176,61 @@
    }
    /**
     * Returns the string representation of this address mask.
     *
     * @return The string representation of this address mask.
     */
    @Override
    public String toString() {
        return ruleString;
    }
    /**
     * Try to determine what type of rule string this is. See RuleType above for
     * valid types.
     *
     * @param ruleString
     *            The rule string to be examined.
     * @throws LocalizedIllegalArgumentException
     *             If the rule type cannot be determined from the rule string.
     */
    private void determineRuleType(final String ruleString) {
        // Rule ending with '.' is invalid'
        if (ruleString.endsWith(".")) {
            throw genericDecodeError();
        } else if (ruleString.startsWith(".")) {
            ruleType = RuleType.HOSTPATTERN;
        } else if (ruleString.startsWith("[") || ruleString.indexOf(':') != -1) {
            ruleType = RuleType.IPv6;
        } else {
            int wildCount = 0;
            final String[] s = ruleString.split("\\.", -1);
            /*
             * Try to figure out how many wildcards and if the rule is hostname
             * (can't begin with digit) or ipv4 address. Default to IPv4
             * ruletype.
             */
            ruleType = RuleType.HOST;
            for (final String value : s) {
                if (value.equals("*")) {
                    wildCount++;
                    continue;
                }
                // Looks like an ipv4 address
                if (Character.isDigit(value.charAt(0))) {
                    ruleType = RuleType.IPv4;
                    break;
                }
            }
            // All wildcards (*.*.*.*)
            if (wildCount == s.length) {
                ruleType = RuleType.ALLWILDCARD;
            }
        }
    }
    /**
     * Try to match remote client address using prefix mask and rule mask.
     *
     * @param remoteMask
@@ -309,7 +295,8 @@
     */
    private boolean matchPattern(final String remoteHostName) {
        final int len = remoteHostName.length() - hostPattern.length();
        return len > 0 && remoteHostName.regionMatches(true, len, hostPattern, 0, hostPattern.length());
        return len > 0
                && remoteHostName.regionMatches(true, len, hostPattern, 0, hostPattern.length());
    }
    /**
@@ -324,7 +311,7 @@
            this.prefixMask[i] = (byte) 0xff;
            prefix -= 8;
        }
        this.prefixMask[i] = (byte) ((0xff) << (8 - prefix));
        this.prefixMask[i] = (byte) (0xff << 8 - prefix);
    }
    /**
@@ -349,15 +336,14 @@
     *
     * @param rule
     *            The rule string.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the rule string is not a valid host name.
     */
    private void processHost(final String rule) throws ConfigException {
    private void processHost(final String rule) {
        // Note that '*' is valid in host rule
        final String []s = rule.split("^[0-9a-zA-z-.*]+");
        if (s.length > 0) {
            final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(message);
            throw genericDecodeError();
        }
        hostName = rule.split("\\.", -1);
    }
@@ -368,15 +354,14 @@
     *
     * @param rule
     *            The rule string to examine.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the rule string is not a valid host pattern rule.
     */
    private void processHostPattern(final String rule) throws ConfigException {
    private void processHostPattern(final String rule) {
        // quick check for invalid chars like " "
        final String []s = rule.split("^[0-9a-zA-z-.]+");
        if (s.length > 0) {
            final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(message);
            throw genericDecodeError();
        }
        hostPattern = rule;
    }
@@ -387,15 +372,15 @@
     *
     * @param rule
     *            The rule string containing the IPv4 rule.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the rule string is not a valid IPv4 rule.
     */
    private void processIpv4(final String rule) throws ConfigException {
    private void processIpv4(final String rule) {
        final String[] s = rule.split("/", -1);
        this.ruleMask = new byte[IN4ADDRSZ];
        this.prefixMask = new byte[IN4ADDRSZ];
        prefixMask(processPrefix(s, IPV4MAXPREFIX));
        processIPv4Subnet((s.length == 0) ? rule : s[0]);
        processIPv4Subnet(s.length == 0 ? rule : s[0]);
    }
    /**
@@ -404,16 +389,15 @@
     *
     * @param subnet
     *            The subnet string part of the rule.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the subnet string is not a valid IPv4 subnet string.
     */
    private void processIPv4Subnet(final String subnet) throws ConfigException {
    private void processIPv4Subnet(final String subnet) {
        final String[] s = subnet.split("\\.", -1);
        try {
            // Make sure we have four parts
            if (s.length != IN4ADDRSZ) {
                final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
                throw new ConfigException(message);
                throw genericDecodeError();
            }
            for (int i = 0; i < IN4ADDRSZ; i++) {
                final String quad = s[i].trim();
@@ -422,16 +406,14 @@
                } else {
                    final long val = Integer.parseInt(quad);
                    // must be between 0-255
                    if ((val < 0) || (val > 0xff)) {
                        final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
                        throw new ConfigException(message);
                    if (val < 0 || val > 0xff) {
                        throw genericDecodeError();
                    }
                    ruleMask[i] = (byte) (val & 0xff);
                }
            }
        } catch (final NumberFormatException nfex) {
            final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(message);
            throw genericDecodeError();
        }
    }
@@ -441,17 +423,16 @@
     *
     * @param rule
     *            The rule string containing the IPv6 rule.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the rule string is not a valid IPv6 rule.
     */
    private void processIPv6(final String rule) throws ConfigException {
    private void processIPv6(final String rule) {
        final String[] s = rule.split("/", -1);
        InetAddress addr;
        try {
            addr = InetAddress.getByName(s[0]);
        } catch (final UnknownHostException ex) {
            final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(message);
            throw genericDecodeError();
        }
        if (addr instanceof Inet6Address) {
            this.ruleType = RuleType.IPv6;
@@ -465,8 +446,7 @@
             * the rule has a prefix.
             */
            if (s.length == 2) {
                final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
                throw new ConfigException(message);
                throw genericDecodeError();
            }
            this.ruleMask = addr.getAddress();
            this.ruleType = RuleType.IPv4;
@@ -483,33 +463,35 @@
     * @param maxPrefix
     *            The max value the prefix can be.
     * @return The prefix integer value.
     * @throws ConfigException
     * @throws LocalizedIllegalArgumentException
     *             If the string array and prefix are not valid.
     */
    private int processPrefix(final String[] s, final int maxPrefix) throws ConfigException {
    private int processPrefix(final String[] s, final int maxPrefix) {
        int prefix = maxPrefix;
        try {
            // can only have one prefix value and a subnet string
            if ((s.length < 1) || (s.length > 2)) {
                final LocalizableMessage message = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
                throw new ConfigException(message);
            if (s.length < 1 || s.length > 2) {
                throw genericDecodeError();
            } else if (s.length == 2) {
                // can't have wildcard with a prefix
                if (s[0].indexOf('*') > -1) {
                    final LocalizableMessage message = ERR_ADDRESSMASK_WILDCARD_DECODE_ERROR.get();
                    throw new ConfigException(message);
                    throw new LocalizedIllegalArgumentException(
                            ERR_ADDRESSMASK_WILDCARD_DECODE_ERROR.get());
                }
                prefix = Integer.parseInt(s[1]);
            }
            // must be between 0-maxprefix
            if ((prefix < 0) || (prefix > maxPrefix)) {
                final LocalizableMessage message = ERR_ADDRESSMASK_PREFIX_DECODE_ERROR.get();
                throw new ConfigException(message);
            if (prefix < 0 || prefix > maxPrefix) {
                throw new LocalizedIllegalArgumentException(ERR_ADDRESSMASK_PREFIX_DECODE_ERROR
                        .get());
            }
        } catch (final NumberFormatException nfex) {
            final LocalizableMessage msg = ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get();
            throw new ConfigException(msg);
            throw genericDecodeError();
        }
        return prefix;
    }
    private LocalizedIllegalArgumentException genericDecodeError() {
        return new LocalizedIllegalArgumentException(ERR_ADDRESSMASK_FORMAT_DECODE_ERROR.get());
    }
}
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -22,7 +22,7 @@
#
#
#      Copyright 2010 Sun Microsystems, Inc.
#      Portions copyright 2011-2013 ForgeRock AS
#      Portions copyright 2011-2014 ForgeRock AS
#
ERR_ATTR_SYNTAX_UNKNOWN_APPROXIMATE_MATCHING_RULE=Unable to retrieve \
 approximate matching rule %s used as the default for the %s attribute syntax. \
@@ -1548,3 +1548,11 @@
ERR_ENTRY_GENERATOR_EXCEPTION_DURING_PARSE=An error occurred while \
 attempting to parse the template file:  %s
ERR_ENTRY_GENERATOR_MISSING_TEMPLATE_FILE=Unexpected error when initializing config : no template file provided as input
ERR_ADDRESSMASK_PREFIX_DECODE_ERROR=Cannot decode the provided \
 address mask prefix because an invalid value was specified. The permitted \
 values for IPv4are 0 to32 and for IPv6 0 to128
ERR_ADDRESSMASK_WILDCARD_DECODE_ERROR=Cannot decode the provided \
 address mask because an prefix mask was specified with an wild card "*" match \
 character
ERR_ADDRESSMASK_FORMAT_DECODE_ERROR=Cannot decode the provided \
 address mask because the it has an invalid format
opendj-core/src/test/java/org/forgerock/opendj/ldap/AddressMaskTestCase.java
New file
@@ -0,0 +1,252 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at legal-notices/CDDLv1_0.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions copyright 2011-2014 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
public class AddressMaskTestCase extends SdkTestCase {
    /* These are all valid rules -- should all pass. */
    @DataProvider(name = "validRules")
    public Object[][] validData() {
        return new Object[][] { { "129.34.55.67" }, { "129.*.78.55" }, { ".central.sun.com" },
            { "foo.central.sun.com" }, { "foo.*.sun.*" }, { "128.*.*.*" }, { "129.45.23.67/22" },
            { "128.33.23.21/32" }, { "*.*.*.*" }, { "129.45.67.34/0" }, { "foo.com" }, { "foo" } };
    }
    @DataProvider(name = "invalidRules")
    public Object[][] invalidData() {
        return new Object[][] { { "129.*.900.67" }, { "129.67" }, { "   " },
            { "129.56.78.90/2000" }, { "677.777.AG.BC" }, { "/34" }, { "234.12.12.*/31" },
            { "234.12.12.90/" }, { "129.34.56.78/-100" }, { "129" }, { "129.34.-90.67" },
            { "129.**.56.67" }, { "foo bar.com" }, { "12foo.example.com" }, { "123.45." },
            { ".central.sun day.com" }, { "129.34.45.45/4/3/" } };
    }
    @DataProvider(name = "toStringRule")
    public Object[][] toStringData() {
        return new Object[][] { { "129.35.45.66/12" } };
    }
    @Test(dataProvider = "validRules")
    public void testValidDecode(String mask) {
        AddressMask.valueOf(mask);
    }
    @Test(expectedExceptions = LocalizedIllegalArgumentException.class,
            dataProvider = "invalidRules")
    public void testInvalidDecode(String mask) throws Exception {
        AddressMask.valueOf(mask);
    }
    @DataProvider(name = "matchRules")
    public Object[][] ruleMatchData() {
        // @Checkstyle:off
        return new Object[][] { {
            //Rules
            new String[] { "129.56.*.22", //1
                "*.domain.com", //2
                "foo.example.com", //3
                "126.67.89.90", //4
                "90.89.78.67/30", //5
                ".test.com", //6
                "128.153.147.32/21", //7
                "128.153.146.32/26", //8
                "90.89.78.67/26" }, //9
            //Addresses
            new String[] { "128.153.147.45", //rule 7
                "128.153.146.60", //rule 8
                "148.45.45.46", //host
                "129.56.78.22", //rule 1
                "148.45.45.47", //host
                "148.45.45.48", //host
                "90.89.78.65" }, //rule 5
            //Hostnames
            new String[] { "some.host.name", //addr
                "some.host.name", //addr
                "foo.example.com", //rule 3
                "some.host.name", //addr
                "foo.test.com", //rule 6
                "foo.domain.com", //rule 2
                "some.host.name" //addr
            } } };
        // @Checkstyle:on
    }
    @DataProvider(name = "noMatchRules")
    public Object[][] ruleNoMatchData() {
        // @Checkstyle:off
        return new Object[][] { {
            // Rule to not match
            new String[] { "129.56.*.22", //1
                "*.domain.com", //2
                "foo.example.com", //3
                "126.67.89.90", //4
                "90.89.78.67/30", //5
                ".test.com", //6
                "128.153.147.32/21", //7
                "128.153.146.32/26", //8
                "90.89.78.67/26" }, //9
            //Addresses
            new String[] { "128.153.140.45", "128.153.143.255", "148.45.45.46", "126.56.78.22",
                "148.45.45.47", "148.45.45.48", "90.89.78.128", "148.45.45.49" },
            //Hostnames
            new String[] { "some.host.name", "some.host.name", "foo.examplee.com",
                "some.host.name", "foo.ttest.com", "foo.domain.comm", "some.host.name", "f.e.c",
                "foo.domain.cm" } } };
        // @Checkstyle:on
    }
    @DataProvider(name = "matchWCRules")
    public Object[][] ruleMatchWCData() {
        // @Checkstyle:off
        return new Object[][] { {
            //Rules
            new String[] { "*.*.*", "*.*.*.*" },
            //Addresses
            new String[] { "129.34.45.12", "129.34.45.13" },
            //Hostnames
            new String[] { "some.host.name", "some.host.name" } } };
        // @Checkstyle:on
    }
    @Test(dataProvider = "matchRules")
    public void testMatch(String[] rules, String[] addrs, String[] hostNames) throws Exception {
        assertTrue(match(rules, addrs, hostNames));
    }
    @Test(dataProvider = "matchWCRules")
    public void testWildCardMatch(String[] rules, String[] addrs, String[] hostNames)
            throws Exception {
        assertTrue(match(rules, addrs, hostNames));
    }
    @Test(dataProvider = "noMatchRules")
    public void testNoMatch(String[] rules, String[] addrs, String[] hostNames) throws Exception {
        assertFalse(match(rules, addrs, hostNames));
    }
    @Test(dataProvider = "toStringRule")
    public void testToString(String rule) {
        AddressMask m = AddressMask.valueOf(rule);
        assertEquals(rule, m.toString());
    }
    @Test
    public void testNullMatch() {
        AddressMask m = AddressMask.valueOf("*.*.*.*");
        assertFalse(AddressMask.matchesAny(Arrays.asList(m), null));
    }
    private boolean match(String[] rules, String[] addrs, String[] hostNames)
            throws UnknownHostException {
        int i = 0;
        Collection<AddressMask> m = new ArrayList<AddressMask>(rules.length);
        for (i = 0; i < rules.length; i++) {
            m.add(AddressMask.valueOf(rules[i]));
        }
        for (int j = 0; j < addrs.length; j++) {
            InetAddress addr =
                    InetAddress.getByAddress(hostNames[j], InetAddress.getByName(addrs[j])
                            .getAddress());
            if (!AddressMask.matchesAny(m, addr)) {
                return false;
            }
        }
        return true;
    }
    /*
     * IPV6 data and tests.
     */
    //Invalid IPv6 expressions.
    @DataProvider(name = "invalid6Rules")
    public Object[][] inValid6Data() {
        return new Object[][] { { "2001:feca:ba23:cd1f:dcb1:1010:9234:4088///124" },
            { "2001:feca:ba23:cd1f:dcb1:1010:9234:4088?124" },
            { "2001:fecz:ba23:cd1f:dcb1:1010:9234:4088/124" },
            { "2001:fecd:ba23:cd1ff:dcb1:1010:9234:4088/46" }, { "0:0:0:0:0:ffff:101..45.75.219" },
            { "0:0:0:0:0:0:101.45.75.700" }, { "1080::8:800:200C:417A/500" },
            { "1080::8:800:*:417A/66" }, { "2001:fecd:ba23:cd1ff:dcb1:1010:202.45.66.20" }, };
    }
    //Valid IPv6 expressions.
    @DataProvider(name = "valid6Rules")
    public Object[][] valid6Data() {
        return new Object[][] { { "2001:fecd:ba23:cd1f:dcb1:1010:9234:4088/124" },
            { "2001:fecd:ba23:cd1f:dcb1:1010:9234:4088" },
            { "[2001:fecd:ba23:cd1f:dcb1:1010:9234:4088]/45" }, { "::/128" }, { "::1/128" },
            { "::" }, { "0:0:0:0:0:ffff:101.45.75.219" }, { "1080::8:800:200C:417A" },
            { "0:0:0:0:0:0:101.45.75.219" }, { "::101.45.75.219" } };
    }
    @DataProvider(name = "match6Rules")
    public Object[][] ruleMatch6Data() {
        // @Checkstyle:off
        return new Object[][] { {
            //IPV6 Rules
            new String[] { "[12ab:0:0:cd30::]/60", "::ffff:72.56.78.9", "::", "42ab:0:0:dd30::" },
            //IPv6 Addresses
            new String[] { "12ab:0:0:cd3f:0000:0000:23DC:DC30", "72.56.78.9", "::",
                "42ab:0000:0000:dd30:0000:0000:0000:0000" },
            //ignored Hostnames
            new String[] { "ignored.host.name", "ignored.host.name", "ignored.host.name",
                "ignored.host.name" } } };
        // @Checkstyle:on
    }
    @Test(dataProvider = "valid6Rules")
    public void testValid6Decode(String mask) {
        AddressMask.valueOf(mask);
    }
    @Test(expectedExceptions = LocalizedIllegalArgumentException.class,
            dataProvider = "invalid6Rules")
    public void testInvalid6Decode(String mask) {
        AddressMask.valueOf(mask);
    }
    @Test(dataProvider = "match6Rules")
    public void testMatch6(String[] rules, String[] addrs, String[] hostNames)
            throws UnknownHostException {
        assertTrue(match(rules, addrs, hostNames));
    }
}