001    /*
002     * Copyright 2010-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2010-2015 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     */
021    package com.unboundid.ldap.listener;
022    
023    
024    
025    import java.net.InetAddress;
026    import javax.net.ServerSocketFactory;
027    
028    import com.unboundid.util.Mutable;
029    import com.unboundid.util.ThreadSafety;
030    import com.unboundid.util.ThreadSafetyLevel;
031    import 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)
045    public 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    }