001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.net; 019 020import java.io.Closeable; 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.net.InetAddress; 025import java.net.InetSocketAddress; 026import java.net.Proxy; 027import java.net.Socket; 028import java.net.SocketException; 029import java.nio.charset.Charset; 030 031import javax.net.ServerSocketFactory; 032import javax.net.SocketFactory; 033 034 035/** 036 * The SocketClient provides the basic operations that are required of 037 * client objects accessing sockets. It is meant to be 038 * subclassed to avoid having to rewrite the same code over and over again 039 * to open a socket, close a socket, set timeouts, etc. Of special note 040 * is the {@link #setSocketFactory setSocketFactory } 041 * method, which allows you to control the type of Socket the SocketClient 042 * creates for initiating network connections. This is especially useful 043 * for adding SSL or proxy support as well as better support for applets. For 044 * example, you could create a 045 * {@link javax.net.SocketFactory} that 046 * requests browser security capabilities before creating a socket. 047 * All classes derived from SocketClient should use the 048 * {@link #_socketFactory_ _socketFactory_ } member variable to 049 * create Socket and ServerSocket instances rather than instantiating 050 * them by directly invoking a constructor. By honoring this contract 051 * you guarantee that a user will always be able to provide his own 052 * Socket implementations by substituting his own SocketFactory. 053 * @see SocketFactory 054 */ 055public abstract class SocketClient 056{ 057 /** 058 * The end of line character sequence used by most IETF protocols. That 059 * is a carriage return followed by a newline: "\r\n" 060 */ 061 public static final String NETASCII_EOL = "\r\n"; 062 063 /** The default SocketFactory shared by all SocketClient instances. */ 064 private static final SocketFactory DEFAULT_SOCKET_FACTORY = 065 SocketFactory.getDefault(); 066 067 /** The default {@link ServerSocketFactory} */ 068 private static final ServerSocketFactory DEFAULT_SERVER_SOCKET_FACTORY = 069 ServerSocketFactory.getDefault(); 070 071 /** 072 * A ProtocolCommandSupport object used to manage the registering of 073 * ProtocolCommandListeners and the firing of ProtocolCommandEvents. 074 */ 075 private ProtocolCommandSupport commandSupport; 076 077 /** The timeout to use after opening a socket. */ 078 protected int _timeout_; 079 080 /** The socket used for the connection. */ 081 protected Socket _socket_; 082 083 /** The hostname used for the connection (null = no hostname supplied). */ 084 protected String _hostname_; 085 086 /** The default port the client should connect to. */ 087 protected int _defaultPort_; 088 089 /** The socket's InputStream. */ 090 protected InputStream _input_; 091 092 /** The socket's OutputStream. */ 093 protected OutputStream _output_; 094 095 /** The socket's SocketFactory. */ 096 protected SocketFactory _socketFactory_; 097 098 /** The socket's ServerSocket Factory. */ 099 protected ServerSocketFactory _serverSocketFactory_; 100 101 /** The socket's connect timeout (0 = infinite timeout) */ 102 private static final int DEFAULT_CONNECT_TIMEOUT = 60000; 103 104 protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT; 105 106 /** Hint for SO_RCVBUF size */ 107 private int receiveBufferSize = -1; 108 109 /** Hint for SO_SNDBUF size */ 110 private int sendBufferSize = -1; 111 112 /** The proxy to use when connecting. */ 113 private Proxy connProxy; 114 115 /** 116 * Charset to use for byte IO. 117 */ 118 private Charset charset = Charset.defaultCharset(); 119 120 /** 121 * Default constructor for SocketClient. Initializes 122 * _socket_ to null, _timeout_ to 0, _defaultPort to 0, 123 * _isConnected_ to false, charset to {@code Charset.defaultCharset()} 124 * and _socketFactory_ to a shared instance of 125 * {@link org.apache.commons.net.DefaultSocketFactory}. 126 */ 127 public SocketClient() 128 { 129 _socket_ = null; 130 _hostname_ = null; 131 _input_ = null; 132 _output_ = null; 133 _timeout_ = 0; 134 _defaultPort_ = 0; 135 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 136 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 137 } 138 139 140 /** 141 * Because there are so many connect() methods, the _connectAction_() 142 * method is provided as a means of performing some action immediately 143 * after establishing a connection, rather than reimplementing all 144 * of the connect() methods. The last action performed by every 145 * connect() method after opening a socket is to call this method. 146 * <p> 147 * This method sets the timeout on the just opened socket to the default 148 * timeout set by {@link #setDefaultTimeout setDefaultTimeout() }, 149 * sets _input_ and _output_ to the socket's InputStream and OutputStream 150 * respectively, and sets _isConnected_ to true. 151 * <p> 152 * Subclasses overriding this method should start by calling 153 * <code> super._connectAction_() </code> first to ensure the 154 * initialization of the aforementioned protected variables. 155 * @throws IOException (SocketException) if a problem occurs with the socket 156 */ 157 protected void _connectAction_() throws IOException 158 { 159 applySocketAttributes(); 160 _input_ = _socket_.getInputStream(); 161 _output_ = _socket_.getOutputStream(); 162 } 163 164 /** 165 * Applies socket attributes. 166 * 167 * @throws SocketException if there is an error in the underlying protocol, such as a TCP error. 168 * @since 3.8.0 169 */ 170 protected void applySocketAttributes() throws SocketException { 171 _socket_.setSoTimeout(_timeout_); 172 } 173 174 /** 175 * Opens a Socket connected to a remote host at the specified port and 176 * originating from the current host at a system assigned port. 177 * Before returning, {@link #_connectAction_ _connectAction_() } 178 * is called to perform connection initialization actions. 179 * <p> 180 * @param host The remote host. 181 * @param port The port to connect to on the remote host. 182 * @throws SocketException If the socket timeout could not be set. 183 * @throws IOException If the socket could not be opened. In most 184 * cases you will only want to catch IOException since SocketException is 185 * derived from it. 186 */ 187 public void connect(final InetAddress host, final int port) 188 throws SocketException, IOException 189 { 190 _hostname_ = null; 191 _connect(host, port, null, -1); 192 } 193 194 /** 195 * Opens a Socket connected to a remote host at the specified port and 196 * originating from the current host at a system assigned port. 197 * Before returning, {@link #_connectAction_ _connectAction_() } 198 * is called to perform connection initialization actions. 199 * <p> 200 * @param hostname The name of the remote host. 201 * @param port The port to connect to on the remote host. 202 * @throws SocketException If the socket timeout could not be set. 203 * @throws IOException If the socket could not be opened. In most 204 * cases you will only want to catch IOException since SocketException is 205 * derived from it. 206 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 207 */ 208 public void connect(final String hostname, final int port) 209 throws SocketException, IOException 210 { 211 _hostname_ = hostname; 212 _connect(InetAddress.getByName(hostname), port, null, -1); 213 } 214 215 216 /** 217 * Opens a Socket connected to a remote host at the specified port and 218 * originating from the specified local address and port. 219 * Before returning, {@link #_connectAction_ _connectAction_() } 220 * is called to perform connection initialization actions. 221 * <p> 222 * @param host The remote host. 223 * @param port The port to connect to on the remote host. 224 * @param localAddr The local address to use. 225 * @param localPort The local port to use. 226 * @throws SocketException If the socket timeout could not be set. 227 * @throws IOException If the socket could not be opened. In most 228 * cases you will only want to catch IOException since SocketException is 229 * derived from it. 230 */ 231 public void connect(final InetAddress host, final int port, 232 final InetAddress localAddr, final int localPort) 233 throws SocketException, IOException 234 { 235 _hostname_ = null; 236 _connect(host, port, localAddr, localPort); 237 } 238 239 // helper method to allow code to be shared with connect(String,...) methods 240 private void _connect(final InetAddress host, final int port, final InetAddress localAddr, final int localPort) 241 throws SocketException, IOException 242 { 243 _socket_ = _socketFactory_.createSocket(); 244 if (receiveBufferSize != -1) { 245 _socket_.setReceiveBufferSize(receiveBufferSize); 246 } 247 if (sendBufferSize != -1) { 248 _socket_.setSendBufferSize(sendBufferSize); 249 } 250 if (localAddr != null) { 251 _socket_.bind(new InetSocketAddress(localAddr, localPort)); 252 } 253 _socket_.connect(new InetSocketAddress(host, port), connectTimeout); 254 _connectAction_(); 255 } 256 257 /** 258 * Opens a Socket connected to a remote host at the specified port and 259 * originating from the specified local address and port. 260 * Before returning, {@link #_connectAction_ _connectAction_() } 261 * is called to perform connection initialization actions. 262 * <p> 263 * @param hostname The name of the remote host. 264 * @param port The port to connect to on the remote host. 265 * @param localAddr The local address to use. 266 * @param localPort The local port to use. 267 * @throws SocketException If the socket timeout could not be set. 268 * @throws IOException If the socket could not be opened. In most 269 * cases you will only want to catch IOException since SocketException is 270 * derived from it. 271 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 272 */ 273 public void connect(final String hostname, final int port, 274 final InetAddress localAddr, final int localPort) 275 throws SocketException, IOException 276 { 277 _hostname_ = hostname; 278 _connect(InetAddress.getByName(hostname), port, localAddr, localPort); 279 } 280 281 282 /** 283 * Opens a Socket connected to a remote host at the current default port 284 * and originating from the current host at a system assigned port. 285 * Before returning, {@link #_connectAction_ _connectAction_() } 286 * is called to perform connection initialization actions. 287 * <p> 288 * @param host The remote host. 289 * @throws SocketException If the socket timeout could not be set. 290 * @throws IOException If the socket could not be opened. In most 291 * cases you will only want to catch IOException since SocketException is 292 * derived from it. 293 */ 294 public void connect(final InetAddress host) throws SocketException, IOException 295 { 296 _hostname_ = null; 297 connect(host, _defaultPort_); 298 } 299 300 301 /** 302 * Opens a Socket connected to a remote host at the current default 303 * port and originating from the current host at a system assigned port. 304 * Before returning, {@link #_connectAction_ _connectAction_() } 305 * is called to perform connection initialization actions. 306 * <p> 307 * @param hostname The name of the remote host. 308 * @throws SocketException If the socket timeout could not be set. 309 * @throws IOException If the socket could not be opened. In most 310 * cases you will only want to catch IOException since SocketException is 311 * derived from it. 312 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 313 */ 314 public void connect(final String hostname) throws SocketException, IOException 315 { 316 connect(hostname, _defaultPort_); 317 } 318 319 320 /** 321 * Disconnects the socket connection. 322 * You should call this method after you've finished using the class 323 * instance and also before you call 324 * {@link #connect connect() } 325 * again. _isConnected_ is set to false, _socket_ is set to null, 326 * _input_ is set to null, and _output_ is set to null. 327 * <p> 328 * @throws IOException If there is an error closing the socket. 329 */ 330 public void disconnect() throws IOException 331 { 332 closeQuietly(_socket_); 333 closeQuietly(_input_); 334 closeQuietly(_output_); 335 _socket_ = null; 336 _hostname_ = null; 337 _input_ = null; 338 _output_ = null; 339 } 340 341 private void closeQuietly(final Socket socket) { 342 if (socket != null){ 343 try { 344 socket.close(); 345 } catch (final IOException e) { 346 // Ignored 347 } 348 } 349 } 350 351 private void closeQuietly(final Closeable close){ 352 if (close != null){ 353 try { 354 close.close(); 355 } catch (final IOException e) { 356 // Ignored 357 } 358 } 359 } 360 /** 361 * Returns true if the client is currently connected to a server. 362 * <p> 363 * Delegates to {@link Socket#isConnected()} 364 * @return True if the client is currently connected to a server, 365 * false otherwise. 366 */ 367 public boolean isConnected() 368 { 369 if (_socket_ == null) { 370 return false; 371 } 372 373 return _socket_.isConnected(); 374 } 375 376 /** 377 * Make various checks on the socket to test if it is available for use. 378 * Note that the only sure test is to use it, but these checks may help 379 * in some cases. 380 * @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a> 381 * @return {@code true} if the socket appears to be available for use 382 * @since 3.0 383 */ 384 @SuppressWarnings("resource") 385 public boolean isAvailable(){ 386 if (isConnected()) { 387 try 388 { 389 if (_socket_.getInetAddress() == null) { 390 return false; 391 } 392 if (_socket_.getPort() == 0) { 393 return false; 394 } 395 if (_socket_.getRemoteSocketAddress() == null) { 396 return false; 397 } 398 if (_socket_.isClosed()) { 399 return false; 400 } 401 /* these aren't exact checks (a Socket can be half-open), 402 but since we usually require two-way data transfer, 403 we check these here too: */ 404 if (_socket_.isInputShutdown()) { 405 return false; 406 } 407 if (_socket_.isOutputShutdown()) { 408 return false; 409 } 410 /* ignore the result, catch exceptions: */ 411 // No need to close 412 _socket_.getInputStream(); 413 // No need to close 414 _socket_.getOutputStream(); 415 } 416 catch (final IOException ioex) 417 { 418 return false; 419 } 420 return true; 421 } 422 return false; 423 } 424 425 /** 426 * Sets the default port the SocketClient should connect to when a port 427 * is not specified. The {@link #_defaultPort_ _defaultPort_ } 428 * variable stores this value. If never set, the default port is equal 429 * to zero. 430 * <p> 431 * @param port The default port to set. 432 */ 433 public void setDefaultPort(final int port) 434 { 435 _defaultPort_ = port; 436 } 437 438 /** 439 * Returns the current value of the default port (stored in 440 * {@link #_defaultPort_ _defaultPort_ }). 441 * <p> 442 * @return The current value of the default port. 443 */ 444 public int getDefaultPort() 445 { 446 return _defaultPort_; 447 } 448 449 450 /** 451 * Set the default timeout in milliseconds to use when opening a socket. 452 * This value is only used previous to a call to 453 * {@link #connect connect()} 454 * and should not be confused with {@link #setSoTimeout setSoTimeout()} 455 * which operates on an the currently opened socket. _timeout_ contains 456 * the new timeout value. 457 * <p> 458 * @param timeout The timeout in milliseconds to use for the socket 459 * connection. 460 */ 461 public void setDefaultTimeout(final int timeout) 462 { 463 _timeout_ = timeout; 464 } 465 466 467 /** 468 * Returns the default timeout in milliseconds that is used when 469 * opening a socket. 470 * <p> 471 * @return The default timeout in milliseconds that is used when 472 * opening a socket. 473 */ 474 public int getDefaultTimeout() 475 { 476 return _timeout_; 477 } 478 479 480 /** 481 * Set the timeout in milliseconds of a currently open connection. 482 * Only call this method after a connection has been opened 483 * by {@link #connect connect()}. 484 * <p> 485 * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead. 486 * 487 * @param timeout The timeout in milliseconds to use for the currently 488 * open socket connection. 489 * @throws SocketException If the operation fails. 490 * @throws NullPointerException if the socket is not currently open 491 */ 492 public void setSoTimeout(final int timeout) throws SocketException 493 { 494 _socket_.setSoTimeout(timeout); 495 } 496 497 498 /** 499 * Set the underlying socket send buffer size. 500 * <p> 501 * @param size The size of the buffer in bytes. 502 * @throws SocketException never thrown, but subclasses might want to do so 503 * @since 2.0 504 */ 505 public void setSendBufferSize(final int size) throws SocketException { 506 sendBufferSize = size; 507 } 508 509 /** 510 * Get the current sendBuffer size 511 * @return the size, or -1 if not initialized 512 * @since 3.0 513 */ 514 protected int getSendBufferSize(){ 515 return sendBufferSize; 516 } 517 518 /** 519 * Sets the underlying socket receive buffer size. 520 * <p> 521 * @param size The size of the buffer in bytes. 522 * @throws SocketException never (but subclasses may wish to do so) 523 * @since 2.0 524 */ 525 public void setReceiveBufferSize(final int size) throws SocketException { 526 receiveBufferSize = size; 527 } 528 529 /** 530 * Get the current receivedBuffer size 531 * @return the size, or -1 if not initialized 532 * @since 3.0 533 */ 534 protected int getReceiveBufferSize(){ 535 return receiveBufferSize; 536 } 537 538 /** 539 * Returns the timeout in milliseconds of the currently opened socket. 540 * <p> 541 * @return The timeout in milliseconds of the currently opened socket. 542 * @throws SocketException If the operation fails. 543 * @throws NullPointerException if the socket is not currently open 544 */ 545 public int getSoTimeout() throws SocketException 546 { 547 return _socket_.getSoTimeout(); 548 } 549 550 /** 551 * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the 552 * currently opened socket. 553 * <p> 554 * @param on True if Nagle's algorithm is to be enabled, false if not. 555 * @throws SocketException If the operation fails. 556 * @throws NullPointerException if the socket is not currently open 557 */ 558 public void setTcpNoDelay(final boolean on) throws SocketException 559 { 560 _socket_.setTcpNoDelay(on); 561 } 562 563 564 /** 565 * Returns true if Nagle's algorithm is enabled on the currently opened 566 * socket. 567 * <p> 568 * @return True if Nagle's algorithm is enabled on the currently opened 569 * socket, false otherwise. 570 * @throws SocketException If the operation fails. 571 * @throws NullPointerException if the socket is not currently open 572 */ 573 public boolean getTcpNoDelay() throws SocketException 574 { 575 return _socket_.getTcpNoDelay(); 576 } 577 578 /** 579 * Sets the SO_KEEPALIVE flag on the currently opened socket. 580 * 581 * From the Javadocs, the default keepalive time is 2 hours (although this is 582 * implementation dependent). It looks as though the Windows WSA sockets implementation 583 * allows a specific keepalive value to be set, although this seems not to be the case on 584 * other systems. 585 * @param keepAlive If true, keepAlive is turned on 586 * @throws SocketException if there is a problem with the socket 587 * @throws NullPointerException if the socket is not currently open 588 * @since 2.2 589 */ 590 public void setKeepAlive(final boolean keepAlive) throws SocketException { 591 _socket_.setKeepAlive(keepAlive); 592 } 593 594 /** 595 * Returns the current value of the SO_KEEPALIVE flag on the currently opened socket. 596 * Delegates to {@link Socket#getKeepAlive()} 597 * @return True if SO_KEEPALIVE is enabled. 598 * @throws SocketException if there is a problem with the socket 599 * @throws NullPointerException if the socket is not currently open 600 * @since 2.2 601 */ 602 public boolean getKeepAlive() throws SocketException { 603 return _socket_.getKeepAlive(); 604 } 605 606 /** 607 * Sets the SO_LINGER timeout on the currently opened socket. 608 * <p> 609 * @param on True if linger is to be enabled, false if not. 610 * @param val The linger timeout (in hundredths of a second?) 611 * @throws SocketException If the operation fails. 612 * @throws NullPointerException if the socket is not currently open 613 */ 614 public void setSoLinger(final boolean on, final int val) throws SocketException 615 { 616 _socket_.setSoLinger(on, val); 617 } 618 619 620 /** 621 * Returns the current SO_LINGER timeout of the currently opened socket. 622 * <p> 623 * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns 624 * -1. 625 * @throws SocketException If the operation fails. 626 * @throws NullPointerException if the socket is not currently open 627 */ 628 public int getSoLinger() throws SocketException 629 { 630 return _socket_.getSoLinger(); 631 } 632 633 634 /** 635 * Returns the port number of the open socket on the local host used 636 * for the connection. 637 * Delegates to {@link Socket#getLocalPort()} 638 * <p> 639 * @return The port number of the open socket on the local host used 640 * for the connection. 641 * @throws NullPointerException if the socket is not currently open 642 */ 643 public int getLocalPort() 644 { 645 return _socket_.getLocalPort(); 646 } 647 648 649 /** 650 * Returns the local address to which the client's socket is bound. 651 * Delegates to {@link Socket#getLocalAddress()} 652 * <p> 653 * @return The local address to which the client's socket is bound. 654 * @throws NullPointerException if the socket is not currently open 655 */ 656 public InetAddress getLocalAddress() 657 { 658 return _socket_.getLocalAddress(); 659 } 660 661 /** 662 * Returns the port number of the remote host to which the client is 663 * connected. 664 * Delegates to {@link Socket#getPort()} 665 * <p> 666 * @return The port number of the remote host to which the client is 667 * connected. 668 * @throws NullPointerException if the socket is not currently open 669 */ 670 public int getRemotePort() 671 { 672 return _socket_.getPort(); 673 } 674 675 676 /** 677 * @return The remote address to which the client is connected. 678 * Delegates to {@link Socket#getInetAddress()} 679 * @throws NullPointerException if the socket is not currently open 680 */ 681 public InetAddress getRemoteAddress() 682 { 683 return _socket_.getInetAddress(); 684 } 685 686 687 /** 688 * Verifies that the remote end of the given socket is connected to the 689 * the same host that the SocketClient is currently connected to. This 690 * is useful for doing a quick security check when a client needs to 691 * accept a connection from a server, such as an FTP data connection or 692 * a BSD R command standard error stream. 693 * <p> 694 * @param socket the item to check against 695 * @return True if the remote hosts are the same, false if not. 696 */ 697 public boolean verifyRemote(final Socket socket) 698 { 699 final InetAddress host1; 700 final InetAddress host2; 701 702 host1 = socket.getInetAddress(); 703 host2 = getRemoteAddress(); 704 705 return host1.equals(host2); 706 } 707 708 709 /** 710 * Sets the SocketFactory used by the SocketClient to open socket 711 * connections. If the factory value is null, then a default 712 * factory is used (only do this to reset the factory after having 713 * previously altered it). 714 * Any proxy setting is discarded. 715 * <p> 716 * @param factory The new SocketFactory the SocketClient should use. 717 */ 718 public void setSocketFactory(final SocketFactory factory) 719 { 720 if (factory == null) { 721 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 722 } else { 723 _socketFactory_ = factory; 724 } 725 // re-setting the socket factory makes the proxy setting useless, 726 // so set the field to null so that getProxy() doesn't return a 727 // Proxy that we're actually not using. 728 connProxy = null; 729 } 730 731 /** 732 * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket 733 * connections. If the factory value is null, then a default 734 * factory is used (only do this to reset the factory after having 735 * previously altered it). 736 * <p> 737 * @param factory The new ServerSocketFactory the SocketClient should use. 738 * @since 2.0 739 */ 740 public void setServerSocketFactory(final ServerSocketFactory factory) { 741 if (factory == null) { 742 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 743 } else { 744 _serverSocketFactory_ = factory; 745 } 746 } 747 748 /** 749 * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's 750 * connect() method. 751 * @param connectTimeout The connection timeout to use (in ms) 752 * @since 2.0 753 */ 754 public void setConnectTimeout(final int connectTimeout) { 755 this.connectTimeout = connectTimeout; 756 } 757 758 /** 759 * Get the underlying socket connection timeout. 760 * @return timeout (in ms) 761 * @since 2.0 762 */ 763 public int getConnectTimeout() { 764 return connectTimeout; 765 } 766 767 /** 768 * Get the underlying {@link ServerSocketFactory} 769 * @return The server socket factory 770 * @since 2.2 771 */ 772 public ServerSocketFactory getServerSocketFactory() { 773 return _serverSocketFactory_; 774 } 775 776 777 /** 778 * Adds a ProtocolCommandListener. 779 * 780 * @param listener The ProtocolCommandListener to add. 781 * @since 3.0 782 */ 783 public void addProtocolCommandListener(final ProtocolCommandListener listener) { 784 getCommandSupport().addProtocolCommandListener(listener); 785 } 786 787 /** 788 * Removes a ProtocolCommandListener. 789 * 790 * @param listener The ProtocolCommandListener to remove. 791 * @since 3.0 792 */ 793 public void removeProtocolCommandListener(final ProtocolCommandListener listener) { 794 getCommandSupport().removeProtocolCommandListener(listener); 795 } 796 797 /** 798 * If there are any listeners, send them the reply details. 799 * 800 * @param replyCode the code extracted from the reply 801 * @param reply the full reply text 802 * @since 3.0 803 */ 804 protected void fireReplyReceived(final int replyCode, final String reply) { 805 if (getCommandSupport().getListenerCount() > 0) { 806 getCommandSupport().fireReplyReceived(replyCode, reply); 807 } 808 } 809 810 /** 811 * If there are any listeners, send them the command details. 812 * 813 * @param command the command name 814 * @param message the complete message, including command name 815 * @since 3.0 816 */ 817 protected void fireCommandSent(final String command, final String message) { 818 if (getCommandSupport().getListenerCount() > 0) { 819 getCommandSupport().fireCommandSent(command, message); 820 } 821 } 822 823 /** 824 * Create the CommandSupport instance if required 825 */ 826 protected void createCommandSupport(){ 827 commandSupport = new ProtocolCommandSupport(this); 828 } 829 830 /** 831 * Subclasses can override this if they need to provide their own 832 * instance field for backwards compatibilty. 833 * 834 * @return the CommandSupport instance, may be {@code null} 835 * @since 3.0 836 */ 837 protected ProtocolCommandSupport getCommandSupport() { 838 return commandSupport; 839 } 840 841 /** 842 * Sets the proxy for use with all the connections. 843 * The proxy is used for connections established after the 844 * call to this method. 845 * 846 * @param proxy the new proxy for connections. 847 * @since 3.2 848 */ 849 public void setProxy(final Proxy proxy) { 850 setSocketFactory(new DefaultSocketFactory(proxy)); 851 connProxy = proxy; 852 } 853 854 /** 855 * Gets the proxy for use with all the connections. 856 * @return the current proxy for connections. 857 */ 858 public Proxy getProxy() { 859 return connProxy; 860 } 861 862 /** 863 * Gets the charset name. 864 * 865 * @return the charset. 866 * @since 3.3 867 * @deprecated Since the code now requires Java 1.6 as a mininmum 868 */ 869 @Deprecated 870 public String getCharsetName() { 871 return charset.name(); 872 } 873 874 /** 875 * Gets the charset. 876 * 877 * @return the charset. 878 * @since 3.3 879 */ 880 public Charset getCharset() { 881 return charset; 882 } 883 884 /** 885 * Sets the charset. 886 * 887 * @param charset the charset. 888 * @since 3.3 889 */ 890 public void setCharset(final Charset charset) { 891 this.charset = charset; 892 } 893 894 /* 895 * N.B. Fields cannot be pulled up into a super-class without breaking binary compatibility, 896 * so the abstract method is needed to pass the instance to the methods which were moved here. 897 */ 898} 899 900