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