diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-11-28 21:35:16 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-11-28 21:35:16 +0100 |
commit | 1d6791e6fa004ae80e85dbc6a6c7c2e4b8037a4f (patch) | |
tree | 650307f35d321145410248f703943ef7525f94fb /jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty | |
parent | 0606896d63cc8bbe4919c7c37126fb9bc3f6e34e (diff) | |
parent | 7e8f8da8f249cf3c529cec8ecdcf13b69c99da13 (diff) |
Merge with master
Diffstat (limited to 'jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty')
7 files changed, 164 insertions, 270 deletions
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java index 3363c7d3284..c3c83474e56 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java @@ -5,6 +5,7 @@ import com.google.common.base.Objects; import com.yahoo.container.logging.AccessLog; import com.yahoo.container.logging.AccessLogEntry; +import com.yahoo.jdisc.http.servlet.ServletRequest; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.RequestLog; import org.eclipse.jetty.server.Response; @@ -17,6 +18,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.security.Principal; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -107,6 +109,12 @@ public class AccessLogRequestLog extends AbstractLifeCycle implements RequestLog accessLogEntry.setPeerPort(peerPort); } accessLogEntry.setHttpVersion(request.getProtocol()); + accessLogEntry.setScheme(request.getScheme()); + accessLogEntry.setLocalPort(request.getLocalPort()); + Principal principal = (Principal) request.getAttribute(ServletRequest.JDISC_REQUEST_PRINCIPAL); + if (principal != null) { + accessLogEntry.setUserPrincipal(principal); + } } private static String getRemoteAddress(final HttpServletRequest request) { diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java index 43513b4efba..e30d50ecdbf 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java @@ -54,24 +54,27 @@ public class AccessLoggingRequestHandler extends AbstractRequestHandler { Preconditions.checkArgument(request instanceof HttpRequest, "Expected HttpRequest, got " + request); final HttpRequest httpRequest = (HttpRequest) request; httpRequest.context().put(CONTEXT_KEY_ACCESS_LOG_ENTRY, accessLogEntry); - final ResponseHandler accessLoggingResponseHandler = new AccessLoggingResponseHandler(handler, accessLogEntry); + final ResponseHandler accessLoggingResponseHandler = new AccessLoggingResponseHandler(httpRequest, handler, accessLogEntry); final ContentChannel requestContentChannel = delegate.handleRequest(request, accessLoggingResponseHandler); return requestContentChannel; } private static class AccessLoggingResponseHandler implements ResponseHandler { + private final HttpRequest request; private final ResponseHandler delegateHandler; private final AccessLogEntry accessLogEntry; public AccessLoggingResponseHandler( - final ResponseHandler delegateHandler, + HttpRequest request, final ResponseHandler delegateHandler, final AccessLogEntry accessLogEntry) { + this.request = request; this.delegateHandler = delegateHandler; this.accessLogEntry = accessLogEntry; } @Override public ContentChannel handleResponse(Response response) { + accessLogEntry.setUserPrincipal(request.getUserPrincipal()); return delegateHandler.handleResponse(response); } diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java index 96180f48229..8255e16e0ee 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java @@ -1,66 +1,41 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jdisc.http.server.jetty; -import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.http.ConnectorConfig; import com.yahoo.jdisc.http.ConnectorConfig.Ssl; -import com.yahoo.jdisc.http.ConnectorConfig.Ssl.PemKeyStore; import com.yahoo.jdisc.http.SecretStore; -import com.yahoo.jdisc.http.ssl.ReaderForPath; -import com.yahoo.jdisc.http.ssl.SslKeyStore; -import com.yahoo.jdisc.http.ssl.pem.PemSslKeyStore; +import com.yahoo.jdisc.http.ssl.DefaultSslKeyStoreContext; +import com.yahoo.jdisc.http.ssl.SslKeyStoreConfigurator; import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnectionStatistics; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; -import javax.servlet.ServletRequest; -import java.io.IOException; -import java.io.Reader; -import java.lang.reflect.Field; -import java.net.Socket; -import java.net.SocketException; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.util.Map; -import java.util.Optional; -import java.util.TreeMap; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static com.google.common.io.Closeables.closeQuietly; -import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.JKS; -import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.PEM; -import static com.yahoo.jdisc.http.server.jetty.Exceptions.throwUnchecked; /** * @author Einar M R Rosenvinge + * @author bjorncs */ public class ConnectorFactory { - private final static Logger log = Logger.getLogger(ConnectorFactory.class.getName()); private final ConnectorConfig connectorConfig; private final SecretStore secretStore; + private final SslKeyStoreConfigurator sslKeyStoreConfigurator; @Inject - public ConnectorFactory(ConnectorConfig connectorConfig, SecretStore secretStore) { + public ConnectorFactory(ConnectorConfig connectorConfig, + SecretStore secretStore, + SslKeyStoreConfigurator sslKeyStoreConfigurator) { this.connectorConfig = connectorConfig; this.secretStore = secretStore; + this.sslKeyStoreConfigurator = sslKeyStoreConfigurator; if (connectorConfig.ssl().enabled()) validateSslConfig(connectorConfig); @@ -69,14 +44,8 @@ public class ConnectorFactory { // TODO: can be removed when we have dedicated SSL config in services.xml private static void validateSslConfig(ConnectorConfig config) { ConnectorConfig.Ssl ssl = config.ssl(); - - if (ssl.keyStoreType() == JKS) { - if (! ssl.pemKeyStore().keyPath().isEmpty() || ! ssl.pemKeyStore().certificatePath().isEmpty()) - throw new IllegalArgumentException("pemKeyStore attributes can not be set when keyStoreType is JKS."); - } - if (ssl.keyStoreType() == PEM) { - if (! ssl.keyStorePath().isEmpty()) - throw new IllegalArgumentException("keyStorePath can not be set when keyStoreType is PEM"); + if (!ssl.trustStorePath().isEmpty() && ssl.useTrustStorePassword() && ssl.keyDbKey().isEmpty()) { + throw new IllegalArgumentException("Missing password for JKS truststore"); } } @@ -84,11 +53,11 @@ public class ConnectorFactory { return connectorConfig; } - public ServerConnector createConnector(final Metric metric, final Server server, final ServerSocketChannel ch, Map<Path, FileChannel> keyStoreChannels) { + public ServerConnector createConnector(final Metric metric, final Server server, final ServerSocketChannel ch) { ServerConnector connector; if (connectorConfig.ssl().enabled()) { connector = new JDiscServerConnector(connectorConfig, metric, server, ch, - newSslConnectionFactory(keyStoreChannels), + newSslConnectionFactory(), newHttpConnectionFactory()); } else { connector = new JDiscServerConnector(connectorConfig, metric, server, ch, @@ -125,10 +94,13 @@ public class ConnectorFactory { } //TODO: does not support loading non-yahoo readable JKS key stores. - private SslConnectionFactory newSslConnectionFactory(Map<Path, FileChannel> keyStoreChannels) { + private SslConnectionFactory newSslConnectionFactory() { Ssl sslConfig = connectorConfig.ssl(); SslContextFactory factory = new SslContextFactory(); + + sslKeyStoreConfigurator.configure(new DefaultSslKeyStoreContext(factory)); + switch (sslConfig.clientAuth()) { case NEED_AUTH: factory.setNeedClientAuth(true); @@ -172,25 +144,14 @@ public class ConnectorFactory { factory.setIncludeCipherSuites(ciphs); } - Optional<String> keyDbPassword = secret(sslConfig.keyDbKey()); - switch (sslConfig.keyStoreType()) { - case PEM: - factory.setKeyStore(getKeyStore(sslConfig.pemKeyStore(), keyStoreChannels)); - if (keyDbPassword.isPresent()) - log.warning("Encrypted PEM key stores are not supported."); - break; - case JKS: - factory.setKeyStorePath(sslConfig.keyStorePath()); - factory.setKeyStoreType(sslConfig.keyStoreType().toString()); - factory.setKeyStorePassword(keyDbPassword.orElseThrow(passwordRequiredForJKSKeyStore("key"))); - break; - } + String keyDbPassword = sslConfig.keyDbKey(); if (!sslConfig.trustStorePath().isEmpty()) { factory.setTrustStorePath(sslConfig.trustStorePath()); factory.setTrustStoreType(sslConfig.trustStoreType().toString()); - if (sslConfig.useTrustStorePassword()) - factory.setTrustStorePassword(keyDbPassword.orElseThrow(passwordRequiredForJKSKeyStore("trust"))); + if (sslConfig.useTrustStorePassword()) { + factory.setTrustStorePassword(secretStore.getSecret(keyDbPassword)); + } } factory.setKeyManagerFactoryAlgorithm(sslConfig.sslKeyManagerFactoryAlgorithm()); @@ -198,162 +159,4 @@ public class ConnectorFactory { return new SslConnectionFactory(factory, HttpVersion.HTTP_1_1.asString()); } - /** Returns the secret password with the given name, or empty if the password name is null or empty */ - private Optional<String> secret(String keyname) { - return Optional.of(keyname).filter(key -> !key.isEmpty()).map(secretStore::getSecret); - } - - @SuppressWarnings("ThrowableInstanceNeverThrown") - private Supplier<RuntimeException> passwordRequiredForJKSKeyStore(String type) { - return () -> new RuntimeException(String.format("Password is required for JKS %s store", type)); - } - - private KeyStore getKeyStore(PemKeyStore pemKeyStore, Map<Path, FileChannel> keyStoreChannels) { - Preconditions.checkArgument(!pemKeyStore.certificatePath().isEmpty(), "Missing certificate path."); - Preconditions.checkArgument(!pemKeyStore.keyPath().isEmpty(), "Missing key path."); - - class KeyStoreReaderForPath implements AutoCloseable { - private final Optional<FileChannel> channel; - public final ReaderForPath readerForPath; - - - KeyStoreReaderForPath(String pathString) { - Path path = Paths.get(pathString); - channel = Optional.ofNullable(keyStoreChannels.get(path)); - readerForPath = new ReaderForPath(channel.map(this::getReader).orElseGet(() -> getReader(path)), path); - } - - private Reader getReader(FileChannel channel) { - try { - channel.position(0); - return Channels.newReader(channel, StandardCharsets.UTF_8.newDecoder(), -1); - } catch (IOException e) { - throw throwUnchecked(e); - } - - } - - private Reader getReader(Path path) { - try { - return Files.newBufferedReader(path); - } catch (IOException e) { - throw new RuntimeException("Failed opening " + path, e); - } - } - - @Override - public void close() { - //channels are reused - if (!channel.isPresent()) { - closeQuietly(readerForPath.reader); - } - } - } - - try (KeyStoreReaderForPath certificateReader = new KeyStoreReaderForPath(pemKeyStore.certificatePath()); - KeyStoreReaderForPath keyReader = new KeyStoreReaderForPath(pemKeyStore.keyPath())) { - SslKeyStore keyStore = new PemSslKeyStore( - new com.yahoo.jdisc.http.ssl.pem.PemKeyStore.KeyStoreLoadParameter( - certificateReader.readerForPath, keyReader.readerForPath)); - return keyStore.loadJavaKeyStore(); - } catch (Exception e) { - throw new RuntimeException("Failed setting up key store for " + pemKeyStore.keyPath() + ", " + pemKeyStore.certificatePath(), e); - } - } - - public static class JDiscServerConnector extends ServerConnector { - public static final String REQUEST_ATTRIBUTE = JDiscServerConnector.class.getName(); - private final static Logger log = Logger.getLogger(JDiscServerConnector.class.getName()); - private final Metric.Context metricCtx; - private final ServerConnectionStatistics statistics; - private final boolean tcpKeepAlive; - private final boolean tcpNoDelay; - private final ServerSocketChannel channelOpenedByActivator; - - private JDiscServerConnector(ConnectorConfig config, Metric metric, Server server, - ServerSocketChannel channelOpenedByActivator, ConnectionFactory... factories) { - super(server, factories); - this.channelOpenedByActivator = channelOpenedByActivator; - this.tcpKeepAlive = config.tcpKeepAliveEnabled(); - this.tcpNoDelay = config.tcpNoDelay(); - this.metricCtx = createMetricContext(config, metric); - - this.statistics = new ServerConnectionStatistics(); - addBean(statistics); - } - - private Metric.Context createMetricContext(ConnectorConfig config, Metric metric) { - Map<String, Object> props = new TreeMap<>(); - props.put(JettyHttpServer.Metrics.NAME_DIMENSION, config.name()); - props.put(JettyHttpServer.Metrics.PORT_DIMENSION, config.listenPort()); - return metric.createContext(props); - } - - @Override - protected void configure(final Socket socket) { - super.configure(socket); - try { - socket.setKeepAlive(tcpKeepAlive); - socket.setTcpNoDelay(tcpNoDelay); - } catch (SocketException ignored) { - } - } - - @Override - public void open() throws IOException { - if (channelOpenedByActivator == null) { - log.log(Level.INFO, "No channel set by activator, opening channel ourselves."); - try { - super.open(); - } catch (RuntimeException e) { - log.log(Level.SEVERE, "failed org.eclipse.jetty.server.Server open() with port "+getPort()); - throw e; - } - return; - } - log.log(Level.INFO, "Using channel set by activator: " + channelOpenedByActivator); - - channelOpenedByActivator.socket().setReuseAddress(getReuseAddress()); - int localPort = channelOpenedByActivator.socket().getLocalPort(); - try { - uglySetLocalPort(localPort); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Could not set local port.", e); - } - if (localPort <= 0) { - throw new IOException("Server channel not bound"); - } - addBean(channelOpenedByActivator); - channelOpenedByActivator.configureBlocking(true); - addBean(channelOpenedByActivator); - - try { - uglySetChannel(channelOpenedByActivator); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Could not set server channel.", e); - } - } - - private void uglySetLocalPort(int localPort) throws NoSuchFieldException, IllegalAccessException { - Field localPortField = ServerConnector.class.getDeclaredField("_localPort"); - localPortField.setAccessible(true); - localPortField.set(this, localPort); - } - - private void uglySetChannel(ServerSocketChannel channelOpenedByActivator) throws NoSuchFieldException, - IllegalAccessException { - Field acceptChannelField = ServerConnector.class.getDeclaredField("_acceptChannel"); - acceptChannelField.setAccessible(true); - acceptChannelField.set(this, channelOpenedByActivator); - } - - public ServerConnectionStatistics getStatistics() { return statistics; } - - public Metric.Context getMetricContext() { return metricCtx; } - - public static JDiscServerConnector fromRequest(ServletRequest request) { - return (JDiscServerConnector)request.getAttribute(REQUEST_ATTRIBUTE); - } - } - } diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java index 7f169c7c8d0..5cabe8acd27 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java @@ -12,6 +12,7 @@ import com.yahoo.jdisc.handler.OverloadException; import com.yahoo.jdisc.handler.RequestHandler; import com.yahoo.jdisc.http.HttpHeaders; import com.yahoo.jdisc.http.HttpRequest; +import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.server.HttpConnection; import javax.servlet.AsyncContext; @@ -122,7 +123,11 @@ class HttpRequestDispatch { boolean reportedError = false; if (error != null) { - if (!(error instanceof OverloadException || error instanceof BindingNotFoundException)) { + if (error instanceof EofException) { + log.log(Level.FINE, + "Network connection was unexpectedly terminated: " + parent.servletRequest.getRequestURI(), + error); + } else if (!(error instanceof OverloadException || error instanceof BindingNotFoundException)) { log.log(Level.WARNING, "Request failed: " + parent.servletRequest.getRequestURI(), error); } reportedError = true; diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java index 543cf8ab43e..27f72c7b4bf 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java @@ -20,7 +20,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.jdisc.http.core.HttpServletRequestUtils.getConnection; -import static com.yahoo.jdisc.http.server.jetty.ConnectorFactory.JDiscServerConnector; /** * @author Simon Thoresen Hult diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java new file mode 100644 index 00000000000..8dd50074c32 --- /dev/null +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java @@ -0,0 +1,122 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.server.jetty; + +import com.yahoo.jdisc.Metric; +import com.yahoo.jdisc.http.ConnectorConfig; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnectionStatistics; +import org.eclipse.jetty.server.ServerConnector; + +import javax.servlet.ServletRequest; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.Socket; +import java.net.SocketException; +import java.nio.channels.ServerSocketChannel; +import java.util.Map; +import java.util.TreeMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author bjorncs + */ +class JDiscServerConnector extends ServerConnector { + public static final String REQUEST_ATTRIBUTE = JDiscServerConnector.class.getName(); + private final static Logger log = Logger.getLogger(JDiscServerConnector.class.getName()); + private final Metric.Context metricCtx; + private final ServerConnectionStatistics statistics; + private final boolean tcpKeepAlive; + private final boolean tcpNoDelay; + private final ServerSocketChannel channelOpenedByActivator; + + JDiscServerConnector(ConnectorConfig config, Metric metric, Server server, + ServerSocketChannel channelOpenedByActivator, ConnectionFactory... factories) { + super(server, factories); + this.channelOpenedByActivator = channelOpenedByActivator; + this.tcpKeepAlive = config.tcpKeepAliveEnabled(); + this.tcpNoDelay = config.tcpNoDelay(); + this.metricCtx = createMetricContext(config, metric); + + this.statistics = new ServerConnectionStatistics(); + addBean(statistics); + } + + private Metric.Context createMetricContext(ConnectorConfig config, Metric metric) { + Map<String, Object> props = new TreeMap<>(); + props.put(JettyHttpServer.Metrics.NAME_DIMENSION, config.name()); + props.put(JettyHttpServer.Metrics.PORT_DIMENSION, config.listenPort()); + return metric.createContext(props); + } + + @Override + protected void configure(final Socket socket) { + super.configure(socket); + try { + socket.setKeepAlive(tcpKeepAlive); + socket.setTcpNoDelay(tcpNoDelay); + } catch (SocketException ignored) { + } + } + + @Override + public void open() throws IOException { + if (channelOpenedByActivator == null) { + log.log(Level.INFO, "No channel set by activator, opening channel ourselves."); + try { + super.open(); + } catch (RuntimeException e) { + log.log(Level.SEVERE, "failed org.eclipse.jetty.server.Server open() with port " + getPort()); + throw e; + } + return; + } + log.log(Level.INFO, "Using channel set by activator: " + channelOpenedByActivator); + + channelOpenedByActivator.socket().setReuseAddress(getReuseAddress()); + int localPort = channelOpenedByActivator.socket().getLocalPort(); + try { + uglySetLocalPort(localPort); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Could not set local port.", e); + } + if (localPort <= 0) { + throw new IOException("Server channel not bound"); + } + addBean(channelOpenedByActivator); + channelOpenedByActivator.configureBlocking(true); + addBean(channelOpenedByActivator); + + try { + uglySetChannel(channelOpenedByActivator); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Could not set server channel.", e); + } + } + + private void uglySetLocalPort(int localPort) throws NoSuchFieldException, IllegalAccessException { + Field localPortField = ServerConnector.class.getDeclaredField("_localPort"); + localPortField.setAccessible(true); + localPortField.set(this, localPort); + } + + private void uglySetChannel(ServerSocketChannel channelOpenedByActivator) throws NoSuchFieldException, + IllegalAccessException { + Field acceptChannelField = ServerConnector.class.getDeclaredField("_acceptChannel"); + acceptChannelField.setAccessible(true); + acceptChannelField.set(this, channelOpenedByActivator); + } + + public ServerConnectionStatistics getStatistics() { + return statistics; + } + + public Metric.Context getMetricContext() { + return metricCtx; + } + + public static JDiscServerConnector fromRequest(ServletRequest request) { + return (JDiscServerConnector) request.getAttribute(REQUEST_ATTRIBUTE); + } +} diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java index 509bf42d466..7bff685e780 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java @@ -44,15 +44,11 @@ import javax.servlet.DispatcherType; import java.lang.management.ManagementFactory; import java.net.BindException; import java.net.MalformedURLException; -import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.EnumSet; import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -62,9 +58,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import static com.yahoo.jdisc.http.server.jetty.ConnectorFactory.JDiscServerConnector; -import static com.yahoo.jdisc.http.server.jetty.Exceptions.throwUnchecked; - /** * @author Simon Thoresen Hult * @author bjorncs @@ -147,11 +140,9 @@ public class JettyHttpServer extends AbstractServerProvider { setupJmx(server, serverConfig); ((QueuedThreadPool)server.getThreadPool()).setMaxThreads(serverConfig.maxWorkerThreads()); - Map<Path, FileChannel> keyStoreChannels = getKeyStoreFileChannels(osgiFramework.bundleContext()); - for (ConnectorFactory connectorFactory : connectorFactories.allComponents()) { ServerSocketChannel preBoundChannel = getChannelFromServiceLayer(connectorFactory.getConnectorConfig().listenPort(), osgiFramework.bundleContext()); - server.addConnector(connectorFactory.createConnector(metric, server, preBoundChannel, keyStoreChannels)); + server.addConnector(connectorFactory.createConnector(metric, server, preBoundChannel)); listenedPorts.add(connectorFactory.getConnectorConfig().listenPort()); } @@ -257,43 +248,6 @@ public class JettyHttpServer extends AbstractServerProvider { return "/" + servletPathsConfig.servlets(id.stringValue()).path(); } - // Ugly trick to get generic type literal. - @SuppressWarnings("unchecked") - private static final Class<Map<?, ?>> mapClass = (Class<Map<?, ?>>) (Object) Map.class; - - private Map<Path, FileChannel> getKeyStoreFileChannels(BundleContext bundleContext) { - try { - Collection<ServiceReference<Map<?, ?>>> serviceReferences = bundleContext.getServiceReferences(mapClass, - "(role=com.yahoo.container.standalone.StandaloneContainerActivator.KeyStoreFileChannels)"); - - if (serviceReferences == null || serviceReferences.isEmpty()) - return Collections.emptyMap(); - - if (serviceReferences.size() != 1) - throw new IllegalStateException("Multiple KeyStoreFileChannels registered"); - - return getKeyStoreFileChannels(bundleContext, serviceReferences.iterator().next()); - } catch (InvalidSyntaxException e) { - throw throwUnchecked(e); - } - } - - @SuppressWarnings("unchecked") - private Map<Path, FileChannel> getKeyStoreFileChannels(BundleContext bundleContext, ServiceReference<Map<?, ?>> keyStoreFileChannelReference) { - Map<?, ?> fileChannelMap = bundleContext.getService(keyStoreFileChannelReference); - try { - if (fileChannelMap == null) - return Collections.emptyMap(); - - Map<Path, FileChannel> result = (Map<Path, FileChannel>) fileChannelMap; - log.fine("Using file channel for " + result.keySet()); - return result; - } finally { - //if we change this to be anything other than a simple map, we should hold the reference as long as the object is in use. - bundleContext.ungetService(keyStoreFileChannelReference); - } - } - private ServletContextHandler createServletContextHandler() { ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS); servletContextHandler.setContextPath("/"); @@ -324,8 +278,8 @@ public class JettyHttpServer extends AbstractServerProvider { return bundleContext.getService(ref); } - private static ExecutorService newJanitor(final ThreadFactory factory) { - final int threadPoolSize = Runtime.getRuntime().availableProcessors(); + private static ExecutorService newJanitor(ThreadFactory factory) { + int threadPoolSize = Runtime.getRuntime().availableProcessors(); log.info("Creating janitor executor with " + threadPoolSize + " threads"); return Executors.newFixedThreadPool( threadPoolSize, |