diff options
Diffstat (limited to 'standalone-container')
2 files changed, 82 insertions, 18 deletions
diff --git a/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneContainerActivator.java b/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneContainerActivator.java index baf0b41b270..d03a08a27db 100644 --- a/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneContainerActivator.java +++ b/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneContainerActivator.java @@ -19,15 +19,24 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Hashtable; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toMap; /** * @author Einar M R Rosenvinge @@ -36,19 +45,69 @@ public class StandaloneContainerActivator implements BundleActivator { @Override public void start(BundleContext bundleContext) throws Exception { - for (ConnectorConfig config: getConnectorConfigs(getContainer())) { + Container container = getContainer(); + List<ConnectorConfig> connectorConfigs = getConnectorConfigs(container); + + Stream<Path> keyStorePaths = getKeyStorePaths(connectorConfigs); + Map<Path, FileChannel> fileChannels = openFiles(keyStorePaths); + registerKeyStoreFileChannels(bundleContext, fileChannels); + + for (ConnectorConfig config: connectorConfigs) { ServerSocketChannel socketChannel = bindChannel(config); registerChannels(bundleContext, config.listenPort(), socketChannel); } } - static void registerChannels(BundleContext bundleContext, int listenPort, ServerSocketChannel boundChannel) { + private void registerKeyStoreFileChannels(BundleContext bundleContext, Map<Path, FileChannel> fileChannels) { + Hashtable<String, Object> properties = new Hashtable<>(); + properties.put("role", "com.yahoo.container.standalone.StandaloneContainerActivator.KeyStoreFileChannels"); + //Since Standalone container and jdisc http service don't have a suitable common module for placing a wrapper class for fileChannels, + //we register it with the type map. In the future, we should wrap this. + bundleContext.registerService(Map.class, + Collections.unmodifiableMap(fileChannels), + properties); + } + + private Map<Path, FileChannel> openFiles(Stream<Path> keyStorePaths) { + return keyStorePaths.collect(toMap( + Function.<Path>identity(), + StandaloneContainerActivator::getFileChannel)); + } + + private static FileChannel getFileChannel(Path path) { + try { + FileInputStream inputStream = new FileInputStream(path.toFile()); + //don't close the inputStream, as that will close the underlying channel. + return inputStream.getChannel(); + } catch (IOException e) { + throw new RuntimeException("Failed opening path " + path, e); + } + } + + private Stream<Path> getKeyStorePaths(List<ConnectorConfig> connectorConfigs) { + return connectorConfigs.stream(). + map(ConnectorConfig::ssl). + flatMap(StandaloneContainerActivator::getKeyStorePaths); + } + + private static Stream<Path> getKeyStorePaths(ConnectorConfig.Ssl ssl) { + Stream<String> paths = Stream.of( + ssl.keyStorePath(), + ssl.pemKeyStore().certificatePath(), + ssl.pemKeyStore().keyPath()); + + return paths. + filter(path -> !path.isEmpty()). + map(Paths::get); + } + + void registerChannels(BundleContext bundleContext, int listenPort, ServerSocketChannel boundChannel) { Hashtable<String, Integer> properties = new Hashtable<>(); properties.put("port", listenPort); bundleContext.registerService(ServerSocketChannel.class, boundChannel, properties); } - static ServerSocketChannel bindChannel(ConnectorConfig channelInfo) throws IOException { + ServerSocketChannel bindChannel(ConnectorConfig channelInfo) throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); InetSocketAddress bindAddress = new InetSocketAddress(channelInfo.listenPort()); serverChannel.socket().bind(bindAddress, channelInfo.acceptQueueSize()); @@ -58,7 +117,7 @@ public class StandaloneContainerActivator implements BundleActivator { @Override public void stop(BundleContext bundleContext) throws Exception { } - static Container getContainer(Module... modules) { + Container getContainer(Module... modules) { Module activatorModule = new ActivatorModule(); List<Module> allModules = new ArrayList<>(); allModules.addAll(Arrays.asList(modules)); @@ -68,7 +127,7 @@ public class StandaloneContainerActivator implements BundleActivator { return app.container(); } - static List<ConnectorConfig> getConnectorConfigs(Container container) { + List<ConnectorConfig> getConnectorConfigs(Container container) { Http http = container.getHttp(); return (http == null) ? diff --git a/standalone-container/src/test/java/com/yahoo/container/standalone/StandaloneContainerActivatorTest.java b/standalone-container/src/test/java/com/yahoo/container/standalone/StandaloneContainerActivatorTest.java index 8d413ade0f0..48c882c78db 100644 --- a/standalone-container/src/test/java/com/yahoo/container/standalone/StandaloneContainerActivatorTest.java +++ b/standalone-container/src/test/java/com/yahoo/container/standalone/StandaloneContainerActivatorTest.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.container.standalone; +import com.google.inject.Binder; import com.google.inject.Module; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.http.ConnectorConfig; @@ -17,7 +18,6 @@ import java.nio.file.Path; import java.util.List; import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.collection.IsEmptyCollection.empty; @@ -29,7 +29,7 @@ import static org.junit.Assert.assertThat; */ public class StandaloneContainerActivatorTest { - private static String getJdiscXml(String contents) throws ParserConfigurationException, IOException, SAXException { + private String getJdiscXml(String contents) throws ParserConfigurationException, IOException, SAXException { return "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<services>\n" + " <jdisc version=\"1.0\" jetty=\"true\">\n" + @@ -38,7 +38,7 @@ public class StandaloneContainerActivatorTest { "</services>"; } - private static void writeApplicationPackage(String servicesXml, Path tmpDir) throws IOException { + private void writeApplicationPackage(String servicesXml, Path tmpDir) throws IOException { FileWriter fw = new FileWriter(tmpDir.resolve("services.xml").toFile(), false); fw.write(servicesXml); fw.close(); @@ -50,16 +50,16 @@ public class StandaloneContainerActivatorTest { try { writeApplicationPackage(getJdiscXml(""), applicationDir); StandaloneContainerActivator activator = new StandaloneContainerActivator(); - Container container = StandaloneContainerActivator.getContainer(newAppDirBinding(applicationDir)); + Container container = activator.getContainer(newAppDirBinding(applicationDir)); List<Integer> ports = getPorts(activator, container); - assertThat(ports, is(singletonList(Defaults.getDefaults().vespaWebServicePort()))); + assertThat(ports, is(asList(Defaults.getDefaults().vespaWebServicePort()))); } finally { IOUtils.recursiveDeleteDir(applicationDir.toFile()); } } - private static List<Integer> getPorts(StandaloneContainerActivator activator, Container container) { - return StandaloneContainerActivator.getConnectorConfigs(container).stream(). + private List<Integer> getPorts(StandaloneContainerActivator activator, Container container) { + return activator.getConnectorConfigs(container).stream(). map(ConnectorConfig::listenPort). collect(toList()); } @@ -70,7 +70,7 @@ public class StandaloneContainerActivatorTest { try { writeApplicationPackage(getJdiscXml("<http/>"), applicationDir); StandaloneContainerActivator activator = new StandaloneContainerActivator(); - Container container = StandaloneContainerActivator.getContainer(newAppDirBinding(applicationDir)); + Container container = activator.getContainer(newAppDirBinding(applicationDir)); List<Integer> ports = getPorts(activator, container); assertThat(ports, empty()); } finally { @@ -90,7 +90,7 @@ public class StandaloneContainerActivatorTest { "</http>\n"; writeApplicationPackage(getJdiscXml(contents), applicationDir); StandaloneContainerActivator activator = new StandaloneContainerActivator(); - Container container = StandaloneContainerActivator.getContainer(newAppDirBinding(applicationDir)); + Container container = activator.getContainer(newAppDirBinding(applicationDir)); List<Integer> ports = getPorts(activator, container); assertThat(ports, is(asList(123, 456, 789))); } finally { @@ -98,10 +98,15 @@ public class StandaloneContainerActivatorTest { } } - private static Module newAppDirBinding(final Path applicationDir) { - return binder -> binder.bind(Path.class) - .annotatedWith(StandaloneContainerApplication.applicationPathName()) - .toInstance(applicationDir); + private Module newAppDirBinding(final Path applicationDir) { + return new Module() { + @Override + public void configure(Binder binder) { + binder.bind(Path.class) + .annotatedWith(StandaloneContainerApplication.applicationPathName()) + .toInstance(applicationDir); + } + }; } } |