001/* 002 * Copyright 2010-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2010-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2010-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.listener; 037 038 039 040import java.net.InetAddress; 041import javax.net.ServerSocketFactory; 042 043import com.unboundid.util.Mutable; 044import com.unboundid.util.ThreadSafety; 045import com.unboundid.util.ThreadSafetyLevel; 046import com.unboundid.util.Validator; 047 048 049 050/** 051 * This class provides a mechanism for defining the configuration to use for an 052 * {@link LDAPListener} instance. Note that while instances of this class are 053 * not inherently threadsafe, a private copy of the configuration will be 054 * created whenever a new {@code LDAPListener} is created so that this 055 * configuration may continue to be altered for new instances without impacting 056 * any existing listeners. 057 */ 058@Mutable() 059@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 060public final class LDAPListenerConfig 061{ 062 // Indicates whether to use the SO_KEEPALIVE socket option for sockets 063 // accepted by the listener. 064 private boolean useKeepAlive; 065 066 // Indicates whether to use the SO_LINGER socket option for sockets accepted 067 // by the listener. 068 private boolean useLinger; 069 070 // Indicates whether to use the SO_REUSEADDR socket option for sockets 071 // accepted by the listener. 072 private boolean useReuseAddress; 073 074 // Indicates whether to use the TCP_NODELAY for sockets accepted by the 075 // listener. 076 private boolean useTCPNoDelay; 077 078 // The address on which to listen for client connections. 079 private InetAddress listenAddress; 080 081 // The linger timeout in seconds to use for sockets accepted by the listener. 082 private int lingerTimeout; 083 084 // The port on which to listen for client connections. 085 private int listenPort; 086 087 // The maximum number of concurrent connections that will be allowed. 088 private int maxConnections; 089 090 // The receive buffer size to use for sockets accepted by the listener. 091 private int receiveBufferSize; 092 093 // The send buffer size to use for sockets accepted by the listener. 094 private int sendBufferSize; 095 096 // The exception handler to use for the listener and associated connections. 097 private LDAPListenerExceptionHandler exceptionHandler; 098 099 // The request handler that will be used to process requests read from 100 // clients. 101 private LDAPListenerRequestHandler requestHandler; 102 103 // The factory that will be used to create server sockets. 104 private ServerSocketFactory serverSocketFactory; 105 106 107 108 /** 109 * Creates a new listener configuration. 110 * 111 * @param listenPort The port on which to listen for client connections. 112 * It must be an integer between 1 and 65535, or 0 to 113 * indicate that a free port should be chosen by the 114 * JVM. 115 * @param requestHandler The request handler that will be used to process 116 * requests read from clients. It must not be 117 * {@code null}. 118 */ 119 public LDAPListenerConfig(final int listenPort, 120 final LDAPListenerRequestHandler requestHandler) 121 { 122 Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65_535)); 123 Validator.ensureNotNull(requestHandler); 124 125 this.listenPort = listenPort; 126 this.requestHandler = requestHandler; 127 128 useKeepAlive = true; 129 useLinger = true; 130 useReuseAddress = true; 131 useTCPNoDelay = true; 132 lingerTimeout = 5; 133 listenAddress = null; 134 maxConnections = 0; 135 receiveBufferSize = 0; 136 sendBufferSize = 0; 137 exceptionHandler = null; 138 serverSocketFactory = ServerSocketFactory.getDefault(); 139 } 140 141 142 143 /** 144 * Retrieves the port number on which to listen for client connections. A 145 * value of zero indicates that the listener should allow the JVM to choose a 146 * free port. 147 * 148 * @return The port number on which to listen for client connections. 149 */ 150 public int getListenPort() 151 { 152 return listenPort; 153 } 154 155 156 157 /** 158 * Specifies the port number on which to listen for client connections. The 159 * provided value must be between 1 and 65535, or it may be 0 to indicate that 160 * the JVM should select a free port on the system. 161 * 162 * @param listenPort The port number on which to listen for client 163 * connections. 164 */ 165 public void setListenPort(final int listenPort) 166 { 167 Validator.ensureTrue((listenPort >= 0) && (listenPort <= 65_535)); 168 169 this.listenPort = listenPort; 170 } 171 172 173 174 /** 175 * Retrieves the LDAP listener request handler that should be used to process 176 * requests read from clients. 177 * 178 * @return The LDAP listener request handler that should be used to process 179 * requests read from clients. 180 */ 181 public LDAPListenerRequestHandler getRequestHandler() 182 { 183 return requestHandler; 184 } 185 186 187 188 /** 189 * Specifies the LDAP listener request handler that should be used to process 190 * requests read from clients. 191 * 192 * @param requestHandler The LDAP listener request handler that should be 193 * used to process requests read from clients. It 194 * must not be {@code null}. 195 */ 196 public void setRequestHandler(final LDAPListenerRequestHandler requestHandler) 197 { 198 Validator.ensureNotNull(requestHandler); 199 200 this.requestHandler = requestHandler; 201 } 202 203 204 205 /** 206 * Indicates whether to use the SO_KEEPALIVE socket option for sockets 207 * accepted by the listener. 208 * 209 * @return {@code true} if the SO_KEEPALIVE socket option should be used for 210 * sockets accepted by the listener, or {@code false} if not. 211 */ 212 public boolean useKeepAlive() 213 { 214 return useKeepAlive; 215 } 216 217 218 219 /** 220 * Specifies whether to use the SO_KEEPALIVE socket option for sockets 221 * accepted by the listener. 222 * 223 * @param useKeepAlive Indicates whether to use the SO_KEEPALIVE socket 224 * option for sockets accepted by the listener. 225 */ 226 public void setUseKeepAlive(final boolean useKeepAlive) 227 { 228 this.useKeepAlive = useKeepAlive; 229 } 230 231 232 233 /** 234 * Indicates whether to use the SO_LINGER socket option for sockets accepted 235 * by the listener. 236 * 237 * @return {@code true} if the SO_LINGER socket option should be used for 238 * sockets accepted by the listener, or {@code false} if not. 239 */ 240 public boolean useLinger() 241 { 242 return useLinger; 243 } 244 245 246 247 /** 248 * Specifies whether to use the SO_LINGER socket option for sockets accepted 249 * by the listener. 250 * 251 * @param useLinger Indicates whether to use the SO_LINGER socket option for 252 * sockets accepted by the listener. 253 */ 254 public void setUseLinger(final boolean useLinger) 255 { 256 this.useLinger = useLinger; 257 } 258 259 260 261 /** 262 * Indicates whether to use the SO_REUSEADDR socket option for sockets 263 * accepted by the listener. 264 * 265 * @return {@code true} if the SO_REUSEADDR socket option should be used for 266 * sockets accepted by the listener, or {@code false} if not. 267 */ 268 public boolean useReuseAddress() 269 { 270 return useReuseAddress; 271 } 272 273 274 275 /** 276 * Specifies whether to use the SO_REUSEADDR socket option for sockets 277 * accepted by the listener. 278 * 279 * @param useReuseAddress Indicates whether to use the SO_REUSEADDR socket 280 * option for sockets accepted by the listener. 281 */ 282 public void setUseReuseAddress(final boolean useReuseAddress) 283 { 284 this.useReuseAddress = useReuseAddress; 285 } 286 287 288 289 /** 290 * Indicates whether to use the TCP_NODELAY socket option for sockets accepted 291 * by the listener. 292 * 293 * @return {@code true} if the TCP_NODELAY socket option should be used for 294 * sockets accepted by the listener, or {@code false} if not. 295 */ 296 public boolean useTCPNoDelay() 297 { 298 return useTCPNoDelay; 299 } 300 301 302 303 /** 304 * Specifies whether to use the TCP_NODELAY socket option for sockets accepted 305 * by the listener. 306 * 307 * @param useTCPNoDelay Indicates whether to use the TCP_NODELAY socket 308 * option for sockets accepted by the listener. 309 */ 310 public void setUseTCPNoDelay(final boolean useTCPNoDelay) 311 { 312 this.useTCPNoDelay = useTCPNoDelay; 313 } 314 315 316 317 /** 318 * Retrieves the address on which to listen for client connections, if 319 * defined. 320 * 321 * @return The address on which to listen for client connections, or 322 * {@code null} if it should listen on all available addresses on all 323 * interfaces. 324 */ 325 public InetAddress getListenAddress() 326 { 327 return listenAddress; 328 } 329 330 331 332 /** 333 * Specifies the address on which to listen for client connections. 334 * 335 * @param listenAddress The address on which to listen for client 336 * connections. It may be {@code null} to indicate 337 * that it should listen on all available addresses on 338 * all interfaces. 339 */ 340 public void setListenAddress(final InetAddress listenAddress) 341 { 342 this.listenAddress = listenAddress; 343 } 344 345 346 347 /** 348 * Retrieves the timeout in seconds that should be used if the SO_LINGER 349 * socket option is enabled. 350 * 351 * @return The timeout in seconds that should be used if the SO_LINGER socket 352 * option is enabled. 353 */ 354 public int getLingerTimeoutSeconds() 355 { 356 return lingerTimeout; 357 } 358 359 360 361 /** 362 * Specifies the timeout in seconds that should be used if the SO_LINGER 363 * socket option is enabled. 364 * 365 * @param lingerTimeout The timeout in seconds that should be used if the 366 * SO_LINGER socket option is enabled. The value must 367 * be between 0 and 65535, inclusive. 368 */ 369 public void setLingerTimeoutSeconds(final int lingerTimeout) 370 { 371 Validator.ensureTrue((lingerTimeout >= 0) && (lingerTimeout <= 65_535)); 372 373 this.lingerTimeout = lingerTimeout; 374 } 375 376 377 378 /** 379 * Retrieves the maximum number of concurrent connections that the listener 380 * will allow. If a client tries to establish a new connection while the 381 * listener already has the maximum number of concurrent connections, then the 382 * new connection will be rejected. 383 * 384 * @return The maximum number of concurrent connections that the listener 385 * will allow, or zero if no limit should be enforced. 386 */ 387 public int getMaxConnections() 388 { 389 return maxConnections; 390 } 391 392 393 394 /** 395 * Specifies the maximum number of concurrent connections that the listener 396 * will allow. If a client tries to establish a new connection while the 397 * listener already has the maximum number of concurrent connections, then the 398 * new connection will be rejected. 399 * 400 * @param maxConnections The maximum number of concurrent connections that 401 * the listener will allow. A value that is less than 402 * or equal to zero indicates no limit. 403 */ 404 public void setMaxConnections(final int maxConnections) 405 { 406 if (maxConnections > 0) 407 { 408 this.maxConnections = maxConnections; 409 } 410 else 411 { 412 this.maxConnections = 0; 413 } 414 } 415 416 417 418 /** 419 * Retrieves the receive buffer size that should be used for sockets accepted 420 * by the listener. 421 * 422 * @return The receive buffer size that should be used for sockets accepted 423 * by the listener, or 0 if the default receive buffer size should be 424 * used. 425 */ 426 public int getReceiveBufferSize() 427 { 428 return receiveBufferSize; 429 } 430 431 432 433 /** 434 * Specifies the receive buffer size that should be used for sockets accepted 435 * by the listener. A value less than or equal to zero indicates that the 436 * default receive buffer size should be used. 437 * 438 * @param receiveBufferSize The receive buffer size that should be used for 439 * sockets accepted by the listener. 440 */ 441 public void setReceiveBufferSize(final int receiveBufferSize) 442 { 443 if (receiveBufferSize > 0) 444 { 445 this.receiveBufferSize = receiveBufferSize; 446 } 447 else 448 { 449 this.receiveBufferSize = 0; 450 } 451 } 452 453 454 455 /** 456 * Retrieves the send buffer size that should be used for sockets accepted 457 * by the listener. 458 * 459 * @return The send buffer size that should be used for sockets accepted by 460 * the listener, or 0 if the default send buffer size should be used. 461 */ 462 public int getSendBufferSize() 463 { 464 return sendBufferSize; 465 } 466 467 468 469 /** 470 * Specifies the send buffer size that should be used for sockets accepted by 471 * the listener. A value less than or equal to zero indicates that the 472 * default send buffer size should be used. 473 * 474 * @param sendBufferSize The send buffer size that should be used for 475 * sockets accepted by the listener. 476 */ 477 public void setSendBufferSize(final int sendBufferSize) 478 { 479 if (sendBufferSize > 0) 480 { 481 this.sendBufferSize = sendBufferSize; 482 } 483 else 484 { 485 this.sendBufferSize = 0; 486 } 487 } 488 489 490 491 /** 492 * Retrieves the exception handler that should be notified of any exceptions 493 * caught while attempting to accept or interact with a client connection. 494 * 495 * @return The exception handler that should be notified of any exceptions 496 * caught while attempting to accept or interact with a client 497 * connection, or {@code null} if none is defined. 498 */ 499 public LDAPListenerExceptionHandler getExceptionHandler() 500 { 501 return exceptionHandler; 502 } 503 504 505 506 /** 507 * Specifies the exception handler that should be notified of any exceptions 508 * caught while attempting to accept or interact with a client connection. 509 * 510 * @param exceptionHandler The exception handler that should be notified of 511 * any exceptions encountered during processing. It 512 * may be {@code null} if no exception handler 513 * should be used. 514 */ 515 public void setExceptionHandler( 516 final LDAPListenerExceptionHandler exceptionHandler) 517 { 518 this.exceptionHandler = exceptionHandler; 519 } 520 521 522 523 /** 524 * Retrieves the factory that will be used to create the server socket that 525 * will listen for client connections. 526 * 527 * @return The factory that will be used to create the server socket that 528 * will listen for client connections. 529 */ 530 public ServerSocketFactory getServerSocketFactory() 531 { 532 return serverSocketFactory; 533 } 534 535 536 537 /** 538 * Specifies the factory that will be used to create the server socket that 539 * will listen for client connections. 540 * 541 * @param serverSocketFactory The factory that will be used to create the 542 * server socket that will listen for client 543 * connections. It may be {@code null} to use 544 * the JVM-default server socket factory. 545 */ 546 public void setServerSocketFactory( 547 final ServerSocketFactory serverSocketFactory) 548 { 549 if (serverSocketFactory == null) 550 { 551 this.serverSocketFactory = ServerSocketFactory.getDefault(); 552 } 553 else 554 { 555 this.serverSocketFactory = serverSocketFactory; 556 } 557 } 558 559 560 561/** 562 * Creates a copy of this configuration that may be altered without impacting 563 * this configuration, and which will not be altered by changes to this 564 * configuration. 565 * 566 * @return A copy of this configuration that may be altered without impacting 567 * this configuration, and which will not be altered by changes to 568 * this configuration. 569 */ 570 public LDAPListenerConfig duplicate() 571 { 572 final LDAPListenerConfig copy = 573 new LDAPListenerConfig(listenPort, requestHandler); 574 575 copy.useKeepAlive = useKeepAlive; 576 copy.useLinger = useLinger; 577 copy.useReuseAddress = useReuseAddress; 578 copy.useTCPNoDelay = useTCPNoDelay; 579 copy.listenAddress = listenAddress; 580 copy.lingerTimeout = lingerTimeout; 581 copy.maxConnections = maxConnections; 582 copy.receiveBufferSize = receiveBufferSize; 583 copy.sendBufferSize = sendBufferSize; 584 copy.exceptionHandler = exceptionHandler; 585 copy.serverSocketFactory = serverSocketFactory; 586 587 return copy; 588 } 589 590 591 592 /** 593 * Retrieves a string representation of this LDAP listener config. 594 * 595 * @return A string representation of this LDAP listener config. 596 */ 597 @Override() 598 public String toString() 599 { 600 final StringBuilder buffer = new StringBuilder(); 601 toString(buffer); 602 return buffer.toString(); 603 } 604 605 606 607 /** 608 * Appends a string representation of this LDAP listener config to the 609 * provided buffer. 610 * 611 * @param buffer The buffer to which the information should be appended. 612 */ 613 public void toString(final StringBuilder buffer) 614 { 615 buffer.append("LDAPListenerConfig(listenAddress="); 616 617 if (listenAddress == null) 618 { 619 buffer.append("null"); 620 } 621 else 622 { 623 buffer.append('\''); 624 buffer.append(listenAddress.getHostAddress()); 625 buffer.append('\''); 626 } 627 628 buffer.append(", listenPort="); 629 buffer.append(listenPort); 630 buffer.append(", requestHandlerClass='"); 631 buffer.append(requestHandler.getClass().getName()); 632 buffer.append("', serverSocketFactoryClass='"); 633 buffer.append(serverSocketFactory.getClass().getName()); 634 buffer.append('\''); 635 636 if (exceptionHandler != null) 637 { 638 buffer.append(", exceptionHandlerClass='"); 639 buffer.append(exceptionHandler.getClass().getName()); 640 buffer.append('\''); 641 } 642 643 buffer.append(", useKeepAlive="); 644 buffer.append(useKeepAlive); 645 buffer.append(", useTCPNoDelay="); 646 buffer.append(useTCPNoDelay); 647 648 if (useLinger) 649 { 650 buffer.append(", useLinger=true, lingerTimeout="); 651 buffer.append(lingerTimeout); 652 } 653 else 654 { 655 buffer.append(", useLinger=false"); 656 } 657 658 buffer.append(", maxConnections="); 659 buffer.append(maxConnections); 660 buffer.append(", useReuseAddress="); 661 buffer.append(useReuseAddress); 662 buffer.append(", receiveBufferSize="); 663 buffer.append(receiveBufferSize); 664 buffer.append(", sendBufferSize="); 665 buffer.append(sendBufferSize); 666 buffer.append(')'); 667 } 668}