static ProtocolHandlerWithClassLoader load(ProtocolHandlerMetadata metadata,
                                               String narExtractionDirectory) throws IOException {
        final File narFile = metadata.getArchivePath().toAbsolutePath().toFile();
        NarClassLoader ncl = NarClassLoaderBuilder.builder()
                .narFile(narFile)
                .parentClassLoader(ProtocolHandler.class.getClassLoader())
                .extractionDirectory(narExtractionDirectory)
                .build();

        ProtocolHandlerDefinition phDef = getProtocolHandlerDefinition(ncl);
        if (StringUtils.isBlank(phDef.getHandlerClass())) {
            throw new IOException("Protocol handler `" + phDef.getName() + "` does NOT provide a protocol"
                + " handler implementation");
        }

        try {
            Class handlerClass = ncl.loadClass(phDef.getHandlerClass());
            Object handler = handlerClass.getDeclaredConstructor().newInstance();
            if (!(handler instanceof ProtocolHandler)) {
                throw new IOException("Class " + phDef.getHandlerClass()
                    + " does not implement protocol handler interface");
            }
            ProtocolHandler ph = (ProtocolHandler) handler;
            return new ProtocolHandlerWithClassLoader(ph, ncl);
        } catch (Throwable t) {
            rethrowIOException(t);
            return null;
        }
    }
@Test
    public void testLoadProtocolHandler() throws Exception {
        ProtocolHandlerDefinition def = new ProtocolHandlerDefinition();
        def.setHandlerClass(MockProtocolHandler.class.getName());
        def.setDescription("test-protocol-handler");

        String archivePath = "/path/to/protocol/handler/nar";

        ProtocolHandlerMetadata metadata = new ProtocolHandlerMetadata();
        metadata.setDefinition(def);
        metadata.setArchivePath(Paths.get(archivePath));

        NarClassLoader mockLoader = mock(NarClassLoader.class);
        when(mockLoader.getServiceDefinition(eq(PULSAR_PROTOCOL_HANDLER_DEFINITION_FILE)))
            .thenReturn(ObjectMapperFactory.getYamlMapper().writer().writeValueAsString(def));
        Class handlerClass = MockProtocolHandler.class;
        when(mockLoader.loadClass(eq(MockProtocolHandler.class.getName())))
            .thenReturn(handlerClass);

        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);

            ProtocolHandlerWithClassLoader returnedPhWithCL = ProtocolHandlerUtils.load(metadata, "");
            ProtocolHandler returnedPh = returnedPhWithCL.getHandler();

            assertSame(mockLoader, returnedPhWithCL.getClassLoader());
            assertTrue(returnedPh instanceof MockProtocolHandler);
        }
    }