Search in sources :

Example 1 with NarClassLoader

use of org.apache.pulsar.common.nar.NarClassLoader in project pulsar by apache.

the class OffloaderUtils method getOffloaderFactory.

/**
 * Extract the Pulsar offloader class from a offloader archive.
 *
 * @param narPath nar package path
 * @return the offloader class name
 * @throws IOException when fail to retrieve the pulsar offloader class
 */
static Pair<NarClassLoader, LedgerOffloaderFactory> getOffloaderFactory(String narPath, String narExtractionDirectory) throws IOException {
    // need to load offloader NAR to the classloader that also loaded LedgerOffloaderFactory in case
    // LedgerOffloaderFactory is loaded by a classloader that is not the default classloader
    // as is the case for the pulsar presto plugin
    NarClassLoader ncl = NarClassLoaderBuilder.builder().narFile(new File(narPath)).parentClassLoader(LedgerOffloaderFactory.class.getClassLoader()).extractionDirectory(narExtractionDirectory).build();
    String configStr = ncl.getServiceDefinition(PULSAR_OFFLOADER_SERVICE_NAME);
    OffloaderDefinition conf = ObjectMapperFactory.getThreadLocalYaml().readValue(configStr, OffloaderDefinition.class);
    if (StringUtils.isEmpty(conf.getOffloaderFactoryClass())) {
        throw new IOException(String.format("The '%s' offloader does not provide an offloader factory implementation", conf.getName()));
    }
    try {
        // Try to load offloader factory class and check it implements Offloader interface
        Class factoryClass = ncl.loadClass(conf.getOffloaderFactoryClass());
        CompletableFuture<LedgerOffloaderFactory> loadFuture = new CompletableFuture<>();
        Thread loadingThread = new Thread(() -> {
            Thread.currentThread().setContextClassLoader(ncl);
            try {
                Object offloader = factoryClass.getDeclaredConstructor().newInstance();
                if (!(offloader instanceof LedgerOffloaderFactory)) {
                    throw new IOException("Class " + conf.getOffloaderFactoryClass() + " does not implement " + "interface " + LedgerOffloaderFactory.class.getName());
                }
                loadFuture.complete((LedgerOffloaderFactory) offloader);
            } catch (Throwable t) {
                loadFuture.completeExceptionally(t);
            }
        }, "load-factory-" + factoryClass);
        try {
            loadingThread.start();
            return Pair.of(ncl, loadFuture.get());
        } finally {
            loadingThread.join();
        }
    } catch (Throwable t) {
        rethrowIOException(t);
    }
    return null;
}
Also used : LedgerOffloaderFactory(org.apache.bookkeeper.mledger.LedgerOffloaderFactory) CompletableFuture(java.util.concurrent.CompletableFuture) NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader) IOException(java.io.IOException) File(java.io.File)

Example 2 with NarClassLoader

use of org.apache.pulsar.common.nar.NarClassLoader in project pulsar by apache.

the class AdditionalServletUtilsTest method testLoadEventListenerWithBlankListerClass.

@Test(expectedExceptions = IOException.class)
public void testLoadEventListenerWithBlankListerClass() throws Exception {
    AdditionalServletDefinition def = new AdditionalServletDefinition();
    def.setDescription("test-proxy-listener");
    String archivePath = "/path/to/proxy/listener/nar";
    AdditionalServletMetadata metadata = new AdditionalServletMetadata();
    metadata.setDefinition(def);
    metadata.setArchivePath(Paths.get(archivePath));
    NarClassLoader mockLoader = mock(NarClassLoader.class);
    when(mockLoader.getServiceDefinition(eq(AdditionalServletUtils.ADDITIONAL_SERVLET_FILE))).thenReturn(ObjectMapperFactory.getThreadLocalYaml().writeValueAsString(def));
    Class listenerClass = MockAdditionalServlet.class;
    when(mockLoader.loadClass(eq(MockAdditionalServlet.class.getName()))).thenReturn(listenerClass);
    final NarClassLoaderBuilder mockedBuilder = mock(NarClassLoaderBuilder.class, RETURNS_SELF);
    when(mockedBuilder.build()).thenReturn(mockLoader);
    try (MockedStatic<NarClassLoaderBuilder> builder = Mockito.mockStatic(NarClassLoaderBuilder.class)) {
        builder.when(() -> NarClassLoaderBuilder.builder()).thenReturn(mockedBuilder);
        AdditionalServletUtils.load(metadata, "");
    }
}
Also used : NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader) NarClassLoaderBuilder(org.apache.pulsar.common.nar.NarClassLoaderBuilder) Test(org.testng.annotations.Test)

Example 3 with NarClassLoader

use of org.apache.pulsar.common.nar.NarClassLoader in project pulsar by apache.

the class AdditionalServletUtilsTest method testLoadEventListenerWithWrongListerClass.

@Test(expectedExceptions = IOException.class)
public void testLoadEventListenerWithWrongListerClass() throws Exception {
    AdditionalServletDefinition def = new AdditionalServletDefinition();
    def.setAdditionalServletClass(Runnable.class.getName());
    def.setDescription("test-proxy-listener");
    String archivePath = "/path/to/proxy/listener/nar";
    AdditionalServletMetadata metadata = new AdditionalServletMetadata();
    metadata.setDefinition(def);
    metadata.setArchivePath(Paths.get(archivePath));
    NarClassLoader mockLoader = mock(NarClassLoader.class);
    when(mockLoader.getServiceDefinition(eq(AdditionalServletUtils.ADDITIONAL_SERVLET_FILE))).thenReturn(ObjectMapperFactory.getThreadLocalYaml().writeValueAsString(def));
    Class listenerClass = Runnable.class;
    when(mockLoader.loadClass(eq(Runnable.class.getName()))).thenReturn(listenerClass);
    final NarClassLoaderBuilder mockedBuilder = mock(NarClassLoaderBuilder.class, RETURNS_SELF);
    when(mockedBuilder.build()).thenReturn(mockLoader);
    try (MockedStatic<NarClassLoaderBuilder> builder = Mockito.mockStatic(NarClassLoaderBuilder.class)) {
        builder.when(() -> NarClassLoaderBuilder.builder()).thenReturn(mockedBuilder);
        AdditionalServletUtils.load(metadata, "");
    }
}
Also used : NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader) NarClassLoaderBuilder(org.apache.pulsar.common.nar.NarClassLoaderBuilder) Test(org.testng.annotations.Test)

Example 4 with NarClassLoader

use of org.apache.pulsar.common.nar.NarClassLoader in project pulsar by apache.

the class AdditionalServletWithPulsarServiceTest method testLoadAdditionalServlet.

@Test
public void testLoadAdditionalServlet() throws Exception {
    AdditionalServletDefinition def = new AdditionalServletDefinition();
    def.setAdditionalServletClass(MockAdditionalServletWithClassLoader.class.getName());
    def.setDescription("test-additional-servlet");
    String archivePath = "/path/to/additional/servlet/nar";
    AdditionalServletMetadata metadata = new AdditionalServletMetadata();
    metadata.setDefinition(def);
    metadata.setArchivePath(Paths.get(archivePath));
    NarClassLoader mockLoader = mock(NarClassLoader.class);
    when(mockLoader.getServiceDefinition(eq(AdditionalServletUtils.ADDITIONAL_SERVLET_FILE))).thenReturn(ObjectMapperFactory.getThreadLocalYaml().writeValueAsString(def));
    Class additionalServletClass = MockAdditionalServletWithClassLoader.class;
    when(mockLoader.loadClass(eq(MockAdditionalServletWithClassLoader.class.getName()))).thenReturn(additionalServletClass);
    final NarClassLoaderBuilder mockedBuilder = mock(NarClassLoaderBuilder.class, RETURNS_SELF);
    when(mockedBuilder.build()).thenReturn(mockLoader);
    try (MockedStatic<NarClassLoaderBuilder> builder = Mockito.mockStatic(NarClassLoaderBuilder.class)) {
        builder.when(() -> NarClassLoaderBuilder.builder()).thenReturn(mockedBuilder);
        AdditionalServletWithClassLoader returnedASWithCL = AdditionalServletUtils.load(metadata, "");
        AdditionalServlet returnedPh = returnedASWithCL.getServlet();
        assertSame(mockLoader, returnedASWithCL.getClassLoader());
        assertTrue(returnedPh instanceof MockAdditionalServletWithClassLoader);
    }
}
Also used : NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader) NarClassLoaderBuilder(org.apache.pulsar.common.nar.NarClassLoaderBuilder) Test(org.testng.annotations.Test)

Example 5 with NarClassLoader

use of org.apache.pulsar.common.nar.NarClassLoader in project pulsar by apache.

the class PulsarFunctionLocalRunTest method runWithNarClassLoader.

private void runWithNarClassLoader(Assert.ThrowingRunnable throwingRunnable) throws Throwable {
    ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try (NarClassLoader classLoader = NarClassLoaderBuilder.builder().narFile(getPulsarIODataGeneratorNar()).parentClassLoader(originalClassLoader).extractionDirectory(NarClassLoader.DEFAULT_NAR_EXTRACTION_DIR).build()) {
        try {
            Thread.currentThread().setContextClassLoader(classLoader);
            throwingRunnable.run();
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }
    }
}
Also used : URLClassLoader(java.net.URLClassLoader) NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader) NarClassLoader(org.apache.pulsar.common.nar.NarClassLoader)

Aggregations

NarClassLoader (org.apache.pulsar.common.nar.NarClassLoader)40 Test (org.testng.annotations.Test)26 IOException (java.io.IOException)17 NarClassLoaderBuilder (org.apache.pulsar.common.nar.NarClassLoaderBuilder)16 File (java.io.File)13 FileInputStream (java.io.FileInputStream)5 UtilityClass (lombok.experimental.UtilityClass)5 Namespace (org.apache.distributedlog.api.namespace.Namespace)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 ServiceConfiguration (org.apache.pulsar.broker.ServiceConfiguration)4 Lists (com.google.common.collect.Lists)3 InputStream (java.io.InputStream)3 Files (java.nio.file.Files)3 Paths (java.nio.file.Paths)3 StandardCopyOption (java.nio.file.StandardCopyOption)3 LinkedList (java.util.LinkedList)3 List (java.util.List)3 Consumer (java.util.function.Consumer)3 Response (javax.ws.rs.core.Response)3