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;
}
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, "");
}
}
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, "");
}
}
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);
}
}
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);
}
}
}
Aggregations