001/*
002 * Copyright 2010-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-2014 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.listener;
022
023
024
025import java.net.InetAddress;
026import javax.net.ServerSocketFactory;
027
028import com.unboundid.util.Mutable;
029import com.unboundid.util.ThreadSafety;
030import com.unboundid.util.ThreadSafetyLevel;
031import com.unboundid.util.Validator;
032
033
034
035/**
036 * This class provides a mechanism for defining the configuration to use for an
037 * {@link LDAPListener} instance.  Note that while instances of this class are
038 * not inherently threadsafe, a private copy of the configuration will be
039 * created whenever a new {@code LDAPListener} is created so that this
040 * configuration may continue to be altered for new instances without impacting
041 * any existing listeners.
042 */
043@Mutable()
044@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
045public final class LDAPListenerConfig
046{
047  // Indicates whether to use the SO_KEEPALIVE socket option for sockets
048  // accepted by the listener.
049  private boolean useKeepAlive;
050
051  // Indicates whether to use the SO_LINGER socket option for sockets accepted
052  // by the listener.
053  private boolean useLinger;
054
055  // Indicates whether to use the SO_REUSEADDR socket option for sockets
056  // accepted by the listener.
057  private boolean useReuseAddress;
058
059  // Indicates whether to use the TCP_NODELAY for sockets accepted by the
060  // listener.
061  private boolean useTCPNoDelay;
062
063  // The address on which to listen for client connections.
064  private InetAddress listenAddress;
065
066  // The linger timeout in seconds to use for sockets accepted by the listener.
067  private int lingerTimeout;
068
069  // The port on which to listen for client connections.
070  private int listenPort;
071
072  // The receive buffer size to use for sockets accepted by the listener.
073  private int receiveBufferSize;
074
075  // The send buffer size to use for sockets accepted by the listener.
076  private int sendBufferSize;
077
078  // The exception handler to use for the listener and associated connections.
079  private LDAPListenerExceptionHandler exceptionHandler;
080
081  // The request handler that will be used to process requests read from
082  // clients.
083  private LDAPListenerRequestHandler requestHandler;
084
085  // The factory that will be used to create server sockets.
086  private ServerSocketFactory serverSocketFactory;
087
088
089
090  /**
091   * Creates a new listener configuration.
092   *
093   * @param  listenPort      The port on which to listen for client connections.
094   *                         It must be an integer between 1 and 65535, or 0 to
095   *                         indicate that a free port should be chosen by the
096   *                         JVM.
097   * @param  requestHandler  The request handler that will be used to process
098   *                         requests read from clients.  It must not be
099   *                         {@code null}.
100   */
101  public LDAPListenerConfig(final int listenPort,
102                            final LDAPListenerRequestHandler requestHandler)
103  {
104    Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65535));
105    Validator.ensureNotNull(requestHandler);
106
107    this.listenPort     = listenPort;
108    this.requestHandler = requestHandler;
109
110    useKeepAlive        = true;
111    useLinger           = true;
112    useReuseAddress     = true;
113    useTCPNoDelay       = true;
114    lingerTimeout       = 5;
115    listenAddress       = null;
116    receiveBufferSize   = 0;
117    sendBufferSize      = 0;
118    exceptionHandler    = null;
119    serverSocketFactory = ServerSocketFactory.getDefault();
120  }
121
122
123
124  /**
125   * Retrieves the port number on which to listen for client connections.  A
126   * value of zero indicates that the listener should allow the JVM to choose a
127   * free port.
128   *
129   * @return  The port number on which to listen for client connections.
130   */
131  public int getListenPort()
132  {
133    return listenPort;
134  }
135
136
137
138  /**
139   * Specifies the port number on which to listen for client connections.  The
140   * provided value must be between 1 and 65535, or it may be 0 to indicate that
141   * the JVM should select a free port on the system.
142   *
143   * @param  listenPort  The port number on which to listen for client
144   *                     connections.
145   */
146  public void setListenPort(final int listenPort)
147  {
148    Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65535));
149
150    this.listenPort = listenPort;
151  }
152
153
154
155  /**
156   * Retrieves the LDAP listener request handler that should be used to process
157   * requests read from clients.
158   *
159   * @return  The LDAP listener request handler that should be used to process
160   *          requests read from clients.
161   */
162  public LDAPListenerRequestHandler getRequestHandler()
163  {
164    return requestHandler;
165  }
166
167
168
169  /**
170   * Specifies the LDAP listener request handler that should be used to process
171   * requests read from clients.
172   *
173   * @param  requestHandler  The LDAP listener request handler that should be
174   *                         used to process requests read from clients.  It
175   *                         must not be {@code null}.
176   */
177  public void setRequestHandler(final LDAPListenerRequestHandler requestHandler)
178  {
179    Validator.ensureNotNull(requestHandler);
180
181    this.requestHandler = requestHandler;
182  }
183
184
185
186  /**
187   * Indicates whether to use the SO_KEEPALIVE socket option for sockets
188   * accepted by the listener.
189   *
190   * @return  {@code true} if the SO_KEEPALIVE socket option should be used for
191   *          sockets accepted by the listener, or {@code false} if not.
192   */
193  public boolean useKeepAlive()
194  {
195    return useKeepAlive;
196  }
197
198
199
200  /**
201   * Specifies whether to use the SO_KEEPALIVE socket option for sockets
202   * accepted by the listener.
203   *
204   * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE socket
205   *                       option for sockets accepted by the listener.
206   */
207  public void setUseKeepAlive(final boolean useKeepAlive)
208  {
209    this.useKeepAlive = useKeepAlive;
210  }
211
212
213
214  /**
215   * Indicates whether to use the SO_LINGER socket option for sockets accepted
216   * by the listener.
217   *
218   * @return  {@code true} if the SO_LINGER socket option should be used for
219   *          sockets accepted by the listener, or {@code false} if not.
220   */
221  public boolean useLinger()
222  {
223    return useLinger;
224  }
225
226
227
228  /**
229   * Specifies whether to use the SO_LINGER socket option for sockets accepted
230   * by the listener.
231   *
232   * @param  useLinger  Indicates whether to use the SO_LINGER socket option for
233   *                    sockets accepted by the listener.
234   */
235  public void setUseLinger(final boolean useLinger)
236  {
237    this.useLinger = useLinger;
238  }
239
240
241
242  /**
243   * Indicates whether to use the SO_REUSEADDR socket option for sockets
244   * accepted by the listener.
245   *
246   * @return  {@code true} if the SO_REUSEADDR socket option should be used for
247   *          sockets accepted by the listener, or {@code false} if not.
248   */
249  public boolean useReuseAddress()
250  {
251    return useReuseAddress;
252  }
253
254
255
256  /**
257   * Specifies whether to use the SO_REUSEADDR socket option for sockets
258   * accepted by the listener.
259   *
260   * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR socket
261   *                          option for sockets accepted by the listener.
262   */
263  public void setUseReuseAddress(final boolean useReuseAddress)
264  {
265    this.useReuseAddress = useReuseAddress;
266  }
267
268
269
270  /**
271   * Indicates whether to use the TCP_NODELAY socket option for sockets accepted
272   * by the listener.
273   *
274   * @return  {@code true} if the TCP_NODELAY socket option should be used for
275   *          sockets accepted by the listener, or {@code false} if not.
276   */
277  public boolean useTCPNoDelay()
278  {
279    return useTCPNoDelay;
280  }
281
282
283
284  /**
285   * Specifies whether to use the TCP_NODELAY socket option for sockets accepted
286   * by the listener.
287   *
288   * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY socket
289   *                        option for sockets accepted by the listener.
290   */
291  public void setUseTCPNoDelay(final boolean useTCPNoDelay)
292  {
293    this.useTCPNoDelay = useTCPNoDelay;
294  }
295
296
297
298  /**
299   * Retrieves the address on which to listen for client connections, if
300   * defined.
301   *
302   * @return  The address on which to listen for client connections, or
303   *          {@code null} if it should listen on all available addresses on all
304   *          interfaces.
305   */
306  public InetAddress getListenAddress()
307  {
308    return listenAddress;
309  }
310
311
312
313  /**
314   * Specifies the address on which to listen for client connections.
315   *
316   * @param  listenAddress  The address on which to listen for client
317   *                        connections.  It may be {@code null} to indicate
318   *                        that it should listen on all available addresses on
319   *                        all interfaces.
320   */
321  public void setListenAddress(final InetAddress listenAddress)
322  {
323    this.listenAddress = listenAddress;
324  }
325
326
327
328  /**
329   * Retrieves the timeout in seconds that should be used if the SO_LINGER
330   * socket option is enabled.
331   *
332   * @return  The timeout in seconds that should be used if the SO_LINGER socket
333   *           option is enabled.
334   */
335  public int getLingerTimeoutSeconds()
336  {
337    return lingerTimeout;
338  }
339
340
341
342  /**
343   * Specifies the timeout in seconds that should be used if the SO_LINGER
344   * socket option is enabled.
345   *
346   * @param  lingerTimeout  The timeout in seconds that should be used if the
347   *                        SO_LINGER socket option is enabled.  The value must
348   *                        be between 0 and 65535, inclusive.
349   */
350  public void setLingerTimeoutSeconds(final int lingerTimeout)
351  {
352    Validator.ensureTrue((lingerTimeout >= 0) && (lingerTimeout <= 65535));
353
354    this.lingerTimeout = lingerTimeout;
355  }
356
357
358
359  /**
360   * Retrieves the receive buffer size that should be used for sockets accepted
361   * by the listener.
362   *
363   * @return  The receive buffer size that should be used for sockets accepted
364   *          by the listener, or 0 if the default receive buffer size should be
365   *          used.
366   */
367  public int getReceiveBufferSize()
368  {
369    return receiveBufferSize;
370  }
371
372
373
374  /**
375   * Specifies the receive buffer size that should be used for sockets accepted
376   * by the listener.  A value less than or equal to zero indicates that the
377   * default receive buffer size should be used.
378   *
379   * @param  receiveBufferSize  The receive buffer size that should be used for
380   *                            sockets accepted by the listener.
381   */
382  public void setReceiveBufferSize(final int receiveBufferSize)
383  {
384    if (receiveBufferSize > 0)
385    {
386      this.receiveBufferSize = receiveBufferSize;
387    }
388    else
389    {
390      this.receiveBufferSize = 0;
391    }
392  }
393
394
395
396  /**
397   * Retrieves the send  buffer size that should be used for sockets accepted
398   * by the listener.
399   *
400   * @return  The send buffer size that should be used for sockets accepted by
401   *          the listener, or 0 if the default send buffer size should be used.
402   */
403  public int getSendBufferSize()
404  {
405    return sendBufferSize;
406  }
407
408
409
410  /**
411   * Specifies the send buffer size that should be used for sockets accepted by
412   * the listener.  A value less than or equal to zero indicates that the
413   * default send buffer size should be used.
414   *
415   * @param  sendBufferSize  The send buffer size that should be used for
416   *                         sockets accepted by the listener.
417   */
418  public void setSendBufferSize(final int sendBufferSize)
419  {
420    if (sendBufferSize > 0)
421    {
422      this.sendBufferSize = sendBufferSize;
423    }
424    else
425    {
426      this.sendBufferSize = 0;
427    }
428  }
429
430
431
432  /**
433   * Retrieves the exception handler that should be notified of any exceptions
434   * caught while attempting to accept or interact with a client connection.
435   *
436   * @return  The exception handler that should be notified of any exceptions
437   *          caught while attempting to accept or interact with a client
438   *          connection, or {@code null} if none is defined.
439   */
440  public LDAPListenerExceptionHandler getExceptionHandler()
441  {
442    return exceptionHandler;
443  }
444
445
446
447  /**
448   * Specifies the exception handler that should be notified of any exceptions
449   * caught while attempting to accept or interact with a client connection.
450   *
451   * @param  exceptionHandler  The exception handler that should be notified of
452   *                           any exceptions encountered during processing.  It
453   *                           may be {@code null} if no exception handler
454   *                           should be used.
455   */
456  public void setExceptionHandler(
457                   final LDAPListenerExceptionHandler exceptionHandler)
458  {
459    this.exceptionHandler = exceptionHandler;
460  }
461
462
463
464  /**
465   * Retrieves the factory that will be used to create the server socket that
466   * will listen for client connections.
467   *
468   * @return  The factory that will be used to create the server socket that
469   *          will listen for client connections.
470   */
471  public ServerSocketFactory getServerSocketFactory()
472  {
473    return serverSocketFactory;
474  }
475
476
477
478  /**
479   * Specifies the factory that will be used to create the server socket that
480   * will listen for client connections.
481   *
482   * @param  serverSocketFactory  The factory that will be used to create the
483   *                              server socket that will listen for client
484   *                              connections.  It may be {@code null} to use
485   *                              the JVM-default server socket factory.
486   */
487  public void setServerSocketFactory(
488                   final ServerSocketFactory serverSocketFactory)
489  {
490    if (serverSocketFactory == null)
491    {
492      this.serverSocketFactory = ServerSocketFactory.getDefault();
493    }
494    else
495    {
496      this.serverSocketFactory = serverSocketFactory;
497    }
498  }
499
500
501
502/**
503   * Creates a copy of this configuration that may be altered without impacting
504   * this configuration, and which will not be altered by changes to this
505   * configuration.
506   *
507   * @return  A copy of this configuration that may be altered without impacting
508   *          this configuration, and which will not be altered by changes to
509   *          this configuration.
510   */
511  public LDAPListenerConfig duplicate()
512  {
513    final LDAPListenerConfig copy =
514         new LDAPListenerConfig(listenPort, requestHandler);
515
516    copy.useKeepAlive        = useKeepAlive;
517    copy.useLinger           = useLinger;
518    copy.useReuseAddress     = useReuseAddress;
519    copy.useTCPNoDelay       = useTCPNoDelay;
520    copy.listenAddress       = listenAddress;
521    copy.lingerTimeout       = lingerTimeout;
522    copy.receiveBufferSize   = receiveBufferSize;
523    copy.sendBufferSize      = sendBufferSize;
524    copy.exceptionHandler    = exceptionHandler;
525    copy.serverSocketFactory = serverSocketFactory;
526
527    return copy;
528  }
529}