All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.developerdan.blocklist.tools.Domain Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
package com.developerdan.blocklist.tools;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.IDN;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Optional;

public final class Domain implements Comparable {

    private final String name;
    private static final Logger LOGGER = LoggerFactory.getLogger(Domain.class);

    private Domain(String name) {
        this.name = normalize(name);
    }

    public static Optional fromUrl(final String url) {
        try {
            var uri = new URI(url);
            return Domain.fromString(uri.getHost());
        } catch (URISyntaxException ex) {
            // not a URL, maybe is just a host
            return Domain.fromString(url);
        }
    }

    public static Optional fromString(final String domainInput) {
        var domain = new Domain(domainInput);
        if (domain.isValid()) {
            return Optional.of(domain);
        }
        return Optional.empty();
    }

    public boolean isValid() {
        return !name.isEmpty();
    }

    @Override
    public String toString() {
        return name;
    }

    private static String normalize(final String domain) {
        if (domain == null
            || domain.length() > 255
            || domain.startsWith("-")
            || domain.endsWith("-")
            || domain.endsWith(".")
            || domain.matches(".*[~!%\\*\\(\\)\"\\s'#`<>\\?=&@\\\\\\^\\]\\[{}:\\$\\|/\\+;].*")
            || domain.matches(".*\\.\\d+$")
            || domain.matches(".*[\\s]+.*")
        ) {
            LOGGER.info("Domain <{}> is not valid", domain);
            return "";
        }
        try {
            var normalized = IDN.toASCII(domain);
            normalized = IDN.toASCII(normalized);
            return normalized.toLowerCase(Locale.ENGLISH);
        } catch (IllegalArgumentException ex) {
            LOGGER.info("Domain <{}> is not valid: {}", domain, ex.getMessage());
            return "";
        }
    }

    private ArrayList domainParts()
    {
        var domainParts = Arrays.asList(name.split("\\.", -1));
        Collections.reverse(domainParts);
        return new ArrayList<>(domainParts);
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other == null || getClass() != other.getClass()) {
            return false;
        }
        Domain otherDomain = (Domain) other;
        return name.equals(otherDomain.name);
    }

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

    @Override
    public int compareTo(Domain other) {
        if (other == null) {
            return 1;
        }
        if (this.equals(other)) {
            return 0;
        }

        var domainParts = domainParts();
        var otherDomainParts = other.domainParts();
        var index = 0;
        for (String part: domainParts) {
            if (otherDomainParts.size() <= index) {
                return 1;
            }
            var comparison = part.compareTo(otherDomainParts.get(index));
            if (comparison != 0) {
                return comparison;
            }
            index++;
        }
        // we know that the domains are not equal, and we've already looped
        // through all our sections, so 'other' must be longer
        return -1;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy