void readOperatingSystemList(String initialOperatingSystemJson) throws IOException {
        JSONArray systems = JSONArray.fromObject(initialOperatingSystemJson);
        if (systems.isEmpty()) {
            throw new IOException("Empty data set");
        }
        for (Object systemObj : systems) {
            if (!(systemObj instanceof JSONObject)) {
                throw new IOException("Wrong object type in data file");
            }
            JSONObject system = (JSONObject) systemObj;

            if (!system.has("pattern")) {
                throw new IOException("Missing pattern in definition file");
            }
            String pattern = system.getString("pattern");

            if (!system.has("endOfLife")) {
                throw new IOException("No end of life date for " + pattern);
            }
            LocalDate endOfLife = LocalDate.parse(system.getString("endOfLife"));

            /* Start date defaults to 6 months before end of life */
            LocalDate startDate = system.has("start") ? LocalDate.parse(system.getString("start")) : endOfLife.minusMonths(6);

            File dataFile = getDataFile(system);

            LOGGER.log(Level.FINEST, "Pattern {0} starts {1} and reaches end of life {2} from file {3}",
                    new Object[]{pattern, startDate, endOfLife, dataFile});

            String name = readOperatingSystemName(dataFile, pattern);
            if (name.isEmpty()) {
                LOGGER.log(Level.FINE, "Pattern {0} did not match from file {1}",
                        new Object[]{pattern, dataFile});
                continue;
            }

            if (startDate.isBefore(warningsStartDate)) {
                warningsStartDate = startDate;
                LOGGER.log(Level.FINE, "Warnings start date is now {0}", warningsStartDate);
            }

            LOGGER.log(Level.FINE, "Matched operating system {0}", name);
            if (startDate.isBefore(LocalDate.now())) {
                this.operatingSystemName = name;
                this.documentationUrl = buildDocumentationUrl(this.operatingSystemName);
                this.endOfLifeDate = endOfLife.toString();
                if (endOfLife.isBefore(LocalDate.now())) {
                    LOGGER.log(Level.FINE, "Operating system {0} is after end of life {1}",
                            new Object[]{name, endOfLife});
                    afterEndOfLifeDate = true;
                } else {
                    LOGGER.log(Level.FINE, "Operating system {0} started warnings {1} and reaches end of life {2}",
                            new Object[]{name, startDate, endOfLife});
                }
            }
        }
        if (lastLines != null) {
            // Discard the cached contents of the last read file
            lastLines.clear();
        }
    }
@Test
    public void testReadOperatingSystemListNoEndOfLife() {
        IOException e = assertThrows(IOException.class, () -> monitor.readOperatingSystemList("[{\"pattern\": \"Alpine\"}]"));
        assertThat(e.getMessage(), is("No end of life date for Alpine"));
    }