11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac/*
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * CDDL HEADER START
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * The contents of this file are subject to the terms of the
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Common Development and Distribution License, Version 1.0 only
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * (the "License"). You may not use this file except in compliance
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * with the License.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * or http://forgerock.org/license/CDDLv1.0.html.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * See the License for the specific language governing permissions
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * and limitations under the License.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * When distributing Covered Code, include this CDDL HEADER in each
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * file and include the License file at legal-notices/CDDLv1_0.txt.
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * If applicable, add the following below this CDDL HEADER, with the
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * fields enclosed by brackets "[]" replaced with your own identifying
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * information:
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Portions Copyright [yyyy] [name of copyright owner]
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * CDDL HEADER END
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Copyright 2013 ForgeRock AS
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacpackage org.opends.server.protocols.http;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport java.io.File;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport java.io.IOException;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport java.net.InetAddress;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport java.util.*;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport java.util.concurrent.ConcurrentHashMap;
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignacimport java.util.concurrent.TimeUnit;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport java.util.logging.Level;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport java.util.logging.Logger;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport javax.net.ssl.KeyManager;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport javax.net.ssl.SSLContext;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport javax.net.ssl.SSLEngine;
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignacimport javax.servlet.DispatcherType;
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignacimport javax.servlet.Filter;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport javax.servlet.ServletException;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignacimport org.codehaus.jackson.JsonParseException;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.codehaus.jackson.JsonParser;
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignacimport org.codehaus.jackson.map.JsonMappingException;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.codehaus.jackson.map.ObjectMapper;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.fluent.JsonValue;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.resource.CollectionResourceProvider;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.resource.ConnectionFactory;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.resource.Resources;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.resource.Router;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.json.resource.servlet.HttpServlet;
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignacimport org.forgerock.opendj.ldap.SearchScope;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.opendj.rest2ldap.AuthorizationPolicy;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.opendj.rest2ldap.Rest2LDAP;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.forgerock.opendj.rest2ldap.servlet.Rest2LDAPContextFactory;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignacimport org.glassfish.grizzly.http.HttpProbe;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.glassfish.grizzly.http.server.HttpServer;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignacimport org.glassfish.grizzly.http.server.HttpServerMonitoringConfig;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.glassfish.grizzly.http.server.NetworkListener;
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignacimport org.glassfish.grizzly.http.server.ServerConfiguration;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignacimport org.glassfish.grizzly.monitoring.MonitoringConfig;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.glassfish.grizzly.nio.transport.TCPNIOTransport;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.glassfish.grizzly.servlet.WebappContext;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.glassfish.grizzly.ssl.SSLEngineConfigurator;
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignacimport org.glassfish.grizzly.strategies.SameThreadIOStrategy;
0d79a83a6c8d3af62f592c6e6f4a5b4d01719787matthewimport org.glassfish.grizzly.utils.Charsets;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.messages.Message;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.admin.server.ConfigurationChangeListener;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.admin.std.server.ConnectionHandlerCfg;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.admin.std.server.HTTPConnectionHandlerCfg;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport org.opends.server.api.*;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.config.ConfigException;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.core.DirectoryServer;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.extensions.NullKeyManagerProvider;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.extensions.NullTrustManagerProvider;
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignacimport org.opends.server.loggers.HTTPAccessLogger;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.loggers.debug.DebugTracer;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignacimport org.opends.server.monitors.ClientConnectionMonitorProvider;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport org.opends.server.types.*;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacimport org.opends.server.util.SelectableCertificateKeyManager;
caa0e374c1499ea42d335764d752b060a7174368JnRouvignacimport org.opends.server.util.StaticUtils;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.messages.ConfigMessages.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.messages.ProtocolMessages.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.server.loggers.ErrorLogger.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.server.loggers.debug.DebugLogger.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.server.util.ServerConstants.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignacimport static org.opends.server.util.StaticUtils.*;
1ed0da1f17cd5bc56955e29bc2536cf56c53a9bcJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac/**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * This class defines a connection handler that will be used for communicating
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * with clients over HTTP. The connection handler is responsible for
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * starting/stopping the embedded web server.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignacpublic class HTTPConnectionHandler extends
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac ConnectionHandler<HTTPConnectionHandlerCfg> implements
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac ConfigurationChangeListener<HTTPConnectionHandlerCfg>,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac ServerShutdownListener, AlertGenerator
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac{
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The tracer object for the debug logger. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private static final DebugTracer TRACER = getTracer();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** Default friendly name for this connection handler. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private static final String DEFAULT_FRIENDLY_NAME = "HTTP Connection Handler";
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** SSL instance name used in context creation. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS";
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac private static final ObjectMapper JSON_MAPPER = new ObjectMapper().configure(
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac JsonParser.Feature.ALLOW_COMMENTS, true);
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The initialization configuration. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private HTTPConnectionHandlerCfg initConfig;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The current configuration. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private HTTPConnectionHandlerCfg currentConfig;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Indicates whether the Directory Server is in the process of shutting down.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private volatile boolean shutdownRequested;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac /** Indicates whether this connection handler is enabled. */
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac private boolean enabled;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The set of listeners for this connection handler. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private List<HostPort> listeners = new LinkedList<HostPort>();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The HTTP server embedded in OpenDJ. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private HttpServer httpServer;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac /** The HTTP probe that collects stats. */
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac private HTTPStatsProbe httpProbe;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Holds the current client connections. Using {@link ConcurrentHashMap} to
0231adf34e4b43f90bb6ccae759ade8e0de51ea2JnRouvignac * ensure no concurrent reads/writes can happen and adds/removes are fast. We
0231adf34e4b43f90bb6ccae759ade8e0de51ea2JnRouvignac * only use the keys, so it does not matter what value is put there.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
0231adf34e4b43f90bb6ccae759ade8e0de51ea2JnRouvignac private Map<ClientConnection, ClientConnection> clientConnections =
0231adf34e4b43f90bb6ccae759ade8e0de51ea2JnRouvignac new ConcurrentHashMap<ClientConnection, ClientConnection>();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac /** The set of statistics collected for this connection handler. */
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac private HTTPStatistics statTracker;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac /**
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * The client connection monitor provider associated with this connection
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * handler.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac */
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac private ClientConnectionMonitorProvider connMonitor;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The unique name assigned to this connection handler. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private String handlerName;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** The protocol used by this connection handler. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private String protocol;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * The condition variable that will be used by the start method to wait for
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * the socket port to be opened and ready to process requests before
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * returning.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private final Object waitListen = new Object();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac /** The friendly name of this connection handler. */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private String friendlyName;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c9e40c4ae6863d2ba547b452801067171491c082matthew /**
c9e40c4ae6863d2ba547b452801067171491c082matthew * The SSL engine configurator is used for obtaining default SSL parameters.
c9e40c4ae6863d2ba547b452801067171491c082matthew */
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac private SSLEngineConfigurator sslEngineConfigurator;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Default constructor. It is invoked by reflection to create this
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * {@link ConnectionHandler}.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public HTTPConnectionHandler()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac super(DEFAULT_FRIENDLY_NAME);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac /**
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac * Returns whether unauthenticated HTTP requests are allowed. The server
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac * checks whether unauthenticated requests are allowed server-wide first then
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac * for the HTTP Connection Handler second.
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac *
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac * @return true if unauthenticated requests are allowed, false otherwise.
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac */
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac public boolean acceptUnauthenticatedRequests()
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac {
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac // the global setting overrides the more specific setting here.
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac return !DirectoryServer.rejectUnauthenticatedRequests()
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac && !this.currentConfig.isAuthenticationRequired();
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac }
f27d9a3dda3291133be6a78210fb636bbfd07aa4JnRouvignac
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac /**
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * Registers a client connection to track it.
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac *
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * @param clientConnection
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * the client connection to register
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac */
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac void addClientConnection(ClientConnection clientConnection)
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac {
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac clientConnections.put(clientConnection, clientConnection);
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac }
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public ConfigChangeResult applyConfigurationChange(
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac HTTPConnectionHandlerCfg config)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Create variables to include in the response.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac boolean adminActionRequired = false;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac List<Message> messages = new ArrayList<Message>();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (anyChangeRequiresRestart(config))
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac adminActionRequired = true;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac messages.add(ERR_CONNHANDLER_CONFIG_CHANGES_REQUIRE_RESTART.get("HTTP"));
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Reconfigure SSL if needed.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac configureSSL(config);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (DirectoryException e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (debugEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac messages.add(e.getMessageObject());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return new ConfigChangeResult(e.getResultCode(), adminActionRequired,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac messages);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac if (config.isEnabled() && this.currentConfig.isEnabled() && isListening())
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac { // server was running and will still be running
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac // if the "enabled" was flipped, leave it to the stop / start server to
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac // handle it
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac if (!this.currentConfig.isKeepStats() && config.isKeepStats())
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac { // it must now keep stats while it was not previously
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac setHttpStatsProbe(this.httpServer);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac else if (this.currentConfig.isKeepStats() && !config.isKeepStats()
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac && this.httpProbe != null)
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac { // it must NOT keep stats anymore
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac getHttpConfig(this.httpServer).removeProbes(this.httpProbe);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac this.httpProbe = null;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac this.initConfig = config;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac this.currentConfig = config;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac this.enabled = this.currentConfig.isEnabled();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac messages);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private boolean anyChangeRequiresRestart(HTTPConnectionHandlerCfg newCfg)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return !equals(newCfg.getListenPort(), initConfig.getListenPort())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getListenAddress(), initConfig.getListenAddress())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getMaxRequestSize(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getMaxRequestSize())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.isAllowTCPReuseAddress(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .isAllowTCPReuseAddress())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.isUseTCPKeepAlive(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .isUseTCPKeepAlive())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.isUseTCPNoDelay(), currentConfig.isUseTCPNoDelay())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getMaxBlockedWriteTimeLimit(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getMaxBlockedWriteTimeLimit())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getBufferSize(), currentConfig.getBufferSize())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getAcceptBacklog(), currentConfig.getAcceptBacklog())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.isUseSSL(), currentConfig.isUseSSL())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getKeyManagerProviderDN(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getKeyManagerProviderDN())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getSSLCertNickname(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getSSLCertNickname())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getTrustManagerProviderDN(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getTrustManagerProviderDN())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getSSLProtocol(), currentConfig.getSSLProtocol())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getSSLCipherSuite(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getSSLCipherSuite())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac || !equals(newCfg.getSSLClientAuthPolicy(), currentConfig
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getSSLClientAuthPolicy());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private boolean equals(Object o1, Object o2)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (o1 == null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return o2 == null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return o1.equals(o2);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private boolean equals(long l1, long l2)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return l1 == l2;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private boolean equals(boolean b1, boolean b2)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return b1 == b2;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private void configureSSL(HTTPConnectionHandlerCfg config)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac throws DirectoryException
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac protocol = config.isUseSSL() ? "HTTPS" : "HTTP";
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (config.isUseSSL())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac sslEngineConfigurator = createSSLEngineConfigurator(config);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac else
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac sslEngineConfigurator = null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void finalizeConnectionHandler(Message finalizeReason)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac shutdownRequested = true;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Unregister this as a change listener.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac currentConfig.removeHTTPChangeListener(this);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac if (connMonitor != null)
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac {
194d53ecdae39d8241c06b2b60ef828f5f137bc4matthew DirectoryServer.deregisterMonitorProvider(connMonitor);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac if (statTracker != null)
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac {
194d53ecdae39d8241c06b2b60ef828f5f137bc4matthew DirectoryServer.deregisterMonitorProvider(statTracker);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
cbb1c6adc466ca43dd1b9ae738d6e242c6b80ae7JnRouvignac public Map<String, String> getAlerts()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
cbb1c6adc466ca43dd1b9ae738d6e242c6b80ae7JnRouvignac Map<String, String> alerts = new LinkedHashMap<String, String>();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac alerts.put(ALERT_TYPE_HTTP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES,
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac ALERT_DESCRIPTION_HTTP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES);
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac return alerts;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public String getClassName()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return HTTPConnectionHandler.class.getName();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public Collection<ClientConnection> getClientConnections()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return clientConnections.keySet();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public DN getComponentEntryDN()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return currentConfig.dn();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public String getConnectionHandlerName()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return handlerName;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Returns the current config of this connection handler.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @return the current config of this connection handler
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac HTTPConnectionHandlerCfg getCurrentConfig()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return this.currentConfig;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public Collection<String> getEnabledSSLCipherSuites()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac final SSLEngineConfigurator configurator = sslEngineConfigurator;
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (configurator != null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac return Arrays.asList(configurator.getEnabledCipherSuites());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return super.getEnabledSSLCipherSuites();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public Collection<String> getEnabledSSLProtocols()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac final SSLEngineConfigurator configurator = sslEngineConfigurator;
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (configurator != null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac return Arrays.asList(configurator.getEnabledProtocols());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return super.getEnabledSSLProtocols();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public Collection<HostPort> getListeners()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return listeners;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Returns the listen port for this connection handler.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @return the listen port for this connection handler.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac int getListenPort()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return this.initConfig.getListenPort();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public String getProtocol()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return protocol;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Returns the SSL engine configured for this connection handler if SSL is
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * enabled, null otherwise.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @return the SSL engine if SSL is enabled, null otherwise
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac SSLEngine getSSLEngine()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac return sslEngineConfigurator.createSSLEngine();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public String getShutdownListenerName()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return handlerName;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac /**
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * Retrieves the set of statistics maintained by this connection handler.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac *
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * @return The set of statistics maintained by this connection handler.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac */
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac public HTTPStatistics getStatTracker()
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac {
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac return statTracker;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void initializeConnectionHandler(HTTPConnectionHandlerCfg config)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac throws ConfigException, InitializationException
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (friendlyName == null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac friendlyName = config.dn().getRDN().getAttributeValue(0).toString();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac int listenPort = config.getListenPort();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac for (InetAddress a : config.getListenAddress())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac listeners.add(new HostPort(a.getHostAddress(), listenPort));
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac handlerName = getHandlerName(config);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Configure SSL if needed.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac configureSSL(config);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (DirectoryException e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (debugEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac throw new InitializationException(e.getMessageObject());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac // Create and register monitors.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac statTracker = new HTTPStatistics(handlerName + " Statistics");
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac DirectoryServer.registerMonitorProvider(statTracker);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac connMonitor = new ClientConnectionMonitorProvider(this);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac DirectoryServer.registerMonitorProvider(connMonitor);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Register this as a change listener.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac config.addHTTPChangeListener(this);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac this.initConfig = config;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac this.currentConfig = config;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac this.enabled = this.currentConfig.isEnabled();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private String getHandlerName(HTTPConnectionHandlerCfg config)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac StringBuilder nameBuffer = new StringBuilder();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac nameBuffer.append(friendlyName);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac for (InetAddress a : config.getListenAddress())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac nameBuffer.append(" ");
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac nameBuffer.append(a.getHostAddress());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac nameBuffer.append(" port ");
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac nameBuffer.append(config.getListenPort());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return nameBuffer.toString();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public boolean isConfigurationAcceptable(ConnectionHandlerCfg configuration,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac List<Message> unacceptableReasons)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac HTTPConnectionHandlerCfg config = (HTTPConnectionHandlerCfg) configuration;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac if ((currentConfig == null) || (!this.enabled && config.isEnabled()))
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Attempt to bind to the listen port on all configured addresses to
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // verify whether the connection handler will be able to start.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac Message errorMessage =
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac checkAnyListenAddressInUse(config.getListenAddress(), config
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .getListenPort(), config.isAllowTCPReuseAddress(), config.dn());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (errorMessage != null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac unacceptableReasons.add(errorMessage);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return false;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (config.isEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Check that the SSL configuration is valid.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (config.isUseSSL())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac createSSLEngineConfigurator(config);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (DirectoryException e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (debugEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac unacceptableReasons.add(e.getMessageObject());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return false;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return true;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /**
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * Checks whether any listen address is in use for the given port. The check
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * is performed by binding to each address and port.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac *
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @param listenAddresses
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * the listen {@link InetAddress} to test
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @param listenPort
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * the listen port to test
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @param allowReuseAddress
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * whether addresses can be reused
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @param configEntryDN
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * the configuration entry DN
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * @return an error message if at least one of the address is already in use,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac * null otherwise.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private Message checkAnyListenAddressInUse(
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac Collection<InetAddress> listenAddresses, int listenPort,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac boolean allowReuseAddress, DN configEntryDN)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac for (InetAddress a : listenAddresses)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (isAddressInUse(a, listenPort, allowReuseAddress))
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac throw new IOException(ERR_CONNHANDLER_ADDRESS_INUSE.get().toString());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (IOException e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (debugEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return ERR_CONNHANDLER_CANNOT_BIND.get("HTTP", String
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac .valueOf(configEntryDN), a.getHostAddress(), listenPort,
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac getExceptionMessage(e));
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public boolean isConfigurationChangeAcceptable(
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac HTTPConnectionHandlerCfg configuration, List<Message> unacceptableReasons)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return isConfigurationAcceptable(configuration, unacceptableReasons);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac /**
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * Indicates whether this connection handler should maintain usage statistics.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac *
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * @return <CODE>true</CODE> if this connection handler should maintain usage
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac * statistics, or <CODE>false</CODE> if not.
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac */
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac public boolean keepStats()
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac {
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac return currentConfig.isKeepStats();
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void processServerShutdown(Message reason)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac shutdownRequested = true;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private boolean isListening()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return httpServer != null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void start()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // The Directory Server start process should only return
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // when the connection handlers port are fully opened
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // and working. The start method therefore needs to wait for
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // the created thread to
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac synchronized (waitListen)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac super.start();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac waitListen.wait();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (InterruptedException e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // If something interrupted the start its probably better
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // to return ASAP.
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac /**
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * Unregisters a client connection to stop tracking it.
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac *
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * @param clientConnection
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac * the client connection to unregister
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac */
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac void removeClientConnection(ClientConnection clientConnection)
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac {
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac clientConnections.remove(clientConnection);
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac }
43b51b383215ce9df9001940d3930d32ea1a784fJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void run()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac setName(handlerName);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac boolean lastIterationFailed = false;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac while (!shutdownRequested)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // If this connection handler is not enabled, then just sleep
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // for a bit and check again.
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac if (!this.enabled)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (isListening())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac stopHttpServer();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
caa0e374c1499ea42d335764d752b060a7174368JnRouvignac StaticUtils.sleep(1000);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac continue;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (isListening())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // If already listening, then sleep for a bit and check again.
caa0e374c1499ea42d335764d752b060a7174368JnRouvignac StaticUtils.sleep(1000);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac continue;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac try
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // At this point, the connection Handler either started
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // correctly or failed to start but the start process
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // should be notified and resume its work in any cases.
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac synchronized (waitListen)
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac waitListen.notify();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // If we have gotten here, then we are about to start listening
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // for the first time since startup or since we were previously
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // disabled. Start the embedded HTTP server
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac startHttpServer();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac lastIterationFailed = false;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac catch (Exception e)
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // clean up the messed up HTTP server
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac cleanUpHttpServer();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // error + alert about the horked config
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac if (debugEnabled())
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac logError(ERR_CONNHANDLER_CANNOT_ACCEPT_CONNECTION.get(friendlyName,
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac String.valueOf(currentConfig.dn()), getExceptionMessage(e)));
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac if (lastIterationFailed)
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // The last time through the accept loop we also
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // encountered a failure. Rather than enter a potential
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // infinite loop of failures, disable this acceptor and
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac // log an error.
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac Message message =
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac ERR_CONNHANDLER_CONSECUTIVE_ACCEPT_FAILURES.get(friendlyName,
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac String.valueOf(currentConfig.dn()),
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac stackTraceToSingleLineString(e));
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac logError(message);
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac DirectoryServer.sendAlertNotification(this,
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac ALERT_TYPE_HTTP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES, message);
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac this.enabled = false;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac else
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac lastIterationFailed = true;
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac // Initiate shutdown
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac stopHttpServer();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac private void startHttpServer() throws Exception
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac // silence Grizzly's own logging
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac Logger.getLogger("org.glassfish.grizzly").setLevel(Level.OFF);
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignac if (HTTPAccessLogger.getHTTPAccessLogPublishers().isEmpty())
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignac {
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignac logError(WARN_CONFIG_LOGGER_NO_ACTIVE_HTTP_ACCESS_LOGGERS.get());
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignac }
a26e1a1d15f3dd480d0a0813ef13ac73fe6c7dceJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac this.httpServer = createHttpServer();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // register servlet as default servlet and also able to serve REST requests
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac createAndRegisterServlet("OpenDJ Rest2LDAP servlet", "", "/*");
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac TRACER.debugInfo("Starting HTTP server...");
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac this.httpServer.start();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac TRACER.debugInfo("HTTP server started");
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac logError(NOTE_CONNHANDLER_STARTED_LISTENING.get(handlerName));
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac }
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac private HttpServer createHttpServer()
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final HttpServer server = new HttpServer();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final int requestSize = (int) currentConfig.getMaxRequestSize();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final ServerConfiguration serverConfig = server.getServerConfiguration();
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignac serverConfig.setMaxBufferedPostSize(requestSize);
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignac serverConfig.setMaxFormPostSize(requestSize);
0d79a83a6c8d3af62f592c6e6f4a5b4d01719787matthew serverConfig.setDefaultQueryEncoding(Charsets.UTF8_CHARSET);
0d79a83a6c8d3af62f592c6e6f4a5b4d01719787matthew
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac if (keepStats())
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac setHttpStatsProbe(server);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // configure the network listener
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final NetworkListener listener =
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac new NetworkListener("Rest2LDAP", NetworkListener.DEFAULT_NETWORK_HOST,
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac initConfig.getListenPort());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac server.addListener(listener);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // configure the network transport
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final TCPNIOTransport transport = listener.getTransport();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setReuseAddress(currentConfig.isAllowTCPReuseAddress());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setKeepAlive(currentConfig.isUseTCPKeepAlive());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setTcpNoDelay(currentConfig.isUseTCPNoDelay());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setWriteTimeout(currentConfig.getMaxBlockedWriteTimeLimit(),
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac TimeUnit.MILLISECONDS);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final int bufferSize = (int) currentConfig.getBufferSize();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setReadBufferSize(bufferSize);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setWriteBufferSize(bufferSize);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setIOStrategy(SameThreadIOStrategy.getInstance());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final int numRequestHandlers =
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac getNumRequestHandlers(currentConfig.getNumRequestHandlers(),
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac friendlyName);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setSelectorRunnersCount(numRequestHandlers);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac transport.setServerConnectionBackLog(currentConfig.getAcceptBacklog());
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // configure SSL
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac if (sslEngineConfigurator != null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac listener.setSecure(true);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac listener.setSSLEngineConfig(sslEngineConfigurator);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac return server;
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac private void setHttpStatsProbe(HttpServer server)
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac this.httpProbe = new HTTPStatsProbe(this.statTracker);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac getHttpConfig(server).addProbes(this.httpProbe);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac }
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac private MonitoringConfig<HttpProbe> getHttpConfig(HttpServer server)
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final HttpServerMonitoringConfig monitoringCfg =
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac server.getServerConfiguration().getMonitoringConfig();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac return monitoringCfg.getHttpConfig();
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac }
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac private void createAndRegisterServlet(final String servletName,
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final String... urlPatterns) throws Exception
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac {
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // parse and use JSON config
70e52b34d009d7ce7699b27dfee2ef539ebf1e64JnRouvignac File jsonConfigFile = getFileForPath(this.currentConfig.getConfigFile());
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac final JsonValue configuration =
70e52b34d009d7ce7699b27dfee2ef539ebf1e64JnRouvignac parseJsonConfiguration(jsonConfigFile).recordKeyAccesses();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac final HTTPAuthenticationConfig authenticationConfig =
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac getAuthenticationConfig(configuration);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final ConnectionFactory connFactory = getConnectionFactory(configuration);
70e52b34d009d7ce7699b27dfee2ef539ebf1e64JnRouvignac configuration.verifyAllKeysAccessed();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac Filter filter =
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac new CollectClientConnectionsFilter(this, authenticationConfig);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final HttpServlet servlet = new HttpServlet(connFactory,
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // Used for hooking our HTTPClientConnection in Rest2LDAP
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac Rest2LDAPContextFactory.getHttpServletContextFactory());
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac // Create and deploy the Web app context
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac final WebappContext ctx = new WebappContext(servletName);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac ctx.addFilter("collectClientConnections", filter).addMappingForUrlPatterns(
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac EnumSet.of(DispatcherType.REQUEST), true, urlPatterns);
1ac8954c65ecc45727536c6c1699483ef858ff64JnRouvignac ctx.addServlet(servletName, servlet).addMapping(urlPatterns);
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac ctx.deploy(this.httpServer);
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac }
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac private HTTPAuthenticationConfig getAuthenticationConfig(
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac final JsonValue configuration)
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac {
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac final HTTPAuthenticationConfig result = new HTTPAuthenticationConfig();
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac final JsonValue val = configuration.get("authenticationFilter");
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setBasicAuthenticationSupported(asBool(val,
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac "supportHTTPBasicAuthentication"));
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setCustomHeadersAuthenticationSupported(asBool(val,
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac "supportAltAuthentication"));
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setCustomHeaderUsername(val.get("altAuthenticationUsernameHeader")
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac .asString());
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setCustomHeaderPassword(val.get("altAuthenticationPasswordHeader")
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac .asString());
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac final String searchBaseDN = asString(val, "searchBaseDN");
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setSearchBaseDN(org.forgerock.opendj.ldap.DN.valueOf(searchBaseDN));
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setSearchScope(SearchScope.valueOf(asString(val, "searchScope")));
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac result.setSearchFilterTemplate(asString(val, "searchFilterTemplate"));
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac return result;
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac }
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac private String asString(JsonValue value, String key)
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac {
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac return value.get(key).required().asString();
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac }
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac private boolean asBool(JsonValue value, String key)
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac {
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac return value.get(key).defaultTo(false).asBoolean();
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac }
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac private ConnectionFactory getConnectionFactory(final JsonValue configuration)
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac {
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac final Router router = new Router();
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac final JsonValue mappings =
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac configuration.get("servlet").get("mappings").required();
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac for (final String mappingUrl : mappings.keys())
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac {
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac final JsonValue mapping = mappings.get(mappingUrl);
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac final CollectionResourceProvider provider =
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac Rest2LDAP.builder().authorizationPolicy(AuthorizationPolicy.REUSE)
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac .configureMapping(mapping).build();
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac router.addRoute(mappingUrl, provider);
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac }
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac return Resources.newInternalConnectionFactory(router);
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac }
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac private JsonValue parseJsonConfiguration(File configFile) throws IOException,
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac JsonParseException, JsonMappingException, ServletException
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac {
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac // Parse the config file.
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac final Object content = JSON_MAPPER.readValue(configFile, Object.class);
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac if (!(content instanceof Map))
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac {
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac throw new ServletException("Servlet configuration file '" + configFile
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac + "' does not contain a valid JSON configuration");
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac }
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac return new JsonValue(content);
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac }
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private void stopHttpServer()
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac if (this.httpServer != null)
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac TRACER.debugInfo("Stopping HTTP server...");
703d96151f92bc0db629eb2417f57870911a7acaJnRouvignac this.httpServer.shutdownNow();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac cleanUpHttpServer();
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac TRACER.debugInfo("HTTP server stopped");
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac logError(NOTE_CONNHANDLER_STOPPED_LISTENING.get(handlerName));
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac }
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac private void cleanUpHttpServer()
cc86899f30c9197d2867036037e4f1c4638d3e2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac this.httpServer = null;
c87c8fef4847562b343af5b65855fe0f5587c72eJnRouvignac this.httpProbe = null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac /** {@inheritDoc} */
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac @Override
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac public void toString(StringBuilder buffer)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac buffer.append(handlerName);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac private SSLEngineConfigurator createSSLEngineConfigurator(
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac HTTPConnectionHandlerCfg config) throws DirectoryException
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (!config.isUseSSL())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac try
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac SSLContext sslContext = createSSLContext(config);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac SSLEngineConfigurator configurator =
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac new SSLEngineConfigurator(sslContext);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setClientMode(false);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac // configure with defaults from the JVM
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac final SSLEngine defaults = sslContext.createSSLEngine();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setEnabledProtocols(defaults.getEnabledProtocols());
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setEnabledCipherSuites(defaults.getEnabledCipherSuites());
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac final Set<String> protocols = config.getSSLProtocol();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (!protocols.isEmpty())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac String[] array = protocols.toArray(new String[protocols.size()]);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setEnabledProtocols(array);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac final Set<String> ciphers = config.getSSLCipherSuite();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (!ciphers.isEmpty())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac String[] array = ciphers.toArray(new String[ciphers.size()]);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setEnabledCipherSuites(array);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac switch (config.getSSLClientAuthPolicy())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac case DISABLED:
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setNeedClientAuth(false);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setWantClientAuth(false);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac break;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac case REQUIRED:
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setNeedClientAuth(true);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setWantClientAuth(true);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac break;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac case OPTIONAL:
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac default:
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setNeedClientAuth(false);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac configurator.setWantClientAuth(true);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac break;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac return configurator;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac catch (Exception e)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (debugEnabled())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac TRACER.debugCaught(DebugLogLevel.ERROR, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac ResultCode resCode = DirectoryServer.getServerErrorResultCode();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac Message message =
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE.get(getExceptionMessage(e));
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac throw new DirectoryException(resCode, message, e);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac private SSLContext createSSLContext(HTTPConnectionHandlerCfg config)
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac throws Exception
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac if (!config.isUseSSL())
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac return null;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac DN keyMgrDN = config.getKeyManagerProviderDN();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac KeyManagerProvider<?> keyManagerProvider =
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac DirectoryServer.getKeyManagerProvider(keyMgrDN);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (keyManagerProvider == null)
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac keyManagerProvider = new NullKeyManagerProvider();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac String alias = config.getSSLCertNickname();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac KeyManager[] keyManagers;
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (alias == null)
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac keyManagers = keyManagerProvider.getKeyManagers();
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac else
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac keyManagers =
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac SelectableCertificateKeyManager.wrap(keyManagerProvider
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac .getKeyManagers(), alias);
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac DN trustMgrDN = config.getTrustManagerProviderDN();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac TrustManagerProvider<?> trustManagerProvider =
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac DirectoryServer.getTrustManagerProvider(trustMgrDN);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac if (trustManagerProvider == null)
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac {
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac trustManagerProvider = new NullTrustManagerProvider();
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac }
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac sslContext.init(keyManagers, trustManagerProvider.getTrustManagers(), null);
4b818465d78607099770cce29266d0dd1c61846aJnRouvignac return sslContext;
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac }
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac
11dea2cb49f8dfbd12424d677ab779a25d453b2aJnRouvignac}