001/*
002 * Copyright 2010-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-2017 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 maximum number of concurrent connections that will be allowed.
073  private int maxConnections;
074
075  // The receive buffer size to use for sockets accepted by the listener.
076  private int receiveBufferSize;
077
078  // The send buffer size to use for sockets accepted by the listener.
079  private int sendBufferSize;
080
081  // The exception handler to use for the listener and associated connections.
082  private LDAPListenerExceptionHandler exceptionHandler;
083
084  // The request handler that will be used to process requests read from
085  // clients.
086  private LDAPListenerRequestHandler requestHandler;
087
088  // The factory that will be used to create server sockets.
089  private ServerSocketFactory serverSocketFactory;
090
091
092
093  /**
094   * Creates a new listener configuration.
095   *
096   * @param  listenPort      The port on which to listen for client connections.
097   *                         It must be an integer between 1 and 65535, or 0 to
098   *                         indicate that a free port should be chosen by the
099   *                         JVM.
100   * @param  requestHandler  The request handler that will be used to process
101   *                         requests read from clients.  It must not be
102   *                         {@code null}.
103   */
104  public LDAPListenerConfig(final int listenPort,
105                            final LDAPListenerRequestHandler requestHandler)
106  {
107    Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65535));
108    Validator.ensureNotNull(requestHandler);
109
110    this.listenPort     = listenPort;
111    this.requestHandler = requestHandler;
112
113    useKeepAlive        = true;
114    useLinger           = true;
115    useReuseAddress     = true;
116    useTCPNoDelay       = true;
117    lingerTimeout       = 5;
118    listenAddress       = null;
119    maxConnections      = 0;
120    receiveBufferSize   = 0;
121    sendBufferSize      = 0;
122    exceptionHandler    = null;
123    serverSocketFactory = ServerSocketFactory.getDefault();
124  }
125
126
127
128  /**
129   * Retrieves the port number on which to listen for client connections.  A
130   * value of zero indicates that the listener should allow the JVM to choose a
131   * free port.
132   *
133   * @return  The port number on which to listen for client connections.
134   */
135  public int getListenPort()
136  {
137    return listenPort;
138  }
139
140
141
142  /**
143   * Specifies the port number on which to listen for client connections.  The
144   * provided value must be between 1 and 65535, or it may be 0 to indicate that
145   * the JVM should select a free port on the system.
146   *
147   * @param  listenPort  The port number on which to listen for client
148   *                     connections.
149   */
150  public void setListenPort(final int listenPort)
151  {
152    Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65535));
153
154    this.listenPort = listenPort;
155  }
156
157
158
159  /**
160   * Retrieves the LDAP listener request handler that should be used to process
161   * requests read from clients.
162   *
163   * @return  The LDAP listener request handler that should be used to process
164   *          requests read from clients.
165   */
166  public LDAPListenerRequestHandler getRequestHandler()
167  {
168    return requestHandler;
169  }
170
171
172
173  /**
174   * Specifies the LDAP listener request handler that should be used to process
175   * requests read from clients.
176   *
177   * @param  requestHandler  The LDAP listener request handler that should be
178   *                         used to process requests read from clients.  It
179   *                         must not be {@code null}.
180   */
181  public void setRequestHandler(final LDAPListenerRequestHandler requestHandler)
182  {
183    Validator.ensureNotNull(requestHandler);
184
185    this.requestHandler = requestHandler;
186  }
187
188
189
190  /**
191   * Indicates whether to use the SO_KEEPALIVE socket option for sockets
192   * accepted by the listener.
193   *
194   * @return  {@code true} if the SO_KEEPALIVE socket option should be used for
195   *          sockets accepted by the listener, or {@code false} if not.
196   */
197  public boolean useKeepAlive()
198  {
199    return useKeepAlive;
200  }
201
202
203
204  /**
205   * Specifies whether to use the SO_KEEPALIVE socket option for sockets
206   * accepted by the listener.
207   *
208   * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE socket
209   *                       option for sockets accepted by the listener.
210   */
211  public void setUseKeepAlive(final boolean useKeepAlive)
212  {
213    this.useKeepAlive = useKeepAlive;
214  }
215
216
217
218  /**
219   * Indicates whether to use the SO_LINGER socket option for sockets accepted
220   * by the listener.
221   *
222   * @return  {@code true} if the SO_LINGER socket option should be used for
223   *          sockets accepted by the listener, or {@code false} if not.
224   */
225  public boolean useLinger()
226  {
227    return useLinger;
228  }
229
230
231
232  /**
233   * Specifies whether to use the SO_LINGER socket option for sockets accepted
234   * by the listener.
235   *
236   * @param  useLinger  Indicates whether to use the SO_LINGER socket option for
237   *                    sockets accepted by the listener.
238   */
239  public void setUseLinger(final boolean useLinger)
240  {
241    this.useLinger = useLinger;
242  }
243
244
245
246  /**
247   * Indicates whether to use the SO_REUSEADDR socket option for sockets
248   * accepted by the listener.
249   *
250   * @return  {@code true} if the SO_REUSEADDR socket option should be used for
251   *          sockets accepted by the listener, or {@code false} if not.
252   */
253  public boolean useReuseAddress()
254  {
255    return useReuseAddress;
256  }
257
258
259
260  /**
261   * Specifies whether to use the SO_REUSEADDR socket option for sockets
262   * accepted by the listener.
263   *
264   * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR socket
265   *                          option for sockets accepted by the listener.
266   */
267  public void setUseReuseAddress(final boolean useReuseAddress)
268  {
269    this.useReuseAddress = useReuseAddress;
270  }
271
272
273
274  /**
275   * Indicates whether to use the TCP_NODELAY socket option for sockets accepted
276   * by the listener.
277   *
278   * @return  {@code true} if the TCP_NODELAY socket option should be used for
279   *          sockets accepted by the listener, or {@code false} if not.
280   */
281  public boolean useTCPNoDelay()
282  {
283    return useTCPNoDelay;
284  }
285
286
287
288  /**
289   * Specifies whether to use the TCP_NODELAY socket option for sockets accepted
290   * by the listener.
291   *
292   * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY socket
293   *                        option for sockets accepted by the listener.
294   */
295  public void setUseTCPNoDelay(final boolean useTCPNoDelay)
296  {
297    this.useTCPNoDelay = useTCPNoDelay;
298  }
299
300
301
302  /**
303   * Retrieves the address on which to listen for client connections, if
304   * defined.
305   *
306   * @return  The address on which to listen for client connections, or
307   *          {@code null} if it should listen on all available addresses on all
308   *          interfaces.
309   */
310  public InetAddress getListenAddress()
311  {
312    return listenAddress;
313  }
314
315
316
317  /**
318   * Specifies the address on which to listen for client connections.
319   *
320   * @param  listenAddress  The address on which to listen for client
321   *                        connections.  It may be {@code null} to indicate
322   *                        that it should listen on all available addresses on
323   *                        all interfaces.
324   */
325  public void setListenAddress(final InetAddress listenAddress)
326  {
327    this.listenAddress = listenAddress;
328  }
329
330
331
332  /**
333   * Retrieves the timeout in seconds that should be used if the SO_LINGER
334   * socket option is enabled.
335   *
336   * @return  The timeout in seconds that should be used if the SO_LINGER socket
337   *           option is enabled.
338   */
339  public int getLingerTimeoutSeconds()
340  {
341    return lingerTimeout;
342  }
343
344
345
346  /**
347   * Specifies the timeout in seconds that should be used if the SO_LINGER
348   * socket option is enabled.
349   *
350   * @param  lingerTimeout  The timeout in seconds that should be used if the
351   *                        SO_LINGER socket option is enabled.  The value must
352   *                        be between 0 and 65535, inclusive.
353   */
354  public void setLingerTimeoutSeconds(final int lingerTimeout)
355  {
356    Validator.ensureTrue((lingerTimeout >= 0) && (lingerTimeout <= 65535));
357
358    this.lingerTimeout = lingerTimeout;
359  }
360
361
362
363  /**
364   * Retrieves the maximum number of concurrent connections that the listener
365   * will allow.  If a client tries to establish a new connection while the
366   * listener already has the maximum number of concurrent connections, then the
367   * new connection will be rejected.
368   *
369   * @return  The maximum number of concurrent connections that the listener
370   *          will allow, or zero if no limit should be enforced.
371   */
372  public int getMaxConnections()
373  {
374    return maxConnections;
375  }
376
377
378
379  /**
380   * Specifies the maximum number of concurrent connections that the listener
381   * will allow.  If a client tries to establish a new connection while the
382   * listener already has the maximum number of concurrent connections, then the
383   * new connection will be rejected.
384   *
385   * @param  maxConnections  The maximum number of concurrent connections that
386   *                         the listener will allow.  A value that is less than
387   *                         or equal to zero indicates no limit.
388   */
389  public void setMaxConnections(final int maxConnections)
390  {
391    if (maxConnections > 0)
392    {
393      this.maxConnections = maxConnections;
394    }
395    else
396    {
397      this.maxConnections = 0;
398    }
399  }
400
401
402
403  /**
404   * Retrieves the receive buffer size that should be used for sockets accepted
405   * by the listener.
406   *
407   * @return  The receive buffer size that should be used for sockets accepted
408   *          by the listener, or 0 if the default receive buffer size should be
409   *          used.
410   */
411  public int getReceiveBufferSize()
412  {
413    return receiveBufferSize;
414  }
415
416
417
418  /**
419   * Specifies the receive buffer size that should be used for sockets accepted
420   * by the listener.  A value less than or equal to zero indicates that the
421   * default receive buffer size should be used.
422   *
423   * @param  receiveBufferSize  The receive buffer size that should be used for
424   *                            sockets accepted by the listener.
425   */
426  public void setReceiveBufferSize(final int receiveBufferSize)
427  {
428    if (receiveBufferSize > 0)
429    {
430      this.receiveBufferSize = receiveBufferSize;
431    }
432    else
433    {
434      this.receiveBufferSize = 0;
435    }
436  }
437
438
439
440  /**
441   * Retrieves the send  buffer size that should be used for sockets accepted
442   * by the listener.
443   *
444   * @return  The send buffer size that should be used for sockets accepted by
445   *          the listener, or 0 if the default send buffer size should be used.
446   */
447  public int getSendBufferSize()
448  {
449    return sendBufferSize;
450  }
451
452
453
454  /**
455   * Specifies the send buffer size that should be used for sockets accepted by
456   * the listener.  A value less than or equal to zero indicates that the
457   * default send buffer size should be used.
458   *
459   * @param  sendBufferSize  The send buffer size that should be used for
460   *                         sockets accepted by the listener.
461   */
462  public void setSendBufferSize(final int sendBufferSize)
463  {
464    if (sendBufferSize > 0)
465    {
466      this.sendBufferSize = sendBufferSize;
467    }
468    else
469    {
470      this.sendBufferSize = 0;
471    }
472  }
473
474
475
476  /**
477   * Retrieves the exception handler that should be notified of any exceptions
478   * caught while attempting to accept or interact with a client connection.
479   *
480   * @return  The exception handler that should be notified of any exceptions
481   *          caught while attempting to accept or interact with a client
482   *          connection, or {@code null} if none is defined.
483   */
484  public LDAPListenerExceptionHandler getExceptionHandler()
485  {
486    return exceptionHandler;
487  }
488
489
490
491  /**
492   * Specifies the exception handler that should be notified of any exceptions
493   * caught while attempting to accept or interact with a client connection.
494   *
495   * @param  exceptionHandler  The exception handler that should be notified of
496   *                           any exceptions encountered during processing.  It
497   *                           may be {@code null} if no exception handler
498   *                           should be used.
499   */
500  public void setExceptionHandler(
501                   final LDAPListenerExceptionHandler exceptionHandler)
502  {
503    this.exceptionHandler = exceptionHandler;
504  }
505
506
507
508  /**
509   * Retrieves the factory that will be used to create the server socket that
510   * will listen for client connections.
511   *
512   * @return  The factory that will be used to create the server socket that
513   *          will listen for client connections.
514   */
515  public ServerSocketFactory getServerSocketFactory()
516  {
517    return serverSocketFactory;
518  }
519
520
521
522  /**
523   * Specifies the factory that will be used to create the server socket that
524   * will listen for client connections.
525   *
526   * @param  serverSocketFactory  The factory that will be used to create the
527   *                              server socket that will listen for client
528   *                              connections.  It may be {@code null} to use
529   *                              the JVM-default server socket factory.
530   */
531  public void setServerSocketFactory(
532                   final ServerSocketFactory serverSocketFactory)
533  {
534    if (serverSocketFactory == null)
535    {
536      this.serverSocketFactory = ServerSocketFactory.getDefault();
537    }
538    else
539    {
540      this.serverSocketFactory = serverSocketFactory;
541    }
542  }
543
544
545
546/**
547   * Creates a copy of this configuration that may be altered without impacting
548   * this configuration, and which will not be altered by changes to this
549   * configuration.
550   *
551   * @return  A copy of this configuration that may be altered without impacting
552   *          this configuration, and which will not be altered by changes to
553   *          this configuration.
554   */
555  public LDAPListenerConfig duplicate()
556  {
557    final LDAPListenerConfig copy =
558         new LDAPListenerConfig(listenPort, requestHandler);
559
560    copy.useKeepAlive        = useKeepAlive;
561    copy.useLinger           = useLinger;
562    copy.useReuseAddress     = useReuseAddress;
563    copy.useTCPNoDelay       = useTCPNoDelay;
564    copy.listenAddress       = listenAddress;
565    copy.lingerTimeout       = lingerTimeout;
566    copy.maxConnections      = maxConnections;
567    copy.receiveBufferSize   = receiveBufferSize;
568    copy.sendBufferSize      = sendBufferSize;
569    copy.exceptionHandler    = exceptionHandler;
570    copy.serverSocketFactory = serverSocketFactory;
571
572    return copy;
573  }
574
575
576
577  /**
578   * Retrieves a string representation of this LDAP listener config.
579   *
580   * @return  A string representation of this LDAP listener config.
581   */
582  @Override()
583  public String toString()
584  {
585    final StringBuilder buffer = new StringBuilder();
586    toString(buffer);
587    return buffer.toString();
588  }
589
590
591
592  /**
593   * Appends a string representation of this LDAP listener config to the
594   * provided buffer.
595   *
596   * @param  buffer  The buffer to which the information should be appended.
597   */
598  public void toString(final StringBuilder buffer)
599  {
600    buffer.append("LDAPListenerConfig(listenAddress=");
601
602    if (listenAddress == null)
603    {
604      buffer.append("null");
605    }
606    else
607    {
608      buffer.append('\'');
609      buffer.append(listenAddress.getHostAddress());
610      buffer.append('\'');
611    }
612
613    buffer.append(", listenPort=");
614    buffer.append(listenPort);
615    buffer.append(", requestHandlerClass='");
616    buffer.append(requestHandler.getClass().getName());
617    buffer.append("', serverSocketFactoryClass='");
618    buffer.append(serverSocketFactory.getClass().getName());
619    buffer.append('\'');
620
621    if (exceptionHandler != null)
622    {
623      buffer.append(", exceptionHandlerClass='");
624      buffer.append(exceptionHandler.getClass().getName());
625      buffer.append('\'');
626    }
627
628    buffer.append(", useKeepAlive=");
629    buffer.append(useKeepAlive);
630    buffer.append(", useTCPNoDelay=");
631    buffer.append(useTCPNoDelay);
632
633    if (useLinger)
634    {
635      buffer.append(", useLinger=true, lingerTimeout=");
636      buffer.append(lingerTimeout);
637    }
638    else
639    {
640      buffer.append(", useLinger=false");
641    }
642
643    buffer.append(", maxConnections=");
644    buffer.append(maxConnections);
645    buffer.append(", useReuseAddress=");
646    buffer.append(useReuseAddress);
647    buffer.append(", receiveBufferSize=");
648    buffer.append(receiveBufferSize);
649    buffer.append(", sendBufferSize=");
650    buffer.append(sendBufferSize);
651    buffer.append(')');
652  }
653}