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