Changeset 19689 in josm for trunk/test/unit


Ignore:
Timestamp:
2026-11-12T18:02:08+01:00 (11 hours ago)
Author:
stoecker
Message:

fix #25029 - fix DomainValidatorTestIT, update TLDs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/data/validation/routines/DomainValidatorTestIT.java

    r19527 r19689  
    3232import java.net.HttpURLConnection;
    3333import java.net.IDN;
    34 import java.net.URL;
     34import java.net.URI;
    3535import java.nio.charset.StandardCharsets;
    3636import java.nio.file.Files;
    … …  
    4343import java.util.Set;
    4444import java.util.TreeMap;
    45 import java.util.regex.Matcher;
    46 import java.util.regex.Pattern;
     45
     46import jakarta.json.Json;
     47import jakarta.json.JsonArray;
     48import jakarta.json.JsonObject;
     49import jakarta.json.JsonReader;
     50import jakarta.json.JsonValue;
    4751
    4852import org.junit.jupiter.api.Test;
    … …  
    5054import org.openstreetmap.josm.testutils.annotations.IntegrationTest;
    5155import org.openstreetmap.josm.tools.Logging;
    52 
    53 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    5456
    5557/**
    … …  
    8385        File txtFile = new File(System.getProperty("java.io.tmpdir"), "tlds-alpha-by-domain.txt");
    8486        long timestamp;
     87        String tlds = "https://data.iana.org/TLD/tlds-alpha-by-domain.txt";
    8588        try {
    86             timestamp = download(txtFile, "http://data.iana.org/TLD/tlds-alpha-by-domain.txt", 0L);
     89            timestamp = download(txtFile, tlds, 0L);
    8790        } catch (ConnectException e) {
    8891            Logging.error(e);
    8992            // Try again one more time in case of random network issue
    90             timestamp = download(txtFile, "http://data.iana.org/TLD/tlds-alpha-by-domain.txt", 0L);
    91         }
    92         final File htmlFile = new File(System.getProperty("java.io.tmpdir"), "tlds-alpha-by-domain.html");
    93         // N.B. sometimes the html file may be updated a day or so after the txt file
    94         // if the txt file contains entries not found in the html file, try again in a day or two
    95         download(htmlFile, "http://www.iana.org/domains/root/db", timestamp);
     93            timestamp = download(txtFile, tlds, 0L);
     94        }
     95        final File jsonFile = new File(System.getProperty("java.io.tmpdir"), "tlds-alpha-by-domain.json");
     96        // N.B. sometimes the JSON data may be updated a day or so after the txt file
     97        // if the txt file contains entries not found in the JSON file, try again in a day or two
     98        download(jsonFile, "https://data.iana.org/TLD/v1/tlds.json", timestamp);
    9699
    97100        try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(txtFile.toPath()), StandardCharsets.UTF_8))) {
    … …  
    106109            final boolean generateUnicodeTlds = false; // Change this to generate Unicode TLDs as well
    107110
    108             // Parse html page to get entries
    109             Map<String, String[]> htmlInfo = getHtmlInfo(htmlFile);
     111            // Parse JOSN to get entries
     112            Map<String, String[]> jsonInfo = getJSONInfo(jsonFile);
    110113            Map<String, String> missingTLD = new TreeMap<>(); // stores entry and comments as String[]
    111114            Map<String, String> missingCC = new TreeMap<>();
    … …  
    121124                        unicodeTld = asciiTld;
    122125                    }
    123                     String[] info = htmlInfo.get(asciiTld);
     126                    String[] info = jsonInfo.get(asciiTld);
    124127                    if (info != null) {
    125128                        String type = info[0];
    126                         String comment = info[1].replaceAll("&quot;", "\"").replaceAll("&#x27;", "'").replaceAll("&amp;", "&");
     129                        String comment = info[1];
    127130                        if ("country-code".equals(type)) { // Which list to use?
    128131                            if (!dv.isValidInfrastructureTld(asciiTld)) {
    … …  
    150153                                }
    151154                            }
    152                         } else {
    153                             Logging.error("Expected to find HTML info for "+ asciiTld);
    154155                        }
     156                    } else {
     157                        Logging.error("Expected to find JSON information for "+ asciiTld);
    155158                    }
    156159                    ianaTlds.add(asciiTld);
    … …  
    163166                }
    164167            }
    165             // List html entries not in TLD text list
    166             for (String key : (new TreeMap<>(htmlInfo)).keySet()) {
     168            // List JSON entries not in TLD text list
     169            for (String key : (new TreeMap<>(jsonInfo)).keySet()) {
    167170                if (!ianaTlds.contains(key)) {
    168                     if (isNotInRootZone(key)) {
    169                         Logging.info("HTML entry not yet in root zone: "+key);
    170                     } else {
    171                         Logging.warn("Expected to find text entry for html: "+key);
    172                     }
     171                    Logging.warn("Expected to find text entry for JSON: "+key);
    173172                }
    174173            }
    … …  
    177176            if (s != null) /* text too long, shorten a bit */
    178177                allTLD.replace("melbourne", s.replace("represented by its ", ""));
    179             printMap(header, allTLD, "allTLD");
    180             printMap(header, allCC, "allCC");
     178            printMap(header, allTLD, "allTLD", "in");
     179            printMap(header, allCC, "allCC", "in");
    181180            if (!missingTLD.isEmpty()) {
    182                 printMap(header, missingTLD, "TLD");
     181                printMap(header, missingTLD, "TLD", "missing from");
    183182                fail("missing TLD");
    184183            }
    185184            if (!missingCC.isEmpty()) {
    186                 printMap(header, missingCC, "CC");
     185                printMap(header, missingCC, "CC", "missing from");
    187186                fail("missing CC");
    188187            }
    … …  
    195194    }
    196195
    197     private static void printMap(final String header, Map<String, String> map, String string) {
    198         Logging.warn("Entries missing from "+ string +" List\n");
     196    private static void printMap(final String header, Map<String, String> map, String string, String mode) {
     197        Logging.warn("Entries " + mode + " "+ string +" List\n");
    199198        if (header != null) {
    200199            Logging.warn("        // Taken from " + header);
    … …  
    206205    }
    207206
    208     @SuppressFBWarnings(value = "PERFORMANCE")
    209     private static Map<String, String[]> getHtmlInfo(final File f) throws IOException {
     207    private static Map<String, String[]> getJSONInfo(final File f) throws IOException {
    210208        final Map<String, String[]> info = new HashMap<>();
    211209
    212         final Pattern domain = Pattern.compile(".*<a href=\"/domains/root/db/([^.]+)\\.html");
    213         final Pattern type = Pattern.compile("\\s+<td>([^<]+)</td>");
    214         final Pattern comment = Pattern.compile("\\s+<td>([^<]+)</td>");
    215 
    216         try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(f.toPath()), StandardCharsets.UTF_8))) {
    217             String line;
    218             while ((line = br.readLine()) != null) {
    219                 Matcher m = domain.matcher(line);
    220                 if (m.lookingAt()) {
    221                     String dom = m.group(1);
    222                     String typ = "??";
     210        try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(f.toPath()), StandardCharsets.UTF_8));
     211            JsonReader reader = Json.createReader(br)) {
     212           
     213            JsonObject root = reader.readObject();
     214            JsonArray domains = root.getJsonArray("domains");
     215
     216            if (domains != null) {
     217                for (JsonValue val : domains) {
     218                    JsonObject domainNode = val.asJsonObject();
     219                   
     220                    String dom = domainNode.getString("name", "");
     221                    String typ = domainNode.getString("type", "??");
     222                    String status = domainNode.getString("status", "");
     223
    223224                    String com = "??";
    224                     line = br.readLine();
    225                     while (line != null && line.matches("^\\s*$")) { // extra blank lines introduced
    226                         line = br.readLine();
    227                     }
    228                     Matcher t = type.matcher(line);
    229                     if (t.lookingAt()) {
    230                         typ = t.group(1);
    231                         line = br.readLine();
    232                         if (line != null && line.matches("\\s+<!--.*")) {
    233                             while (line != null && !line.matches(".*-->.*")) {
    234                                 line = br.readLine();
    235                             }
    236                             line = br.readLine();
     225                    if (domainNode.containsKey("manager") && !domainNode.isNull("manager")) {
     226                        JsonObject managerNode = domainNode.getJsonObject("manager");
     227                        if (managerNode != null && managerNode.containsKey("organization") && !managerNode.isNull("organization")) {
     228                            com = managerNode.getString("organization", "??");
    237229                        }
    238                         // Should have comment; is it wrapped?
    239                         while (line != null && !line.matches(".*</td>.*")) {
    240                             line += " " +br.readLine();
    241                         }
    242                         Matcher n = comment.matcher(line);
    243                         if (n.lookingAt()) {
    244                             com = n.group(1);
    245                         }
    246                         // Don't save unused entries
    247                         if (!com.contains("Not assigned") && !com.contains("Retired") && !typ.equals("test")) {
    248                             info.put(dom.toLowerCase(Locale.ENGLISH), new String[]{typ, com});
    249                         }
    250                     } else {
    251                         Logging.error("Unexpected type: " + line);
     230                    }
     231
     232                    boolean isRetired = "retired".equalsIgnoreCase(status);
     233                    boolean isTest = "test".equalsIgnoreCase(typ);
     234                    boolean isNotAssigned = com.contains("Not assigned") || com.equals("??");
     235
     236                    if (!isRetired && !isTest && !isNotAssigned) {
     237                        info.put(dom.toLowerCase(Locale.ENGLISH), new String[]{typ, com});
    252238                    }
    253239                }
    … …  
    260246     * Download a file if it is more recent than our cached copy.
    261247     * Unfortunately the server does not seem to honour If-Modified-Since for the
    262      * Html page, so we check if it is newer than the txt file and skip download if so
     248     * page, so we check if it is newer than the txt file and skip download if so
    263249     */
    264250    private static long download(File f, String tldurl, long timestamp) throws IOException {
    … …  
    275261            modTime = 0;
    276262        }
    277         HttpURLConnection hc = (HttpURLConnection) new URL(tldurl).openConnection();
     263        HttpURLConnection hc = (HttpURLConnection) URI.create(tldurl).toURL().openConnection();
    278264        if (modTime > 0) {
    279265            SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); //Sun, 06 Nov 1994 08:49:37 GMT
    … …  
    288274            byte[] buff = new byte[1024];
    289275            try (InputStream is = hc.getInputStream();
    290                  FileOutputStream fos = new FileOutputStream(f)) {
    291                 int len;
    292                 while ((len = is.read(buff)) != -1) {
    293                     fos.write(buff, 0, len);
     276                FileOutputStream fos = new FileOutputStream(f)) {
     277                    int len;
     278                    while ((len = is.read(buff)) != -1) {
     279                        fos.write(buff, 0, len);
    294280                }
    295281            }
    … …  
    297283        }
    298284        return f.lastModified();
    299     }
    300 
    301     /**
    302      * Check whether the domain is in the root zone currently.
    303      * Reads the URL http://www.iana.org/domains/root/db/*domain*.html
    304      * (using a local disk cache)
    305      * and checks for the string "This domain is not present in the root zone at this time."
    306      * @param domain the domain to check
    307      * @return true if the string is found
    308      */
    309     private static boolean isNotInRootZone(String domain) {
    310         String tldurl = "http://www.iana.org/domains/root/db/" + domain + ".html";
    311         BufferedReader in = null;
    312         try {
    313             File rootCheck = new File(System.getProperty("java.io.tmpdir"), "tld_" + domain + ".html");
    314             download(rootCheck, tldurl, 0L);
    315             in = new BufferedReader(new InputStreamReader(Files.newInputStream(rootCheck.toPath()), StandardCharsets.UTF_8));
    316             String inputLine;
    317             while ((inputLine = in.readLine()) != null) {
    318                 if (inputLine.contains("This domain is not present in the root zone at this time.")) {
    319                     return true;
    320                 }
    321             }
    322             in.close();
    323         } catch (IOException e) {
    324             e.printStackTrace();
    325         } finally {
    326             closeQuietly(in);
    327         }
    328         return false;
    329285    }
    330286
Note: See TracChangeset for help on using the changeset viewer.