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}