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

org.elasticsearch.ReleaseVersions Maven / Gradle / Ivy

There is a newer version: 8.15.1
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch;

import org.elasticsearch.common.Strings;
import org.elasticsearch.core.UpdateForV9;
import org.elasticsearch.internal.BuildExtension;
import org.elasticsearch.plugins.ExtensionLoader;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableMap;
import java.util.ServiceLoader;
import java.util.TreeMap;
import java.util.function.IntFunction;
import java.util.regex.Pattern;

public class ReleaseVersions {

    private static final boolean USES_VERSIONS;

    static {
        USES_VERSIONS = ExtensionLoader.loadSingleton(ServiceLoader.load(BuildExtension.class))
            .map(BuildExtension::hasReleaseVersioning)
            .orElse(true);
    }

    private static final Pattern VERSION_LINE = Pattern.compile("(\\d+\\.\\d+\\.\\d+),(\\d+)");

    public static IntFunction generateVersionsLookup(Class versionContainer) {
        if (USES_VERSIONS == false) return Integer::toString;

        try {
            String versionsFileName = versionContainer.getSimpleName() + ".csv";
            InputStream versionsFile = versionContainer.getResourceAsStream(versionsFileName);
            if (versionsFile == null) {
                throw new FileNotFoundException(Strings.format("Could not find versions file for class [%s]", versionContainer));
            }

            NavigableMap> versions = new TreeMap<>();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(versionsFile, StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    var matcher = VERSION_LINE.matcher(line);
                    if (matcher.matches() == false) {
                        throw new IOException(Strings.format("Incorrect format for line [%s] in [%s]", line, versionsFileName));
                    }
                    try {
                        Integer id = Integer.valueOf(matcher.group(2));
                        Version version = Version.fromString(matcher.group(1));
                        versions.computeIfAbsent(id, k -> new ArrayList<>()).add(version);
                    } catch (IllegalArgumentException e) {
                        // cannot happen??? regex is wrong...
                        assert false : "Regex allowed non-integer id or incorrect version through: " + e;
                        throw new IOException(Strings.format("Incorrect format for line [%s] in [%s]", line, versionsFileName), e);
                    }
                }
            }

            // replace all version lists with the smallest & greatest versions
            versions.replaceAll((k, v) -> {
                if (v.size() == 1) {
                    return List.of(v.get(0));
                } else {
                    v.sort(Comparator.naturalOrder());
                    return List.of(v.get(0), v.get(v.size() - 1));
                }
            });

            return lookupFunction(versions);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private static IntFunction lookupFunction(NavigableMap> versions) {
        assert versions.values().stream().allMatch(vs -> vs.size() == 1 || vs.size() == 2)
            : "Version ranges have not been properly processed: " + versions;

        return id -> {
            List versionRange = versions.get(id);

            String lowerBound, upperBound;
            if (versionRange != null) {
                lowerBound = versionRange.get(0).toString();
                upperBound = lastItem(versionRange).toString();
            } else {
                // infer the bounds from the surrounding entries
                var lowerRange = versions.lowerEntry(id);
                if (lowerRange != null) {
                    // the next version is just a guess - might be a newer revision, might be a newer minor or major...
                    lowerBound = nextVersion(lastItem(lowerRange.getValue())).toString();
                } else {
                    // a really old version we don't have a record for
                    // assume it's an old version id - we can just return it directly
                    // this will no longer be the case with ES 10 (which won't know about ES v8.x where we introduced separated versions)
                    // maybe keep the release mapping around in the csv file?
                    // SEP for now
                    @UpdateForV9
                    // @UpdateForV10
                    Version oldVersion = Version.fromId(id);
                    return oldVersion.toString();
                }

                var upperRange = versions.higherEntry(id);
                if (upperRange != null) {
                    // too hard to guess what version this id might be for using the next version - just use it directly
                    upperBound = upperRange.getValue().get(0).toString();
                } else {
                    // likely a version created after the last release tagged version - ok
                    upperBound = "snapshot[" + id + "]";
                }
            }

            return lowerBound.equals(upperBound) ? lowerBound : lowerBound + "-" + upperBound;
        };
    }

    private static  T lastItem(List list) {
        return list.get(list.size() - 1);
    }

    private static Version nextVersion(Version version) {
        return new Version(version.id + 100);   // +1 to revision
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy