Modularize Elasticsearch (#81066)

This PR represents the initial phase of Modularizing Elasticsearch (with
Java Modules).

This initial phase modularizes the core of the Elasticsearch server
with Java Modules, which is then used to load and configure extension
components atop the server. Only a subset of extension components are
modularized at this stage (other components come in a later phase).
Components are loaded dynamically at runtime with custom class loaders
(same as is currently done). Components with a module-info.class are
defined to a module layer.

This architecture is somewhat akin to the Modular JDK, where
applications run on the classpath. In the analogy, the Elasticsearch
server modules are the platform (thus are always resolved and present),
while components without a module-info.class are non-modular code
running atop the Elasticsearch server modules. The extension components
cannot access types from non-exported packages of the server modules, in
the same way that classpath applications cannot access types from
non-exported packages of modules from the JDK. Broadly, the core
Elasticseach java modules simply "wrap" the existing packages and export
them. There are opportunites to export less, which is best done in more
narrowly focused follow-up PRs.

The Elasticsearch distribution startup scripts are updated to put jars
on the module path (the class path is empty), so the distribution will
run the core of the server as java modules. A number of key components
have been retrofitted with module-info.java's too, and the remaining
components can follow later. Unit and functional tests run as
non-modular (since they commonly require package-private access), while
higher-level integration tests, that run the distribution, run as
modular.

Co-authored-by: Chris Hegarty <christopher.hegarty@elastic.co>
Co-authored-by: Ryan Ernst <ryan@iernst.net>
Co-authored-by: Rene Groeschke <rene@elastic.co>
This commit is contained in:
Chris Hegarty 2022-05-20 13:11:42 +01:00 committed by GitHub
parent f06da24c8f
commit 3071c6a055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 1648 additions and 44 deletions

View File

@ -6,5 +6,8 @@
<option name="m_ignoreExpressionsContainingConstants" value="true" />
</inspection_tool>
<inspection_tool class="jol" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="IllegalDependencyOnInternalPackage" enabled="true" level="ERROR" enabled_by_default="false">
<scope name="Production" level="ERROR" enabled="true" />
</inspection_tool>
</profile>
</component>
</component>

View File

@ -8,6 +8,8 @@
package org.elasticsearch.gradle.internal
import spock.lang.IgnoreIf
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.fixtures.AbstractJavaGradleFuncTest
import org.gradle.internal.os.OperatingSystem
@ -17,6 +19,7 @@ import org.objectweb.asm.tree.ClassNode
import java.nio.file.Files
@IgnoreIf({ os.isWindows() })
class ElasticsearchJavaModulePathPluginFuncTest extends AbstractJavaGradleFuncTest {
public static final GString JAVA_BASE_MODULE = "java.base:${System.getProperty("java.version")}"

View File

@ -159,6 +159,7 @@ public class ElasticsearchJavaModulePathPlugin implements Plugin<Project> {
}
if (isModuleProject) {
extraArgs.add("--module-version=" + VersionProperties.getElasticsearch());
extraArgs.add("-Xlint:-module,-exports,-requires-automatic,-requires-transitive-automatic,-missing-explicit-ctor");
}
return List.copyOf(extraArgs);
}

View File

@ -43,6 +43,7 @@ public class ElasticsearchJavaPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
project.getPluginManager().apply(JavaLibraryPlugin.class);
project.getPluginManager().apply(ElasticsearchJavaModulePathPlugin.class);
// configureConfigurations(project);
configureJars(project);
@ -137,5 +138,4 @@ public class ElasticsearchJavaPlugin implements Plugin<Project> {
// ensure javadoc task is run with 'check'
project.getTasks().named(LifecycleBasePlugin.CHECK_TASK_NAME).configure(t -> t.dependsOn(javadoc));
}
}

View File

@ -55,13 +55,17 @@ public class InternalDistributionArchiveCheckPlugin implements InternalPlugin {
// sanity checks if archives can be extracted
TaskProvider<Copy> checkExtraction = registerCheckExtractionTask(project, buildDistTask, archiveExtractionDir);
TaskProvider<Task> checkLicense = registerCheckLicenseTask(project, checkExtraction);
TaskProvider<Task> checkNotice = registerCheckNoticeTask(project, checkExtraction);
TaskProvider<Task> checkModulesTask = InternalDistributionModuleCheckTaskProvider.registerCheckModulesTask(
project,
checkExtraction
);
TaskProvider<Task> checkTask = project.getTasks().named("check");
checkTask.configure(task -> {
task.dependsOn(checkExtraction);
task.dependsOn(checkLicense);
task.dependsOn(checkNotice);
task.dependsOn(checkModulesTask);
});
String projectName = project.getName();

View File

@ -0,0 +1,129 @@
/*
* 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.gradle.internal;
import org.elasticsearch.gradle.VersionProperties;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.TaskProvider;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import static java.util.stream.Collectors.joining;
/**
* Distribution level checks for Elasticsearch Java modules, i.e. modular jar files.
* Currently, ES modular jar files are in the lib directory.
*/
public class InternalDistributionModuleCheckTaskProvider {
private static final Logger LOGGER = Logging.getLogger(InternalDistributionModuleCheckTaskProvider.class);
private static final String MODULE_INFO = "module-info.class";
private static final String ES_JAR_PREFIX = "elasticsearch-";
/** ES jars in the lib directory that are not modularized. For now, es-log4j is the only one. */
private static final List<String> ES_JAR_EXCLUDES = List.of("elasticsearch-log4j");
/** List of the current Elasticsearch Java Modules, by name. */
private static final List<String> EXPECTED_ES_SERVER_MODULES = List.of(
"org.elasticsearch.base",
"org.elasticsearch.cli",
"org.elasticsearch.geo",
"org.elasticsearch.lz4",
"org.elasticsearch.pluginclassloader",
"org.elasticsearch.securesm",
"org.elasticsearch.server",
"org.elasticsearch.xcontent"
);
private static final Predicate<ModuleReference> isESModule = mref -> mref.descriptor().name().startsWith("org.elasticsearch");
private static Predicate<Path> isESJar = path -> path.getFileName().toString().startsWith(ES_JAR_PREFIX);
private static Predicate<Path> isNotExcluded = path -> ES_JAR_EXCLUDES.stream()
.filter(path.getFileName().toString()::startsWith)
.findAny()
.isEmpty();
private static final Function<ModuleReference, String> toName = mref -> mref.descriptor().name();
private InternalDistributionModuleCheckTaskProvider() {};
/** Registers the checkModules tasks, which contains all checks relevant to ES Java Modules. */
static TaskProvider<Task> registerCheckModulesTask(Project project, TaskProvider<Copy> checkExtraction) {
return project.getTasks().register("checkModules", task -> {
task.dependsOn(checkExtraction);
task.doLast(new Action<Task>() {
@Override
public void execute(Task task) {
final Path libPath = checkExtraction.get()
.getDestinationDir()
.toPath()
.resolve("elasticsearch-" + VersionProperties.getElasticsearch())
.resolve("lib");
try {
assertAllESJarsAreModular(libPath);
assertAllModulesPresent(libPath);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
});
});
}
/** Checks that all expected ES jar files are modular, i.e. contain a module-info.class in their root. */
private static void assertAllESJarsAreModular(Path libPath) throws IOException {
try (var s = Files.walk(libPath, 1)) {
s.filter(Files::isRegularFile).filter(isESJar).filter(isNotExcluded).sorted().forEach(path -> {
try (JarFile jf = new JarFile(path.toFile())) {
JarEntry entry = jf.getJarEntry(MODULE_INFO);
if (entry == null) {
throw new GradleException(MODULE_INFO + " no found in " + path);
}
} catch (IOException e) {
throw new GradleException("Failed when reading jar file " + path, e);
}
});
}
}
/** Checks that all expected Elasticsearch modules are present. */
private static void assertAllModulesPresent(Path libPath) {
List<String> actualESModules = ModuleFinder.of(libPath).findAll().stream().filter(isESModule).map(toName).sorted().toList();
if (actualESModules.equals(EXPECTED_ES_SERVER_MODULES) == false) {
throw new GradleException(
"expected modules " + listToString(EXPECTED_ES_SERVER_MODULES) + ", \nactual modules " + listToString(actualESModules)
);
}
}
// ####: eventually assert hashes, etc
static String listToString(List<String> list) {
return list.stream().sorted().collect(joining("\n ", "[\n ", "]"));
}
}

View File

@ -44,6 +44,7 @@ public class InternalPrecommitTasks {
project.getPluginManager().apply(ThirdPartyAuditPrecommitPlugin.class);
project.getPluginManager().apply(DependencyLicensesPrecommitPlugin.class);
project.getPluginManager().apply(SplitPackagesAuditPrecommitPlugin.class);
project.getPluginManager().apply(JavaModulePrecommitPlugin.class);
}
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.gradle.internal.precommit;
import org.elasticsearch.gradle.internal.InternalPlugin;
import org.elasticsearch.gradle.internal.conventions.precommit.PrecommitPlugin;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider;
public class JavaModulePrecommitPlugin extends PrecommitPlugin implements InternalPlugin {
public static final String TASK_NAME = "validateModule";
@Override
public TaskProvider<? extends Task> createTask(Project project) {
TaskProvider<JavaModulePrecommitTask> task = project.getTasks().register(TASK_NAME, JavaModulePrecommitTask.class);
task.configure(t -> {
SourceSet mainSourceSet = GradleUtils.getJavaSourceSets(project).findByName(SourceSet.MAIN_SOURCE_SET_NAME);
t.getSrcDirs().set(project.provider(() -> mainSourceSet.getAllSource().getSrcDirs()));
t.setClasspath(project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
t.setClassesDirs(mainSourceSet.getOutput().getClassesDirs());
t.setResourcesDirs(mainSourceSet.getOutput().getResourcesDir());
});
return task;
}
}

View File

@ -0,0 +1,164 @@
/*
* 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.gradle.internal.precommit;
import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.internal.conventions.precommit.PrecommitTask;
import org.gradle.api.GradleException;
import org.gradle.api.file.FileCollection;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.TaskAction;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
import static java.util.stream.Collectors.toSet;
public class JavaModulePrecommitTask extends PrecommitTask {
private static final String expectedVersion = VersionProperties.getElasticsearch();
private final SetProperty<File> srcDirs;
private FileCollection classesDirs;
private FileCollection classpath;
private File resourcesDir;
@Inject
public JavaModulePrecommitTask(ObjectFactory objectFactory) {
srcDirs = objectFactory.setProperty(File.class);
}
@InputFiles
public FileCollection getClassesDirs() {
return this.classesDirs;
}
public void setClassesDirs(FileCollection classesDirs) {
Objects.requireNonNull(classesDirs, "classesDirs");
this.classesDirs = classesDirs;
}
@InputFiles
public File getResourcesDir() {
return this.resourcesDir;
}
public void setResourcesDirs(File resourcesDirs) {
Objects.requireNonNull(resourcesDirs, "resourcesDirs");
this.resourcesDir = resourcesDirs;
}
@InputFiles
@SkipWhenEmpty
@PathSensitive(PathSensitivity.RELATIVE)
public SetProperty<File> getSrcDirs() {
return srcDirs;
}
@Classpath
@InputFiles
public FileCollection getClasspath() {
return classpath;
}
public void setClasspath(FileCollection classpath) {
this.classpath = classpath;
}
@TaskAction
public void checkModule() {
if (hasModuleInfoDotJava(getSrcDirs()) == false) {
return; // non-modular project, nothing to do
}
ModuleReference mod = esModuleFor(getClassesDirs().getSingleFile());
getLogger().info("%s checking module %s".formatted(this, mod));
checkModuleVersion(mod);
checkModuleNamePrefix(mod);
checkModuleServices(mod);
}
private void checkModuleVersion(ModuleReference mref) {
getLogger().info("%s checking module version for %s".formatted(this, mref.descriptor().name()));
String mVersion = mref.descriptor()
.rawVersion()
.orElseThrow(() -> new GradleException("no version found in module " + mref.descriptor().name()));
if (mVersion.equals(expectedVersion) == false) {
throw new GradleException("Expected version [" + expectedVersion + "], in " + mref.descriptor());
}
}
private void checkModuleNamePrefix(ModuleReference mref) {
getLogger().info("%s checking module name prefix for %s".formatted(this, mref.descriptor().name()));
if (mref.descriptor().name().startsWith("org.elasticsearch.") == false) {
throw new GradleException("Expected name starting with \"org.elasticsearch.\", in " + mref.descriptor());
}
}
private void checkModuleServices(ModuleReference mref) {
getLogger().info("%s checking module services for %s".formatted(this, mref.descriptor().name()));
Set<String> modServices = mref.descriptor().provides().stream().map(ModuleDescriptor.Provides::service).collect(toSet());
Path servicesRoot = getResourcesDir().toPath().resolve("META-INF").resolve("services");
getLogger().info("%s servicesRoot %s".formatted(this, servicesRoot));
if (Files.exists(servicesRoot)) {
try {
Files.walk(servicesRoot)
.filter(Files::isRegularFile)
.map(p -> servicesRoot.relativize(p))
.map(Path::toString)
.peek(s -> getLogger().info("%s checking service %s".formatted(this, s)))
.forEach(service -> {
if (modServices.contains(service) == false) {
throw new GradleException(
"Expected provides %s in module %s with provides %s.".formatted(
service,
mref.descriptor().name(),
mref.descriptor().provides()
)
);
}
});
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
private static boolean hasModuleInfoDotJava(SetProperty<File> srcDirs) {
return srcDirs.get().stream().map(dir -> dir.toPath().resolve("module-info.java")).anyMatch(Files::exists);
}
private static ModuleReference esModuleFor(File filePath) {
return ModuleFinder.of(filePath.toPath())
.findAll()
.stream()
.sorted(Comparator.comparing(ModuleReference::descriptor))
.findFirst()
.orElseThrow(() -> new GradleException("module not found in " + filePath));
}
}

View File

@ -4,6 +4,10 @@
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<property name="charset" value="UTF-8" />
<module name="SuppressionFilter">

View File

@ -15,6 +15,8 @@ for %%I in ("%ES_HOME%..") do set ES_HOME=%%~dpfI
rem now set the classpath
set ES_CLASSPATH=!ES_HOME!\lib\*
set ES_MODULEPATH=!ES_HOME!\lib
set LAUNCHERS_CLASSPATH=!ES_CLASSPATH!;!ES_HOME!\lib\launchers\*;!ES_HOME!\lib\java-version-checker\*
set SERVER_CLI_CLASSPATH=!ES_CLASSPATH!;!ES_HOME!\lib\tools\server-cli\*
set HOSTNAME=%COMPUTERNAME%

View File

@ -9,5 +9,7 @@ call "%~dp0elasticsearch-cli.bat" ^
%%* ^
|| goto exit
endlocal
endlocal
:exit
exit /b %ERRORLEVEL%

View File

@ -221,11 +221,10 @@ public class ServerProcess {
boolean isWindows = processInfo.sysprops().get("os.name").startsWith("Windows");
command.add(javaHome.resolve("bin").resolve("java" + (isWindows ? ".exe" : "")).toString());
command.addAll(jvmOptions);
command.add("-cp");
// The '*' isn't allowed by the windows filesystem, so we need to force it into the classpath after converting to a string.
// Thankfully this will all go away when switching to modules, which take the directory instead of a glob.
command.add(esHome.resolve("lib") + (isWindows ? "\\" : "/") + "*");
command.add("org.elasticsearch.bootstrap.Elasticsearch");
command.add("--module-path");
command.add(esHome.resolve("lib").toString());
command.add("-m");
command.add("org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch");
var builder = new ProcessBuilder(command);
builder.environment().putAll(envVars);

View File

@ -346,21 +346,20 @@ public class ServerProcessTests extends ESTestCase {
}
public void testCommandLine() throws Exception {
String mainClass = "org.elasticsearch.bootstrap.Elasticsearch";
String mainClass = "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch";
String distroSysprop = "-Des.distribution.type=testdistro";
String modulePath = esHomeDir.resolve("lib").toString();
Path javaBin = Paths.get("javahome").resolve("bin");
sysprops.put("es.distribution.type", "testdistro");
AtomicReference<String> expectedJava = new AtomicReference<>(javaBin.resolve("java").toString());
AtomicReference<String> expectedClasspath = new AtomicReference<>(esHomeDir.resolve("lib") + "/*");
processValidator = pb -> {
assertThat(pb.command(), hasItems(expectedJava.get(), distroSysprop, "-cp", expectedClasspath.get(), mainClass));
assertThat(pb.command(), hasItems(expectedJava.get(), distroSysprop, "--module-path", modulePath, "-m", mainClass));
};
runForeground();
sysprops.put("os.name", "Windows 10");
sysprops.put("java.io.tmpdir", createTempDir().toString());
expectedJava.set(javaBin.resolve("java.exe").toString());
expectedClasspath.set(esHomeDir.resolve("lib") + "\\*");
runForeground();
}

View File

@ -0,0 +1,15 @@
/*
* 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.
*/
/** Elasticsearch Command Line Interface. */
module org.elasticsearch.cli {
requires jopt.simple;
requires org.elasticsearch.base;
exports org.elasticsearch.cli;
}

View File

@ -0,0 +1,15 @@
/*
* 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.
*/
module org.elasticsearch.base {
requires static jsr305;
exports org.elasticsearch.core;
exports org.elasticsearch.jdk;
exports org.elasticsearch.core.internal.provider to org.elasticsearch.xcontent;
}

View File

@ -0,0 +1,12 @@
/*
* 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.
*/
module org.elasticsearch.geo {
exports org.elasticsearch.geometry;
exports org.elasticsearch.geometry.utils;
}

View File

@ -0,0 +1,13 @@
/*
* 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.
*/
module org.elasticsearch.lz4 {
requires org.lz4.java;
exports org.elasticsearch.lz4;
}

View File

@ -0,0 +1,11 @@
/*
* 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.
*/
module org.elasticsearch.pluginclassloader {
exports org.elasticsearch.plugins.loader;
}

View File

@ -0,0 +1,11 @@
/*
* 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.
*/
module org.elasticsearch.securesm {
exports org.elasticsearch.secure_sm;
}

View File

@ -0,0 +1,13 @@
/*
* 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.
*/
module org.elasticsearch.sslconfig {
requires org.elasticsearch.base;
exports org.elasticsearch.common.ssl;
}

View File

@ -0,0 +1,18 @@
/*
* 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.
*/
module org.elasticsearch.xcontent.impl {
requires com.fasterxml.jackson.core;
requires com.fasterxml.jackson.dataformat.cbor;
requires com.fasterxml.jackson.dataformat.smile;
requires com.fasterxml.jackson.dataformat.yaml;
requires org.elasticsearch.base;
requires org.elasticsearch.xcontent;
provides org.elasticsearch.xcontent.spi.XContentProvider with org.elasticsearch.xcontent.provider.XContentProviderImpl;
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
/**
* The X-Content module.
*/
module org.elasticsearch.xcontent {
requires org.elasticsearch.base;
exports org.elasticsearch.xcontent;
exports org.elasticsearch.xcontent.cbor;
exports org.elasticsearch.xcontent.json;
exports org.elasticsearch.xcontent.smile;
exports org.elasticsearch.xcontent.spi;
exports org.elasticsearch.xcontent.support;
exports org.elasticsearch.xcontent.support.filtering;
exports org.elasticsearch.xcontent.yaml;
uses org.elasticsearch.xcontent.ErrorOnUnknown;
uses org.elasticsearch.xcontent.XContentBuilderExtension;
uses org.elasticsearch.xcontent.spi.XContentProvider;
}

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
module org.elasticsearch.aggs.matrix {
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires org.apache.logging.log4j;
requires org.apache.lucene.core;
exports org.elasticsearch.search.aggregations.matrix;
exports org.elasticsearch.search.aggregations.matrix.stats;
provides org.elasticsearch.plugins.spi.NamedXContentProvider
with
org.elasticsearch.search.aggregations.matrix.spi.MatrixStatsNamedXContentProvider;
}

View File

@ -0,0 +1,14 @@
/*
* 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.
*/
module org.elasticsearch.painless.spi {
requires org.elasticsearch.server;
exports org.elasticsearch.painless.spi;
exports org.elasticsearch.painless.spi.annotation;
}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
module org.elasticsearch.painless {
requires org.elasticsearch.base;
requires org.elasticsearch.geo;
requires org.elasticsearch.painless.spi;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires antlr4.runtime;
requires org.apache.lucene.core;
requires org.objectweb.asm;
requires org.objectweb.asm.commons;
requires org.objectweb.asm.util;
exports org.elasticsearch.painless;
exports org.elasticsearch.painless.api;
exports org.elasticsearch.painless.action;
opens org.elasticsearch.painless to org.elasticsearch.painless.spi; // whitelist access
opens org.elasticsearch.painless.action to org.elasticsearch.server; // guice
}

View File

@ -0,0 +1,18 @@
/*
* 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.
*/
module org.elasticsearch.percolator {
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires org.apache.lucene.core;
requires org.apache.lucene.join;
requires org.apache.lucene.memory;
requires org.apache.lucene.queries;
requires org.apache.lucene.sandbox;
}

View File

@ -0,0 +1,18 @@
/*
* 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.
*/
module org.elasticsearch.rankeval {
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires org.elasticsearch.base;
requires java.naming;
exports org.elasticsearch.index.rankeval;
provides org.elasticsearch.plugins.spi.NamedXContentProvider with org.elasticsearch.index.rankeval.RankEvalNamedXContentProvider;
}

View File

@ -0,0 +1,24 @@
/*
* 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.
*/
module org.elasticsearch.transport.netty4 {
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires org.apache.logging.log4j;
requires org.apache.lucene.core;
requires io.netty.buffer;
requires io.netty.codec;
requires io.netty.common;
requires io.netty.handler;
requires io.netty.transport;
requires io.netty.codec.http;
exports org.elasticsearch.http.netty4;
exports org.elasticsearch.transport.netty4;
}

View File

@ -0,0 +1,18 @@
/*
* 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.
*/
module org.elasticsearch.analysis.icu {
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
requires com.ibm.icu;
requires org.apache.lucene.core;
requires org.apache.lucene.analysis.icu;
// exports nothing
}

View File

@ -0,0 +1,356 @@
/*
* 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.
*/
/** The Elasticsearch Server Module. */
module org.elasticsearch.server {
requires java.logging;
requires java.security.jgss;
requires java.sql;
requires java.management;
requires jdk.unsupported;
requires org.elasticsearch.cli;
requires org.elasticsearch.base;
requires org.elasticsearch.geo;
requires org.elasticsearch.lz4;
requires org.elasticsearch.pluginclassloader;
requires org.elasticsearch.securesm;
requires org.elasticsearch.xcontent;
requires com.sun.jna;
requires hppc;
requires HdrHistogram;
requires jopt.simple;
requires log4j2.ecs.layout;
requires org.lz4.java;
requires t.digest;
requires org.apache.logging.log4j;
requires org.apache.logging.log4j.core;
requires org.apache.lucene.analysis.common;
requires org.apache.lucene.backward_codecs;
requires org.apache.lucene.core;
requires org.apache.lucene.grouping;
requires org.apache.lucene.highlighter;
requires org.apache.lucene.join;
requires org.apache.lucene.memory;
requires org.apache.lucene.misc;
requires org.apache.lucene.queries;
requires org.apache.lucene.queryparser;
requires org.apache.lucene.sandbox;
requires org.apache.lucene.suggest;
exports org.elasticsearch;
exports org.elasticsearch.action;
exports org.elasticsearch.action.admin.cluster.allocation;
exports org.elasticsearch.action.admin.cluster.configuration;
exports org.elasticsearch.action.admin.cluster.health;
exports org.elasticsearch.action.admin.cluster.migration;
exports org.elasticsearch.action.admin.cluster.node.hotthreads;
exports org.elasticsearch.action.admin.cluster.node.info;
exports org.elasticsearch.action.admin.cluster.node.reload;
exports org.elasticsearch.action.admin.cluster.node.stats;
exports org.elasticsearch.action.admin.cluster.node.tasks.cancel;
exports org.elasticsearch.action.admin.cluster.node.tasks.get;
exports org.elasticsearch.action.admin.cluster.node.tasks.list;
exports org.elasticsearch.action.admin.cluster.node.usage;
exports org.elasticsearch.action.admin.cluster.remote;
exports org.elasticsearch.action.admin.cluster.repositories.cleanup;
exports org.elasticsearch.action.admin.cluster.repositories.delete;
exports org.elasticsearch.action.admin.cluster.repositories.get;
exports org.elasticsearch.action.admin.cluster.repositories.put;
exports org.elasticsearch.action.admin.cluster.repositories.verify;
exports org.elasticsearch.action.admin.cluster.reroute;
exports org.elasticsearch.action.admin.cluster.settings;
exports org.elasticsearch.action.admin.cluster.shards;
exports org.elasticsearch.action.admin.cluster.snapshots.clone;
exports org.elasticsearch.action.admin.cluster.snapshots.create;
exports org.elasticsearch.action.admin.cluster.snapshots.delete;
exports org.elasticsearch.action.admin.cluster.snapshots.features;
exports org.elasticsearch.action.admin.cluster.snapshots.get;
exports org.elasticsearch.action.admin.cluster.snapshots.get.shard;
exports org.elasticsearch.action.admin.cluster.snapshots.restore;
exports org.elasticsearch.action.admin.cluster.snapshots.status;
exports org.elasticsearch.action.admin.cluster.state;
exports org.elasticsearch.action.admin.cluster.stats;
exports org.elasticsearch.action.admin.cluster.storedscripts;
exports org.elasticsearch.action.admin.cluster.tasks;
exports org.elasticsearch.action.admin.indices.alias;
exports org.elasticsearch.action.admin.indices.alias.get;
exports org.elasticsearch.action.admin.indices.analyze;
exports org.elasticsearch.action.admin.indices.cache.clear;
exports org.elasticsearch.action.admin.indices.close;
exports org.elasticsearch.action.admin.indices.create;
exports org.elasticsearch.action.admin.indices.dangling;
exports org.elasticsearch.action.admin.indices.dangling.delete;
exports org.elasticsearch.action.admin.indices.dangling.find;
exports org.elasticsearch.action.admin.indices.dangling.import_index;
exports org.elasticsearch.action.admin.indices.dangling.list;
exports org.elasticsearch.action.admin.indices.delete;
exports org.elasticsearch.action.admin.indices.diskusage;
exports org.elasticsearch.action.admin.indices.flush;
exports org.elasticsearch.action.admin.indices.forcemerge;
exports org.elasticsearch.action.admin.indices.get;
exports org.elasticsearch.action.admin.indices.mapping.get;
exports org.elasticsearch.action.admin.indices.mapping.put;
exports org.elasticsearch.action.admin.indices.open;
exports org.elasticsearch.action.admin.indices.readonly;
exports org.elasticsearch.action.admin.indices.recovery;
exports org.elasticsearch.action.admin.indices.refresh;
exports org.elasticsearch.action.admin.indices.resolve;
exports org.elasticsearch.action.admin.indices.rollover;
exports org.elasticsearch.action.admin.indices.segments;
exports org.elasticsearch.action.admin.indices.settings.get;
exports org.elasticsearch.action.admin.indices.settings.put;
exports org.elasticsearch.action.admin.indices.shards;
exports org.elasticsearch.action.admin.indices.shrink;
exports org.elasticsearch.action.admin.indices.stats;
exports org.elasticsearch.action.admin.indices.template.delete;
exports org.elasticsearch.action.admin.indices.template.get;
exports org.elasticsearch.action.admin.indices.template.post;
exports org.elasticsearch.action.admin.indices.template.put;
exports org.elasticsearch.action.admin.indices.validate.query;
exports org.elasticsearch.action.bulk;
exports org.elasticsearch.action.datastreams;
exports org.elasticsearch.action.delete;
exports org.elasticsearch.action.explain;
exports org.elasticsearch.action.fieldcaps;
exports org.elasticsearch.action.get;
exports org.elasticsearch.action.index;
exports org.elasticsearch.action.ingest;
exports org.elasticsearch.action.main;
exports org.elasticsearch.action.resync;
exports org.elasticsearch.action.search;
exports org.elasticsearch.action.support;
exports org.elasticsearch.action.support.broadcast;
exports org.elasticsearch.action.support.broadcast.node;
exports org.elasticsearch.action.support.master;
exports org.elasticsearch.action.support.master.info;
exports org.elasticsearch.action.support.nodes;
exports org.elasticsearch.action.support.replication;
exports org.elasticsearch.action.support.single.instance;
exports org.elasticsearch.action.support.single.shard;
exports org.elasticsearch.action.support.tasks;
exports org.elasticsearch.action.termvectors;
exports org.elasticsearch.action.update;
exports org.elasticsearch.bootstrap;
exports org.elasticsearch.bootstrap.plugins;
exports org.elasticsearch.client.internal;
exports org.elasticsearch.client.internal.node;
exports org.elasticsearch.client.internal.support;
exports org.elasticsearch.client.internal.transport;
exports org.elasticsearch.cluster;
exports org.elasticsearch.cluster.ack;
exports org.elasticsearch.cluster.action.index;
exports org.elasticsearch.cluster.action.shard;
exports org.elasticsearch.cluster.block;
exports org.elasticsearch.cluster.coordination;
exports org.elasticsearch.cluster.health;
exports org.elasticsearch.cluster.metadata;
exports org.elasticsearch.cluster.node;
exports org.elasticsearch.cluster.routing;
exports org.elasticsearch.cluster.routing.allocation;
exports org.elasticsearch.cluster.routing.allocation.allocator;
exports org.elasticsearch.cluster.routing.allocation.command;
exports org.elasticsearch.cluster.routing.allocation.decider;
exports org.elasticsearch.cluster.service;
exports org.elasticsearch.common;
exports org.elasticsearch.common.blobstore;
exports org.elasticsearch.common.blobstore.fs;
exports org.elasticsearch.common.blobstore.support;
exports org.elasticsearch.common.breaker;
exports org.elasticsearch.common.bytes;
exports org.elasticsearch.common.cache;
exports org.elasticsearch.common.cli;
exports org.elasticsearch.common.collect;
exports org.elasticsearch.common.component;
exports org.elasticsearch.common.compress;
exports org.elasticsearch.common.document;
exports org.elasticsearch.common.filesystem;
exports org.elasticsearch.common.geo;
exports org.elasticsearch.common.hash;
exports org.elasticsearch.common.inject;
exports org.elasticsearch.common.inject.binder;
exports org.elasticsearch.common.inject.internal;
exports org.elasticsearch.common.inject.matcher;
exports org.elasticsearch.common.inject.multibindings;
exports org.elasticsearch.common.inject.name;
exports org.elasticsearch.common.inject.spi;
exports org.elasticsearch.common.inject.util;
exports org.elasticsearch.common.io;
exports org.elasticsearch.common.io.stream;
exports org.elasticsearch.common.logging;
exports org.elasticsearch.common.lucene;
exports org.elasticsearch.common.lucene.index;
exports org.elasticsearch.common.lucene.search;
exports org.elasticsearch.common.lucene.search.function;
exports org.elasticsearch.common.lucene.store;
exports org.elasticsearch.common.lucene.uid;
exports org.elasticsearch.common.metrics;
exports org.elasticsearch.common.network;
exports org.elasticsearch.common.path;
exports org.elasticsearch.common.recycler;
exports org.elasticsearch.common.regex;
exports org.elasticsearch.common.settings;
exports org.elasticsearch.common.text;
exports org.elasticsearch.common.time;
exports org.elasticsearch.common.transport;
exports org.elasticsearch.common.unit;
exports org.elasticsearch.common.util;
exports org.elasticsearch.common.util.concurrent;
exports org.elasticsearch.common.util.iterable;
exports org.elasticsearch.common.util.set;
exports org.elasticsearch.common.xcontent;
exports org.elasticsearch.common.xcontent.support;
exports org.elasticsearch.discovery;
exports org.elasticsearch.env;
exports org.elasticsearch.gateway;
exports org.elasticsearch.health;
exports org.elasticsearch.http;
exports org.elasticsearch.index;
exports org.elasticsearch.index.analysis;
exports org.elasticsearch.index.bulk.stats;
exports org.elasticsearch.index.cache;
exports org.elasticsearch.index.cache.bitset;
exports org.elasticsearch.index.cache.query;
exports org.elasticsearch.index.cache.request;
exports org.elasticsearch.index.codec;
exports org.elasticsearch.index.engine;
exports org.elasticsearch.index.fielddata;
exports org.elasticsearch.index.fielddata.fieldcomparator;
exports org.elasticsearch.index.fielddata.ordinals;
exports org.elasticsearch.index.fielddata.plain;
exports org.elasticsearch.index.fieldvisitor;
exports org.elasticsearch.index.flush;
exports org.elasticsearch.index.get;
exports org.elasticsearch.index.mapper;
exports org.elasticsearch.index.mapper.flattened;
exports org.elasticsearch.index.merge;
exports org.elasticsearch.index.query;
exports org.elasticsearch.index.query.functionscore;
exports org.elasticsearch.index.query.support;
exports org.elasticsearch.index.recovery;
exports org.elasticsearch.index.refresh;
exports org.elasticsearch.index.reindex;
exports org.elasticsearch.index.search;
exports org.elasticsearch.index.search.stats;
exports org.elasticsearch.index.seqno;
exports org.elasticsearch.index.shard;
exports org.elasticsearch.index.similarity;
exports org.elasticsearch.index.snapshots;
exports org.elasticsearch.index.snapshots.blobstore;
exports org.elasticsearch.index.stats;
exports org.elasticsearch.index.store;
exports org.elasticsearch.index.termvectors;
exports org.elasticsearch.index.translog;
exports org.elasticsearch.index.warmer;
exports org.elasticsearch.indices;
exports org.elasticsearch.indices.analysis;
exports org.elasticsearch.indices.breaker;
exports org.elasticsearch.indices.cluster;
exports org.elasticsearch.indices.fielddata.cache;
exports org.elasticsearch.indices.recovery;
exports org.elasticsearch.indices.recovery.plan;
exports org.elasticsearch.indices.store;
exports org.elasticsearch.ingest;
exports org.elasticsearch.lucene.analysis.miscellaneous;
exports org.elasticsearch.lucene.grouping;
exports org.elasticsearch.lucene.queries;
exports org.elasticsearch.lucene.search.uhighlight;
exports org.elasticsearch.lucene.search.vectorhighlight;
exports org.elasticsearch.lucene.similarity;
exports org.elasticsearch.lucene.util;
exports org.elasticsearch.monitor;
exports org.elasticsearch.monitor.fs;
exports org.elasticsearch.monitor.jvm;
exports org.elasticsearch.monitor.os;
exports org.elasticsearch.monitor.process;
exports org.elasticsearch.node;
exports org.elasticsearch.persistent;
exports org.elasticsearch.persistent.decider;
exports org.elasticsearch.plugins;
exports org.elasticsearch.plugins.interceptor to org.elasticsearch.security;
exports org.elasticsearch.plugins.spi;
exports org.elasticsearch.repositories;
exports org.elasticsearch.repositories.blobstore;
exports org.elasticsearch.repositories.fs;
exports org.elasticsearch.rest;
exports org.elasticsearch.rest.action;
exports org.elasticsearch.rest.action.admin.cluster;
exports org.elasticsearch.rest.action.admin.cluster.dangling;
exports org.elasticsearch.rest.action.admin.indices;
exports org.elasticsearch.rest.action.cat;
exports org.elasticsearch.rest.action.document;
exports org.elasticsearch.rest.action.ingest;
exports org.elasticsearch.rest.action.search;
exports org.elasticsearch.rollup;
exports org.elasticsearch.script;
exports org.elasticsearch.script.field;
exports org.elasticsearch.search;
exports org.elasticsearch.search.aggregations;
exports org.elasticsearch.search.aggregations.bucket;
exports org.elasticsearch.search.aggregations.bucket.adjacency;
exports org.elasticsearch.search.aggregations.bucket.composite;
exports org.elasticsearch.search.aggregations.bucket.filter;
exports org.elasticsearch.search.aggregations.bucket.geogrid;
exports org.elasticsearch.search.aggregations.bucket.global;
exports org.elasticsearch.search.aggregations.bucket.histogram;
exports org.elasticsearch.search.aggregations.bucket.missing;
exports org.elasticsearch.search.aggregations.bucket.nested;
exports org.elasticsearch.search.aggregations.bucket.range;
exports org.elasticsearch.search.aggregations.bucket.sampler;
exports org.elasticsearch.search.aggregations.bucket.terms;
exports org.elasticsearch.search.aggregations.bucket.terms.heuristic;
exports org.elasticsearch.search.aggregations.metrics;
exports org.elasticsearch.search.aggregations.pipeline;
exports org.elasticsearch.search.aggregations.support;
exports org.elasticsearch.search.aggregations.support.values;
exports org.elasticsearch.search.aggregations.timeseries;
exports org.elasticsearch.search.builder;
exports org.elasticsearch.search.collapse;
exports org.elasticsearch.search.dfs;
exports org.elasticsearch.search.fetch;
exports org.elasticsearch.search.fetch.subphase;
exports org.elasticsearch.search.fetch.subphase.highlight;
exports org.elasticsearch.search.internal;
exports org.elasticsearch.search.lookup;
exports org.elasticsearch.search.profile;
exports org.elasticsearch.search.profile.aggregation;
exports org.elasticsearch.search.profile.query;
exports org.elasticsearch.search.query;
exports org.elasticsearch.search.rescore;
exports org.elasticsearch.search.runtime;
exports org.elasticsearch.search.searchafter;
exports org.elasticsearch.search.slice;
exports org.elasticsearch.search.sort;
exports org.elasticsearch.search.suggest;
exports org.elasticsearch.search.suggest.completion;
exports org.elasticsearch.search.suggest.completion.context;
exports org.elasticsearch.search.suggest.phrase;
exports org.elasticsearch.search.suggest.term;
exports org.elasticsearch.shutdown;
exports org.elasticsearch.snapshots;
exports org.elasticsearch.tasks;
exports org.elasticsearch.threadpool;
exports org.elasticsearch.timeseries.support;
exports org.elasticsearch.transport;
exports org.elasticsearch.upgrades;
exports org.elasticsearch.usage;
exports org.elasticsearch.watcher;
opens org.elasticsearch.common.logging to org.apache.logging.log4j.core;
provides java.util.spi.CalendarDataProvider with org.elasticsearch.common.time.IsoCalendarDataProvider;
provides org.elasticsearch.xcontent.ErrorOnUnknown with org.elasticsearch.common.xcontent.SuggestingErrorOnUnknown;
provides org.elasticsearch.xcontent.XContentBuilderExtension with org.elasticsearch.common.xcontent.XContentElasticsearchExtension;
provides org.elasticsearch.cli.CliToolProvider
with
org.elasticsearch.cluster.coordination.NodeToolCliProvider,
org.elasticsearch.index.shard.ShardToolCliProvider;
}

View File

@ -112,7 +112,7 @@ final class Security {
static void configure(Environment environment, boolean filterBadDefaults) throws IOException, NoSuchAlgorithmException {
// enable security policy: union of template and environment-based paths, and possibly plugin permissions
Map<String, URL> codebases = PolicyUtil.getCodebaseJarMap(JarHell.parseClassPath());
Map<String, URL> codebases = PolicyUtil.getCodebaseJarMap(JarHell.parseModulesAndClassPath());
Policy.setPolicy(
new ESPolicy(
codebases,

View File

@ -55,6 +55,10 @@ class PluginBundle {
return urls;
}
boolean hasSPI() {
return spiUrls != null;
}
Set<URL> getExtensionUrls() {
if (spiUrls != null) {
return spiUrls;

View File

@ -20,13 +20,21 @@ import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.core.PathUtils;
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.jdk.JarHell;
import org.elasticsearch.node.ReportingService;
import org.elasticsearch.plugins.spi.SPIClassIterator;
import java.io.IOException;
import java.lang.ModuleLayer.Controller;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
@ -41,6 +49,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@ -56,8 +65,25 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
* @param info Metadata about the plugin, usually loaded from plugin properties
* @param instance The constructed instance of the plugin's main class
* @param loader The classloader for the plugin
* @param layer The module layer for the plugin
*/
record LoadedPlugin(PluginInfo info, Plugin instance, ClassLoader loader) {}
record LoadedPlugin(PluginInfo info, Plugin instance, ClassLoader loader, ModuleLayer layer) {
LoadedPlugin {
Objects.requireNonNull(info);
Objects.requireNonNull(instance);
Objects.requireNonNull(loader);
Objects.requireNonNull(layer);
}
/**
* Creates a loaded <i>classpath plugin</i>. A <i>classpath plugin</i> is a plugin loaded
* by the system classloader and defined to the unnamed module of the boot layer.
*/
LoadedPlugin(PluginInfo info, Plugin instance) {
this(info, instance, PluginsService.class.getClassLoader(), ModuleLayer.boot());
}
}
private static final Logger logger = LogManager.getLogger(PluginsService.class);
@ -119,7 +145,7 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
if (logger.isTraceEnabled()) {
logger.trace("plugin loaded from classpath [{}]", pluginInfo);
}
pluginsLoaded.add(new LoadedPlugin(pluginInfo, plugin, null));
pluginsLoaded.add(new LoadedPlugin(pluginInfo, plugin));
pluginsList.add(pluginInfo);
pluginsNames.add(pluginInfo.getName());
}
@ -354,11 +380,12 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
private Plugin loadBundle(PluginBundle bundle, Map<String, LoadedPlugin> loaded) {
String name = bundle.plugin.getName();
logger.debug(() -> "Loading bundle: " + name);
PluginsUtils.verifyCompatibility(bundle.plugin);
// collect loaders of extended plugins
List<ClassLoader> extendedLoaders = new ArrayList<>();
// collect the list of extended plugins
List<LoadedPlugin> extendedPlugins = new ArrayList<>();
for (String extendedPluginName : bundle.plugin.getExtendedPlugins()) {
LoadedPlugin extendedPlugin = loaded.get(extendedPluginName);
assert extendedPlugin != null;
@ -366,36 +393,42 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
throw new IllegalStateException("Plugin [" + name + "] cannot extend non-extensible plugin [" + extendedPluginName + "]");
}
assert extendedPlugin.loader() != null : "All non-classpath plugins should be loaded with a classloader";
extendedLoaders.add(extendedPlugin.loader());
extendedPlugins.add(extendedPlugin);
logger.debug(
() -> "Loading bundle: " + name + ", ext plugins: " + extendedPlugins.stream().map(lp -> lp.info().getName()).toList()
);
}
ClassLoader parentLoader = PluginLoaderIndirection.createLoader(getClass().getClassLoader(), extendedLoaders);
ClassLoader spiLoader = null;
if (bundle.spiUrls != null) {
spiLoader = URLClassLoader.newInstance(bundle.spiUrls.toArray(new URL[0]), parentLoader);
final ClassLoader parentLoader = PluginLoaderIndirection.createLoader(
getClass().getClassLoader(),
extendedPlugins.stream().map(LoadedPlugin::loader).toList()
);
LayerAndLoader spiLayerAndLoader = null;
if (bundle.hasSPI()) {
spiLayerAndLoader = createSPI(bundle, parentLoader, extendedPlugins);
}
ClassLoader loader = URLClassLoader.newInstance(bundle.urls.toArray(new URL[0]), spiLoader == null ? parentLoader : spiLoader);
if (spiLoader == null) {
final ClassLoader pluginParentLoader = spiLayerAndLoader == null ? parentLoader : spiLayerAndLoader.loader();
final LayerAndLoader pluginLayerAndLoader = createPlugin(bundle, pluginParentLoader, extendedPlugins, spiLayerAndLoader);
final ClassLoader pluginClassLoader = pluginLayerAndLoader.loader();
if (spiLayerAndLoader == null) {
// use full implementation for plugins extending this one
spiLoader = loader;
spiLayerAndLoader = pluginLayerAndLoader;
}
// reload SPI with any new services from the plugin
reloadLuceneSPI(loader);
reloadLuceneSPI(pluginClassLoader);
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
// Set context class loader to plugin's class loader so that plugins
// that have dependencies with their own SPI endpoints have a chance to load
// and initialize them appropriately.
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
Thread.currentThread().setContextClassLoader(loader);
return null;
});
privilegedSetContextClassLoader(pluginClassLoader);
Class<? extends Plugin> pluginClass = loadPluginClass(bundle.plugin.getClassname(), loader);
if (loader != pluginClass.getClassLoader()) {
Class<? extends Plugin> pluginClass = loadPluginClass(bundle.plugin.getClassname(), pluginClassLoader);
if (pluginClassLoader != pluginClass.getClassLoader()) {
throw new IllegalStateException(
"Plugin ["
+ name
@ -407,13 +440,41 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
);
}
Plugin plugin = loadPlugin(pluginClass, settings, configPath);
loaded.put(name, new LoadedPlugin(bundle.plugin, plugin, spiLoader));
loaded.put(name, new LoadedPlugin(bundle.plugin, plugin, spiLayerAndLoader.loader(), spiLayerAndLoader.layer()));
return plugin;
} finally {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
Thread.currentThread().setContextClassLoader(cl);
return null;
});
privilegedSetContextClassLoader(cl);
}
}
static LayerAndLoader createSPI(PluginBundle bundle, ClassLoader parentLoader, List<LoadedPlugin> extendedPlugins) {
final PluginInfo plugin = bundle.plugin;
if (plugin.getModuleName().isPresent()) {
logger.debug(() -> "Loading bundle: " + plugin.getName() + ", creating spi, modular");
return createSpiModuleLayer(bundle.spiUrls, parentLoader, extendedPlugins.stream().map(LoadedPlugin::layer).toList());
} else {
logger.debug(() -> "Loading bundle: " + plugin.getName() + ", creating spi, non-modular");
return LayerAndLoader.ofLoader(URLClassLoader.newInstance(bundle.spiUrls.toArray(new URL[0]), parentLoader));
}
}
static LayerAndLoader createPlugin(
PluginBundle bundle,
ClassLoader pluginParentLoader,
List<LoadedPlugin> extendedPlugins,
LayerAndLoader spiLayerAndLoader
) {
final PluginInfo plugin = bundle.plugin;
if (plugin.getModuleName().isPresent()) {
logger.debug(() -> "Loading bundle: " + plugin.getName() + ", modular");
var parentLayers = Stream.concat(
Stream.ofNullable(spiLayerAndLoader != null ? spiLayerAndLoader.layer() : null),
extendedPlugins.stream().map(LoadedPlugin::layer)
).toList();
return createPluginModuleLayer(bundle, pluginParentLoader, parentLayers);
} else {
logger.debug(() -> "Loading bundle: " + plugin.getName() + ", non-modular");
return LayerAndLoader.ofLoader(URLClassLoader.newInstance(bundle.urls.toArray(URL[]::new), pluginParentLoader));
}
}
@ -485,4 +546,171 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
public <T> List<T> filterPlugins(Class<T> type) {
return plugins.stream().filter(x -> type.isAssignableFrom(x.instance().getClass())).map(p -> ((T) p.instance())).toList();
}
static final LayerAndLoader createPluginModuleLayer(PluginBundle bundle, ClassLoader parentLoader, List<ModuleLayer> parentLayers) {
assert bundle.plugin.getModuleName().isPresent();
return createModuleLayer(
bundle.plugin.getClassname(),
bundle.plugin.getModuleName().get(),
urlsToPaths(bundle.urls),
parentLoader,
parentLayers
);
}
static final LayerAndLoader createSpiModuleLayer(Set<URL> urls, ClassLoader parentLoader, List<ModuleLayer> parentLayers) {
// assert bundle.plugin.getModuleName().isPresent();
return createModuleLayer(
null, // no entry point
spiModuleName(urls),
urlsToPaths(urls),
parentLoader,
parentLayers
);
}
private static final Module serverModule = PluginsService.class.getModule();
static final LayerAndLoader createModuleLayer(
String className,
String moduleName,
Path[] paths,
ClassLoader parentLoader,
List<ModuleLayer> parentLayers
) {
logger.debug(() -> "Loading bundle: creating module layer and loader for module " + moduleName);
var finder = ModuleFinder.of(paths);
var configuration = Configuration.resolveAndBind(
ModuleFinder.of(),
parentConfigurationOrBoot(parentLayers),
finder,
Set.of(moduleName)
);
var controller = privilegedDefineModulesWithOneLoader(configuration, parentLayersOrBoot(parentLayers), parentLoader);
var pluginModule = controller.layer().findModule(moduleName).get();
ensureEntryPointAccessible(controller, pluginModule, className);
addQualifiedExports(pluginModule);
addQualifiedOpens(pluginModule);
logger.debug(() -> "Loading bundle: created module layer and loader for module " + moduleName);
return new LayerAndLoader(controller.layer(), privilegedFindLoader(controller.layer(), moduleName));
}
private static List<ModuleLayer> parentLayersOrBoot(List<ModuleLayer> parentLayers) {
if (parentLayers == null || parentLayers.isEmpty()) {
return List.of(ModuleLayer.boot());
} else {
return parentLayers;
}
}
private static List<Configuration> parentConfigurationOrBoot(List<ModuleLayer> parentLayers) {
if (parentLayers == null || parentLayers.isEmpty()) {
return List.of(ModuleLayer.boot().configuration());
} else {
return parentLayers.stream().map(ModuleLayer::configuration).toList();
}
}
/** Ensures that the plugins main class (its entry point), if any, is accessible to the server. */
private static void ensureEntryPointAccessible(Controller controller, Module pluginModule, String className) {
if (className != null) {
controller.addOpens(pluginModule, toPackageName(className), serverModule);
}
}
/**
* Adds qualified exports declared in the server module descriptor to the target module.
* This is required since qualified exports targeting yet-to-be-created modules, i.e. plugins,
* are silently dropped when the boot layer is created.
*/
private static void addQualifiedExports(Module target) {
serverModule.getDescriptor()
.exports()
.stream()
.filter(ModuleDescriptor.Exports::isQualified)
.filter(exports -> exports.targets().contains(target.getName()))
.forEach(exports -> serverModule.addExports(exports.source(), target));
}
/**
* Adds qualified opens declared in the server module descriptor to the target module.
* This is required since qualified opens targeting yet-to-be-created modules, i.e. plugins,
* are silently dropped when the boot layer is created.
*/
private static void addQualifiedOpens(Module target) {
serverModule.getDescriptor()
.opens()
.stream()
.filter(ModuleDescriptor.Opens::isQualified)
.filter(opens -> opens.targets().contains(target.getName()))
.forEach(opens -> serverModule.addExports(opens.source(), target));
}
/** Determines the module name of the SPI module, given its URL. */
static String spiModuleName(Set<URL> spiURLS) {
ModuleFinder finder = ModuleFinder.of(urlsToPaths(spiURLS));
var mrefs = finder.findAll();
assert mrefs.size() == 1 : "Expected a single module, got:" + mrefs;
return mrefs.stream().findFirst().get().descriptor().name();
}
/**
* Tuple of module layer and loader.
* Modular Plugins have a plugin specific loader and layer.
* Non-Modular plugins have a plugin specific loader and the boot layer.
*/
record LayerAndLoader(ModuleLayer layer, ClassLoader loader) {
LayerAndLoader {
Objects.requireNonNull(layer);
Objects.requireNonNull(loader);
}
static LayerAndLoader ofLoader(ClassLoader loader) {
return new LayerAndLoader(ModuleLayer.boot(), loader);
}
}
@SuppressForbidden(reason = "I need to convert URL's to Paths")
static final Path[] urlsToPaths(Set<URL> urls) {
return urls.stream().map(PluginsService::uncheckedToURI).map(PathUtils::get).toArray(Path[]::new);
}
static final URI uncheckedToURI(URL url) {
try {
return url.toURI();
} catch (URISyntaxException e) {
throw new AssertionError(new IOException(e));
}
}
static final String toPackageName(String className) {
assert className.endsWith(".") == false;
int index = className.lastIndexOf(".");
if (index == -1) {
throw new IllegalStateException("invalid class name:" + className);
}
return className.substring(0, index);
}
@SuppressWarnings("removal")
private static void privilegedSetContextClassLoader(ClassLoader loader) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
Thread.currentThread().setContextClassLoader(loader);
return null;
});
}
@SuppressWarnings("removal")
static Controller privilegedDefineModulesWithOneLoader(Configuration cf, List<ModuleLayer> parentLayers, ClassLoader parentLoader) {
return AccessController.doPrivileged(
(PrivilegedAction<Controller>) () -> ModuleLayer.defineModulesWithOneLoader(cf, parentLayers, parentLoader)
);
}
@SuppressWarnings("removal")
static ClassLoader privilegedFindLoader(ModuleLayer layer, String name) {
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> layer.findLoader(name));
}
}

View File

@ -26,6 +26,10 @@ grant codeBase "${codebase.elasticsearch}" {
permission java.net.SocketPermission "127.0.0.1", "listen, accept";
// required if started with -Djava.net.preferIPv6Addresses=true
permission java.net.SocketPermission "0:0:0:0:0:0:0:1", "listen, accept";
// for module layer
permission java.lang.RuntimePermission "createClassLoader";
permission java.lang.RuntimePermission "getClassLoader";
};
//// Very special jar permissions:

View File

@ -0,0 +1,82 @@
/*
* 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.module;
import org.elasticsearch.core.PathUtils;
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.jdk.JarHell;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.function.Predicate.not;
import static org.elasticsearch.test.hamcrest.ModuleDescriptorMatchers.exportsOf;
import static org.elasticsearch.test.hamcrest.ModuleDescriptorMatchers.opensOf;
import static org.elasticsearch.test.hamcrest.OptionalMatchers.isPresent;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItem;
public class BasicServerModuleTests extends ESTestCase {
private static final String SERVER_MODULE_NAME = "org.elasticsearch.server";
public void testQualifiedExports() {
var md = getServerDescriptor();
// The package containing the RestInterceptor type, org.elasticsearch.plugins.interceptor,
// should only be exported to security.
assertThat(md.exports(), hasItem(exportsOf("org.elasticsearch.plugins.interceptor", Set.of("org.elasticsearch.security"))));
// additional qualified export constraint go here
}
// Ensures that there are no unqualified opens - too dangerous
public void testEnsureNoUnqualifiedOpens() {
var md = getServerDescriptor();
assertThat(md.opens().stream().filter(not(ModuleDescriptor.Opens::isQualified)).collect(Collectors.toSet()), empty());
}
public void testQualifiedOpens() {
var md = getServerDescriptor();
// We tolerate introspection by log4j, for Plugins, e.g. ECSJsonLayout
assertThat(md.opens(), hasItem(opensOf("org.elasticsearch.common.logging", Set.of("org.apache.logging.log4j.core"))));
// additional qualified opens constraint go here
}
private static ModuleDescriptor getServerDescriptor() {
var finder = ModuleFinder.of(urlsToPaths(JarHell.parseClassPath()));
var omref = finder.find(SERVER_MODULE_NAME);
assertThat(omref, isPresent());
return omref.get().descriptor();
}
@SuppressForbidden(reason = "I need to convert URL's to Paths")
private static Path[] urlsToPaths(Set<URL> urls) {
return urls.stream().map(BasicServerModuleTests::uncheckedToURI).map(PathUtils::get).toArray(Path[]::new);
}
private static URI uncheckedToURI(URL url) {
try {
return url.toURI();
} catch (URISyntaxException e) {
throw new UncheckedIOException(new IOException(e));
}
}
}

View File

@ -460,8 +460,7 @@ public class PluginsServiceTests extends ESTestCase {
List.of(
new PluginsService.LoadedPlugin(
new PluginInfo("extensible", null, null, null, null, null, null, List.of(), false, PluginType.ISOLATED, "", false),
extensiblePlugin,
null
extensiblePlugin
)
)
);
@ -475,8 +474,7 @@ public class PluginsServiceTests extends ESTestCase {
List.of(
new PluginsService.LoadedPlugin(
new PluginInfo("extensible", null, null, null, null, null, null, List.of(), false, PluginType.ISOLATED, "", false),
extensiblePlugin,
null
extensiblePlugin
),
new PluginsService.LoadedPlugin(
new PluginInfo(
@ -493,8 +491,7 @@ public class PluginsServiceTests extends ESTestCase {
"",
false
),
testPlugin,
null
testPlugin
)
)
);

View File

@ -110,7 +110,7 @@ public class DieWithDignityIT extends ESRestTestCase {
String jvmArgs = null;
String line;
while ((line = in.readLine()) != null) {
if (line.equals("java_command: org.elasticsearch.bootstrap.Elasticsearch")) {
if (line.equals("java_command: org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch")) {
isElasticsearch = true;
}
if (line.startsWith("jvm_args")) {

View File

@ -0,0 +1,213 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
module org.elasticsearch.xcore {
requires org.elasticsearch.cli;
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.sslconfig;
requires org.elasticsearch.xcontent;
requires org.apache.httpcomponents.httpcore;
requires org.apache.httpcomponents.httpclient;
requires org.apache.httpcomponents.httpasyncclient;
requires org.apache.httpcomponents.httpcore.nio;
requires org.apache.logging.log4j;
requires org.apache.lucene.core;
requires org.apache.lucene.join;
requires unboundid.ldapsdk;
exports org.elasticsearch.index.engine.frozen;
exports org.elasticsearch.license;
exports org.elasticsearch.protocol.xpack.common;
exports org.elasticsearch.protocol.xpack.frozen;
exports org.elasticsearch.protocol.xpack.graph;
exports org.elasticsearch.protocol.xpack.license;
exports org.elasticsearch.protocol.xpack.watcher;
exports org.elasticsearch.protocol.xpack;
exports org.elasticsearch.snapshots.sourceonly;
exports org.elasticsearch.xpack.cluster.action;
exports org.elasticsearch.xpack.cluster.routing.allocation.mapper;
exports org.elasticsearch.xpack.cluster.routing.allocation;
exports org.elasticsearch.xpack.core;
exports org.elasticsearch.xpack.core.action.util;
exports org.elasticsearch.xpack.core.action;
exports org.elasticsearch.xpack.core.aggregatemetric;
exports org.elasticsearch.xpack.core.analytics.action;
exports org.elasticsearch.xpack.core.analytics;
exports org.elasticsearch.xpack.core.archive;
exports org.elasticsearch.xpack.core.async;
exports org.elasticsearch.xpack.core.ccr.action;
exports org.elasticsearch.xpack.core.ccr;
exports org.elasticsearch.xpack.core.common.notifications;
exports org.elasticsearch.xpack.core.common.search.aggregations;
exports org.elasticsearch.xpack.core.common.socket;
exports org.elasticsearch.xpack.core.common.stats;
exports org.elasticsearch.xpack.core.common.table;
exports org.elasticsearch.xpack.core.common.time;
exports org.elasticsearch.xpack.core.common.validation;
exports org.elasticsearch.xpack.core.common;
exports org.elasticsearch.xpack.core.datastreams;
exports org.elasticsearch.xpack.core.deprecation;
exports org.elasticsearch.xpack.core.enrich.action;
exports org.elasticsearch.xpack.core.enrich;
exports org.elasticsearch.xpack.core.eql;
exports org.elasticsearch.xpack.core.frozen.action;
exports org.elasticsearch.xpack.core.frozen;
exports org.elasticsearch.xpack.core.graph.action;
exports org.elasticsearch.xpack.core.graph;
exports org.elasticsearch.xpack.core.ilm.action;
exports org.elasticsearch.xpack.core.ilm.step.info;
exports org.elasticsearch.xpack.core.ilm;
exports org.elasticsearch.xpack.core.index.query;
exports org.elasticsearch.xpack.core.indexing;
exports org.elasticsearch.xpack.core.logstash;
exports org.elasticsearch.xpack.core.ml.action;
exports org.elasticsearch.xpack.core.ml.annotations;
exports org.elasticsearch.xpack.core.ml.calendars;
exports org.elasticsearch.xpack.core.ml.datafeed.extractor;
exports org.elasticsearch.xpack.core.ml.datafeed;
exports org.elasticsearch.xpack.core.ml.dataframe.analyses;
exports org.elasticsearch.xpack.core.ml.dataframe.evaluation.classification;
exports org.elasticsearch.xpack.core.ml.dataframe.evaluation.common;
exports org.elasticsearch.xpack.core.ml.dataframe.evaluation.outlierdetection;
exports org.elasticsearch.xpack.core.ml.dataframe.evaluation.regression;
exports org.elasticsearch.xpack.core.ml.dataframe.evaluation;
exports org.elasticsearch.xpack.core.ml.dataframe.explain;
exports org.elasticsearch.xpack.core.ml.dataframe.stats.classification;
exports org.elasticsearch.xpack.core.ml.dataframe.stats.common;
exports org.elasticsearch.xpack.core.ml.dataframe.stats.outlierdetection;
exports org.elasticsearch.xpack.core.ml.dataframe.stats.regression;
exports org.elasticsearch.xpack.core.ml.dataframe.stats;
exports org.elasticsearch.xpack.core.ml.dataframe;
exports org.elasticsearch.xpack.core.ml.inference.assignment;
exports org.elasticsearch.xpack.core.ml.inference.persistence;
exports org.elasticsearch.xpack.core.ml.inference.preprocessing.customwordembedding;
exports org.elasticsearch.xpack.core.ml.inference.preprocessing;
exports org.elasticsearch.xpack.core.ml.inference.results;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel.ensemble;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel.inference;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel.langident;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel.metadata;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel.tree;
exports org.elasticsearch.xpack.core.ml.inference.trainedmodel;
exports org.elasticsearch.xpack.core.ml.inference.utils;
exports org.elasticsearch.xpack.core.ml.inference;
exports org.elasticsearch.xpack.core.ml.job.config;
exports org.elasticsearch.xpack.core.ml.job.groups;
exports org.elasticsearch.xpack.core.ml.job.messages;
exports org.elasticsearch.xpack.core.ml.job.persistence;
exports org.elasticsearch.xpack.core.ml.job.process.autodetect.output;
exports org.elasticsearch.xpack.core.ml.job.process.autodetect.state;
exports org.elasticsearch.xpack.core.ml.job.results;
exports org.elasticsearch.xpack.core.ml.job.snapshot.upgrade;
exports org.elasticsearch.xpack.core.ml.notifications;
exports org.elasticsearch.xpack.core.ml.process.writer;
exports org.elasticsearch.xpack.core.ml.stats;
exports org.elasticsearch.xpack.core.ml.utils.time;
exports org.elasticsearch.xpack.core.ml.utils;
exports org.elasticsearch.xpack.core.ml;
exports org.elasticsearch.xpack.core.monitoring.action;
exports org.elasticsearch.xpack.core.monitoring.exporter;
exports org.elasticsearch.xpack.core.monitoring;
exports org.elasticsearch.xpack.core.rest.action;
exports org.elasticsearch.xpack.core.rollup.action;
exports org.elasticsearch.xpack.core.rollup.job;
exports org.elasticsearch.xpack.core.rollup;
exports org.elasticsearch.xpack.core.scheduler;
exports org.elasticsearch.xpack.core.search.action;
exports org.elasticsearch.xpack.core.searchablesnapshots;
exports org.elasticsearch.xpack.core.security.action.apikey;
exports org.elasticsearch.xpack.core.security.action.enrollment;
exports org.elasticsearch.xpack.core.security.action.oidc;
exports org.elasticsearch.xpack.core.security.action.privilege;
exports org.elasticsearch.xpack.core.security.action.profile;
exports org.elasticsearch.xpack.core.security.action.realm;
exports org.elasticsearch.xpack.core.security.action.role;
exports org.elasticsearch.xpack.core.security.action.rolemapping;
exports org.elasticsearch.xpack.core.security.action.saml;
exports org.elasticsearch.xpack.core.security.action.service;
exports org.elasticsearch.xpack.core.security.action.token;
exports org.elasticsearch.xpack.core.security.action.user;
exports org.elasticsearch.xpack.core.security.action;
exports org.elasticsearch.xpack.core.security.authc.esnative;
exports org.elasticsearch.xpack.core.security.authc.file;
exports org.elasticsearch.xpack.core.security.authc.jwt;
exports org.elasticsearch.xpack.core.security.authc.kerberos;
exports org.elasticsearch.xpack.core.security.authc.ldap.support;
exports org.elasticsearch.xpack.core.security.authc.ldap;
exports org.elasticsearch.xpack.core.security.authc.oidc;
exports org.elasticsearch.xpack.core.security.authc.pki;
exports org.elasticsearch.xpack.core.security.authc.saml;
exports org.elasticsearch.xpack.core.security.authc.service;
exports org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl;
exports org.elasticsearch.xpack.core.security.authc.support.mapper;
exports org.elasticsearch.xpack.core.security.authc.support;
exports org.elasticsearch.xpack.core.security.authc;
exports org.elasticsearch.xpack.core.security.authz.accesscontrol;
exports org.elasticsearch.xpack.core.security.authz.permission;
exports org.elasticsearch.xpack.core.security.authz.privilege;
exports org.elasticsearch.xpack.core.security.authz.store;
exports org.elasticsearch.xpack.core.security.authz.support;
exports org.elasticsearch.xpack.core.security.authz;
exports org.elasticsearch.xpack.core.security.index;
exports org.elasticsearch.xpack.core.security.support;
exports org.elasticsearch.xpack.core.security.user;
exports org.elasticsearch.xpack.core.security.xcontent;
exports org.elasticsearch.xpack.core.security;
exports org.elasticsearch.xpack.core.slm.action;
exports org.elasticsearch.xpack.core.slm;
exports org.elasticsearch.xpack.core.spatial.action;
exports org.elasticsearch.xpack.core.spatial.search.aggregations;
exports org.elasticsearch.xpack.core.spatial;
exports org.elasticsearch.xpack.core.sql;
exports org.elasticsearch.xpack.core.ssl.action;
exports org.elasticsearch.xpack.core.ssl.cert;
exports org.elasticsearch.xpack.core.ssl.rest;
exports org.elasticsearch.xpack.core.ssl;
exports org.elasticsearch.xpack.core.template;
exports org.elasticsearch.xpack.core.termsenum.action;
exports org.elasticsearch.xpack.core.termsenum.rest;
exports org.elasticsearch.xpack.core.textstructure.action;
exports org.elasticsearch.xpack.core.textstructure.structurefinder;
exports org.elasticsearch.xpack.core.transform.action;
exports org.elasticsearch.xpack.core.transform.notifications;
exports org.elasticsearch.xpack.core.transform.transforms.latest;
exports org.elasticsearch.xpack.core.transform.transforms.persistence;
exports org.elasticsearch.xpack.core.transform.transforms.pivot;
exports org.elasticsearch.xpack.core.transform.transforms;
exports org.elasticsearch.xpack.core.transform.utils;
exports org.elasticsearch.xpack.core.transform;
exports org.elasticsearch.xpack.core.upgrade;
exports org.elasticsearch.xpack.core.votingonly;
exports org.elasticsearch.xpack.core.watcher.actions.throttler;
exports org.elasticsearch.xpack.core.watcher.actions;
exports org.elasticsearch.xpack.core.watcher.client;
exports org.elasticsearch.xpack.core.watcher.common.secret;
exports org.elasticsearch.xpack.core.watcher.common.stats;
exports org.elasticsearch.xpack.core.watcher.condition;
exports org.elasticsearch.xpack.core.watcher.crypto;
exports org.elasticsearch.xpack.core.watcher.execution;
exports org.elasticsearch.xpack.core.watcher.history;
exports org.elasticsearch.xpack.core.watcher.input.none;
exports org.elasticsearch.xpack.core.watcher.input;
exports org.elasticsearch.xpack.core.watcher.support.xcontent;
exports org.elasticsearch.xpack.core.watcher.support;
exports org.elasticsearch.xpack.core.watcher.transform.chain;
exports org.elasticsearch.xpack.core.watcher.transform;
exports org.elasticsearch.xpack.core.watcher.transport.actions.ack;
exports org.elasticsearch.xpack.core.watcher.transport.actions.activate;
exports org.elasticsearch.xpack.core.watcher.transport.actions.delete;
exports org.elasticsearch.xpack.core.watcher.transport.actions.execute;
exports org.elasticsearch.xpack.core.watcher.transport.actions.get;
exports org.elasticsearch.xpack.core.watcher.transport.actions.put;
exports org.elasticsearch.xpack.core.watcher.transport.actions.service;
exports org.elasticsearch.xpack.core.watcher.transport.actions.stats;
exports org.elasticsearch.xpack.core.watcher.transport.actions;
exports org.elasticsearch.xpack.core.watcher.trigger;
exports org.elasticsearch.xpack.core.watcher.watch;
exports org.elasticsearch.xpack.core.watcher;
}

View File

@ -0,0 +1,20 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
module org.elasticsearch.mapper.unsignedlong {
requires org.apache.lucene.core;
requires org.elasticsearch.server;
requires org.apache.lucene.sandbox;
requires org.elasticsearch.xcontent;
requires org.elasticsearch.painless.spi;
exports org.elasticsearch.xpack.unsignedlong; // for the painless script engine
opens org.elasticsearch.xpack.unsignedlong to org.elasticsearch.painless.spi; // whitelist resource access
provides org.elasticsearch.painless.spi.PainlessExtension with org.elasticsearch.xpack.unsignedlong.DocValuesWhitelistExtension;
}

View File

@ -0,0 +1,76 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
module org.elasticsearch.security {
requires java.naming;
requires java.security.jgss;
requires java.xml;
requires org.elasticsearch.base;
requires org.elasticsearch.cli;
requires org.elasticsearch.server;
requires org.elasticsearch.sslconfig;
requires org.elasticsearch.transport.netty4;
requires org.elasticsearch.xcontent;
requires org.elasticsearch.xcore;
requires org.apache.commons.codec;
requires org.apache.httpcomponents.httpcore;
requires org.apache.httpcomponents.httpclient;
requires org.apache.httpcomponents.httpasyncclient;
requires org.apache.httpcomponents.httpcore.nio;
requires org.apache.log4j;
requires org.apache.logging.log4j;
requires org.apache.lucene.core;
requires org.apache.lucene.queries;
requires org.apache.lucene.sandbox;
requires org.opensaml.core;
requires org.opensaml.saml;
requires org.opensaml.saml.impl;
requires org.opensaml.security.impl;
requires org.opensaml.security;
requires org.opensaml.xmlsec.impl;
requires org.opensaml.xmlsec;
requires com.nimbusds.jose.jwt;
requires io.netty.handler;
requires io.netty.transport;
requires jopt.simple;
requires json.smart;
requires net.shibboleth.utilities.java.support;
requires oauth2.oidc.sdk;
requires slf4j.api;
requires unboundid.ldapsdk;
exports org.elasticsearch.xpack.security.action to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.apikey to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.enrollment to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.oidc to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.privilege to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.profile to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.realm to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.role to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.rolemapping to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.saml to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.service to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.token to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.action.user to org.elasticsearch.server;
exports org.elasticsearch.xpack.security.authc to org.elasticsearch.xcontent;
provides org.elasticsearch.cli.CliToolProvider
with
org.elasticsearch.xpack.security.enrollment.tool.CreateEnrollmentTokenToolProvider,
org.elasticsearch.xpack.security.authc.esnative.tool.ResetPasswordToolProvider,
org.elasticsearch.xpack.security.authc.esnative.tool.SetupPasswordToolProvider,
org.elasticsearch.xpack.security.authc.saml.SamlMetadataToolProvider,
org.elasticsearch.xpack.security.authc.service.FileTokensToolProvider,
org.elasticsearch.xpack.security.crypto.tool.SystemKeyToolProvider,
org.elasticsearch.xpack.security.authc.file.tool.UsersToolProvider,
org.elasticsearch.xpack.security.enrollment.tool.AutoConfigGenerateElasticPasswordHashToolProvider;
}