|
12 | 12 | import org.apache.lucene.util.Constants; |
13 | 13 | import org.elasticsearch.Version; |
14 | 14 | import org.elasticsearch.common.settings.Settings; |
| 15 | +import org.elasticsearch.core.Strings; |
15 | 16 | import org.elasticsearch.env.Environment; |
16 | 17 | import org.elasticsearch.env.TestEnvironment; |
17 | 18 | import org.elasticsearch.index.IndexModule; |
| 19 | +import org.elasticsearch.plugins.spi.TestService; |
18 | 20 | import org.elasticsearch.test.ESTestCase; |
| 21 | +import org.elasticsearch.test.compiler.InMemoryJavaCompiler; |
| 22 | +import org.elasticsearch.test.jar.JarUtils; |
19 | 23 |
|
20 | 24 | import java.io.IOException; |
21 | 25 | import java.io.InputStream; |
22 | 26 | import java.lang.reflect.InvocationTargetException; |
| 27 | +import java.net.URL; |
| 28 | +import java.net.URLClassLoader; |
| 29 | +import java.nio.charset.StandardCharsets; |
23 | 30 | import java.nio.file.FileSystemException; |
24 | 31 | import java.nio.file.Files; |
25 | 32 | import java.nio.file.NoSuchFileException; |
26 | 33 | import java.nio.file.Path; |
27 | 34 | import java.util.ArrayList; |
28 | 35 | import java.util.Arrays; |
29 | 36 | import java.util.Collection; |
| 37 | +import java.util.HashMap; |
30 | 38 | import java.util.List; |
31 | 39 | import java.util.Locale; |
| 40 | +import java.util.Map; |
32 | 41 | import java.util.Set; |
33 | 42 |
|
34 | 43 | import static org.hamcrest.Matchers.containsInAnyOrder; |
@@ -613,6 +622,70 @@ public void testThrowingConstructor() { |
613 | 622 | assertThat(e.getCause().getCause(), hasToString(containsString("test constructor failure"))); |
614 | 623 | } |
615 | 624 |
|
| 625 | + private ClassLoader buildTestProviderPlugin(String name) throws Exception { |
| 626 | + Map<String, CharSequence> sources = Map.of("r.FooPlugin", """ |
| 627 | + package r; |
| 628 | + import org.elasticsearch.plugins.ActionPlugin; |
| 629 | + import org.elasticsearch.plugins.Plugin; |
| 630 | + public final class FooPlugin extends Plugin implements ActionPlugin { } |
| 631 | + """, "r.FooTestService", Strings.format(""" |
| 632 | + package r; |
| 633 | + import org.elasticsearch.plugins.spi.TestService; |
| 634 | + public final class FooTestService implements TestService { |
| 635 | + @Override |
| 636 | + public String name() { |
| 637 | + return "%s"; |
| 638 | + } |
| 639 | + } |
| 640 | + """, name)); |
| 641 | + |
| 642 | + var classToBytes = InMemoryJavaCompiler.compile(sources); |
| 643 | + |
| 644 | + Map<String, byte[]> jarEntries = new HashMap<>(); |
| 645 | + jarEntries.put("r/FooPlugin.class", classToBytes.get("r.FooPlugin")); |
| 646 | + jarEntries.put("r/FooTestService.class", classToBytes.get("r.FooTestService")); |
| 647 | + jarEntries.put("META-INF/services/org.elasticsearch.plugins.spi.TestService", "r.FooTestService".getBytes(StandardCharsets.UTF_8)); |
| 648 | + |
| 649 | + Path topLevelDir = createTempDir(getTestName()); |
| 650 | + Path jar = topLevelDir.resolve(Strings.format("custom_plugin_%s.jar", name)); |
| 651 | + JarUtils.createJarWithEntries(jar, jarEntries); |
| 652 | + URL[] urls = new URL[] { jar.toUri().toURL() }; |
| 653 | + |
| 654 | + URLClassLoader loader = URLClassLoader.newInstance(urls, this.getClass().getClassLoader()); |
| 655 | + return loader; |
| 656 | + } |
| 657 | + |
| 658 | + public void testLoadServiceProviders() throws Exception { |
| 659 | + ClassLoader fakeClassLoader = buildTestProviderPlugin("integer"); |
| 660 | + @SuppressWarnings("unchecked") |
| 661 | + Class<? extends Plugin> fakePluginClass = (Class<? extends Plugin>) fakeClassLoader.loadClass("r.FooPlugin"); |
| 662 | + |
| 663 | + ClassLoader fakeClassLoader1 = buildTestProviderPlugin("string"); |
| 664 | + @SuppressWarnings("unchecked") |
| 665 | + Class<? extends Plugin> fakePluginClass1 = (Class<? extends Plugin>) fakeClassLoader1.loadClass("r.FooPlugin"); |
| 666 | + |
| 667 | + assertFalse(fakePluginClass.getClassLoader().equals(fakePluginClass1.getClassLoader())); |
| 668 | + |
| 669 | + getClass().getModule().addUses(TestService.class); |
| 670 | + |
| 671 | + PluginsService service = newMockPluginsService(List.of(fakePluginClass, fakePluginClass1)); |
| 672 | + |
| 673 | + List<? extends TestService> providers = service.loadServiceProviders(TestService.class); |
| 674 | + assertEquals(2, providers.size()); |
| 675 | + assertThat(providers.stream().map(p -> p.name()).toList(), containsInAnyOrder("string", "integer")); |
| 676 | + |
| 677 | + service = newMockPluginsService(List.of(fakePluginClass)); |
| 678 | + providers = service.loadServiceProviders(TestService.class); |
| 679 | + |
| 680 | + assertEquals(1, providers.size()); |
| 681 | + assertThat(providers.stream().map(p -> p.name()).toList(), containsInAnyOrder("integer")); |
| 682 | + |
| 683 | + service = newMockPluginsService(new ArrayList<>()); |
| 684 | + providers = service.loadServiceProviders(TestService.class); |
| 685 | + |
| 686 | + assertEquals(0, providers.size()); |
| 687 | + } |
| 688 | + |
616 | 689 | private static class TestExtensiblePlugin extends Plugin implements ExtensiblePlugin { |
617 | 690 | private List<TestExtensionPoint> extensions; |
618 | 691 |
|
|
0 commit comments