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