Package com.hazelcast.util

Source Code of com.hazelcast.util.AddressUtil$InvalidAddressException

/*
* Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
*
* 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.
*/

package com.hazelcast.util;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;

public final class AddressUtil {

    private static final int NUMBER_OF_ADDRESSES = 255;

    private AddressUtil() {
    }

    public static boolean matchAnyInterface(String address, Collection<String> interfaces) {
        if (interfaces == null || interfaces.size() == 0) {
            return false;
        }
        for (String interfaceMask : interfaces) {
            if (matchInterface(address, interfaceMask)) {
                return true;
            }
        }
        return false;
    }

    public static boolean matchInterface(String address, String interfaceMask) {
        final AddressMatcher mask;
        try {
            mask = getAddressMatcher(interfaceMask);
        } catch (Exception e) {
            return false;
        }
        return mask.match(address);
    }

    public static boolean matchAnyDomain(String name, Collection<String> patterns) {
        if (patterns == null || patterns.size() == 0) {
            return false;
        }
        for (String pattern : patterns) {
            if (matchDomain(name, pattern)) {
                return true;
            }
        }
        return false;
    }

    public static boolean matchDomain(String name, String pattern) {
        final int index = pattern.indexOf('*');
        if (index == -1) {
            return name.equals(pattern);
        } else {
            String[] names = name.split("\\.");
            String[] patterns = pattern.split("\\.");
            if (patterns.length > names.length) {
                return false;
            }
            int nameIndexDiff = names.length - patterns.length;
            for (int i = patterns.length - 1; i > -1; i--) {
                if ("*".equals(patterns[i])) {
                    continue;
                }
                if (!patterns[i].equals(names[i + nameIndexDiff])) {
                    return false;
                }
            }
            return true;
        }
    }

    public static AddressHolder getAddressHolder(String address) {
        return getAddressHolder(address, -1);
    }

    public static AddressHolder getAddressHolder(final String address, int defaultPort) {
        final int indexBracketStart = address.indexOf('[');
        final int indexBracketEnd = address.indexOf(']', indexBracketStart);
        final int indexColon = address.indexOf(':');
        final int lastIndexColon = address.lastIndexOf(':');
        String host;
        int port = defaultPort;
        String scopeId = null;
        if (indexColon > -1 && lastIndexColon > indexColon) {
            // IPv6
            if (indexBracketStart == 0 && indexBracketEnd > indexBracketStart) {
                host = address.substring(indexBracketStart + 1, indexBracketEnd);
                if (lastIndexColon == indexBracketEnd + 1) {
                    port = Integer.parseInt(address.substring(lastIndexColon + 1));
                }
            } else {
                host = address;
            }
            final int indexPercent = host.indexOf('%');
            if (indexPercent != -1) {
                scopeId = host.substring(indexPercent + 1);
                host = host.substring(0, indexPercent);
            }
        } else if (indexColon > 0 && indexColon == lastIndexColon) {
            host = address.substring(0, indexColon);
            port = Integer.parseInt(address.substring(indexColon + 1));
        } else {
            host = address;
        }
        return new AddressHolder(host, port, scopeId);
    }

    public static boolean isIpAddress(String address) {
        try {
            getAddressMatcher(address);
            return true;
        } catch (InvalidAddressException e) {
            return false;
        }
    }

    public static InetAddress fixScopeIdAndGetInetAddress(final InetAddress inetAddress) throws SocketException {
        Inet6Address resultInetAddress = null;
        if (inetAddress instanceof Inet6Address &&
                (inetAddress.isLinkLocalAddress() || inetAddress.isSiteLocalAddress())) {
            final Inet6Address inet6Address = (Inet6Address) inetAddress;
            if (inet6Address.getScopeId() <= 0 && inet6Address.getScopedInterface() == null) {
                Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
                while (interfaces.hasMoreElements()) {
                    NetworkInterface ni = interfaces.nextElement();
                    Enumeration<InetAddress> addresses = ni.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = addresses.nextElement();
                        if (address instanceof Inet6Address &&
                                Arrays.equals(address.getAddress(), inet6Address.getAddress())) {
                            if (resultInetAddress != null) {
                                throw new IllegalArgumentException("This address " + inet6Address +
                                        " is bound to more than one network interface!");
                            }
                            resultInetAddress = (Inet6Address) address;
                        }
                    }
                }
            }
        }
        return resultInetAddress == null ? inetAddress : resultInetAddress;
    }

    public static Inet6Address getInetAddressFor(final Inet6Address inetAddress, String scope)
            throws UnknownHostException, SocketException {
        if (inetAddress.isLinkLocalAddress() || inetAddress.isSiteLocalAddress()) {
            final char[] chars = scope.toCharArray();
            boolean numeric = true;
            for (char c : chars) {
                if (!Character.isDigit(c)) {
                    numeric = false;
                    break;
                }
            }
            if (numeric) {
                return Inet6Address.getByAddress(null, inetAddress.getAddress(), Integer.parseInt(scope));
            } else {
                return Inet6Address.getByAddress(null, inetAddress.getAddress(), NetworkInterface.getByName(scope));
            }
        }
        return inetAddress;
    }

    public static Collection<Inet6Address> getPossibleInetAddressesFor(final Inet6Address inet6Address) {
        if ((inet6Address.isSiteLocalAddress() || inet6Address.isLinkLocalAddress())
                && inet6Address.getScopeId() <= 0 && inet6Address.getScopedInterface() == null) {
            final LinkedList<Inet6Address> possibleAddresses = new LinkedList<Inet6Address>();
            try {
                final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
                while (interfaces.hasMoreElements()) {
                    NetworkInterface ni = interfaces.nextElement();
                    Enumeration<InetAddress> addresses = ni.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = addresses.nextElement();
                        if (address instanceof Inet4Address) {
                            continue;
                        }
                        if (inet6Address.isLinkLocalAddress() && address.isLinkLocalAddress()
                                || inet6Address.isSiteLocalAddress() && address.isSiteLocalAddress()) {
                            final Inet6Address newAddress = Inet6Address.getByAddress(null, inet6Address.getAddress(),
                                    ((Inet6Address) address).getScopeId());
                            possibleAddresses.addFirst(newAddress);
                        }
                    }
                }
            } catch (IOException ignored) {
            }
            if (possibleAddresses.isEmpty()) {
                throw new IllegalArgumentException("Could not find a proper network interface" +
                        " to connect to " + inet6Address);
            }
            return possibleAddresses;
        }
        return Collections.singleton(inet6Address);
    }

    public static Collection<String> getMatchingIpv4Addresses(final AddressMatcher addressMatcher) {
        if (addressMatcher.isIPv6()) {
            throw new IllegalArgumentException("Cannot wildcard matching for IPv6: " + addressMatcher);
        }
        final Collection<String> addresses = new HashSet<String>();
        final String first3 = addressMatcher.address[0] + "." +
                addressMatcher.address[1] + "." +
                addressMatcher.address[2;
        final String lastPart = addressMatcher.address[3];
        final int dashPos ;
        if ("*".equals(lastPart)) {
            for (int j = 0; j <= NUMBER_OF_ADDRESSES; j++) {
                addresses.add(first3 + "." + j);
            }
        } else if ((dashPos = lastPart.indexOf('-')) > 0) {
            final int start = Integer.parseInt(lastPart.substring(0, dashPos));
            final int end = Integer.parseInt(lastPart.substring(dashPos + 1));
            for (int j = start; j <= end; j++) {
                addresses.add(first3 + "." + j);
            }
        } else {
            addresses.add(addressMatcher.getAddress());
        }
        return addresses;
    }

    /**
     * Gets an AddressMatcher for a given addresses.
     *
     * @param address the address
     * @return the returned AddressMatcher. The returned value will never be null.
     * @throws com.hazelcast.util.AddressUtil.InvalidAddressException if the address is not valid.
     */
    public static AddressMatcher getAddressMatcher(String address) {
        final AddressMatcher matcher;
        final int indexColon = address.indexOf(':');
        final int lastIndexColon = address.lastIndexOf(':');
        final int indexDot = address.indexOf('.');
        final int lastIndexDot = address.lastIndexOf('.');

        if (indexColon > -1 && lastIndexColon > indexColon) {
            if (indexDot == -1) {
                matcher = new Ip6AddressMatcher();
                parseIpv6(matcher, address);
            } else {
                // IPv4 mapped IPv6
                if (indexDot >= lastIndexDot) {
                    throw new InvalidAddressException(address);
                }
                final int lastIndexColon2 = address.lastIndexOf(':');
                final String host2 = address.substring(lastIndexColon2 + 1);
                matcher = new Ip4AddressMatcher();
                parseIpv4(matcher, host2);
            }
        } else if (indexDot > -1 && lastIndexDot > indexDot && indexColon == -1) {
            // IPv4
            matcher = new Ip4AddressMatcher();
            parseIpv4(matcher, address);
        } else {
            throw new InvalidAddressException(address);
        }
        return matcher;
    }

    private static void parseIpv4(AddressMatcher matcher, String address) {
        final String[] parts = address.split("\\.");
        if (parts.length != 4) {
            throw new InvalidAddressException(address);
        }
        for (String part : parts) {
            if (!isValidIpAddressPart(part, false)) {
                throw new InvalidAddressException(address);
            }
        }
        matcher.setAddress(parts);
    }

    private static boolean isValidIpAddressPart(String part, boolean ipv6) {
        if (part.length() == 1 && "*".equals(part)) {
            return true;
        }
        final int rangeIndex = part.indexOf('-');
        if (rangeIndex > -1 &&
                (rangeIndex != part.lastIndexOf('-') || rangeIndex == part.length() - 1)) {
            return false;
        }
        final String[] subParts;
        if (rangeIndex > -1) {
            subParts = part.split("\\-");
        } else {
            subParts = new String[]{part};
        }
        for (String subPart : subParts) {
            try {
                final int num;
                if (ipv6) {
                    num = Integer.parseInt(subPart, 16);
                    if (num > 65535) {
                        return false;
                    }
                } else {
                    num = Integer.parseInt(subPart);
                    if (num > 255) {
                        return false;
                    }
                }
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return true;
    }

    private static void parseIpv6(AddressMatcher matcher, String address) {
        if (address.indexOf('%') > -1) {
            String[] parts = address.split("\\%");
            address = parts[0];
        }
        final String[] parts = address.split("((?<=:)|(?=:))");
        final LinkedList<String> ipString = new LinkedList<String>();
        int count = 0;
        int mark = -1;
        for (int i = 0; i < parts.length; i++) {
            String part = parts[i];
            String nextPart = i < parts.length - 1 ? parts[i + 1] : null;
            if ("".equals(part)) {
                continue;
            }
            if (":".equals(part) && ":".equals(nextPart)) {
                if (mark != -1) {
                    throw new InvalidAddressException(address);
                }
                mark = count;
            } else if (!":".equals(part)) {
                count++;
                ipString.add(part);
            }
        }
        if (mark > -1) {
            final int remaining = (8 - count);
            for (int i = 0; i < remaining; i++) {
                ipString.add((i + mark), "0");
            }
        }
        if (ipString.size() != 8) {
            throw new InvalidAddressException(address);
        }
        final String[] addressParts = ipString.toArray(new String[ipString.size()]);
        for (String part : addressParts) {
            if (!isValidIpAddressPart(part, true)) {
                throw new InvalidAddressException(address);
            }
        }
        matcher.setAddress(addressParts);
    }

    // ----------------- UTILITY CLASSES ------------------

    public static class AddressHolder {

        public final String address;
        public final String scopeId;
        public final int port;

        public AddressHolder(final String address, final int port,
                             final String scopeId) {
            this.address = address;
            this.scopeId = scopeId;
            this.port = port;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            sb.append("AddressHolder ");
            sb.append('[').append(address).append("]:").append(port);
            return sb.toString();
        }
    }

    /**
     * http://docs.oracle.com/javase/1.5.0/docs/guide/net/ipv6_guide/index.html
     */

    public static abstract class AddressMatcher {

        protected final String[] address;

        protected AddressMatcher(final String[] address) {
            this.address = address;
        }

        public abstract boolean isIPv4();

        public abstract boolean isIPv6();

        public abstract void setAddress(String ip[]);

        protected final boolean match(final String[] mask, String[] input, int radix) {
            if (input != null && mask != null) {
                for (int i = 0; i < mask.length; i++) {
                    if (!doMatch(mask[i], input[i], radix)) {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        protected final boolean doMatch(final String mask, String input, int radix) {
            final int dashIndex = mask.indexOf('-');
            final int ipa = Integer.parseInt(input, radix);
            if ("*".equals(mask)) {
                return true;
            } else if (dashIndex != -1) {
                final int start = Integer.parseInt(mask.substring(0, dashIndex).trim(), radix);
                final int end = Integer.parseInt(mask.substring(dashIndex + 1).trim(), radix);
                if (ipa >= start && ipa <= end) {
                    return true;
                }
            } else {
                final int x = Integer.parseInt(mask, radix);
                if (x == ipa) {
                    return true;
                }
            }
            return false;
        }

        public abstract String getAddress();

        public abstract boolean match(AddressMatcher matcher);

        public boolean match(final String address) {
            try {
                return match(getAddressMatcher(address));
            } catch (Exception e) {
                return false;
            }
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            sb.append(getClass().getSimpleName());
            sb.append('{');
            sb.append(getAddress());
            sb.append('}');
            return sb.toString();
        }
    }

    static class Ip4AddressMatcher extends AddressMatcher {

        public Ip4AddressMatcher() {
            super(new String[4])// d.d.d.d
        }

        public boolean isIPv4() {
            return true;
        }

        public boolean isIPv6() {
            return false;
        }

        public void setAddress(String ip[]) {
            System.arraycopy(ip, 0, this.address, 0, ip.length);
        }

        public boolean match(final AddressMatcher matcher) {
            if (matcher.isIPv6()) return false;
            final String[] mask = this.address;
            final String[] input = ((Ip4AddressMatcher) matcher).address;
            return match(mask, input, 10);
        }

        public String getAddress() {
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < address.length; i++) {
                sb.append(address[i]);
                if (i != address.length - 1) {
                    sb.append('.');
                }
            }
            return sb.toString();
        }
    }

    static class Ip6AddressMatcher extends AddressMatcher {

        public Ip6AddressMatcher() {
            super(new String[8])// x:x:x:x:x:x:x:x%s
        }

        public boolean isIPv4() {
            return false;
        }

        public boolean isIPv6() {
            return true;
        }

        public void setAddress(String ip[]) {
            System.arraycopy(ip, 0, this.address, 0, ip.length);
        }

        public boolean match(final AddressMatcher matcher) {
            if (matcher.isIPv4()) return false;
            final Ip6AddressMatcher a = (Ip6AddressMatcher) matcher;
            final String[] mask = this.address;
            final String[] input = a.address;
            return match(mask, input, 16);
        }

        public String getAddress() {
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < address.length; i++) {
                sb.append(address[i]);
                if (i != address.length - 1) {
                    sb.append(':');
                }
            }
            return sb.toString();
        }
    }

    public static class InvalidAddressException extends IllegalArgumentException {

        public InvalidAddressException(final String s) {
            super("Illegal IP address format: " + s);
        }
    }
}
TOP

Related Classes of com.hazelcast.util.AddressUtil$InvalidAddressException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.