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