We have hardcoded Unix-style newlines in PluginInfo.toString. We should use `System.lineSeparator()` instead.
server/src/main/java/org/elasticsearch/plugins/PluginInfo.java
throw new IllegalArgumentException("property [elasticsearch.version] is missing for plugin [" + name + "]");
        }
        final Version esVersion = Version.fromString(esVersionString);
        final String javaVersionString = propsMap.remove("java.version");
        if (javaVersionString == null) {
            throw new IllegalArgumentException("property [java.version] is missing for plugin [" + name + "]");
        }
        JarHell.checkJavaVersion("plugin " + name, javaVersionString);
        final String extendedString = propsMap.remove("extended.plugins");
        final List<String> extendedPlugins;
        if (extendedString == null) {
            extendedPlugins = Collections.emptyList();
        } else {
            extendedPlugins = Arrays.asList(Strings.delimitedListToStringArray(extendedString, ","));
        }
        final boolean hasNativeController = parseBooleanValue(name, "has.native.controller", propsMap.remove("has.native.controller"));
        final PluginType type = getPluginType(name, propsMap.remove("type"));
        final String classname = getClassname(name, type, propsMap.remove("classname"));
        String modulename = propsMap.remove("modulename");
        if (modulename != null && modulename.isBlank()) {
            modulename = null;
        }
        final String javaOpts = propsMap.remove("java.opts");
        if (type != PluginType.BOOTSTRAP && Strings.isNullOrEmpty(javaOpts) == false) {
            throw new IllegalArgumentException(
                "[java.opts] can only have a value when [type] is set to [bootstrap] for plugin [" + name + "]"
            );
        }
        boolean isLicensed = parseBooleanValue(name, "licensed", propsMap.remove("licensed"));
        if (propsMap.isEmpty() == false) {