001 /*
002 * Copyright 2010-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2010-2016 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 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 }