001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2016 ForgeRock AS.
016 */
017package org.opends.server.api;
018
019import static org.opends.messages.ProtocolMessages.*;
020
021import org.forgerock.i18n.slf4j.LocalizedLogger;
022
023import java.util.Collection;
024import java.util.Collections;
025import java.util.List;
026
027import org.forgerock.i18n.LocalizableMessage;
028import org.forgerock.opendj.server.config.server.ConnectionHandlerCfg;
029import org.opends.server.core.ServerContext;
030import org.forgerock.opendj.config.server.ConfigException;
031import org.opends.server.monitors.ConnectionHandlerMonitor;
032import org.forgerock.opendj.ldap.DN;
033import org.opends.server.types.HostPort;
034import org.opends.server.types.InitializationException;
035
036/**
037 * This class defines the set of methods and structures that must be
038 * implemented by a Directory Server connection handler.
039 *
040 * @param <T>
041 *          The type of connection handler configuration handled by
042 *          this connection handler implementation.
043 */
044@org.opends.server.types.PublicAPI(
045     stability=org.opends.server.types.StabilityLevel.VOLATILE,
046     mayInstantiate=false,
047     mayExtend=true,
048     mayInvoke=false)
049public abstract class ConnectionHandler
050       <T extends ConnectionHandlerCfg>
051       extends DirectoryThread
052{
053
054  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
055
056  /** The monitor associated with this connection handler. */
057  private ConnectionHandlerMonitor monitor;
058
059  /** Is this handler the admin connection handler. */
060  private boolean isAdminConnectionHandler;
061
062
063
064  /**
065   * Creates a new instance of this connection handler. This must be
066   * called by all connection handlers, and all connection handlers
067   * must provide default constructors (i.e., those that do not take
068   * any arguments) that invoke this constructor.
069   *
070   * @param threadName
071   *          The name to use for this thread.
072   */
073  protected ConnectionHandler(String threadName) {
074    super(threadName);
075
076    monitor = null;
077  }
078
079
080
081  /**
082   * Closes this connection handler so that it will no longer accept
083   * new client connections. Implementations should disconnect any
084   * existing connections.
085   *
086   * @param finalizeReason
087   *          The reason that this connection handler should be
088   *          finalized.
089   */
090  public abstract void finalizeConnectionHandler(
091      LocalizableMessage finalizeReason);
092
093
094
095  /**
096   * Retrieves a name that may be used to refer to this connection
097   * handler.  Every connection handler instance (even handlers of the
098   * same type) must have a unique name.
099   *
100   * @return  A unique name that may be used to refer to this
101   *          connection handler.
102   */
103  public abstract String getConnectionHandlerName();
104
105
106
107  /**
108   * Retrieves an unmodifiable set of enabled SSL cipher suites configured for
109   * this connection handler, if applicable. Implementations must return an
110   * empty set if use of SSL/TLS is not possible.
111   *
112   * @return The set of enabled SSL cipher suites configured for this connection
113   *         handler.
114   */
115  public Collection<String> getEnabledSSLCipherSuites()
116  {
117    return Collections.emptyList();
118  }
119
120
121
122  /**
123   * Retrieves the set of enabled SSL protocols configured for this connection
124   * handler. Implementations must return an empty set if use of SSL/TLS is not
125   * possible.
126   *
127   * @return The set of enabled SSL protocols configured for this connection
128   *         handler.
129   */
130  public Collection<String> getEnabledSSLProtocols()
131  {
132    return Collections.emptyList();
133  }
134
135
136
137   /**
138   * Retrieves the DN of the configuration entry with which this alert
139   * generator is associated.
140   *
141   * @return The DN of the configuration entry with which this alert
142   *         generator is associated.
143   */
144  public abstract DN getComponentEntryDN();
145
146  /**
147   * Retrieves the name of the protocol used to communicate with
148   * clients.  It should take into account any special naming that may
149   * be needed to express any security mechanisms or other constraints
150   * in place (e.g., "LDAPS" for LDAP over SSL).
151   *
152   * @return  The name of the protocol used to communicate with
153   *          clients.
154   */
155  public abstract String getProtocol();
156
157
158
159  /**
160   * Retrieves information about the listener(s) that will be used to
161   * accept client connections.
162   *
163   * @return  Information about the listener(s) that will be used to
164   *          accept client connections, or an empty list if this
165   *          connection handler does not accept connections from
166   *          network clients.
167   */
168  public abstract Collection<HostPort> getListeners();
169
170
171
172  /**
173   * Retrieves the set of active client connections that have been
174   * established through this connection handler.
175   *
176   * @return The set of active client connections that have been
177   *         established through this connection handler.
178   */
179  public abstract Collection<ClientConnection> getClientConnections();
180
181
182
183  /**
184   * Initializes this connection handler provider based on the
185   * information in the provided connection handler configuration.
186   *
187   * @param serverContext
188   *            The server context.
189   * @param configuration
190   *          The connection handler configuration that contains the
191   *          information to use to initialize this connection
192   *          handler.
193   * @throws ConfigException
194   *           If an unrecoverable problem arises in the process of
195   *           performing the initialization as a result of the server
196   *           configuration.
197   * @throws InitializationException
198   *           If a problem occurs during initialization that is not
199   *           related to the server configuration.
200   */
201  public abstract void initializeConnectionHandler(ServerContext serverContext, T configuration)
202      throws ConfigException, InitializationException;
203
204
205
206  /**
207   * Indicates whether the provided configuration is acceptable for
208   * this connection handler.  It should be possible to call this
209   * method on an uninitialized connection handler instance in order
210   * to determine whether the connection handler would be able to use
211   * the provided configuration.
212   * <BR><BR>
213   * Note that implementations which use a subclass of the provided
214   * configuration class will likely need to cast the configuration
215   * to the appropriate subclass type.
216   *
217   * @param  configuration        The connection handler configuration
218   *                              for which to make the determination.
219   * @param  unacceptableReasons  A list that may be used to hold the
220   *                              reasons that the provided
221   *                              configuration is not acceptable.
222   *
223   * @return  {@code true} if the provided configuration is acceptable
224   *          for this connection handler, or {@code false} if not.
225   */
226  public boolean isConfigurationAcceptable(
227                      ConnectionHandlerCfg configuration,
228                      List<LocalizableMessage> unacceptableReasons)
229  {
230    // This default implementation does not perform any special
231    // validation.  It should be overridden by connection handler
232    // implementations that wish to perform more detailed validation.
233    return true;
234  }
235
236
237
238  /**
239   * Operates in a loop, accepting new connections and ensuring that
240   * requests on those connections are handled properly.
241   */
242  @Override
243  public abstract void run();
244
245
246
247  /**
248   * Retrieves the monitor instance for this connection handler.
249   *
250   * @return  The monitor instance for this connection handler, or
251   *          {@code null} if none has been provided.
252   */
253  public final ConnectionHandlerMonitor getConnectionHandlerMonitor()
254  {
255    return monitor;
256  }
257
258
259
260  /**
261   * Sets the monitor instance for this connection handler.
262   *
263   * @param  monitor  The monitor instance for this connection
264   *                  handler.
265   */
266  public final void setConnectionHandlerMonitor(
267                         ConnectionHandlerMonitor monitor)
268  {
269    this.monitor = monitor;
270  }
271
272
273
274  /**
275   * Sets this connection handler as the admin connection handler.
276   */
277  public void setAdminConnectionHandler() {
278    isAdminConnectionHandler = true;
279  }
280
281
282  /**
283   * Returns whether this connection handler is the admin
284   * connection handler.
285   * @return boolean True if this connection handler is the admin
286   *                 connection handler, false otherwise
287   */
288  public boolean isAdminConnectionHandler() {
289    return isAdminConnectionHandler;
290  }
291
292
293  /**
294   * Determine the number of request handlers.
295   *
296   * @param numRequestHandlers
297   *          the number of request handlers from the configuration.
298   * @param friendlyName
299   *          the friendly name of this connection handler
300   * @return the number of request handlers from the configuration determined
301   *         from the configuration or from the number of available processors
302   *         on the current machine
303   */
304  public int getNumRequestHandlers(Integer numRequestHandlers,
305      String friendlyName)
306  {
307    if (numRequestHandlers == null)
308    {
309      // Automatically choose based on the number of processors.
310      int cpus = Runtime.getRuntime().availableProcessors();
311      int value = Math.max(2, cpus / 2);
312
313      logger.debug(INFO_ERGONOMIC_SIZING_OF_REQUEST_HANDLER_THREADS, friendlyName,
314              value);
315
316      return value;
317    }
318    else
319    {
320      return numRequestHandlers;
321    }
322  }
323
324  /**
325   * Retrieves a string representation of this connection handler.
326   *
327   * @return A string representation of this connection handler.
328   */
329  @Override
330  public String toString() {
331    StringBuilder buffer = new StringBuilder();
332    toString(buffer);
333    return buffer.toString();
334  }
335
336
337
338  /**
339   * Appends a string representation of this connection handler to the
340   * provided buffer.
341   *
342   * @param buffer
343   *          The buffer to which the information should be appended.
344   */
345  public abstract void toString(StringBuilder buffer);
346}