You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/02/20 22:30:09 UTC
[commons-net] 02/02: Sort methods.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-net.git
commit 0376449916aeae1c67348534f0e48b06d85dfa7f
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Feb 20 17:30:01 2021 -0500
Sort methods.
---
.../apache/commons/net/DatagramSocketClient.java | 242 +--
.../apache/commons/net/DefaultSocketFactory.java | 146 +-
.../apache/commons/net/PrintCommandListener.java | 30 +-
.../apache/commons/net/ProtocolCommandEvent.java | 66 +-
.../apache/commons/net/ProtocolCommandSupport.java | 30 +-
.../java/org/apache/commons/net/SocketClient.java | 822 +++----
.../org/apache/commons/net/bsd/RCommandClient.java | 202 +-
.../org/apache/commons/net/bsd/RExecClient.java | 114 +-
.../org/apache/commons/net/bsd/RLoginClient.java | 28 +-
.../commons/net/chargen/CharGenUDPClient.java | 50 +-
.../commons/net/daytime/DaytimeUDPClient.java | 20 +-
.../commons/net/discard/DiscardUDPClient.java | 48 +-
.../org/apache/commons/net/echo/EchoUDPClient.java | 56 +-
.../java/org/apache/commons/net/examples/Main.java | 16 +-
.../commons/net/examples/ftp/FTPClientExample.java | 42 +-
.../commons/net/examples/ftp/TFTPExample.java | 116 +-
.../commons/net/examples/mail/IMAPExportMbox.java | 266 +--
.../commons/net/examples/mail/IMAPImportMbox.java | 66 +-
.../commons/net/examples/mail/POP3ExportMbox.java | 10 +-
.../apache/commons/net/examples/mail/POP3Mail.java | 34 +-
.../apache/commons/net/examples/mail/Utils.java | 8 +-
.../commons/net/examples/nntp/ExtendedNNTPOps.java | 28 +-
.../net/examples/nntp/MessageThreading.java | 6 +-
.../apache/commons/net/examples/ntp/NTPClient.java | 62 +-
.../commons/net/examples/ntp/SimpleNTPServer.java | 166 +-
.../commons/net/examples/ntp/TimeClient.java | 48 +-
.../apache/commons/net/examples/unix/rdate.java | 46 +-
.../apache/commons/net/finger/FingerClient.java | 96 +-
src/main/java/org/apache/commons/net/ftp/FTP.java | 1630 +++++++-------
.../apache/commons/net/ftp/FTPClientConfig.java | 414 ++--
.../org/apache/commons/net/ftp/FTPCommand.java | 20 +-
.../apache/commons/net/ftp/FTPFileEntryParser.java | 30 +-
.../commons/net/ftp/FTPFileEntryParserImpl.java | 32 +-
.../org/apache/commons/net/ftp/FTPHTTPClient.java | 50 +-
.../apache/commons/net/ftp/FTPListParseEngine.java | 182 +-
.../java/org/apache/commons/net/ftp/FTPReply.java | 68 +-
.../org/apache/commons/net/ftp/FTPSClient.java | 1008 ++++-----
.../apache/commons/net/ftp/FTPSSocketFactory.java | 60 +-
.../parser/ConfigurableFTPFileEntryParserImpl.java | 32 +-
.../parser/DefaultFTPFileEntryParserFactory.java | 80 +-
.../net/ftp/parser/FTPFileEntryParserFactory.java | 30 +-
.../net/ftp/parser/FTPTimestampParserImpl.java | 232 +-
.../commons/net/ftp/parser/MLSxEntryParser.java | 186 +-
.../commons/net/ftp/parser/MVSFTPEntryParser.java | 178 +-
.../net/ftp/parser/MacOsPeterFTPEntryParser.java | 28 +-
.../commons/net/ftp/parser/NTFTPEntryParser.java | 32 +-
.../net/ftp/parser/NetwareFTPEntryParser.java | 24 +-
.../commons/net/ftp/parser/OS2FTPEntryParser.java | 28 +-
.../net/ftp/parser/OS400FTPEntryParser.java | 56 +-
.../ftp/parser/RegexFTPFileEntryParserImpl.java | 78 +-
.../commons/net/ftp/parser/UnixFTPEntryParser.java | 38 +-
.../commons/net/ftp/parser/VMSFTPEntryParser.java | 68 +-
.../ftp/parser/VMSVersioningFTPEntryParser.java | 14 +-
.../commons/net/imap/AuthenticatingIMAPClient.java | 146 +-
.../java/org/apache/commons/net/imap/IMAP.java | 470 ++--
.../org/apache/commons/net/imap/IMAPClient.java | 740 +++----
.../org/apache/commons/net/imap/IMAPCommand.java | 30 +-
.../org/apache/commons/net/imap/IMAPReply.java | 114 +-
.../org/apache/commons/net/imap/IMAPSClient.java | 246 +--
.../apache/commons/net/io/CopyStreamAdapter.java | 22 +-
.../org/apache/commons/net/io/CopyStreamEvent.java | 22 +-
.../apache/commons/net/io/CopyStreamException.java | 18 +-
.../commons/net/io/DotTerminatedMessageReader.java | 64 +-
.../commons/net/io/DotTerminatedMessageWriter.java | 156 +-
.../commons/net/io/FromNetASCIIInputStream.java | 80 +-
.../commons/net/io/FromNetASCIIOutputStream.java | 98 +-
.../apache/commons/net/io/SocketOutputStream.java | 30 +-
.../commons/net/io/ToNetASCIIInputStream.java | 46 +-
.../commons/net/io/ToNetASCIIOutputStream.java | 66 +-
src/main/java/org/apache/commons/net/io/Util.java | 358 +--
.../java/org/apache/commons/net/nntp/Article.java | 316 +--
.../apache/commons/net/nntp/ArticleIterator.java | 10 +-
.../java/org/apache/commons/net/nntp/NNTP.java | 734 +++----
.../org/apache/commons/net/nntp/NNTPClient.java | 2288 ++++++++++----------
.../org/apache/commons/net/nntp/NNTPCommand.java | 10 +-
.../org/apache/commons/net/nntp/NNTPReply.java | 70 +-
.../commons/net/nntp/NewGroupsOrNewsQuery.java | 108 +-
.../org/apache/commons/net/nntp/NewsgroupInfo.java | 84 +-
.../apache/commons/net/nntp/NewsgroupIterator.java | 10 +-
.../org/apache/commons/net/nntp/ReplyIterator.java | 18 +-
.../apache/commons/net/nntp/SimpleNNTPHeader.java | 46 +-
.../org/apache/commons/net/nntp/Threadable.java | 6 +-
.../java/org/apache/commons/net/nntp/Threader.java | 252 +--
.../org/apache/commons/net/ntp/NTPUDPClient.java | 32 +-
.../java/org/apache/commons/net/ntp/NtpUtils.java | 60 +-
.../java/org/apache/commons/net/ntp/NtpV3Impl.java | 578 ++---
.../org/apache/commons/net/ntp/NtpV3Packet.java | 154 +-
.../java/org/apache/commons/net/ntp/TimeInfo.java | 104 +-
.../java/org/apache/commons/net/ntp/TimeStamp.java | 400 ++--
.../commons/net/pop3/ExtendedPOP3Client.java | 52 +-
.../java/org/apache/commons/net/pop3/POP3.java | 262 +--
.../org/apache/commons/net/pop3/POP3Client.java | 390 ++--
.../org/apache/commons/net/pop3/POP3Command.java | 8 +-
.../org/apache/commons/net/pop3/POP3SClient.java | 248 +--
.../commons/net/smtp/AuthenticatingSMTPClient.java | 256 +--
.../java/org/apache/commons/net/smtp/SMTP.java | 436 ++--
.../org/apache/commons/net/smtp/SMTPClient.java | 252 +--
.../org/apache/commons/net/smtp/SMTPCommand.java | 10 +-
.../org/apache/commons/net/smtp/SMTPReply.java | 72 +-
.../org/apache/commons/net/smtp/SMTPSClient.java | 250 +--
.../apache/commons/net/smtp/SimpleSMTPHeader.java | 34 +-
.../commons/net/telnet/EchoOptionHandler.java | 18 +-
.../commons/net/telnet/SimpleOptionHandler.java | 22 +-
.../net/telnet/SuppressGAOptionHandler.java | 18 +-
.../java/org/apache/commons/net/telnet/Telnet.java | 1008 ++++-----
.../apache/commons/net/telnet/TelnetClient.java | 332 +--
.../commons/net/telnet/TelnetInputStream.java | 482 ++---
.../commons/net/telnet/TelnetOptionHandler.java | 158 +-
.../commons/net/telnet/TelnetOutputStream.java | 100 +-
.../net/telnet/TerminalTypeOptionHandler.java | 34 +-
.../net/telnet/WindowSizeOptionHandler.java | 50 +-
.../java/org/apache/commons/net/tftp/TFTP.java | 132 +-
.../org/apache/commons/net/tftp/TFTPAckPacket.java | 76 +-
.../org/apache/commons/net/tftp/TFTPClient.java | 144 +-
.../apache/commons/net/tftp/TFTPDataPacket.java | 176 +-
.../apache/commons/net/tftp/TFTPErrorPacket.java | 112 +-
.../org/apache/commons/net/tftp/TFTPPacket.java | 96 +-
.../commons/net/tftp/TFTPReadRequestPacket.java | 30 +-
.../apache/commons/net/tftp/TFTPRequestPacket.java | 82 +-
.../commons/net/tftp/TFTPWriteRequestPacket.java | 30 +-
.../org/apache/commons/net/time/TimeTCPClient.java | 36 +-
.../org/apache/commons/net/time/TimeUDPClient.java | 76 +-
.../java/org/apache/commons/net/util/Base64.java | 1256 +++++------
.../apache/commons/net/util/KeyManagerUtils.java | 222 +-
.../org/apache/commons/net/util/ListenerList.java | 10 +-
.../apache/commons/net/util/SSLContextUtils.java | 8 +-
.../apache/commons/net/util/SSLSocketUtils.java | 8 +-
.../org/apache/commons/net/util/SubnetUtils.java | 446 ++--
.../apache/commons/net/util/TrustManagerUtils.java | 20 +-
.../org/apache/commons/net/whois/WhoisClient.java | 30 +-
.../commons/net/SocketClientFunctionalTest.java | 4 +-
.../org/apache/commons/net/SubnetUtilsTest.java | 166 +-
.../org/apache/commons/net/examples/MainTest.java | 98 +-
.../net/ftp/FTPClientConfigFunctionalTest.java | 54 +-
.../commons/net/ftp/FTPClientConfigTest.java | 144 +-
.../org/apache/commons/net/ftp/FTPClientTest.java | 184 +-
.../org/apache/commons/net/ftp/FTPSClientTest.java | 38 +-
.../ftp/parser/CompositeFTPParseTestFramework.java | 46 +-
.../DefaultFTPFileEntryParserFactoryTest.java | 16 +-
.../commons/net/ftp/parser/DownloadListings.java | 92 +-
.../parser/EnterpriseUnixFTPEntryParserTest.java | 141 +-
.../net/ftp/parser/FTPConfigEntryParserTest.java | 112 +-
.../net/ftp/parser/FTPParseTestFramework.java | 148 +-
.../net/ftp/parser/FTPTimestampParserImplTest.java | 542 ++---
.../commons/net/ftp/parser/MLSDComparison.java | 160 +-
.../net/ftp/parser/MLSxEntryParserTest.java | 8 +-
.../net/ftp/parser/MVSFTPEntryParserTest.java | 84 +-
.../ftp/parser/MacOsPeterFTPEntryParserTest.java | 64 +-
.../net/ftp/parser/NTFTPEntryParserTest.java | 346 +--
.../net/ftp/parser/NetwareFTPEntryParserTest.java | 12 +-
.../net/ftp/parser/OS2FTPEntryParserTest.java | 44 +-
.../parser/OS400FTPEntryParserAdditionalTest.java | 30 +-
.../net/ftp/parser/OS400FTPEntryParserTest.java | 80 +-
.../net/ftp/parser/UnixFTPEntryParserTest.java | 326 +--
.../net/ftp/parser/VMSFTPEntryParserTest.java | 208 +-
.../net/io/DotTerminatedMessageReaderTest.java | 96 +-
.../commons/net/io/ToNetASCIIInputStreamTest.java | 76 +-
.../org/apache/commons/net/nntp/TestThreader.java | 40 +-
.../org/apache/commons/net/ntp/TestNtpPacket.java | 62 +-
.../org/apache/commons/net/ntp/TestTimeInfo.java | 72 +-
.../org/apache/commons/net/ntp/TimeStampTest.java | 12 +-
.../commons/net/pop3/POP3ClientCommandsTest.java | 348 +--
.../apache/commons/net/pop3/POP3ClientTest.java | 50 +-
.../commons/net/pop3/POP3ConstructorTest.java | 20 +-
.../commons/net/smtp/SimpleSMTPHeaderTestCase.java | 106 +-
.../commons/net/telnet/EchoOptionHandlerTest.java | 36 +-
.../net/telnet/SimpleOptionHandlerTest.java | 36 +-
.../net/telnet/SuppressGAOptionHandlerTest.java | 36 +-
.../commons/net/telnet/TelnetClientTest.java | 716 +++---
.../telnet/TelnetOptionHandlerTestAbstract.java | 34 +-
.../commons/net/telnet/TelnetOptionTest.java | 20 +-
.../commons/net/telnet/TelnetTestSimpleServer.java | 74 +-
.../net/telnet/TerminalTypeOptionHandlerTest.java | 74 +-
.../net/telnet/WindowSizeOptionHandlerTest.java | 70 +-
.../org/apache/commons/net/tftp/TFTPServer.java | 1026 ++++-----
.../apache/commons/net/tftp/TFTPServerMain.java | 26 +-
.../java/org/apache/commons/net/tftp/TFTPTest.java | 156 +-
.../apache/commons/net/time/TimeTCPClientTest.java | 48 +-
.../commons/net/time/TimeTestSimpleServer.java | 56 +-
.../org/apache/commons/net/util/Base64Test.java | 82 +-
.../java/org/apache/commons/net/util/UtilTest.java | 172 +-
181 files changed, 14809 insertions(+), 14812 deletions(-)
diff --git a/src/main/java/org/apache/commons/net/DatagramSocketClient.java b/src/main/java/org/apache/commons/net/DatagramSocketClient.java
index d3abf93..2b081e5 100644
--- a/src/main/java/org/apache/commons/net/DatagramSocketClient.java
+++ b/src/main/java/org/apache/commons/net/DatagramSocketClient.java
@@ -89,68 +89,6 @@ public abstract class DatagramSocketClient
/**
- * Opens a DatagramSocket on the local host at the first available port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- * <p>
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @throws SocketException If the socket could not be opened or the
- * timeout could not be set.
- */
- public void open() throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket();
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
- /**
- * Opens a DatagramSocket on the local host at a specified port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- * <p>
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @param port The port to use for the socket.
- * @throws SocketException If the socket could not be opened or the
- * timeout could not be set.
- */
- public void open(final int port) throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket(port);
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
- /**
- * Opens a DatagramSocket at the specified address on the local host
- * at a specified port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- * <p>
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @param port The port to use for the socket.
- * @param laddr The local address to use.
- * @throws SocketException If the socket could not be opened or the
- * timeout could not be set.
- */
- public void open(final int port, final InetAddress laddr) throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
-
- /**
* Closes the DatagramSocket used for the connection.
* You should call this method after you've finished using the class
* instance and also before you call {@link #open open() }
@@ -167,33 +105,30 @@ public abstract class DatagramSocketClient
/**
- * Returns true if the client has a currently open socket.
+ * Gets the charset.
*
- * @return True if the client has a currently open socket, false otherwise.
+ * @return the charset.
+ * @since 3.3
*/
- public boolean isOpen()
- {
- return _isOpen_;
+ public Charset getCharset() {
+ return charset;
}
/**
- * Set the default timeout in milliseconds to use when opening a socket.
- * After a call to open, the timeout for the socket is set using this value.
- * This method should be used prior to a call to {@link #open open()}
- * and should not be confused with {@link #setSoTimeout setSoTimeout()}
- * which operates on the currently open socket. _timeout_ contains
- * the new timeout value.
+ * Gets the charset name.
*
- * @param timeout The timeout in milliseconds to use for the datagram socket
- * connection.
+ * @return the charset name.
+ * @since 3.3
+ * @deprecated Use {@link #getCharset()} instead
*/
- public void setDefaultTimeout(final int timeout)
- {
- _timeout_ = timeout;
+ @Deprecated
+ public String getCharsetName() {
+ return charset.name();
}
+
/**
* Returns the default timeout in milliseconds that is used when
* opening a socket.
@@ -208,17 +143,29 @@ public abstract class DatagramSocketClient
/**
- * Set the timeout in milliseconds of a currently open connection.
- * Only call this method after a connection has been opened
- * by {@link #open open()}.
+ * Returns the local address to which the client's socket is bound.
+ * If you call this method when the client socket is not open, a
+ * NullPointerException is thrown.
*
- * @param timeout The timeout in milliseconds to use for the currently
- * open datagram socket connection.
- * @throws SocketException if an error setting the timeout
+ * @return The local address to which the client's socket is bound.
*/
- public void setSoTimeout(final int timeout) throws SocketException
+ public InetAddress getLocalAddress()
{
- _socket_.setSoTimeout(timeout);
+ return _socket_.getLocalAddress();
+ }
+
+
+ /**
+ * Returns the port number of the open socket on the local host used
+ * for the connection. If you call this method when the client socket
+ * is not open, a NullPointerException is thrown.
+ *
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ */
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
}
@@ -237,33 +184,88 @@ public abstract class DatagramSocketClient
/**
- * Returns the port number of the open socket on the local host used
- * for the connection. If you call this method when the client socket
- * is not open, a NullPointerException is thrown.
+ * Returns true if the client has a currently open socket.
*
- * @return The port number of the open socket on the local host used
- * for the connection.
+ * @return True if the client has a currently open socket, false otherwise.
*/
- public int getLocalPort()
+ public boolean isOpen()
{
- return _socket_.getLocalPort();
+ return _isOpen_;
}
/**
- * Returns the local address to which the client's socket is bound.
- * If you call this method when the client socket is not open, a
- * NullPointerException is thrown.
+ * Opens a DatagramSocket on the local host at the first available port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ * <p>
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
*
- * @return The local address to which the client's socket is bound.
+ * @throws SocketException If the socket could not be opened or the
+ * timeout could not be set.
*/
- public InetAddress getLocalAddress()
+ public void open() throws SocketException
{
- return _socket_.getLocalAddress();
+ _socket_ = _socketFactory_.createDatagramSocket();
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
}
/**
+ * Opens a DatagramSocket on the local host at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ * <p>
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @throws SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ */
+ public void open(final int port) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /**
+ * Opens a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ * <p>
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @throws SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ */
+ public void open(final int port, final InetAddress laddr) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /**
+ * Sets the charset.
+ *
+ * @param charset the charset.
+ * @since 3.3
+ */
+ public void setCharset(final Charset charset) {
+ this.charset = charset;
+ }
+
+ /**
* Sets the DatagramSocketFactory used by the DatagramSocketClient
* to open DatagramSockets. If the factory value is null, then a default
* factory is used (only do this to reset the factory after having
@@ -282,34 +284,32 @@ public abstract class DatagramSocketClient
}
/**
- * Gets the charset name.
- *
- * @return the charset name.
- * @since 3.3
- * @deprecated Use {@link #getCharset()} instead
- */
- @Deprecated
- public String getCharsetName() {
- return charset.name();
- }
-
- /**
- * Gets the charset.
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * After a call to open, the timeout for the socket is set using this value.
+ * This method should be used prior to a call to {@link #open open()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on the currently open socket. _timeout_ contains
+ * the new timeout value.
*
- * @return the charset.
- * @since 3.3
+ * @param timeout The timeout in milliseconds to use for the datagram socket
+ * connection.
*/
- public Charset getCharset() {
- return charset;
+ public void setDefaultTimeout(final int timeout)
+ {
+ _timeout_ = timeout;
}
/**
- * Sets the charset.
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #open open()}.
*
- * @param charset the charset.
- * @since 3.3
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open datagram socket connection.
+ * @throws SocketException if an error setting the timeout
*/
- public void setCharset(final Charset charset) {
- this.charset = charset;
+ public void setSoTimeout(final int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
}
}
diff --git a/src/main/java/org/apache/commons/net/DefaultSocketFactory.java b/src/main/java/org/apache/commons/net/DefaultSocketFactory.java
index 7eda470..8214165 100644
--- a/src/main/java/org/apache/commons/net/DefaultSocketFactory.java
+++ b/src/main/java/org/apache/commons/net/DefaultSocketFactory.java
@@ -65,6 +65,57 @@ public class DefaultSocketFactory extends SocketFactory
}
/**
+ * Creates a ServerSocket bound to a specified port. A port
+ * of 0 will create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @return A ServerSocket that will listen on a specified port.
+ * @throws IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ */
+ public ServerSocket createServerSocket(final int port) throws IOException
+ {
+ return new ServerSocket(port);
+ }
+
+ /**
+ * Creates a ServerSocket bound to a specified port with a given
+ * maximum queue length for incoming connections. A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @return A ServerSocket that will listen on a specified port.
+ * @throws IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ */
+ public ServerSocket createServerSocket(final int port, final int backlog)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog);
+ }
+
+ /**
+ * Creates a ServerSocket bound to a specified port on a given local
+ * address with a given maximum queue length for incoming connections.
+ * A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @param bindAddr The local address to which the ServerSocket should bind.
+ * @return A ServerSocket that will listen on a specified port.
+ * @throws IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ */
+ public ServerSocket createServerSocket(final int port, final int backlog,
+ final InetAddress bindAddr)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog, bindAddr);
+ }
+
+ /**
* Creates an unconnected Socket.
*
* @return A new unconnected Socket.
@@ -84,147 +135,96 @@ public class DefaultSocketFactory extends SocketFactory
/**
* Creates a Socket connected to the given host and port.
*
- * @param host The hostname to connect to.
+ * @param address The address of the host to connect to.
* @param port The port to connect to.
* @return A Socket connected to the given host and port.
- * @throws UnknownHostException If the hostname cannot be resolved.
* @throws IOException If an I/O error occurs while creating the Socket.
*/
@Override
- public Socket createSocket(final String host, final int port)
- throws UnknownHostException, IOException
+ public Socket createSocket(final InetAddress address, final int port)
+ throws IOException
{
if (connProxy != null)
{
final Socket s = new Socket(connProxy);
- s.connect(new InetSocketAddress(host, port));
+ s.connect(new InetSocketAddress(address, port));
return s;
}
- return new Socket(host, port);
+ return new Socket(address, port);
}
/**
- * Creates a Socket connected to the given host and port.
+ * Creates a Socket connected to the given host and port and
+ * originating from the specified local address and port.
*
* @param address The address of the host to connect to.
* @param port The port to connect to.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
* @return A Socket connected to the given host and port.
* @throws IOException If an I/O error occurs while creating the Socket.
*/
@Override
- public Socket createSocket(final InetAddress address, final int port)
+ public Socket createSocket(final InetAddress address, final int port,
+ final InetAddress localAddr, final int localPort)
throws IOException
{
if (connProxy != null)
{
final Socket s = new Socket(connProxy);
+ s.bind(new InetSocketAddress(localAddr, localPort));
s.connect(new InetSocketAddress(address, port));
return s;
}
- return new Socket(address, port);
+ return new Socket(address, port, localAddr, localPort);
}
/**
- * Creates a Socket connected to the given host and port and
- * originating from the specified local address and port.
+ * Creates a Socket connected to the given host and port.
*
* @param host The hostname to connect to.
* @param port The port to connect to.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
* @return A Socket connected to the given host and port.
* @throws UnknownHostException If the hostname cannot be resolved.
* @throws IOException If an I/O error occurs while creating the Socket.
*/
@Override
- public Socket createSocket(final String host, final int port,
- final InetAddress localAddr, final int localPort)
+ public Socket createSocket(final String host, final int port)
throws UnknownHostException, IOException
{
if (connProxy != null)
{
final Socket s = new Socket(connProxy);
- s.bind(new InetSocketAddress(localAddr, localPort));
s.connect(new InetSocketAddress(host, port));
return s;
}
- return new Socket(host, port, localAddr, localPort);
+ return new Socket(host, port);
}
/**
* Creates a Socket connected to the given host and port and
* originating from the specified local address and port.
*
- * @param address The address of the host to connect to.
+ * @param host The hostname to connect to.
* @param port The port to connect to.
* @param localAddr The local address to use.
* @param localPort The local port to use.
* @return A Socket connected to the given host and port.
+ * @throws UnknownHostException If the hostname cannot be resolved.
* @throws IOException If an I/O error occurs while creating the Socket.
*/
@Override
- public Socket createSocket(final InetAddress address, final int port,
+ public Socket createSocket(final String host, final int port,
final InetAddress localAddr, final int localPort)
- throws IOException
+ throws UnknownHostException, IOException
{
if (connProxy != null)
{
final Socket s = new Socket(connProxy);
s.bind(new InetSocketAddress(localAddr, localPort));
- s.connect(new InetSocketAddress(address, port));
+ s.connect(new InetSocketAddress(host, port));
return s;
}
- return new Socket(address, port, localAddr, localPort);
- }
-
- /**
- * Creates a ServerSocket bound to a specified port. A port
- * of 0 will create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @return A ServerSocket that will listen on a specified port.
- * @throws IOException If an I/O error occurs while creating
- * the ServerSocket.
- */
- public ServerSocket createServerSocket(final int port) throws IOException
- {
- return new ServerSocket(port);
- }
-
- /**
- * Creates a ServerSocket bound to a specified port with a given
- * maximum queue length for incoming connections. A port of 0 will
- * create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @param backlog The maximum length of the queue for incoming connections.
- * @return A ServerSocket that will listen on a specified port.
- * @throws IOException If an I/O error occurs while creating
- * the ServerSocket.
- */
- public ServerSocket createServerSocket(final int port, final int backlog)
- throws IOException
- {
- return new ServerSocket(port, backlog);
- }
-
- /**
- * Creates a ServerSocket bound to a specified port on a given local
- * address with a given maximum queue length for incoming connections.
- * A port of 0 will
- * create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @param backlog The maximum length of the queue for incoming connections.
- * @param bindAddr The local address to which the ServerSocket should bind.
- * @return A ServerSocket that will listen on a specified port.
- * @throws IOException If an I/O error occurs while creating
- * the ServerSocket.
- */
- public ServerSocket createServerSocket(final int port, final int backlog,
- final InetAddress bindAddr)
- throws IOException
- {
- return new ServerSocket(port, backlog, bindAddr);
+ return new Socket(host, port, localAddr, localPort);
}
}
diff --git a/src/main/java/org/apache/commons/net/PrintCommandListener.java b/src/main/java/org/apache/commons/net/PrintCommandListener.java
index 3b6e087..c3f4d76 100644
--- a/src/main/java/org/apache/commons/net/PrintCommandListener.java
+++ b/src/main/java/org/apache/commons/net/PrintCommandListener.java
@@ -147,6 +147,21 @@ public class PrintCommandListener implements ProtocolCommandListener
this.directionMarker = showDirection;
}
+ private String getPrintableString(final String msg){
+ if (eolMarker == 0) {
+ return msg;
+ }
+ final int pos = msg.indexOf(SocketClient.NETASCII_EOL);
+ if (pos > 0) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(msg.substring(0,pos));
+ sb.append(eolMarker);
+ sb.append(msg.substring(pos));
+ return sb.toString();
+ }
+ return msg;
+ }
+
@Override
public void protocolCommandSent(final ProtocolCommandEvent event)
{
@@ -175,21 +190,6 @@ public class PrintCommandListener implements ProtocolCommandListener
writer.flush();
}
- private String getPrintableString(final String msg){
- if (eolMarker == 0) {
- return msg;
- }
- final int pos = msg.indexOf(SocketClient.NETASCII_EOL);
- if (pos > 0) {
- final StringBuilder sb = new StringBuilder();
- sb.append(msg.substring(0,pos));
- sb.append(eolMarker);
- sb.append(msg.substring(pos));
- return sb.toString();
- }
- return msg;
- }
-
@Override
public void protocolReplyReceived(final ProtocolCommandEvent event)
{
diff --git a/src/main/java/org/apache/commons/net/ProtocolCommandEvent.java b/src/main/java/org/apache/commons/net/ProtocolCommandEvent.java
index 921fbde..5cb7491 100644
--- a/src/main/java/org/apache/commons/net/ProtocolCommandEvent.java
+++ b/src/main/java/org/apache/commons/net/ProtocolCommandEvent.java
@@ -41,28 +41,6 @@ public class ProtocolCommandEvent extends EventObject
private final String message, command;
/**
- * Creates a ProtocolCommandEvent signalling a command was sent to
- * the server. ProtocolCommandEvents created with this constructor
- * should only be sent after a command has been sent, but before the
- * reply has been received.
- *
- * @param source The source of the event.
- * @param command The string representation of the command type sent, not
- * including the arguments (e.g., "STAT" or "GET").
- * @param message The entire command string verbatim as sent to the server,
- * including all arguments.
- */
- public ProtocolCommandEvent(final Object source, final String command, final String message)
- {
- super(source);
- this.replyCode = 0;
- this.message = message;
- this.isCommand = true;
- this.command = command;
- }
-
-
- /**
* Creates a ProtocolCommandEvent signalling a reply to a command was
* received. ProtocolCommandEvents created with this constructor
* should only be sent after a complete command reply has been received
@@ -85,6 +63,28 @@ public class ProtocolCommandEvent extends EventObject
this.command = null;
}
+
+ /**
+ * Creates a ProtocolCommandEvent signalling a command was sent to
+ * the server. ProtocolCommandEvents created with this constructor
+ * should only be sent after a command has been sent, but before the
+ * reply has been received.
+ *
+ * @param source The source of the event.
+ * @param command The string representation of the command type sent, not
+ * including the arguments (e.g., "STAT" or "GET").
+ * @param message The entire command string verbatim as sent to the server,
+ * including all arguments.
+ */
+ public ProtocolCommandEvent(final Object source, final String command, final String message)
+ {
+ super(source);
+ this.replyCode = 0;
+ this.message = message;
+ this.isCommand = true;
+ this.command = command;
+ }
+
/**
* Returns the string representation of the command type sent (e.g., "STAT"
* or "GET"). If the ProtocolCommandEvent is a reply event, then null
@@ -100,6 +100,17 @@ public class ProtocolCommandEvent extends EventObject
/**
+ * Returns the entire message sent to or received from the server.
+ * Includes the line terminator.
+ *
+ * @return The entire message sent to or received from the server.
+ */
+ public String getMessage()
+ {
+ return message;
+ }
+
+ /**
* Returns the reply code of the received server reply. Undefined if
* this is not a reply event.
*
@@ -134,15 +145,4 @@ public class ProtocolCommandEvent extends EventObject
{
return !isCommand();
}
-
- /**
- * Returns the entire message sent to or received from the server.
- * Includes the line terminator.
- *
- * @return The entire message sent to or received from the server.
- */
- public String getMessage()
- {
- return message;
- }
}
diff --git a/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java b/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
index c55a9d3..c2e409d 100644
--- a/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
+++ b/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
@@ -54,6 +54,16 @@ public class ProtocolCommandSupport implements Serializable
/**
+ * Adds a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to add.
+ */
+ public void addProtocolCommandListener(final ProtocolCommandListener listener)
+ {
+ listeners.addListener(listener);
+ }
+
+ /**
* Fires a ProtocolCommandEvent signalling the sending of a command to all
* registered listeners, invoking their
* {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() }
@@ -101,15 +111,16 @@ public class ProtocolCommandSupport implements Serializable
}
/**
- * Adds a ProtocolCommandListener.
+ * Returns the number of ProtocolCommandListeners currently registered.
*
- * @param listener The ProtocolCommandListener to add.
+ * @return The number of ProtocolCommandListeners currently registered.
*/
- public void addProtocolCommandListener(final ProtocolCommandListener listener)
+ public int getListenerCount()
{
- listeners.addListener(listener);
+ return listeners.getListenerCount();
}
+
/**
* Removes a ProtocolCommandListener.
*
@@ -120,16 +131,5 @@ public class ProtocolCommandSupport implements Serializable
listeners.removeListener(listener);
}
-
- /**
- * Returns the number of ProtocolCommandListeners currently registered.
- *
- * @return The number of ProtocolCommandListeners currently registered.
- */
- public int getListenerCount()
- {
- return listeners.getListenerCount();
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/SocketClient.java b/src/main/java/org/apache/commons/net/SocketClient.java
index 33068db..eddf9ab 100644
--- a/src/main/java/org/apache/commons/net/SocketClient.java
+++ b/src/main/java/org/apache/commons/net/SocketClient.java
@@ -68,6 +68,9 @@ public abstract class SocketClient
private static final ServerSocketFactory DEFAULT_SERVER_SOCKET_FACTORY =
ServerSocketFactory.getDefault();
+ /** The socket's connect timeout (0 = infinite timeout) */
+ private static final int DEFAULT_CONNECT_TIMEOUT = 60000;
+
/**
* A ProtocolCommandSupport object used to manage the registering of
* ProtocolCommandListeners and the firing of ProtocolCommandEvents.
@@ -98,9 +101,6 @@ public abstract class SocketClient
/** The socket's ServerSocket Factory. */
protected ServerSocketFactory _serverSocketFactory_;
- /** The socket's connect timeout (0 = infinite timeout) */
- private static final int DEFAULT_CONNECT_TIMEOUT = 60000;
-
protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
/** Hint for SO_RCVBUF size */
@@ -137,6 +137,24 @@ public abstract class SocketClient
}
+ // helper method to allow code to be shared with connect(String,...) methods
+ private void _connect(final InetAddress host, final int port, final InetAddress localAddr, final int localPort)
+ throws SocketException, IOException
+ {
+ _socket_ = _socketFactory_.createSocket();
+ if (receiveBufferSize != -1) {
+ _socket_.setReceiveBufferSize(receiveBufferSize);
+ }
+ if (sendBufferSize != -1) {
+ _socket_.setSendBufferSize(sendBufferSize);
+ }
+ if (localAddr != null) {
+ _socket_.bind(new InetSocketAddress(localAddr, localPort));
+ }
+ _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
+ _connectAction_();
+ }
+
/**
* Because there are so many connect() methods, the _connectAction_()
* method is provided as a means of performing some action immediately
@@ -162,6 +180,16 @@ public abstract class SocketClient
}
/**
+ * Adds a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to add.
+ * @since 3.0
+ */
+ public void addProtocolCommandListener(final ProtocolCommandListener listener) {
+ getCommandSupport().addProtocolCommandListener(listener);
+ }
+
+ /**
* Applies socket attributes.
*
* @throws SocketException if there is an error in the underlying protocol, such as a TCP error.
@@ -171,45 +199,64 @@ public abstract class SocketClient
_socket_.setSoTimeout(_timeout_);
}
+
+ private void closeQuietly(final Closeable close){
+ if (close != null){
+ try {
+ close.close();
+ } catch (final IOException e) {
+ // Ignored
+ }
+ }
+ }
+
+ private void closeQuietly(final Socket socket) {
+ if (socket != null){
+ try {
+ socket.close();
+ } catch (final IOException e) {
+ // Ignored
+ }
+ }
+ }
+
/**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a system assigned port.
+ * Opens a Socket connected to a remote host at the current default port
+ * and originating from the current host at a system assigned port.
* Before returning, {@link #_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
* <p>
* @param host The remote host.
- * @param port The port to connect to on the remote host.
* @throws SocketException If the socket timeout could not be set.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
*/
- public void connect(final InetAddress host, final int port)
- throws SocketException, IOException
+ public void connect(final InetAddress host) throws SocketException, IOException
{
_hostname_ = null;
- _connect(host, port, null, -1);
+ connect(host, _defaultPort_);
}
+
/**
* Opens a Socket connected to a remote host at the specified port and
* originating from the current host at a system assigned port.
* Before returning, {@link #_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
* <p>
- * @param hostname The name of the remote host.
+ * @param host The remote host.
* @param port The port to connect to on the remote host.
* @throws SocketException If the socket timeout could not be set.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
- * @throws java.net.UnknownHostException If the hostname cannot be resolved.
*/
- public void connect(final String hostname, final int port)
+ public void connect(final InetAddress host, final int port)
throws SocketException, IOException
{
- _hostname_ = hostname;
- _connect(InetAddress.getByName(hostname), port, null, -1);
+ _hostname_ = null;
+ _connect(host, port, null, -1);
}
@@ -236,86 +283,75 @@ public abstract class SocketClient
_connect(host, port, localAddr, localPort);
}
- // helper method to allow code to be shared with connect(String,...) methods
- private void _connect(final InetAddress host, final int port, final InetAddress localAddr, final int localPort)
- throws SocketException, IOException
- {
- _socket_ = _socketFactory_.createSocket();
- if (receiveBufferSize != -1) {
- _socket_.setReceiveBufferSize(receiveBufferSize);
- }
- if (sendBufferSize != -1) {
- _socket_.setSendBufferSize(sendBufferSize);
- }
- if (localAddr != null) {
- _socket_.bind(new InetSocketAddress(localAddr, localPort));
- }
- _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
- _connectAction_();
- }
/**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port.
+ * Opens a Socket connected to a remote host at the current default
+ * port and originating from the current host at a system assigned port.
* Before returning, {@link #_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
* <p>
* @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
* @throws SocketException If the socket timeout could not be set.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
* @throws java.net.UnknownHostException If the hostname cannot be resolved.
*/
- public void connect(final String hostname, final int port,
- final InetAddress localAddr, final int localPort)
- throws SocketException, IOException
+ public void connect(final String hostname) throws SocketException, IOException
{
- _hostname_ = hostname;
- _connect(InetAddress.getByName(hostname), port, localAddr, localPort);
+ connect(hostname, _defaultPort_);
}
-
/**
- * Opens a Socket connected to a remote host at the current default port
- * and originating from the current host at a system assigned port.
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a system assigned port.
* Before returning, {@link #_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
* <p>
- * @param host The remote host.
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
* @throws SocketException If the socket timeout could not be set.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
+ * @throws java.net.UnknownHostException If the hostname cannot be resolved.
*/
- public void connect(final InetAddress host) throws SocketException, IOException
+ public void connect(final String hostname, final int port)
+ throws SocketException, IOException
{
- _hostname_ = null;
- connect(host, _defaultPort_);
+ _hostname_ = hostname;
+ _connect(InetAddress.getByName(hostname), port, null, -1);
}
-
/**
- * Opens a Socket connected to a remote host at the current default
- * port and originating from the current host at a system assigned port.
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port.
* Before returning, {@link #_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
* <p>
* @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
* @throws SocketException If the socket timeout could not be set.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
* @throws java.net.UnknownHostException If the hostname cannot be resolved.
*/
- public void connect(final String hostname) throws SocketException, IOException
+ public void connect(final String hostname, final int port,
+ final InetAddress localAddr, final int localPort)
+ throws SocketException, IOException
{
- connect(hostname, _defaultPort_);
+ _hostname_ = hostname;
+ _connect(InetAddress.getByName(hostname), port, localAddr, localPort);
+ }
+ /**
+ * Create the CommandSupport instance if required
+ */
+ protected void createCommandSupport(){
+ commandSupport = new ProtocolCommandSupport(this);
}
-
/**
* Disconnects the socket connection.
@@ -338,132 +374,89 @@ public abstract class SocketClient
_output_ = null;
}
- private void closeQuietly(final Socket socket) {
- if (socket != null){
- try {
- socket.close();
- } catch (final IOException e) {
- // Ignored
- }
- }
- }
-
- private void closeQuietly(final Closeable close){
- if (close != null){
- try {
- close.close();
- } catch (final IOException e) {
- // Ignored
- }
- }
- }
/**
- * Returns true if the client is currently connected to a server.
- * <p>
- * Delegates to {@link Socket#isConnected()}
- * @return True if the client is currently connected to a server,
- * false otherwise.
+ * If there are any listeners, send them the command details.
+ *
+ * @param command the command name
+ * @param message the complete message, including command name
+ * @since 3.0
*/
- public boolean isConnected()
- {
- if (_socket_ == null) {
- return false;
+ protected void fireCommandSent(final String command, final String message) {
+ if (getCommandSupport().getListenerCount() > 0) {
+ getCommandSupport().fireCommandSent(command, message);
}
-
- return _socket_.isConnected();
}
/**
- * Make various checks on the socket to test if it is available for use.
- * Note that the only sure test is to use it, but these checks may help
- * in some cases.
- * @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a>
- * @return {@code true} if the socket appears to be available for use
+ * If there are any listeners, send them the reply details.
+ *
+ * @param replyCode the code extracted from the reply
+ * @param reply the full reply text
* @since 3.0
*/
- @SuppressWarnings("resource")
- public boolean isAvailable(){
- if (isConnected()) {
- try
- {
- if (_socket_.getInetAddress() == null) {
- return false;
- }
- if (_socket_.getPort() == 0) {
- return false;
- }
- if (_socket_.getRemoteSocketAddress() == null) {
- return false;
- }
- if (_socket_.isClosed()) {
- return false;
- }
- /* these aren't exact checks (a Socket can be half-open),
- but since we usually require two-way data transfer,
- we check these here too: */
- if (_socket_.isInputShutdown()) {
- return false;
- }
- if (_socket_.isOutputShutdown()) {
- return false;
- }
- /* ignore the result, catch exceptions: */
- // No need to close
- _socket_.getInputStream();
- // No need to close
- _socket_.getOutputStream();
- }
- catch (final IOException ioex)
- {
- return false;
- }
- return true;
+ protected void fireReplyReceived(final int replyCode, final String reply) {
+ if (getCommandSupport().getListenerCount() > 0) {
+ getCommandSupport().fireReplyReceived(replyCode, reply);
}
- return false;
}
+
/**
- * Sets the default port the SocketClient should connect to when a port
- * is not specified. The {@link #_defaultPort_ _defaultPort_ }
- * variable stores this value. If never set, the default port is equal
- * to zero.
- * <p>
- * @param port The default port to set.
+ * Gets the charset.
+ *
+ * @return the charset.
+ * @since 3.3
*/
- public void setDefaultPort(final int port)
- {
- _defaultPort_ = port;
+ public Charset getCharset() {
+ return charset;
}
+
/**
- * Returns the current value of the default port (stored in
- * {@link #_defaultPort_ _defaultPort_ }).
- * <p>
- * @return The current value of the default port.
- */
- public int getDefaultPort()
- {
- return _defaultPort_;
+ * Gets the charset name.
+ *
+ * @return the charset.
+ * @since 3.3
+ * @deprecated Since the code now requires Java 1.6 as a mininmum
+ */
+ @Deprecated
+ public String getCharsetName() {
+ return charset.name();
}
/**
- * Set the default timeout in milliseconds to use when opening a socket.
- * This value is only used previous to a call to
- * {@link #connect connect()}
- * and should not be confused with {@link #setSoTimeout setSoTimeout()}
- * which operates on an the currently opened socket. _timeout_ contains
- * the new timeout value.
+ * Subclasses can override this if they need to provide their own
+ * instance field for backwards compatibilty.
+ *
+ * @return the CommandSupport instance, may be {@code null}
+ * @since 3.0
+ */
+ protected ProtocolCommandSupport getCommandSupport() {
+ return commandSupport;
+ }
+
+
+ /**
+ * Get the underlying socket connection timeout.
+ * @return timeout (in ms)
+ * @since 2.0
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ /**
+ * Returns the current value of the default port (stored in
+ * {@link #_defaultPort_ _defaultPort_ }).
* <p>
- * @param timeout The timeout in milliseconds to use for the socket
- * connection.
+ * @return The current value of the default port.
*/
- public void setDefaultTimeout(final int timeout)
+ public int getDefaultPort()
{
- _timeout_ = timeout;
+ return _defaultPort_;
}
-
/**
* Returns the default timeout in milliseconds that is used when
* opening a socket.
@@ -476,54 +469,51 @@ public abstract class SocketClient
return _timeout_;
}
-
/**
- * Set the timeout in milliseconds of a currently open connection.
- * Only call this method after a connection has been opened
- * by {@link #connect connect()}.
- * <p>
- * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead.
- *
- * @param timeout The timeout in milliseconds to use for the currently
- * open socket connection.
- * @throws SocketException If the operation fails.
+ * Returns the current value of the SO_KEEPALIVE flag on the currently opened socket.
+ * Delegates to {@link Socket#getKeepAlive()}
+ * @return True if SO_KEEPALIVE is enabled.
+ * @throws SocketException if there is a problem with the socket
* @throws NullPointerException if the socket is not currently open
+ * @since 2.2
*/
- public void setSoTimeout(final int timeout) throws SocketException
- {
- _socket_.setSoTimeout(timeout);
+ public boolean getKeepAlive() throws SocketException {
+ return _socket_.getKeepAlive();
}
-
/**
- * Set the underlying socket send buffer size.
+ * Returns the local address to which the client's socket is bound.
+ * Delegates to {@link Socket#getLocalAddress()}
* <p>
- * @param size The size of the buffer in bytes.
- * @throws SocketException never thrown, but subclasses might want to do so
- * @since 2.0
+ * @return The local address to which the client's socket is bound.
+ * @throws NullPointerException if the socket is not currently open
*/
- public void setSendBufferSize(final int size) throws SocketException {
- sendBufferSize = size;
+ public InetAddress getLocalAddress()
+ {
+ return _socket_.getLocalAddress();
}
/**
- * Get the current sendBuffer size
- * @return the size, or -1 if not initialized
- * @since 3.0
+ * Returns the port number of the open socket on the local host used
+ * for the connection.
+ * Delegates to {@link Socket#getLocalPort()}
+ * <p>
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ * @throws NullPointerException if the socket is not currently open
*/
- protected int getSendBufferSize(){
- return sendBufferSize;
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
}
+
/**
- * Sets the underlying socket receive buffer size.
- * <p>
- * @param size The size of the buffer in bytes.
- * @throws SocketException never (but subclasses may wish to do so)
- * @since 2.0
+ * Gets the proxy for use with all the connections.
+ * @return the current proxy for connections.
*/
- public void setReceiveBufferSize(final int size) throws SocketException {
- receiveBufferSize = size;
+ public Proxy getProxy() {
+ return connProxy;
}
/**
@@ -536,84 +526,47 @@ public abstract class SocketClient
}
/**
- * Returns the timeout in milliseconds of the currently opened socket.
- * <p>
- * @return The timeout in milliseconds of the currently opened socket.
- * @throws SocketException If the operation fails.
+ * @return The remote address to which the client is connected.
+ * Delegates to {@link Socket#getInetAddress()}
* @throws NullPointerException if the socket is not currently open
*/
- public int getSoTimeout() throws SocketException
+ public InetAddress getRemoteAddress()
{
- return _socket_.getSoTimeout();
+ return _socket_.getInetAddress();
}
/**
- * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
- * currently opened socket.
+ * Returns the port number of the remote host to which the client is
+ * connected.
+ * Delegates to {@link Socket#getPort()}
* <p>
- * @param on True if Nagle's algorithm is to be enabled, false if not.
- * @throws SocketException If the operation fails.
+ * @return The port number of the remote host to which the client is
+ * connected.
* @throws NullPointerException if the socket is not currently open
*/
- public void setTcpNoDelay(final boolean on) throws SocketException
+ public int getRemotePort()
{
- _socket_.setTcpNoDelay(on);
+ return _socket_.getPort();
}
/**
- * Returns true if Nagle's algorithm is enabled on the currently opened
- * socket.
- * <p>
- * @return True if Nagle's algorithm is enabled on the currently opened
- * socket, false otherwise.
- * @throws SocketException If the operation fails.
- * @throws NullPointerException if the socket is not currently open
+ * Get the current sendBuffer size
+ * @return the size, or -1 if not initialized
+ * @since 3.0
*/
- public boolean getTcpNoDelay() throws SocketException
- {
- return _socket_.getTcpNoDelay();
+ protected int getSendBufferSize(){
+ return sendBufferSize;
}
- /**
- * Sets the SO_KEEPALIVE flag on the currently opened socket.
- *
- * From the Javadocs, the default keepalive time is 2 hours (although this is
- * implementation dependent). It looks as though the Windows WSA sockets implementation
- * allows a specific keepalive value to be set, although this seems not to be the case on
- * other systems.
- * @param keepAlive If true, keepAlive is turned on
- * @throws SocketException if there is a problem with the socket
- * @throws NullPointerException if the socket is not currently open
- * @since 2.2
- */
- public void setKeepAlive(final boolean keepAlive) throws SocketException {
- _socket_.setKeepAlive(keepAlive);
- }
/**
- * Returns the current value of the SO_KEEPALIVE flag on the currently opened socket.
- * Delegates to {@link Socket#getKeepAlive()}
- * @return True if SO_KEEPALIVE is enabled.
- * @throws SocketException if there is a problem with the socket
- * @throws NullPointerException if the socket is not currently open
+ * Get the underlying {@link ServerSocketFactory}
+ * @return The server socket factory
* @since 2.2
*/
- public boolean getKeepAlive() throws SocketException {
- return _socket_.getKeepAlive();
- }
-
- /**
- * Sets the SO_LINGER timeout on the currently opened socket.
- * <p>
- * @param on True if linger is to be enabled, false if not.
- * @param val The linger timeout (in hundredths of a second?)
- * @throws SocketException If the operation fails.
- * @throws NullPointerException if the socket is not currently open
- */
- public void setSoLinger(final boolean on, final int val) throws SocketException
- {
- _socket_.setSoLinger(on, val);
+ public ServerSocketFactory getServerSocketFactory() {
+ return _serverSocketFactory_;
}
@@ -630,119 +583,118 @@ public abstract class SocketClient
return _socket_.getSoLinger();
}
-
/**
- * Returns the port number of the open socket on the local host used
- * for the connection.
- * Delegates to {@link Socket#getLocalPort()}
+ * Returns the timeout in milliseconds of the currently opened socket.
* <p>
- * @return The port number of the open socket on the local host used
- * for the connection.
+ * @return The timeout in milliseconds of the currently opened socket.
+ * @throws SocketException If the operation fails.
* @throws NullPointerException if the socket is not currently open
*/
- public int getLocalPort()
+ public int getSoTimeout() throws SocketException
{
- return _socket_.getLocalPort();
+ return _socket_.getSoTimeout();
}
/**
- * Returns the local address to which the client's socket is bound.
- * Delegates to {@link Socket#getLocalAddress()}
- * <p>
- * @return The local address to which the client's socket is bound.
- * @throws NullPointerException if the socket is not currently open
- */
- public InetAddress getLocalAddress()
- {
- return _socket_.getLocalAddress();
- }
-
- /**
- * Returns the port number of the remote host to which the client is
- * connected.
- * Delegates to {@link Socket#getPort()}
+ * Returns true if Nagle's algorithm is enabled on the currently opened
+ * socket.
* <p>
- * @return The port number of the remote host to which the client is
- * connected.
- * @throws NullPointerException if the socket is not currently open
- */
- public int getRemotePort()
- {
- return _socket_.getPort();
- }
-
-
- /**
- * @return The remote address to which the client is connected.
- * Delegates to {@link Socket#getInetAddress()}
+ * @return True if Nagle's algorithm is enabled on the currently opened
+ * socket, false otherwise.
+ * @throws SocketException If the operation fails.
* @throws NullPointerException if the socket is not currently open
*/
- public InetAddress getRemoteAddress()
+ public boolean getTcpNoDelay() throws SocketException
{
- return _socket_.getInetAddress();
+ return _socket_.getTcpNoDelay();
}
/**
- * Verifies that the remote end of the given socket is connected to the
- * the same host that the SocketClient is currently connected to. This
- * is useful for doing a quick security check when a client needs to
- * accept a connection from a server, such as an FTP data connection or
- * a BSD R command standard error stream.
- * <p>
- * @param socket the item to check against
- * @return True if the remote hosts are the same, false if not.
+ * Make various checks on the socket to test if it is available for use.
+ * Note that the only sure test is to use it, but these checks may help
+ * in some cases.
+ * @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a>
+ * @return {@code true} if the socket appears to be available for use
+ * @since 3.0
*/
- public boolean verifyRemote(final Socket socket)
- {
- final InetAddress host1;
- final InetAddress host2;
-
- host1 = socket.getInetAddress();
- host2 = getRemoteAddress();
-
- return host1.equals(host2);
+ @SuppressWarnings("resource")
+ public boolean isAvailable(){
+ if (isConnected()) {
+ try
+ {
+ if (_socket_.getInetAddress() == null) {
+ return false;
+ }
+ if (_socket_.getPort() == 0) {
+ return false;
+ }
+ if (_socket_.getRemoteSocketAddress() == null) {
+ return false;
+ }
+ if (_socket_.isClosed()) {
+ return false;
+ }
+ /* these aren't exact checks (a Socket can be half-open),
+ but since we usually require two-way data transfer,
+ we check these here too: */
+ if (_socket_.isInputShutdown()) {
+ return false;
+ }
+ if (_socket_.isOutputShutdown()) {
+ return false;
+ }
+ /* ignore the result, catch exceptions: */
+ // No need to close
+ _socket_.getInputStream();
+ // No need to close
+ _socket_.getOutputStream();
+ }
+ catch (final IOException ioex)
+ {
+ return false;
+ }
+ return true;
+ }
+ return false;
}
/**
- * Sets the SocketFactory used by the SocketClient to open socket
- * connections. If the factory value is null, then a default
- * factory is used (only do this to reset the factory after having
- * previously altered it).
- * Any proxy setting is discarded.
+ * Returns true if the client is currently connected to a server.
* <p>
- * @param factory The new SocketFactory the SocketClient should use.
+ * Delegates to {@link Socket#isConnected()}
+ * @return True if the client is currently connected to a server,
+ * false otherwise.
*/
- public void setSocketFactory(final SocketFactory factory)
+ public boolean isConnected()
{
- if (factory == null) {
- _socketFactory_ = DEFAULT_SOCKET_FACTORY;
- } else {
- _socketFactory_ = factory;
+ if (_socket_ == null) {
+ return false;
}
- // re-setting the socket factory makes the proxy setting useless,
- // so set the field to null so that getProxy() doesn't return a
- // Proxy that we're actually not using.
- connProxy = null;
+
+ return _socket_.isConnected();
}
/**
- * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
- * connections. If the factory value is null, then a default
- * factory is used (only do this to reset the factory after having
- * previously altered it).
- * <p>
- * @param factory The new ServerSocketFactory the SocketClient should use.
- * @since 2.0
+ * Removes a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ * @since 3.0
*/
- public void setServerSocketFactory(final ServerSocketFactory factory) {
- if (factory == null) {
- _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY;
- } else {
- _serverSocketFactory_ = factory;
- }
+ public void removeProtocolCommandListener(final ProtocolCommandListener listener) {
+ getCommandSupport().removeProtocolCommandListener(listener);
+ }
+
+ /**
+ * Sets the charset.
+ *
+ * @param charset the charset.
+ * @since 3.3
+ */
+ public void setCharset(final Charset charset) {
+ this.charset = charset;
}
/**
@@ -756,139 +708,187 @@ public abstract class SocketClient
}
/**
- * Get the underlying socket connection timeout.
- * @return timeout (in ms)
- * @since 2.0
- */
- public int getConnectTimeout() {
- return connectTimeout;
- }
-
- /**
- * Get the underlying {@link ServerSocketFactory}
- * @return The server socket factory
- * @since 2.2
+ * Sets the default port the SocketClient should connect to when a port
+ * is not specified. The {@link #_defaultPort_ _defaultPort_ }
+ * variable stores this value. If never set, the default port is equal
+ * to zero.
+ * <p>
+ * @param port The default port to set.
*/
- public ServerSocketFactory getServerSocketFactory() {
- return _serverSocketFactory_;
+ public void setDefaultPort(final int port)
+ {
+ _defaultPort_ = port;
}
/**
- * Adds a ProtocolCommandListener.
- *
- * @param listener The ProtocolCommandListener to add.
- * @since 3.0
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * This value is only used previous to a call to
+ * {@link #connect connect()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on an the currently opened socket. _timeout_ contains
+ * the new timeout value.
+ * <p>
+ * @param timeout The timeout in milliseconds to use for the socket
+ * connection.
*/
- public void addProtocolCommandListener(final ProtocolCommandListener listener) {
- getCommandSupport().addProtocolCommandListener(listener);
+ public void setDefaultTimeout(final int timeout)
+ {
+ _timeout_ = timeout;
}
/**
- * Removes a ProtocolCommandListener.
+ * Sets the SO_KEEPALIVE flag on the currently opened socket.
*
- * @param listener The ProtocolCommandListener to remove.
- * @since 3.0
+ * From the Javadocs, the default keepalive time is 2 hours (although this is
+ * implementation dependent). It looks as though the Windows WSA sockets implementation
+ * allows a specific keepalive value to be set, although this seems not to be the case on
+ * other systems.
+ * @param keepAlive If true, keepAlive is turned on
+ * @throws SocketException if there is a problem with the socket
+ * @throws NullPointerException if the socket is not currently open
+ * @since 2.2
*/
- public void removeProtocolCommandListener(final ProtocolCommandListener listener) {
- getCommandSupport().removeProtocolCommandListener(listener);
+ public void setKeepAlive(final boolean keepAlive) throws SocketException {
+ _socket_.setKeepAlive(keepAlive);
}
/**
- * If there are any listeners, send them the reply details.
+ * Sets the proxy for use with all the connections.
+ * The proxy is used for connections established after the
+ * call to this method.
*
- * @param replyCode the code extracted from the reply
- * @param reply the full reply text
- * @since 3.0
+ * @param proxy the new proxy for connections.
+ * @since 3.2
*/
- protected void fireReplyReceived(final int replyCode, final String reply) {
- if (getCommandSupport().getListenerCount() > 0) {
- getCommandSupport().fireReplyReceived(replyCode, reply);
- }
+ public void setProxy(final Proxy proxy) {
+ setSocketFactory(new DefaultSocketFactory(proxy));
+ connProxy = proxy;
}
/**
- * If there are any listeners, send them the command details.
- *
- * @param command the command name
- * @param message the complete message, including command name
- * @since 3.0
+ * Sets the underlying socket receive buffer size.
+ * <p>
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException never (but subclasses may wish to do so)
+ * @since 2.0
*/
- protected void fireCommandSent(final String command, final String message) {
- if (getCommandSupport().getListenerCount() > 0) {
- getCommandSupport().fireCommandSent(command, message);
- }
+ public void setReceiveBufferSize(final int size) throws SocketException {
+ receiveBufferSize = size;
}
/**
- * Create the CommandSupport instance if required
+ * Set the underlying socket send buffer size.
+ * <p>
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException never thrown, but subclasses might want to do so
+ * @since 2.0
*/
- protected void createCommandSupport(){
- commandSupport = new ProtocolCommandSupport(this);
+ public void setSendBufferSize(final int size) throws SocketException {
+ sendBufferSize = size;
}
/**
- * Subclasses can override this if they need to provide their own
- * instance field for backwards compatibilty.
- *
- * @return the CommandSupport instance, may be {@code null}
- * @since 3.0
+ * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ * <p>
+ * @param factory The new ServerSocketFactory the SocketClient should use.
+ * @since 2.0
*/
- protected ProtocolCommandSupport getCommandSupport() {
- return commandSupport;
+ public void setServerSocketFactory(final ServerSocketFactory factory) {
+ if (factory == null) {
+ _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY;
+ } else {
+ _serverSocketFactory_ = factory;
+ }
}
/**
- * Sets the proxy for use with all the connections.
- * The proxy is used for connections established after the
- * call to this method.
- *
- * @param proxy the new proxy for connections.
- * @since 3.2
+ * Sets the SocketFactory used by the SocketClient to open socket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ * Any proxy setting is discarded.
+ * <p>
+ * @param factory The new SocketFactory the SocketClient should use.
*/
- public void setProxy(final Proxy proxy) {
- setSocketFactory(new DefaultSocketFactory(proxy));
- connProxy = proxy;
+ public void setSocketFactory(final SocketFactory factory)
+ {
+ if (factory == null) {
+ _socketFactory_ = DEFAULT_SOCKET_FACTORY;
+ } else {
+ _socketFactory_ = factory;
+ }
+ // re-setting the socket factory makes the proxy setting useless,
+ // so set the field to null so that getProxy() doesn't return a
+ // Proxy that we're actually not using.
+ connProxy = null;
}
/**
- * Gets the proxy for use with all the connections.
- * @return the current proxy for connections.
+ * Sets the SO_LINGER timeout on the currently opened socket.
+ * <p>
+ * @param on True if linger is to be enabled, false if not.
+ * @param val The linger timeout (in hundredths of a second?)
+ * @throws SocketException If the operation fails.
+ * @throws NullPointerException if the socket is not currently open
*/
- public Proxy getProxy() {
- return connProxy;
+ public void setSoLinger(final boolean on, final int val) throws SocketException
+ {
+ _socket_.setSoLinger(on, val);
}
/**
- * Gets the charset name.
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #connect connect()}.
+ * <p>
+ * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead.
*
- * @return the charset.
- * @since 3.3
- * @deprecated Since the code now requires Java 1.6 as a mininmum
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open socket connection.
+ * @throws SocketException If the operation fails.
+ * @throws NullPointerException if the socket is not currently open
*/
- @Deprecated
- public String getCharsetName() {
- return charset.name();
+ public void setSoTimeout(final int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
}
/**
- * Gets the charset.
- *
- * @return the charset.
- * @since 3.3
+ * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
+ * currently opened socket.
+ * <p>
+ * @param on True if Nagle's algorithm is to be enabled, false if not.
+ * @throws SocketException If the operation fails.
+ * @throws NullPointerException if the socket is not currently open
*/
- public Charset getCharset() {
- return charset;
+ public void setTcpNoDelay(final boolean on) throws SocketException
+ {
+ _socket_.setTcpNoDelay(on);
}
/**
- * Sets the charset.
- *
- * @param charset the charset.
- * @since 3.3
+ * Verifies that the remote end of the given socket is connected to the
+ * the same host that the SocketClient is currently connected to. This
+ * is useful for doing a quick security check when a client needs to
+ * accept a connection from a server, such as an FTP data connection or
+ * a BSD R command standard error stream.
+ * <p>
+ * @param socket the item to check against
+ * @return True if the remote hosts are the same, false if not.
*/
- public void setCharset(final Charset charset) {
- this.charset = charset;
+ public boolean verifyRemote(final Socket socket)
+ {
+ final InetAddress host1;
+ final InetAddress host2;
+
+ host1 = socket.getInetAddress();
+ host2 = getRemoteAddress();
+
+ return host1.equals(host2);
}
/*
diff --git a/src/main/java/org/apache/commons/net/bsd/RCommandClient.java b/src/main/java/org/apache/commons/net/bsd/RCommandClient.java
index bfdab17..e5ce9fe 100644
--- a/src/main/java/org/apache/commons/net/bsd/RCommandClient.java
+++ b/src/main/java/org/apache/commons/net/bsd/RCommandClient.java
@@ -104,54 +104,6 @@ public class RCommandClient extends RExecClient
*/
public static final int MAX_CLIENT_PORT = 1023;
- // Overrides method in RExecClient in order to implement proper
- // port number limitations.
- @Override
- InputStream createErrorStream() throws IOException
- {
- int localPort;
- ServerSocket server;
- final Socket socket;
-
- localPort = MAX_CLIENT_PORT;
- server = null; // Keep compiler from barfing
-
- for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
- {
- try
- {
- server = _serverSocketFactory_.createServerSocket(localPort, 1,
- getLocalAddress());
- break; // got a socket
- }
- catch (final SocketException e)
- {
- continue;
- }
- }
-
- if (server == null) {
- throw new BindException("All ports in use.");
- }
-
- _output_.write(Integer.toString(server.getLocalPort()).getBytes(StandardCharsets.UTF_8)); // $NON-NLS
- _output_.write(NULL_CHAR);
- _output_.flush();
-
- socket = server.accept();
- server.close();
-
- if (isRemoteVerificationEnabled() && !verifyRemote(socket))
- {
- socket.close();
- throw new IOException(
- "Security violation: unexpected connection attempt by " +
- socket.getInetAddress().getHostAddress());
- }
-
- return new SocketInputStream(socket, socket.getInputStream());
- }
-
/**
* The default RCommandClient constructor. Initializes the
* default port to <code> DEFAULT_PORT </code>.
@@ -161,6 +113,28 @@ public class RCommandClient extends RExecClient
setDefaultPort(DEFAULT_PORT);
}
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a port in a range acceptable
+ * to the BSD rshell daemon.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @throws SocketException If the socket timeout could not be set.
+ * @throws BindException If all acceptable rshell ports are in use.
+ * @throws IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ @Override
+ public void connect(final InetAddress host, final int port)
+ throws SocketException, IOException
+ {
+ connect(host, port, InetAddress.getLocalHost());
+ }
+
/**
* Opens a Socket connected to a remote host at the specified port and
@@ -210,24 +184,33 @@ public class RCommandClient extends RExecClient
/**
* Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a port in a range acceptable
- * to the BSD rshell daemon.
+ * originating from the specified local address and port. The
+ * local port must lie between <code> MIN_CLIENT_PORT </code> and
+ * <code> MAX_CLIENT_PORT </code> or an IllegalArgumentException will
+ * be thrown.
* Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
*
* @param host The remote host.
* @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
* @throws SocketException If the socket timeout could not be set.
- * @throws BindException If all acceptable rshell ports are in use.
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
+ * @throws IllegalArgumentException If an invalid local port number
+ * is specified.
*/
@Override
- public void connect(final InetAddress host, final int port)
- throws SocketException, IOException
+ public void connect(final InetAddress host, final int port,
+ final InetAddress localAddr, final int localPort)
+ throws SocketException, IOException, IllegalArgumentException
{
- connect(host, port, InetAddress.getLocalHost());
+ if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT) {
+ throw new IllegalArgumentException("Invalid port number " + localPort);
+ }
+ super.connect(host, port, localAddr, localPort);
}
@@ -287,7 +270,7 @@ public class RCommandClient extends RExecClient
* Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
* is called to perform connection initialization actions.
*
- * @param host The remote host.
+ * @param hostname The name of the remote host.
* @param port The port to connect to on the remote host.
* @param localAddr The local address to use.
* @param localPort The local port to use.
@@ -295,51 +278,84 @@ public class RCommandClient extends RExecClient
* @throws IOException If the socket could not be opened. In most
* cases you will only want to catch IOException since SocketException is
* derived from it.
+ * @throws UnknownHostException If the hostname cannot be resolved.
* @throws IllegalArgumentException If an invalid local port number
* is specified.
*/
@Override
- public void connect(final InetAddress host, final int port,
+ public void connect(final String hostname, final int port,
final InetAddress localAddr, final int localPort)
- throws SocketException, IOException, IllegalArgumentException
+ throws SocketException, IOException, IllegalArgumentException, UnknownHostException
{
if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT) {
throw new IllegalArgumentException("Invalid port number " + localPort);
}
- super.connect(host, port, localAddr, localPort);
+ super.connect(hostname, port, localAddr, localPort);
}
- /**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port. The
- * local port must lie between <code> MIN_CLIENT_PORT </code> and
- * <code> MAX_CLIENT_PORT </code> or an IllegalArgumentException will
- * be thrown.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @throws SocketException If the socket timeout could not be set.
- * @throws IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @throws UnknownHostException If the hostname cannot be resolved.
- * @throws IllegalArgumentException If an invalid local port number
- * is specified.
- */
+ // Overrides method in RExecClient in order to implement proper
+ // port number limitations.
@Override
- public void connect(final String hostname, final int port,
- final InetAddress localAddr, final int localPort)
- throws SocketException, IOException, IllegalArgumentException, UnknownHostException
+ InputStream createErrorStream() throws IOException
{
- if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT) {
- throw new IllegalArgumentException("Invalid port number " + localPort);
+ int localPort;
+ ServerSocket server;
+ final Socket socket;
+
+ localPort = MAX_CLIENT_PORT;
+ server = null; // Keep compiler from barfing
+
+ for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
+ {
+ try
+ {
+ server = _serverSocketFactory_.createServerSocket(localPort, 1,
+ getLocalAddress());
+ break; // got a socket
+ }
+ catch (final SocketException e)
+ {
+ continue;
+ }
}
- super.connect(hostname, port, localAddr, localPort);
+
+ if (server == null) {
+ throw new BindException("All ports in use.");
+ }
+
+ _output_.write(Integer.toString(server.getLocalPort()).getBytes(StandardCharsets.UTF_8)); // $NON-NLS
+ _output_.write(NULL_CHAR);
+ _output_.flush();
+
+ socket = server.accept();
+ server.close();
+
+ if (isRemoteVerificationEnabled() && !verifyRemote(socket))
+ {
+ socket.close();
+ throw new IOException(
+ "Security violation: unexpected connection attempt by " +
+ socket.getInetAddress().getHostAddress());
+ }
+
+ return new SocketInputStream(socket, socket.getInputStream());
+ }
+
+
+ /**
+ * Same as
+ * <code> rcommand(localUsername, remoteUsername, command, false); </code>
+ * @param localUsername the local user
+ * @param remoteUsername the remote user
+ * @param command the command
+ * @throws IOException on error
+ */
+ public void rcommand(final String localUsername, final String remoteUsername,
+ final String command)
+ throws IOException
+ {
+ rcommand(localUsername, remoteUsername, command, false);
}
@@ -386,21 +402,5 @@ public class RCommandClient extends RExecClient
rexec(localUsername, remoteUsername, command, separateErrorStream);
}
-
- /**
- * Same as
- * <code> rcommand(localUsername, remoteUsername, command, false); </code>
- * @param localUsername the local user
- * @param remoteUsername the remote user
- * @param command the command
- * @throws IOException on error
- */
- public void rcommand(final String localUsername, final String remoteUsername,
- final String command)
- throws IOException
- {
- rcommand(localUsername, remoteUsername, command, false);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/bsd/RExecClient.java b/src/main/java/org/apache/commons/net/bsd/RExecClient.java
index 2d63f86..b16560a 100644
--- a/src/main/java/org/apache/commons/net/bsd/RExecClient.java
+++ b/src/main/java/org/apache/commons/net/bsd/RExecClient.java
@@ -85,6 +85,17 @@ public class RExecClient extends SocketClient
*/
protected InputStream _errorStream_;
+ /**
+ * The default RExecClient constructor. Initializes the
+ * default port to <code> DEFAULT_PORT </code>.
+ */
+ public RExecClient()
+ {
+ _errorStream_ = null;
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+
// This can be overridden in local package to implement port range
// limitations of rcmd and rlogin
InputStream createErrorStream() throws IOException
@@ -114,13 +125,35 @@ public class RExecClient extends SocketClient
/**
- * The default RExecClient constructor. Initializes the
- * default port to <code> DEFAULT_PORT </code>.
+ * Disconnects from the server, closing all associated open sockets and
+ * streams.
+ *
+ * @throws IOException If there an error occurs while disconnecting.
*/
- public RExecClient()
+ @Override
+ public void disconnect() throws IOException
{
+ if (_errorStream_ != null) {
+ _errorStream_.close();
+ }
_errorStream_ = null;
- setDefaultPort(DEFAULT_PORT);
+ super.disconnect();
+ }
+
+
+ /**
+ * Returns the InputStream from which the standard error of the remote
+ * process can be read if a separate error stream is requested from
+ * the server. Otherwise, null will be returned. The error stream
+ * will only be set after a successful rexec() invocation.
+ *
+ * @return The InputStream from which the standard error of the remote
+ * process can be read if a separate error stream is requested from
+ * the server. Otherwise, null will be returned.
+ */
+ public InputStream getErrorStream()
+ {
+ return _errorStream_;
}
@@ -153,18 +186,29 @@ public class RExecClient extends SocketClient
/**
- * Returns the InputStream from which the standard error of the remote
- * process can be read if a separate error stream is requested from
- * the server. Otherwise, null will be returned. The error stream
- * will only be set after a successful rexec() invocation.
+ * Return whether or not verification of the remote host providing a
+ * separate error stream is enabled. The default behavior is for
+ * verification to be enabled.
*
- * @return The InputStream from which the standard error of the remote
- * process can be read if a separate error stream is requested from
- * the server. Otherwise, null will be returned.
+ * @return True if verification is enabled, false if not.
*/
- public InputStream getErrorStream()
+ public final boolean isRemoteVerificationEnabled()
{
- return _errorStream_;
+ return remoteVerificationEnabled;
+ }
+
+ /**
+ * Same as <code> rexec(username, password, command, false); </code>
+ * @param username the user name
+ * @param password the password
+ * @param command the command to run
+ * @throws IOException if an error occurs
+ */
+ public void rexec(final String username, final String password,
+ final String command)
+ throws IOException
+ {
+ rexec(username, password, command, false);
}
@@ -237,38 +281,6 @@ public class RExecClient extends SocketClient
}
}
-
- /**
- * Same as <code> rexec(username, password, command, false); </code>
- * @param username the user name
- * @param password the password
- * @param command the command to run
- * @throws IOException if an error occurs
- */
- public void rexec(final String username, final String password,
- final String command)
- throws IOException
- {
- rexec(username, password, command, false);
- }
-
- /**
- * Disconnects from the server, closing all associated open sockets and
- * streams.
- *
- * @throws IOException If there an error occurs while disconnecting.
- */
- @Override
- public void disconnect() throws IOException
- {
- if (_errorStream_ != null) {
- _errorStream_.close();
- }
- _errorStream_ = null;
- super.disconnect();
- }
-
-
/**
* Enable or disable verification that the remote host connecting to
* create a separate error stream is the same as the host to which
@@ -283,17 +295,5 @@ public class RExecClient extends SocketClient
remoteVerificationEnabled = enable;
}
- /**
- * Return whether or not verification of the remote host providing a
- * separate error stream is enabled. The default behavior is for
- * verification to be enabled.
- *
- * @return True if verification is enabled, false if not.
- */
- public final boolean isRemoteVerificationEnabled()
- {
- return remoteVerificationEnabled;
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/bsd/RLoginClient.java b/src/main/java/org/apache/commons/net/bsd/RLoginClient.java
index 249e160..f7aa6ed 100644
--- a/src/main/java/org/apache/commons/net/bsd/RLoginClient.java
+++ b/src/main/java/org/apache/commons/net/bsd/RLoginClient.java
@@ -81,6 +81,20 @@ public class RLoginClient extends RCommandClient
/**
+ * Same as the other rlogin method, but no terminal speed is defined.
+ * @param localUsername the local user
+ * @param remoteUsername the remote user
+ * @param terminalType the terminal type
+ * @throws IOException on error
+ */
+ public void rlogin(final String localUsername, final String remoteUsername,
+ final String terminalType)
+ throws IOException
+ {
+ rexec(localUsername, remoteUsername, terminalType, false);
+ }
+
+ /**
* Logins into a remote machine through the rlogind daemon on the server
* to which the RLoginClient is connected. After calling this method,
* you may interact with the remote login shell through its standard input
@@ -116,18 +130,4 @@ public class RLoginClient extends RCommandClient
false);
}
- /**
- * Same as the other rlogin method, but no terminal speed is defined.
- * @param localUsername the local user
- * @param remoteUsername the remote user
- * @param terminalType the terminal type
- * @throws IOException on error
- */
- public void rlogin(final String localUsername, final String remoteUsername,
- final String terminalType)
- throws IOException
- {
- rexec(localUsername, remoteUsername, terminalType, false);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/chargen/CharGenUDPClient.java b/src/main/java/org/apache/commons/net/chargen/CharGenUDPClient.java
index 79d8c16..25a5a77 100644
--- a/src/main/java/org/apache/commons/net/chargen/CharGenUDPClient.java
+++ b/src/main/java/org/apache/commons/net/chargen/CharGenUDPClient.java
@@ -82,31 +82,6 @@ public final class CharGenUDPClient extends DatagramSocketClient
/**
- * Sends the data initiation datagram. This data in the packet is ignored
- * by the server, and merely serves to signal that the server should send
- * its reply.
- *
- * @param host The address of the server.
- * @param port The port of the service.
- * @throws IOException If an error occurs while sending the datagram.
- */
- public void send(final InetAddress host, final int port) throws IOException
- {
- sendPacket.setAddress(host);
- sendPacket.setPort(port);
- _socket_.send(sendPacket);
- }
-
- /** Same as <code>send(host, CharGenUDPClient.DEFAULT_PORT);</code>
- * @param host the destination host
- * @throws IOException on error
- */
- public void send(final InetAddress host) throws IOException
- {
- send(host, DEFAULT_PORT);
- }
-
- /**
* Receive the reply data from the server. This will always be 512 bytes
* or less. Chargen and quote of the day only return one packet. Netstat
* and systat require multiple calls to receive() with timeout detection.
@@ -127,5 +102,30 @@ public final class CharGenUDPClient extends DatagramSocketClient
return result;
}
+ /** Same as <code>send(host, CharGenUDPClient.DEFAULT_PORT);</code>
+ * @param host the destination host
+ * @throws IOException on error
+ */
+ public void send(final InetAddress host) throws IOException
+ {
+ send(host, DEFAULT_PORT);
+ }
+
+ /**
+ * Sends the data initiation datagram. This data in the packet is ignored
+ * by the server, and merely serves to signal that the server should send
+ * its reply.
+ *
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @throws IOException If an error occurs while sending the datagram.
+ */
+ public void send(final InetAddress host, final int port) throws IOException
+ {
+ sendPacket.setAddress(host);
+ sendPacket.setPort(port);
+ _socket_.send(sendPacket);
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/daytime/DaytimeUDPClient.java b/src/main/java/org/apache/commons/net/daytime/DaytimeUDPClient.java
index 5da5046..a41a7ee 100644
--- a/src/main/java/org/apache/commons/net/daytime/DaytimeUDPClient.java
+++ b/src/main/java/org/apache/commons/net/daytime/DaytimeUDPClient.java
@@ -47,6 +47,16 @@ public final class DaytimeUDPClient extends DatagramSocketClient
// Received dates should be less than 256 bytes
private final byte[] timeData = new byte[256];
+ /** Same as <code>getTime(host, DaytimeUDPClient.DEFAULT_PORT);</code>
+ * @param host the host
+ * @return the time
+ * @throws IOException on error
+ */
+ public String getTime(final InetAddress host) throws IOException
+ {
+ return getTime(host, DEFAULT_PORT);
+ }
+
/**
* Retrieves the time string from the specified server and port and
* returns it.
@@ -71,15 +81,5 @@ public final class DaytimeUDPClient extends DatagramSocketClient
return new String(receivePacket.getData(), 0, receivePacket.getLength(), getCharset()); // Java 1.6 can use getCharset()
}
- /** Same as <code>getTime(host, DaytimeUDPClient.DEFAULT_PORT);</code>
- * @param host the host
- * @return the time
- * @throws IOException on error
- */
- public String getTime(final InetAddress host) throws IOException
- {
- return getTime(host, DEFAULT_PORT);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/discard/DiscardUDPClient.java b/src/main/java/org/apache/commons/net/discard/DiscardUDPClient.java
index e290a11..b6b4610 100644
--- a/src/main/java/org/apache/commons/net/discard/DiscardUDPClient.java
+++ b/src/main/java/org/apache/commons/net/discard/DiscardUDPClient.java
@@ -51,24 +51,16 @@ public class DiscardUDPClient extends DatagramSocketClient
/**
- * Sends the specified data to the specified server at the specified port.
- *
- * @param data The discard data to send.
- * @param length The length of the data to send. Should be less than
- * or equal to the length of the data byte array.
- * @param host The address of the server.
- * @param port The service port.
- * @throws IOException If an error occurs during the datagram send
- * operation.
+ * Same as
+ * <code>send(data, data.length, host. DiscardUDPClient.DEFAULT_PORT)</code>.
+ * @param data the buffer to send
+ * @param host the target host
+ * @see #send(byte[], int, InetAddress, int)
+ * @throws IOException if an error occurs
*/
- public void send(final byte[] data, final int length, final InetAddress host, final int port)
- throws IOException
+ public void send(final byte[] data, final InetAddress host) throws IOException
{
- sendPacket.setData(data);
- sendPacket.setLength(length);
- sendPacket.setAddress(host);
- sendPacket.setPort(port);
- _socket_.send(sendPacket);
+ send(data, data.length, host, DEFAULT_PORT);
}
@@ -89,16 +81,24 @@ public class DiscardUDPClient extends DatagramSocketClient
/**
- * Same as
- * <code>send(data, data.length, host. DiscardUDPClient.DEFAULT_PORT)</code>.
- * @param data the buffer to send
- * @param host the target host
- * @see #send(byte[], int, InetAddress, int)
- * @throws IOException if an error occurs
+ * Sends the specified data to the specified server at the specified port.
+ *
+ * @param data The discard data to send.
+ * @param length The length of the data to send. Should be less than
+ * or equal to the length of the data byte array.
+ * @param host The address of the server.
+ * @param port The service port.
+ * @throws IOException If an error occurs during the datagram send
+ * operation.
*/
- public void send(final byte[] data, final InetAddress host) throws IOException
+ public void send(final byte[] data, final int length, final InetAddress host, final int port)
+ throws IOException
{
- send(data, data.length, host, DEFAULT_PORT);
+ sendPacket.setData(data);
+ sendPacket.setLength(length);
+ sendPacket.setAddress(host);
+ sendPacket.setPort(port);
+ _socket_.send(sendPacket);
}
}
diff --git a/src/main/java/org/apache/commons/net/echo/EchoUDPClient.java b/src/main/java/org/apache/commons/net/echo/EchoUDPClient.java
index f7d2e4f..902616e 100644
--- a/src/main/java/org/apache/commons/net/echo/EchoUDPClient.java
+++ b/src/main/java/org/apache/commons/net/echo/EchoUDPClient.java
@@ -46,30 +46,14 @@ public final class EchoUDPClient extends DiscardUDPClient
private final DatagramPacket receivePacket = new DatagramPacket(NetConstants.EMPTY_BTYE_ARRAY, 0);
- /**
- * Sends the specified data to the specified server at the default echo
- * port.
- *
- * @param data The echo data to send.
- * @param length The length of the data to send. Should be less than
- * or equal to the length of the data byte array.
- * @param host The address of the server.
- * @throws IOException If an error occurs during the datagram send
- * operation.
+ /** Same as <code> receive(data, data.length)</code>
+ * @param data the buffer to receive the input
+ * @return the number of bytes
+ * @throws IOException on error
*/
- @Override
- public void send(final byte[] data, final int length, final InetAddress host)
- throws IOException
- {
- send(data, length, host, DEFAULT_PORT);
- }
-
-
- /** Same as <code> send(data, data.length, host) </code> */
- @Override
- public void send(final byte[] data, final InetAddress host) throws IOException
+ public int receive(final byte[] data) throws IOException
{
- send(data, data.length, host, DEFAULT_PORT);
+ return receive(data, data.length);
}
@@ -92,14 +76,30 @@ public final class EchoUDPClient extends DiscardUDPClient
return receivePacket.getLength();
}
- /** Same as <code> receive(data, data.length)</code>
- * @param data the buffer to receive the input
- * @return the number of bytes
- * @throws IOException on error
+
+ /** Same as <code> send(data, data.length, host) </code> */
+ @Override
+ public void send(final byte[] data, final InetAddress host) throws IOException
+ {
+ send(data, data.length, host, DEFAULT_PORT);
+ }
+
+ /**
+ * Sends the specified data to the specified server at the default echo
+ * port.
+ *
+ * @param data The echo data to send.
+ * @param length The length of the data to send. Should be less than
+ * or equal to the length of the data byte array.
+ * @param host The address of the server.
+ * @throws IOException If an error occurs during the datagram send
+ * operation.
*/
- public int receive(final byte[] data) throws IOException
+ @Override
+ public void send(final byte[] data, final int length, final InetAddress host)
+ throws IOException
{
- return receive(data, data.length);
+ send(data, length, host, DEFAULT_PORT);
}
}
diff --git a/src/main/java/org/apache/commons/net/examples/Main.java b/src/main/java/org/apache/commons/net/examples/Main.java
index 1b35cc0..442316d 100644
--- a/src/main/java/org/apache/commons/net/examples/Main.java
+++ b/src/main/java/org/apache/commons/net/examples/Main.java
@@ -31,6 +31,14 @@ import java.util.Properties;
*/
public class Main {
+ private static boolean fromJar() {
+ final CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource();
+ if ( codeSource != null) {
+ return codeSource.getLocation().getFile().endsWith(".jar");
+ }
+ return false; // No idea if this can happen
+ }
+
/**
* Helper application for example classes.
* Lists available classes, and provides shorthand invocation.
@@ -102,12 +110,4 @@ public class Main {
System.out.println(e);
}
}
-
- private static boolean fromJar() {
- final CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource();
- if ( codeSource != null) {
- return codeSource.getLocation().getFile().endsWith(".jar");
- }
- return false; // No idea if this can happen
- }
}
diff --git a/src/main/java/org/apache/commons/net/examples/ftp/FTPClientExample.java b/src/main/java/org/apache/commons/net/examples/ftp/FTPClientExample.java
index 269a91f..c721089 100644
--- a/src/main/java/org/apache/commons/net/examples/ftp/FTPClientExample.java
+++ b/src/main/java/org/apache/commons/net/examples/ftp/FTPClientExample.java
@@ -88,6 +88,27 @@ public final class FTPClientExample
"\t-PrP password - HTTP Proxy server password\n" +
"\t-# - add hash display during transfers\n";
+ private static CopyStreamListener createListener(){
+ return new CopyStreamListener(){
+ private long megsTotal;
+
+ @Override
+ public void bytesTransferred(final CopyStreamEvent event) {
+ bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
+ }
+
+ @Override
+ public void bytesTransferred(final long totalBytesTransferred,
+ final int bytesTransferred, final long streamSize) {
+ final long megs = totalBytesTransferred / 1000000;
+ for (long l = megsTotal; l < megs; l++) {
+ System.err.print("#");
+ }
+ megsTotal = megs;
+ }
+ };
+ }
+
public static void main(final String[] args) throws UnknownHostException
{
boolean storeFile = false, binaryTransfer = false, error = false, listFiles = false, listNames = false, hidden = false;
@@ -551,26 +572,5 @@ __main:
System.out.println("CslDebug="+Arrays.toString(stats));
}
-
- private static CopyStreamListener createListener(){
- return new CopyStreamListener(){
- private long megsTotal;
-
- @Override
- public void bytesTransferred(final CopyStreamEvent event) {
- bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
- }
-
- @Override
- public void bytesTransferred(final long totalBytesTransferred,
- final int bytesTransferred, final long streamSize) {
- final long megs = totalBytesTransferred / 1000000;
- for (long l = megsTotal; l < megs; l++) {
- System.err.print("#");
- }
- megsTotal = megs;
- }
- };
- }
}
diff --git a/src/main/java/org/apache/commons/net/examples/ftp/TFTPExample.java b/src/main/java/org/apache/commons/net/examples/ftp/TFTPExample.java
index cc4483e..ea78266 100644
--- a/src/main/java/org/apache/commons/net/examples/ftp/TFTPExample.java
+++ b/src/main/java/org/apache/commons/net/examples/ftp/TFTPExample.java
@@ -64,6 +64,25 @@ public final class TFTPExample
"\t-v Verbose (trace packets)\n"
;
+ private static boolean close(final TFTPClient tftp, final Closeable output) {
+ boolean closed;
+ tftp.close();
+ try
+ {
+ if (output != null) {
+ output.close();
+ }
+ closed = true;
+ }
+ catch (final IOException e)
+ {
+ closed = false;
+ System.err.println("Error: error closing file.");
+ System.err.println(e.getMessage());
+ }
+ return closed;
+ }
+
public static void main(final String[] args)
{
boolean receiveFile = true, closed;
@@ -153,53 +172,15 @@ public final class TFTPExample
System.out.println("OK");
}
- private static boolean send(final int transferMode, final String hostname, final String localFilename,
- final String remoteFilename, final TFTPClient tftp) {
- final boolean closed;
- FileInputStream input = null;
-
- // Try to open local file for reading
- try
- {
- input = new FileInputStream(localFilename);
- }
- catch (final IOException e)
- {
- tftp.close();
- throw new RuntimeException("Error: could not open local file for reading.", e);
- }
-
- open(tftp);
-
- // Try to send local file via TFTP
+ private static void open(final TFTPClient tftp) {
try
{
- final String [] parts = hostname.split(":");
- if (parts.length == 2) {
- tftp.sendFile(remoteFilename, transferMode, input, parts[0], Integer.parseInt(parts[1]));
- } else {
- tftp.sendFile(remoteFilename, transferMode, input, hostname);
- }
- }
- catch (final UnknownHostException e)
- {
- System.err.println("Error: could not resolve hostname.");
- System.err.println(e.getMessage());
- System.exit(1);
- }
- catch (final IOException e)
- {
- System.err.println("Error: I/O exception occurred while sending file.");
- System.err.println(e.getMessage());
- System.exit(1);
+ tftp.open();
}
- finally
+ catch (final SocketException e)
{
- // Close local socket and input file
- closed = close(tftp, input);
+ throw new RuntimeException("Error: could not open local UDP socket.", e);
}
-
- return closed;
}
private static boolean receive(final int transferMode, final String hostname, final String localFilename,
@@ -262,34 +243,53 @@ public final class TFTPExample
return closed;
}
- private static boolean close(final TFTPClient tftp, final Closeable output) {
- boolean closed;
- tftp.close();
+ private static boolean send(final int transferMode, final String hostname, final String localFilename,
+ final String remoteFilename, final TFTPClient tftp) {
+ final boolean closed;
+ FileInputStream input = null;
+
+ // Try to open local file for reading
try
{
- if (output != null) {
- output.close();
- }
- closed = true;
+ input = new FileInputStream(localFilename);
}
catch (final IOException e)
{
- closed = false;
- System.err.println("Error: error closing file.");
- System.err.println(e.getMessage());
+ tftp.close();
+ throw new RuntimeException("Error: could not open local file for reading.", e);
}
- return closed;
- }
- private static void open(final TFTPClient tftp) {
+ open(tftp);
+
+ // Try to send local file via TFTP
try
{
- tftp.open();
+ final String [] parts = hostname.split(":");
+ if (parts.length == 2) {
+ tftp.sendFile(remoteFilename, transferMode, input, parts[0], Integer.parseInt(parts[1]));
+ } else {
+ tftp.sendFile(remoteFilename, transferMode, input, hostname);
+ }
}
- catch (final SocketException e)
+ catch (final UnknownHostException e)
{
- throw new RuntimeException("Error: could not open local UDP socket.", e);
+ System.err.println("Error: could not resolve hostname.");
+ System.err.println(e.getMessage());
+ System.exit(1);
+ }
+ catch (final IOException e)
+ {
+ System.err.println("Error: I/O exception occurred while sending file.");
+ System.err.println(e.getMessage());
+ System.exit(1);
}
+ finally
+ {
+ // Close local socket and input file
+ closed = close(tftp, input);
+ }
+
+ return closed;
}
}
diff --git a/src/main/java/org/apache/commons/net/examples/mail/IMAPExportMbox.java b/src/main/java/org/apache/commons/net/examples/mail/IMAPExportMbox.java
index 54f5f15..bfb41f4 100644
--- a/src/main/java/org/apache/commons/net/examples/mail/IMAPExportMbox.java
+++ b/src/main/java/org/apache/commons/net/examples/mail/IMAPExportMbox.java
@@ -81,17 +81,144 @@ import org.apache.commons.net.imap.IMAPReply;
public final class IMAPExportMbox
{
+ private static class MboxListener implements IMAPChunkListener {
+
+ private final BufferedWriter bufferedWriter;
+ volatile AtomicInteger total = new AtomicInteger();
+ volatile String lastFetched;
+ volatile List<String> missingIds = new ArrayList<>();
+ volatile long lastSeq = -1;
+ private final String lineSeparator;
+ private final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
+ = new SimpleDateFormat("EEE MMM dd HH:mm:ss YYYY");
+
+ // e.g. INTERNALDATE "27-Oct-2013 07:43:24 +0000"
+ // for parsing INTERNALDATE
+ private final SimpleDateFormat IDPARSE = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z");
+ private final boolean printHash;
+ private final boolean printMarker;
+ private final boolean checkSequence;
+
+ MboxListener(final BufferedWriter bufferedWriter, final String lineSeparator, final boolean printHash,
+ final boolean printMarker, final boolean checkSequence) {
+ this.lineSeparator = lineSeparator;
+ this.printHash = printHash;
+ this.printMarker = printMarker;
+ DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
+ this.bufferedWriter = bufferedWriter;
+ this.checkSequence = checkSequence;
+ }
+
+ @Override
+ public boolean chunkReceived(final IMAP imap) {
+ final String[] replyStrings = imap.getReplyStrings();
+ Date received = new Date();
+ final String firstLine = replyStrings[0];
+ Matcher m = PATID.matcher(firstLine);
+ if (m.lookingAt()) { // found a match
+ final String date = m.group(PATID_DATE_GROUP);
+ try {
+ received=IDPARSE.parse(date);
+ } catch (final ParseException e) {
+ System.err.println(e);
+ }
+ } else {
+ System.err.println("No timestamp found in: " + firstLine + " - using current time");
+ }
+ String replyTo = "MAILER-DAEMON"; // default
+ for(int i=1; i< replyStrings.length - 1; i++) {
+ final String line = replyStrings[i];
+ if (line.startsWith("Return-Path: ")) {
+ final String[] parts = line.split(" ", 2);
+ if (!parts[1].equals("<>")) {// Don't replace default with blank
+ replyTo = parts[1];
+ if (replyTo.startsWith("<")) {
+ if (replyTo.endsWith(">")) {
+ replyTo = replyTo.substring(1,replyTo.length()-1); // drop <> wrapper
+ } else {
+ System.err.println("Unexpected Return-path: '" + line+ "' in " + firstLine);
+ }
+ }
+ }
+ break;
+ }
+ }
+ try {
+ // Add initial mbox header line
+ bufferedWriter.append("From ");
+ bufferedWriter.append(replyTo);
+ bufferedWriter.append(' ');
+ bufferedWriter.append(DATE_FORMAT.format(received));
+ bufferedWriter.append(lineSeparator);
+ // Debug
+ bufferedWriter.append("X-IMAP-Response: ").append(firstLine).append(lineSeparator);
+ if (printMarker) {
+ System.err.println("[" + total + "] " + firstLine);
+ }
+ // Skip first and last lines
+ for(int i=1; i< replyStrings.length - 1; i++) {
+ final String line = replyStrings[i];
+ if (startsWith(line, PATFROM)) {
+ bufferedWriter.append('>'); // Escape a From_ line
+ }
+ bufferedWriter.append(line);
+ bufferedWriter.append(lineSeparator);
+ }
+ // The last line ends with the trailing closing ")" which needs to be stripped
+ final String lastLine = replyStrings[replyStrings.length-1];
+ final int lastLength = lastLine.length();
+ if (lastLength > 1) { // there's some content, we need to save it
+ bufferedWriter.append(lastLine, 0, lastLength-1);
+ bufferedWriter.append(lineSeparator);
+ }
+ bufferedWriter.append(lineSeparator); // blank line between entries
+ } catch (final IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e); // chunkReceived cannot throw a checked Exception
+ }
+ lastFetched = firstLine;
+ total.incrementAndGet();
+ if (checkSequence) {
+ m = PATSEQ.matcher(firstLine);
+ if (m.lookingAt()) { // found a match
+ final long msgSeq = Long.parseLong(m.group(PATSEQ_SEQUENCE_GROUP)); // Cannot fail to parse
+ if (lastSeq != -1) {
+ final long missing = msgSeq - lastSeq - 1;
+ if (missing != 0) {
+ for(long j = lastSeq + 1; j < msgSeq; j++) {
+ missingIds.add(String.valueOf(j));
+ }
+ System.err.println(
+ "*** Sequence error: current=" + msgSeq + " previous=" + lastSeq + " Missing=" + missing);
+ }
+ }
+ lastSeq = msgSeq;
+ }
+ }
+ if (printHash) {
+ System.err.print(".");
+ }
+ return true;
+ }
+
+ public void close() throws IOException {
+ if (bufferedWriter != null) {
+ bufferedWriter.close();
+ }
+ }
+ }
private static final String CRLF = "\r\n";
private static final String LF = "\n";
- private static final String EOL_DEFAULT = System.getProperty("line.separator");
+ private static final String EOL_DEFAULT = System.getProperty("line.separator");
private static final Pattern PATFROM = Pattern.compile(">*From "); // unescaped From_
// e.g. * nnn (INTERNALDATE "27-Oct-2013 07:43:24 +0000" BODY[] {nn} ...)
private static final Pattern PATID = // INTERNALDATE
Pattern.compile(".*INTERNALDATE \"(\\d\\d-\\w{3}-\\d{4} \\d\\d:\\d\\d:\\d\\d [+-]\\d+)\"");
- private static final int PATID_DATE_GROUP = 1;
+ private static final int PATID_DATE_GROUP = 1;
private static final Pattern PATSEQ = Pattern.compile("\\* (\\d+) "); // Sequence number
+
private static final int PATSEQ_SEQUENCE_GROUP = 1;
// e.g. * 382 EXISTS
@@ -99,8 +226,8 @@ public final class IMAPExportMbox
// AAAC NO [TEMPFAIL] FETCH Temporary failure on server [CODE: WBL]
private static final Pattern PATTEMPFAIL = Pattern.compile("[A-Z]{4} NO \\[TEMPFAIL\\] FETCH .*");
-
private static final int CONNECT_TIMEOUT = 10; // Seconds
+
private static final int READ_TIMEOUT = 10;
public static void main(final String[] args) throws IOException, URISyntaxException
@@ -316,11 +443,6 @@ public final class IMAPExportMbox
}
}
- private static boolean startsWith(final String input, final Pattern pat) {
- final Matcher m = pat.matcher(input);
- return m.lookingAt();
- }
-
private static String matches(final String input, final Pattern pat, final int index) {
final Matcher m = pat.matcher(input);
if (m.lookingAt()) {
@@ -329,130 +451,8 @@ public final class IMAPExportMbox
return null;
}
- private static class MboxListener implements IMAPChunkListener {
-
- private final BufferedWriter bufferedWriter;
- volatile AtomicInteger total = new AtomicInteger();
- volatile String lastFetched;
- volatile List<String> missingIds = new ArrayList<>();
- volatile long lastSeq = -1;
- private final String lineSeparator;
- private final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
- = new SimpleDateFormat("EEE MMM dd HH:mm:ss YYYY");
-
- // e.g. INTERNALDATE "27-Oct-2013 07:43:24 +0000"
- // for parsing INTERNALDATE
- private final SimpleDateFormat IDPARSE = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z");
- private final boolean printHash;
- private final boolean printMarker;
- private final boolean checkSequence;
-
- MboxListener(final BufferedWriter bufferedWriter, final String lineSeparator, final boolean printHash,
- final boolean printMarker, final boolean checkSequence) {
- this.lineSeparator = lineSeparator;
- this.printHash = printHash;
- this.printMarker = printMarker;
- DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
- this.bufferedWriter = bufferedWriter;
- this.checkSequence = checkSequence;
- }
-
- @Override
- public boolean chunkReceived(final IMAP imap) {
- final String[] replyStrings = imap.getReplyStrings();
- Date received = new Date();
- final String firstLine = replyStrings[0];
- Matcher m = PATID.matcher(firstLine);
- if (m.lookingAt()) { // found a match
- final String date = m.group(PATID_DATE_GROUP);
- try {
- received=IDPARSE.parse(date);
- } catch (final ParseException e) {
- System.err.println(e);
- }
- } else {
- System.err.println("No timestamp found in: " + firstLine + " - using current time");
- }
- String replyTo = "MAILER-DAEMON"; // default
- for(int i=1; i< replyStrings.length - 1; i++) {
- final String line = replyStrings[i];
- if (line.startsWith("Return-Path: ")) {
- final String[] parts = line.split(" ", 2);
- if (!parts[1].equals("<>")) {// Don't replace default with blank
- replyTo = parts[1];
- if (replyTo.startsWith("<")) {
- if (replyTo.endsWith(">")) {
- replyTo = replyTo.substring(1,replyTo.length()-1); // drop <> wrapper
- } else {
- System.err.println("Unexpected Return-path: '" + line+ "' in " + firstLine);
- }
- }
- }
- break;
- }
- }
- try {
- // Add initial mbox header line
- bufferedWriter.append("From ");
- bufferedWriter.append(replyTo);
- bufferedWriter.append(' ');
- bufferedWriter.append(DATE_FORMAT.format(received));
- bufferedWriter.append(lineSeparator);
- // Debug
- bufferedWriter.append("X-IMAP-Response: ").append(firstLine).append(lineSeparator);
- if (printMarker) {
- System.err.println("[" + total + "] " + firstLine);
- }
- // Skip first and last lines
- for(int i=1; i< replyStrings.length - 1; i++) {
- final String line = replyStrings[i];
- if (startsWith(line, PATFROM)) {
- bufferedWriter.append('>'); // Escape a From_ line
- }
- bufferedWriter.append(line);
- bufferedWriter.append(lineSeparator);
- }
- // The last line ends with the trailing closing ")" which needs to be stripped
- final String lastLine = replyStrings[replyStrings.length-1];
- final int lastLength = lastLine.length();
- if (lastLength > 1) { // there's some content, we need to save it
- bufferedWriter.append(lastLine, 0, lastLength-1);
- bufferedWriter.append(lineSeparator);
- }
- bufferedWriter.append(lineSeparator); // blank line between entries
- } catch (final IOException e) {
- e.printStackTrace();
- throw new RuntimeException(e); // chunkReceived cannot throw a checked Exception
- }
- lastFetched = firstLine;
- total.incrementAndGet();
- if (checkSequence) {
- m = PATSEQ.matcher(firstLine);
- if (m.lookingAt()) { // found a match
- final long msgSeq = Long.parseLong(m.group(PATSEQ_SEQUENCE_GROUP)); // Cannot fail to parse
- if (lastSeq != -1) {
- final long missing = msgSeq - lastSeq - 1;
- if (missing != 0) {
- for(long j = lastSeq + 1; j < msgSeq; j++) {
- missingIds.add(String.valueOf(j));
- }
- System.err.println(
- "*** Sequence error: current=" + msgSeq + " previous=" + lastSeq + " Missing=" + missing);
- }
- }
- lastSeq = msgSeq;
- }
- }
- if (printHash) {
- System.err.print(".");
- }
- return true;
- }
-
- public void close() throws IOException {
- if (bufferedWriter != null) {
- bufferedWriter.close();
- }
- }
+ private static boolean startsWith(final String input, final Pattern pat) {
+ final Matcher m = pat.matcher(input);
+ return m.lookingAt();
}
}
diff --git a/src/main/java/org/apache/commons/net/examples/mail/IMAPImportMbox.java b/src/main/java/org/apache/commons/net/examples/mail/IMAPImportMbox.java
index 373a990..2214c98 100644
--- a/src/main/java/org/apache/commons/net/examples/mail/IMAPImportMbox.java
+++ b/src/main/java/org/apache/commons/net/examples/mail/IMAPImportMbox.java
@@ -51,6 +51,34 @@ public final class IMAPImportMbox
private static final String CRLF = "\r\n";
private static final Pattern PATFROM = Pattern.compile(">+From "); // escaped From
+ private static String getDate(final String msg) {
+ // From SENDER Fri Sep 13 17:04:01 2019
+ final Pattern FROM_RE = Pattern.compile("From \\S+ +\\S+ (\\S+) ?(\\S+) (\\S+) (\\S+)");
+ // [Fri] Sep 13 HMS 2019
+ // output date: 13-Sep-2019 17:04:01 +0000
+ String date = null;
+ final Matcher m = FROM_RE.matcher(msg);
+ if (m.lookingAt()) {
+ date = m.group(2)+"-"+m.group(1)+"-"+m.group(4)+" "+m.group(3)+" +0000";
+ }
+ return date;
+ }
+
+ /**
+ * Is at least one entry in the list contained in the string?
+ * @param contains the list of strings to look for
+ * @param string the String to check against
+ * @return true if at least one entry in the contains list is contained in the string
+ */
+ private static boolean listContains(final List<String> contains, final String string) {
+ for(final String entry : contains) {
+ if (string.contains(entry)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static void main(final String[] args) throws IOException
{
if (args.length < 2)
@@ -146,24 +174,6 @@ public final class IMAPImportMbox
System.out.println("Processed " + total + " messages, loaded " + loaded);
}
- private static boolean startsWith(final String input, final Pattern pat) {
- final Matcher m = pat.matcher(input);
- return m.lookingAt();
- }
-
- private static String getDate(final String msg) {
- // From SENDER Fri Sep 13 17:04:01 2019
- final Pattern FROM_RE = Pattern.compile("From \\S+ +\\S+ (\\S+) ?(\\S+) (\\S+) (\\S+)");
- // [Fri] Sep 13 HMS 2019
- // output date: 13-Sep-2019 17:04:01 +0000
- String date = null;
- final Matcher m = FROM_RE.matcher(msg);
- if (m.lookingAt()) {
- date = m.group(2)+"-"+m.group(1)+"-"+m.group(4)+" "+m.group(3)+" +0000";
- }
- return date;
- }
-
private static boolean process(final StringBuilder sb, final IMAPClient imap, final String folder
,final int msgNum) throws IOException {
final int length = sb.length();
@@ -179,6 +189,11 @@ public final class IMAPImportMbox
return haveMessage;
}
+ private static boolean startsWith(final String input, final Pattern pat) {
+ final Matcher m = pat.matcher(input);
+ return m.lookingAt();
+ }
+
/**
* Is the message wanted?
*
@@ -194,19 +209,4 @@ public final class IMAPImportMbox
|| listContains(contains, line); // contains string
}
- /**
- * Is at least one entry in the list contained in the string?
- * @param contains the list of strings to look for
- * @param string the String to check against
- * @return true if at least one entry in the contains list is contained in the string
- */
- private static boolean listContains(final List<String> contains, final String string) {
- for(final String entry : contains) {
- if (string.contains(entry)) {
- return true;
- }
- }
- return false;
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/examples/mail/POP3ExportMbox.java b/src/main/java/org/apache/commons/net/examples/mail/POP3ExportMbox.java
index a5a1c59..db3bf93 100644
--- a/src/main/java/org/apache/commons/net/examples/mail/POP3ExportMbox.java
+++ b/src/main/java/org/apache/commons/net/examples/mail/POP3ExportMbox.java
@@ -168,6 +168,11 @@ public final class POP3ExportMbox
}
}
+ private static boolean startsWith(final String input, final Pattern pat) {
+ final Matcher m = pat.matcher(input);
+ return m.lookingAt();
+ }
+
private static void writeFile(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
String line;
@@ -200,10 +205,5 @@ public final class POP3ExportMbox
fw.write("\n");
}
}
-
- private static boolean startsWith(final String input, final Pattern pat) {
- final Matcher m = pat.matcher(input);
- return m.lookingAt();
- }
}
diff --git a/src/main/java/org/apache/commons/net/examples/mail/POP3Mail.java b/src/main/java/org/apache/commons/net/examples/mail/POP3Mail.java
index bc921ac..5ea2c86 100644
--- a/src/main/java/org/apache/commons/net/examples/mail/POP3Mail.java
+++ b/src/main/java/org/apache/commons/net/examples/mail/POP3Mail.java
@@ -38,23 +38,6 @@ import org.apache.commons.net.pop3.POP3SClient;
public final class POP3Mail
{
- public static void printMessageInfo(final BufferedReader reader, final int id) throws IOException {
- String from = "";
- String subject = "";
- String line;
- while ((line = reader.readLine()) != null)
- {
- final String lower = line.toLowerCase(Locale.ENGLISH);
- if (lower.startsWith("from: ")) {
- from = line.substring(6).trim();
- } else if (lower.startsWith("subject: ")) {
- subject = line.substring(9).trim();
- }
- }
-
- System.out.println(Integer.toString(id) + " From: " + from + " Subject: " + subject);
- }
-
public static void main(final String[] args)
{
if (args.length < 3)
@@ -172,5 +155,22 @@ public final class POP3Mail
return;
}
}
+
+ public static void printMessageInfo(final BufferedReader reader, final int id) throws IOException {
+ String from = "";
+ String subject = "";
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ final String lower = line.toLowerCase(Locale.ENGLISH);
+ if (lower.startsWith("from: ")) {
+ from = line.substring(6).trim();
+ } else if (lower.startsWith("subject: ")) {
+ subject = line.substring(9).trim();
+ }
+ }
+
+ System.out.println(Integer.toString(id) + " From: " + from + " Subject: " + subject);
+ }
}
diff --git a/src/main/java/org/apache/commons/net/examples/mail/Utils.java b/src/main/java/org/apache/commons/net/examples/mail/Utils.java
index 996c319..6408c10 100644
--- a/src/main/java/org/apache/commons/net/examples/mail/Utils.java
+++ b/src/main/java/org/apache/commons/net/examples/mail/Utils.java
@@ -28,10 +28,6 @@ import java.util.Locale;
*/
class Utils {
- private Utils() {
- // not instantiable
- }
-
/**
* If the initial password is:
* '*' - replace it with a line read from the system console
@@ -67,4 +63,8 @@ class Utils {
return password;
}
+ private Utils() {
+ // not instantiable
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/examples/nntp/ExtendedNNTPOps.java b/src/main/java/org/apache/commons/net/examples/nntp/ExtendedNNTPOps.java
index f640ba4..4e2961e 100644
--- a/src/main/java/org/apache/commons/net/examples/nntp/ExtendedNNTPOps.java
+++ b/src/main/java/org/apache/commons/net/examples/nntp/ExtendedNNTPOps.java
@@ -32,14 +32,27 @@ import org.apache.commons.net.nntp.NewsgroupInfo;
public class ExtendedNNTPOps {
+ public static void main(final String[] args) {
+ final ExtendedNNTPOps ops;
+
+ final int argc = args.length;
+ if (argc < 1) {
+ System.err.println("usage: ExtendedNNTPOps nntpserver [username password]");
+ System.exit(1);
+ }
+
+ ops = new ExtendedNNTPOps();
+ ops.demo(args[0], argc >=3 ? args[1] : null, argc >=3 ? args[2] : null);
+ }
+
private final NNTPClient client;
+
public ExtendedNNTPOps() {
client = new NNTPClient();
client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
}
-
private void demo(final String host, final String user, final String password) {
try {
client.connect(host);
@@ -81,17 +94,4 @@ public class ExtendedNNTPOps {
}
}
- public static void main(final String[] args) {
- final ExtendedNNTPOps ops;
-
- final int argc = args.length;
- if (argc < 1) {
- System.err.println("usage: ExtendedNNTPOps nntpserver [username password]");
- System.exit(1);
- }
-
- ops = new ExtendedNNTPOps();
- ops.demo(args[0], argc >=3 ? args[1] : null, argc >=3 ? args[2] : null);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/examples/nntp/MessageThreading.java b/src/main/java/org/apache/commons/net/examples/nntp/MessageThreading.java
index a692051..547ede8 100644
--- a/src/main/java/org/apache/commons/net/examples/nntp/MessageThreading.java
+++ b/src/main/java/org/apache/commons/net/examples/nntp/MessageThreading.java
@@ -32,9 +32,6 @@ import org.apache.commons.net.nntp.Threader;
* Sample program demonstrating the use of article iteration and threading.
*/
public class MessageThreading {
- public MessageThreading() {
- }
-
public static void main(final String[] args) throws SocketException, IOException {
if (args.length != 2 && args.length != 4) {
@@ -83,4 +80,7 @@ public class MessageThreading {
Article.printThread(root, 0);
}
+ public MessageThreading() {
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/examples/ntp/NTPClient.java b/src/main/java/org/apache/commons/net/examples/ntp/NTPClient.java
index 7e18a06..1f067f7 100644
--- a/src/main/java/org/apache/commons/net/examples/ntp/NTPClient.java
+++ b/src/main/java/org/apache/commons/net/examples/ntp/NTPClient.java
@@ -49,6 +49,37 @@ public final class NTPClient
private static final NumberFormat numberFormat = new java.text.DecimalFormat("0.00");
+ public static void main(final String[] args)
+ {
+ if (args.length == 0) {
+ System.err.println("Usage: NTPClient <hostname-or-address-list>");
+ System.exit(1);
+ }
+
+ final NTPUDPClient client = new NTPUDPClient();
+ // We want to timeout if a response takes longer than 10 seconds
+ client.setDefaultTimeout(10000);
+ try {
+ client.open();
+ for (final String arg : args)
+ {
+ System.out.println();
+ try {
+ final InetAddress hostAddr = InetAddress.getByName(arg);
+ System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress());
+ final TimeInfo info = client.getTime(hostAddr);
+ processResponse(info);
+ } catch (final IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ } catch (final SocketException e) {
+ e.printStackTrace();
+ }
+
+ client.close();
+ }
+
/**
* Process <code>TimeInfo</code> object and print its details.
* @param info <code>TimeInfo</code> object.
@@ -146,35 +177,4 @@ public final class NTPClient
+ ", clock offset(ms)=" + offset); // offset in ms
}
- public static void main(final String[] args)
- {
- if (args.length == 0) {
- System.err.println("Usage: NTPClient <hostname-or-address-list>");
- System.exit(1);
- }
-
- final NTPUDPClient client = new NTPUDPClient();
- // We want to timeout if a response takes longer than 10 seconds
- client.setDefaultTimeout(10000);
- try {
- client.open();
- for (final String arg : args)
- {
- System.out.println();
- try {
- final InetAddress hostAddr = InetAddress.getByName(arg);
- System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress());
- final TimeInfo info = client.getTime(hostAddr);
- processResponse(info);
- } catch (final IOException ioe) {
- ioe.printStackTrace();
- }
- }
- } catch (final SocketException e) {
- e.printStackTrace();
- }
-
- client.close();
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/examples/ntp/SimpleNTPServer.java b/src/main/java/org/apache/commons/net/examples/ntp/SimpleNTPServer.java
index 0b48dde..7b55d96 100644
--- a/src/main/java/org/apache/commons/net/examples/ntp/SimpleNTPServer.java
+++ b/src/main/java/org/apache/commons/net/examples/ntp/SimpleNTPServer.java
@@ -38,9 +38,28 @@ import org.apache.commons.net.ntp.TimeStamp;
*/
public class SimpleNTPServer implements Runnable {
+ public static void main(final String[] args)
+ {
+ int port = NtpV3Packet.NTP_PORT;
+ if (args.length != 0)
+ {
+ try {
+ port = Integer.parseInt(args[0]);
+ } catch (final NumberFormatException nfe) {
+ nfe.printStackTrace();
+ }
+ }
+ final SimpleNTPServer timeServer = new SimpleNTPServer(port);
+ try {
+ timeServer.start();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
private int port;
private volatile boolean running;
private boolean started;
+
private DatagramSocket socket;
/**
@@ -66,31 +85,6 @@ public class SimpleNTPServer implements Runnable {
this.port = port;
}
- public int getPort()
- {
- return port;
- }
-
- /**
- * Returns state of whether time service is running.
- *
- * @return true if time service is running
- */
- public boolean isRunning()
- {
- return running;
- }
-
- /**
- * Returns state of whether time service is running.
- *
- * @return true if time service is running
- */
- public boolean isStarted()
- {
- return started;
- }
-
/**
* Connects to server socket and listen for client connections.
*
@@ -109,46 +103,9 @@ public class SimpleNTPServer implements Runnable {
}
}
- /**
- * Starts time service and provide time to client connections.
- *
- * @throws java.io.IOException if an I/O error occurs when creating the socket.
- */
- public void start() throws IOException
- {
- if (socket == null)
- {
- connect();
- }
- if (!started)
- {
- started = true;
- new Thread(this).start();
- }
- }
-
- /**
- * Main method to service client connections.
- */
- @Override
- public void run()
+ public int getPort()
{
- running = true;
- final byte buffer[] = new byte[48];
- final DatagramPacket request = new DatagramPacket(buffer, buffer.length);
- do {
- try {
- socket.receive(request);
- final long rcvTime = System.currentTimeMillis();
- handlePacket(request, rcvTime);
- } catch (final IOException e) {
- if (running)
- {
- e.printStackTrace();
- }
- // otherwise socket thrown exception during shutdown
- }
- } while (running);
+ return port;
}
/**
@@ -196,6 +153,68 @@ public class SimpleNTPServer implements Runnable {
}
/**
+ * Returns state of whether time service is running.
+ *
+ * @return true if time service is running
+ */
+ public boolean isRunning()
+ {
+ return running;
+ }
+
+ /**
+ * Returns state of whether time service is running.
+ *
+ * @return true if time service is running
+ */
+ public boolean isStarted()
+ {
+ return started;
+ }
+
+ /**
+ * Main method to service client connections.
+ */
+ @Override
+ public void run()
+ {
+ running = true;
+ final byte buffer[] = new byte[48];
+ final DatagramPacket request = new DatagramPacket(buffer, buffer.length);
+ do {
+ try {
+ socket.receive(request);
+ final long rcvTime = System.currentTimeMillis();
+ handlePacket(request, rcvTime);
+ } catch (final IOException e) {
+ if (running)
+ {
+ e.printStackTrace();
+ }
+ // otherwise socket thrown exception during shutdown
+ }
+ } while (running);
+ }
+
+ /**
+ * Starts time service and provide time to client connections.
+ *
+ * @throws java.io.IOException if an I/O error occurs when creating the socket.
+ */
+ public void start() throws IOException
+ {
+ if (socket == null)
+ {
+ connect();
+ }
+ if (!started)
+ {
+ started = true;
+ new Thread(this).start();
+ }
+ }
+
+ /**
* Closes server socket and stop listening.
*/
public void stop()
@@ -209,23 +228,4 @@ public class SimpleNTPServer implements Runnable {
started = false;
}
- public static void main(final String[] args)
- {
- int port = NtpV3Packet.NTP_PORT;
- if (args.length != 0)
- {
- try {
- port = Integer.parseInt(args[0]);
- } catch (final NumberFormatException nfe) {
- nfe.printStackTrace();
- }
- }
- final SimpleNTPServer timeServer = new SimpleNTPServer(port);
- try {
- timeServer.start();
- } catch (final IOException e) {
- e.printStackTrace();
- }
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/examples/ntp/TimeClient.java b/src/main/java/org/apache/commons/net/examples/ntp/TimeClient.java
index 61619a1..967b0d7 100644
--- a/src/main/java/org/apache/commons/net/examples/ntp/TimeClient.java
+++ b/src/main/java/org/apache/commons/net/examples/ntp/TimeClient.java
@@ -38,30 +38,6 @@ import org.apache.commons.net.time.TimeUDPClient;
public final class TimeClient
{
- public static void timeTCP(final String host) throws IOException
- {
- final TimeTCPClient client = new TimeTCPClient();
- try {
- // We want to timeout if a response takes longer than 60 seconds
- client.setDefaultTimeout(60000);
- client.connect(host);
- System.out.println(client.getDate());
- } finally {
- client.disconnect();
- }
- }
-
- public static void timeUDP(final String host) throws IOException
- {
- final TimeUDPClient client = new TimeUDPClient();
-
- // We want to timeout if a response takes longer than 60 seconds
- client.setDefaultTimeout(60000);
- client.open();
- System.out.println(client.getDate(InetAddress.getByName(host)));
- client.close();
- }
-
public static void main(final String[] args)
{
@@ -97,5 +73,29 @@ public final class TimeClient
}
+ public static void timeTCP(final String host) throws IOException
+ {
+ final TimeTCPClient client = new TimeTCPClient();
+ try {
+ // We want to timeout if a response takes longer than 60 seconds
+ client.setDefaultTimeout(60000);
+ client.connect(host);
+ System.out.println(client.getDate());
+ } finally {
+ client.disconnect();
+ }
+ }
+
+ public static void timeUDP(final String host) throws IOException
+ {
+ final TimeUDPClient client = new TimeUDPClient();
+
+ // We want to timeout if a response takes longer than 60 seconds
+ client.setDefaultTimeout(60000);
+ client.open();
+ System.out.println(client.getDate(InetAddress.getByName(host)));
+ client.close();
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/examples/unix/rdate.java b/src/main/java/org/apache/commons/net/examples/unix/rdate.java
index 3bcdf5e..60edfe3 100644
--- a/src/main/java/org/apache/commons/net/examples/unix/rdate.java
+++ b/src/main/java/org/apache/commons/net/examples/unix/rdate.java
@@ -37,29 +37,6 @@ import org.apache.commons.net.time.TimeUDPClient;
public final class rdate
{
- public static void timeTCP(final String host) throws IOException
- {
- final TimeTCPClient client = new TimeTCPClient();
-
- // We want to timeout if a response takes longer than 60 seconds
- client.setDefaultTimeout(60000);
- client.connect(host);
- System.out.println(client.getDate().toString());
- client.disconnect();
- }
-
- public static void timeUDP(final String host) throws IOException
- {
- final TimeUDPClient client = new TimeUDPClient();
-
- // We want to timeout if a response takes longer than 60 seconds
- client.setDefaultTimeout(60000);
- client.open();
- System.out.println(client.getDate(InetAddress.getByName(host)).toString());
- client.close();
- }
-
-
public static void main(final String[] args)
{
@@ -95,5 +72,28 @@ public final class rdate
}
+ public static void timeTCP(final String host) throws IOException
+ {
+ final TimeTCPClient client = new TimeTCPClient();
+
+ // We want to timeout if a response takes longer than 60 seconds
+ client.setDefaultTimeout(60000);
+ client.connect(host);
+ System.out.println(client.getDate().toString());
+ client.disconnect();
+ }
+
+
+ public static void timeUDP(final String host) throws IOException
+ {
+ final TimeUDPClient client = new TimeUDPClient();
+
+ // We want to timeout if a response takes longer than 60 seconds
+ client.setDefaultTimeout(60000);
+ client.open();
+ System.out.println(client.getDate(InetAddress.getByName(host)).toString());
+ client.close();
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/finger/FingerClient.java b/src/main/java/org/apache/commons/net/finger/FingerClient.java
index 3a8e580..255175e 100644
--- a/src/main/java/org/apache/commons/net/finger/FingerClient.java
+++ b/src/main/java/org/apache/commons/net/finger/FingerClient.java
@@ -72,48 +72,20 @@ public class FingerClient extends SocketClient
/**
- * Fingers a user at the connected host and returns the output
- * as a String. You must first connect to a finger server before
- * calling this method, and you should disconnect afterward.
- *
- * @param longOutput Set to true if long output is requested, false if not.
- * @param username The name of the user to finger.
- * @return The result of the finger query.
- * @throws IOException If an I/O error occurs while reading the socket.
- */
- public String query(final boolean longOutput, final String username) throws IOException
- {
- int read;
- final StringBuilder result = new StringBuilder(buffer.length);
-
- try (final BufferedReader input = new BufferedReader(
- new InputStreamReader(getInputStream(longOutput, username), getCharset()))) {
- while (true) {
- read = input.read(buffer, 0, buffer.length);
- if (read <= 0) {
- break;
- }
- result.append(buffer, 0, read);
- }
- }
-
- return result.toString();
- }
-
-
- /**
- * Fingers the connected host and returns the output
- * as a String. You must first connect to a finger server before
- * calling this method, and you should disconnect afterward.
- * This is equivalent to calling <code> query(longOutput, "") </code>.
+ * Fingers the connected host and returns the input stream from
+ * the network connection of the finger query. This is equivalent to
+ * calling getInputStream(longOutput, ""). You must first connect to a
+ * finger server before calling this method, and you should disconnect
+ * after finishing reading the stream.
*
* @param longOutput Set to true if long output is requested, false if not.
- * @return The result of the finger query.
- * @throws IOException If an I/O error occurs while reading the socket.
+ * @return The InputStream of the network connection of the finger query.
+ * Can be read to obtain finger results.
+ * @throws IOException If an I/O error during the operation.
*/
- public String query(final boolean longOutput) throws IOException
+ public InputStream getInputStream(final boolean longOutput) throws IOException
{
- return query(longOutput, "");
+ return getInputStream(longOutput, "");
}
@@ -135,6 +107,7 @@ public class FingerClient extends SocketClient
return getInputStream(longOutput, username, null);
}
+
/**
* Fingers a user and returns the input stream from the network connection
* of the finger query. You must first connect to a finger server before
@@ -171,20 +144,47 @@ public class FingerClient extends SocketClient
}
/**
- * Fingers the connected host and returns the input stream from
- * the network connection of the finger query. This is equivalent to
- * calling getInputStream(longOutput, ""). You must first connect to a
- * finger server before calling this method, and you should disconnect
- * after finishing reading the stream.
+ * Fingers the connected host and returns the output
+ * as a String. You must first connect to a finger server before
+ * calling this method, and you should disconnect afterward.
+ * This is equivalent to calling <code> query(longOutput, "") </code>.
*
* @param longOutput Set to true if long output is requested, false if not.
- * @return The InputStream of the network connection of the finger query.
- * Can be read to obtain finger results.
- * @throws IOException If an I/O error during the operation.
+ * @return The result of the finger query.
+ * @throws IOException If an I/O error occurs while reading the socket.
*/
- public InputStream getInputStream(final boolean longOutput) throws IOException
+ public String query(final boolean longOutput) throws IOException
{
- return getInputStream(longOutput, "");
+ return query(longOutput, "");
+ }
+
+ /**
+ * Fingers a user at the connected host and returns the output
+ * as a String. You must first connect to a finger server before
+ * calling this method, and you should disconnect afterward.
+ *
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @param username The name of the user to finger.
+ * @return The result of the finger query.
+ * @throws IOException If an I/O error occurs while reading the socket.
+ */
+ public String query(final boolean longOutput, final String username) throws IOException
+ {
+ int read;
+ final StringBuilder result = new StringBuilder(buffer.length);
+
+ try (final BufferedReader input = new BufferedReader(
+ new InputStreamReader(getInputStream(longOutput, username), getCharset()))) {
+ while (true) {
+ read = input.read(buffer, 0, buffer.length);
+ if (read <= 0) {
+ break;
+ }
+ result.append(buffer, 0, read);
+ }
+ }
+
+ return result.toString();
}
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTP.java b/src/main/java/org/apache/commons/net/ftp/FTP.java
index 389e3e3..90fbcb4 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTP.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTP.java
@@ -275,21 +275,6 @@ public class FTP extends SocketClient
_commandSupport_ = new ProtocolCommandSupport(this);
}
- // The RFC-compliant multiline termination check
- private boolean strictCheck(final String line, final String code) {
- return !(line.startsWith(code) && line.charAt(REPLY_CODE_LEN) == ' ');
- }
-
- // The strict check is too strong a condition because of non-conforming ftp
- // servers like ftp.funet.fi which sent 226 as the last line of a
- // 426 multi-line reply in response to ls /. We relax the condition to
- // test that the line starts with a digit rather than starting with
- // the code.
- private boolean lenientCheck(final String line) {
- return !(line.length() > REPLY_CODE_LEN&& line.charAt(REPLY_CODE_LEN) != '-' &&
- Character.isDigit(line.charAt(0)));
- }
-
/**
* Get the reply, but don't pass it to command listeners.
* Used for keep-alive processing only.
@@ -301,83 +286,17 @@ public class FTP extends SocketClient
getReply(false);
}
- private int getReply(final boolean reportReply) throws IOException
- {
- final int length;
-
- _newReplyString = true;
- _replyLines.clear();
-
- String line = _controlInput_.readLine();
-
- if (line == null) {
- throw new FTPConnectionClosedException(
- "Connection closed without indication.");
- }
-
- // In case we run into an anomaly we don't want fatal index exceptions
- // to be thrown.
- length = line.length();
- if (length < REPLY_CODE_LEN) {
- throw new MalformedServerReplyException(
- "Truncated server reply: " + line);
- }
-
- String code = null;
- try
- {
- code = line.substring(0, REPLY_CODE_LEN);
- _replyCode = Integer.parseInt(code);
- }
- catch (final NumberFormatException e)
- {
- throw new MalformedServerReplyException(
- "Could not parse response code.\nServer Reply: " + line);
- }
-
- _replyLines.add(line);
-
- // Check the server reply type
- if (length > REPLY_CODE_LEN) {
- final char sep = line.charAt(REPLY_CODE_LEN);
- // Get extra lines if message continues.
- if (sep == '-') {
- do
- {
- line = _controlInput_.readLine();
-
- if (line == null) {
- throw new FTPConnectionClosedException(
- "Connection closed without indication.");
- }
-
- _replyLines.add(line);
-
- // The length() check handles problems that could arise from readLine()
- // returning too soon after encountering a naked CR or some other
- // anomaly.
- }
- while ( isStrictMultilineParsing() ? strictCheck(line, code) : lenientCheck(line));
-
- } else if (isStrictReplyParsing()) {
- if (length == REPLY_CODE_LEN + 1) { // expecting some text
- throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
- } else if (sep != ' ') {
- throw new MalformedServerReplyException("Invalid server reply: '" + line +"'");
- }
- }
- } else if (isStrictReplyParsing()) {
- throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
- }
-
- if (reportReply) {
- fireReplyReceived(_replyCode, getReplyString());
- }
-
- if (_replyCode == FTPReply.SERVICE_NOT_AVAILABLE) {
- throw new FTPConnectionClosedException("FTP response 421 received. Server closed connection.");
- }
- return _replyCode;
+ /**
+ * Send a noop and get the reply without reporting to the command listener.
+ * Intended for use with keep-alive.
+ *
+ * @throws IOException on error
+ * @since 3.0
+ */
+ protected void __noop() throws IOException {
+ final String msg = buildMessage(FTPCmd.NOOP.getCommand(), null);
+ send(msg);
+ __getReplyNoReport(); // This may timeout
}
/**
@@ -390,7 +309,6 @@ public class FTP extends SocketClient
_connectAction_(null);
}
-
/**
* Initiates control connections and gets initial reply.
* Initializes {@link #_controlInput_} and {@link #_controlOutput_}.
@@ -434,63 +352,51 @@ public class FTP extends SocketClient
}
}
-
/**
- * Saves the character encoding to be used by the FTP control connection.
- * Some FTP servers require that commands be issued in a non-ASCII
- * encoding like UTF-8 so that file names with multi-byte character
- * representations (e.g, Big 8) can be specified.
- * <p>
- * Please note that this has to be set before the connection is established.
+ * A convenience method to send the FTP ABOR command to the server,
+ * receive the reply, and return the reply code.
*
- * @param encoding The new character encoding for the control connection.
- */
- public void setControlEncoding(final String encoding) {
- _controlEncoding = encoding;
- }
-
-
- /**
- * @return The character encoding used to communicate over the
- * control connection.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
*/
- public String getControlEncoding() {
- return _controlEncoding;
+ public int abor() throws IOException
+ {
+ return sendCommand(FTPCmd.ABOR);
}
/**
- * Closes the control connection to the FTP server and sets to null
- * some internal data so that the memory may be reclaimed by the
- * garbage collector. The reply text and code information from the
- * last command is voided so that the memory it used may be reclaimed.
- * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
+ * A convenience method to send the FTP ACCT command to the server,
+ * receive the reply, and return the reply code.
*
- * @throws IOException If an error occurs while disconnecting.
+ * @param account The account name to access.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
*/
- @Override
- public void disconnect() throws IOException
+ public int acct(final String account) throws IOException
{
- super.disconnect();
- _controlInput_ = null;
- _controlOutput_ = null;
- _newReplyString = false;
- _replyString = null;
+ return sendCommand(FTPCmd.ACCT, account);
}
/**
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
*
- * @param command The text representation of the FTP command to send.
- * @param args The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
+ * @param bytes The number of bytes to allocate.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -499,77 +405,19 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int sendCommand(final String command, final String args) throws IOException
+ public int allo(final int bytes) throws IOException
{
- if (_controlOutput_ == null) {
- throw new IOException("Connection is not open");
- }
-
- final String message = buildMessage(command, args);
-
- send(message);
-
- fireCommandSent(command, message);
-
- return getReply();
- }
-
- private String buildMessage(final String command, final String args) {
- final StringBuilder __commandBuffer = new StringBuilder();
-
- __commandBuffer.append(command);
-
- if (args != null)
- {
- __commandBuffer.append(' ');
- __commandBuffer.append(args);
- }
- __commandBuffer.append(SocketClient.NETASCII_EOL);
- return __commandBuffer.toString();
- }
-
- private void send(final String message) throws IOException,
- FTPConnectionClosedException, SocketException {
- try{
- _controlOutput_.write(message);
- _controlOutput_.flush();
- }
- catch (final SocketException e)
- {
- if (!isConnected())
- {
- throw new FTPConnectionClosedException("Connection unexpectedly closed.");
- }
- throw e;
- }
+ return sendCommand(FTPCmd.ALLO, Integer.toString(bytes));
}
- /**
- * Send a noop and get the reply without reporting to the command listener.
- * Intended for use with keep-alive.
- *
- * @throws IOException on error
- * @since 3.0
- */
- protected void __noop() throws IOException {
- final String msg = buildMessage(FTPCmd.NOOP.getCommand(), null);
- send(msg);
- __getReplyNoReport(); // This may timeout
- }
/**
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
*
- * @param command The FTPCommand constant corresponding to the FTP command
- * to send.
- * @param args The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
+ * @param bytes The number of bytes to allocate.
+ * @param recordSize The size of a record.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -577,25 +425,20 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @deprecated (3.3) Use {@link #sendCommand(FTPCmd, String)} instead
*/
- @Deprecated
- public int sendCommand(final int command, final String args) throws IOException
+ public int allo(final int bytes, final int recordSize) throws IOException
{
- return sendCommand(FTPCommand.getCommand(command), args);
+ return sendCommand(FTPCmd.ALLO, Integer.toString(bytes) + " R " +
+ Integer.toString(recordSize));
}
+
/**
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
*
- * @param command The FTPCmd enum corresponding to the FTP command
- * to send.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
+ * @param bytes The number of bytes to allocate.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -603,25 +446,20 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.3
*/
- public int sendCommand(final FTPCmd command) throws IOException{
- return sendCommand(command, null);
+ public int allo(final long bytes) throws IOException
+ {
+ return sendCommand(FTPCmd.ALLO, Long.toString(bytes));
}
+
/**
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
*
- * @param command The FTPCmd enum corresponding to the FTP command
- * to send.
- * @param args The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
+ * @param bytes The number of bytes to allocate.
+ * @param recordSize The size of a record.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -629,22 +467,23 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.3
*/
- public int sendCommand(final FTPCmd command, final String args) throws IOException{
- return sendCommand(command.getCommand(), args);
+ public int allo(final long bytes, final int recordSize) throws IOException
+ {
+ return sendCommand(FTPCmd.ALLO, Long.toString(bytes) + " R " +
+ Integer.toString(recordSize));
}
/**
- * Sends an FTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
+ * A convenience method to send the FTP APPE command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param command The text representation of the FTP command to send.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -653,34 +492,305 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int sendCommand(final String command) throws IOException
+ public int appe(final String pathname) throws IOException
{
- return sendCommand(command, null);
+ return sendCommand(FTPCmd.APPE, pathname);
+ }
+
+ private String buildMessage(final String command, final String args) {
+ final StringBuilder __commandBuffer = new StringBuilder();
+
+ __commandBuffer.append(command);
+
+ if (args != null)
+ {
+ __commandBuffer.append(' ');
+ __commandBuffer.append(args);
+ }
+ __commandBuffer.append(SocketClient.NETASCII_EOL);
+ return __commandBuffer.toString();
+ }
+
+ /**
+ * A convenience method to send the FTP CDUP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int cdup() throws IOException
+ {
+ return sendCommand(FTPCmd.CDUP);
+ }
+
+ /**
+ * A convenience method to send the FTP CWD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param directory The new working directory.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int cwd(final String directory) throws IOException
+ {
+ return sendCommand(FTPCmd.CWD, directory);
+ }
+
+ /**
+ * A convenience method to send the FTP DELE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to delete.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int dele(final String pathname) throws IOException
+ {
+ return sendCommand(FTPCmd.DELE, pathname);
+ }
+
+ /**
+ * Closes the control connection to the FTP server and sets to null
+ * some internal data so that the memory may be reclaimed by the
+ * garbage collector. The reply text and code information from the
+ * last command is voided so that the memory it used may be reclaimed.
+ * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
+ *
+ * @throws IOException If an error occurs while disconnecting.
+ */
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _controlInput_ = null;
+ _controlOutput_ = null;
+ _newReplyString = false;
+ _replyString = null;
+ }
+
+ /**
+ * A convenience method to send the FTP EPRT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * Examples:
+ * <ul>
+ * <li>EPRT |1|132.235.1.2|6275|</li>
+ * <li>EPRT |2|1080::8:800:200C:417A|5282|</li>
+ * </ul>
+ *
+ * @see "http://www.faqs.org/rfcs/rfc2428.html"
+ *
+ * @param host The host owning the port.
+ * @param port The new port.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ * @since 2.2
+ */
+ public int eprt(final InetAddress host, final int port) throws IOException
+ {
+ final int num;
+ final StringBuilder info = new StringBuilder();
+ String h;
+
+ // If IPv6, trim the zone index
+ h = host.getHostAddress();
+ num = h.indexOf('%');
+ if (num > 0) {
+ h = h.substring(0, num);
+ }
+
+ info.append("|");
+
+ if (host instanceof Inet4Address) {
+ info.append("1");
+ } else if (host instanceof Inet6Address) {
+ info.append("2");
+ }
+ info.append("|");
+ info.append(h);
+ info.append("|");
+ info.append(port);
+ info.append("|");
+
+ return sendCommand(FTPCmd.EPRT, info.toString());
+ }
+
+
+ /**
+ * A convenience method to send the FTP EPSV command to the server,
+ * receive the reply, and return the reply code. Remember, it's up
+ * to you to interpret the reply string containing the host/port
+ * information.
+ *
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ * @since 2.2
+ */
+ public int epsv() throws IOException
+ {
+ return sendCommand(FTPCmd.EPSV);
+ }
+
+
+ /**
+ * A convenience method to send the FTP FEAT command to the server, receive the reply,
+ * and return the reply code.
+ * @return The reply code received by the server
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ * @since 2.2
+ */
+ public int feat() throws IOException
+ {
+ return sendCommand(FTPCmd.FEAT);
}
+ /**
+ * Provide command support to super-class
+ */
+ @Override
+ protected ProtocolCommandSupport getCommandSupport() {
+ return _commandSupport_;
+ }
+
+
+ /**
+ * @return The character encoding used to communicate over the
+ * control connection.
+ */
+ public String getControlEncoding() {
+ return _controlEncoding;
+ }
+
+ /**
+ * Fetches a reply from the FTP server and returns the integer reply
+ * code. After calling this method, the actual reply text can be accessed
+ * from either calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }. Only use this
+ * method if you are implementing your own FTP client or if you need to
+ * fetch a secondary response from the FTP server.
+ *
+ * @return The integer value of the reply code of the fetched FTP reply.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while receiving the
+ * server reply.
+ */
+ public int getReply() throws IOException
+ {
+ return getReply(true);
+ }
+
+ private int getReply(final boolean reportReply) throws IOException
+ {
+ final int length;
+
+ _newReplyString = true;
+ _replyLines.clear();
+
+ String line = _controlInput_.readLine();
+
+ if (line == null) {
+ throw new FTPConnectionClosedException(
+ "Connection closed without indication.");
+ }
+
+ // In case we run into an anomaly we don't want fatal index exceptions
+ // to be thrown.
+ length = line.length();
+ if (length < REPLY_CODE_LEN) {
+ throw new MalformedServerReplyException(
+ "Truncated server reply: " + line);
+ }
+
+ String code = null;
+ try
+ {
+ code = line.substring(0, REPLY_CODE_LEN);
+ _replyCode = Integer.parseInt(code);
+ }
+ catch (final NumberFormatException e)
+ {
+ throw new MalformedServerReplyException(
+ "Could not parse response code.\nServer Reply: " + line);
+ }
+
+ _replyLines.add(line);
+
+ // Check the server reply type
+ if (length > REPLY_CODE_LEN) {
+ final char sep = line.charAt(REPLY_CODE_LEN);
+ // Get extra lines if message continues.
+ if (sep == '-') {
+ do
+ {
+ line = _controlInput_.readLine();
+
+ if (line == null) {
+ throw new FTPConnectionClosedException(
+ "Connection closed without indication.");
+ }
+
+ _replyLines.add(line);
+
+ // The length() check handles problems that could arise from readLine()
+ // returning too soon after encountering a naked CR or some other
+ // anomaly.
+ }
+ while ( isStrictMultilineParsing() ? strictCheck(line, code) : lenientCheck(line));
+
+ } else if (isStrictReplyParsing()) {
+ if (length == REPLY_CODE_LEN + 1) { // expecting some text
+ throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
+ } else if (sep != ' ') {
+ throw new MalformedServerReplyException("Invalid server reply: '" + line +"'");
+ }
+ }
+ } else if (isStrictReplyParsing()) {
+ throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
+ }
+
+ if (reportReply) {
+ fireReplyReceived(_replyCode, getReplyString());
+ }
- /**
- * Sends an FTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The FTPCommand constant corresponding to the FTP command
- * to send.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int sendCommand(final int command) throws IOException
- {
- return sendCommand(command, null);
+ if (_replyCode == FTPReply.SERVICE_NOT_AVAILABLE) {
+ throw new FTPConnectionClosedException("FTP response 421 received. Server closed connection.");
+ }
+ return _replyCode;
}
@@ -698,54 +808,6 @@ public class FTP extends SocketClient
}
/**
- * Fetches a reply from the FTP server and returns the integer reply
- * code. After calling this method, the actual reply text can be accessed
- * from either calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }. Only use this
- * method if you are implementing your own FTP client or if you need to
- * fetch a secondary response from the FTP server.
- *
- * @return The integer value of the reply code of the fetched FTP reply.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while receiving the
- * server reply.
- */
- public int getReply() throws IOException
- {
- return getReply(true);
- }
-
-
- /**
- * Returns the lines of text from the last FTP server response as an array
- * of strings, one entry per line. The end of line markers of each are
- * stripped from each line.
- *
- * @return The lines of text from the last FTP response as an array.
- */
- public String[] getReplyStrings()
- {
- return _replyLines.toArray(NetConstants.EMPTY_STRING_ARRAY);
- }
-
- /**
- * Returns the nth line of text from the last FTP server response as a string. The end of line markers of each are
- * stripped from the line.
- *
- * @param index The index of the line to return, 0-based.
- *
- * @return The lines of text from the last FTP response as an array.
- */
- String getReplyString(final int index)
- {
- return _replyLines.get(index);
- }
-
- /**
* Returns the entire text of the last FTP server response exactly
* as it was received, including all end of line markers in NETASCII
* format.
@@ -772,66 +834,34 @@ public class FTP extends SocketClient
return _replyString = buffer.toString();
}
-
/**
- * A convenience method to send the FTP USER command to the server,
- * receive the reply, and return the reply code.
+ * Returns the nth line of text from the last FTP server response as a string. The end of line markers of each are
+ * stripped from the line.
*
- * @param username The username to login under.
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
+ * @param index The index of the line to return, 0-based.
+ *
+ * @return The lines of text from the last FTP response as an array.
*/
- public int user(final String username) throws IOException
+ String getReplyString(final int index)
{
- return sendCommand(FTPCmd.USER, username);
+ return _replyLines.get(index);
}
- /**
- * A convenience method to send the FTP PASS command to the server,
- * receive the reply, and return the reply code.
- * @param password The plain text password of the username being logged into.
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int pass(final String password) throws IOException
- {
- return sendCommand(FTPCmd.PASS, password);
- }
/**
- * A convenience method to send the FTP ACCT command to the server,
- * receive the reply, and return the reply code.
+ * Returns the lines of text from the last FTP server response as an array
+ * of strings, one entry per line. The end of line markers of each are
+ * stripped from each line.
*
- * @param account The account name to access.
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
+ * @return The lines of text from the last FTP response as an array.
*/
- public int acct(final String account) throws IOException
+ public String[] getReplyStrings()
{
- return sendCommand(FTPCmd.ACCT, account);
+ return _replyLines.toArray(NetConstants.EMPTY_STRING_ARRAY);
}
-
/**
- * A convenience method to send the FTP ABOR command to the server,
+ * A convenience method to send the FTP HELP command to the server,
* receive the reply, and return the reply code.
*
* @return The reply code received from the server.
@@ -843,16 +873,16 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int abor() throws IOException
+ public int help() throws IOException
{
- return sendCommand(FTPCmd.ABOR);
+ return sendCommand(FTPCmd.HELP);
}
/**
- * A convenience method to send the FTP CWD command to the server,
+ * A convenience method to send the FTP HELP command to the server,
* receive the reply, and return the reply code.
*
- * @param directory The new working directory.
+ * @param command The command name on which to request help.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -862,70 +892,51 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int cwd(final String directory) throws IOException
+ public int help(final String command) throws IOException
{
- return sendCommand(FTPCmd.CWD, directory);
+ return sendCommand(FTPCmd.HELP, command);
}
/**
- * A convenience method to send the FTP CDUP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
+ * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2.
+ * @return True if strict, false if lenient
+ * @since 2.0
*/
- public int cdup() throws IOException
- {
- return sendCommand(FTPCmd.CDUP);
+ public boolean isStrictMultilineParsing() {
+ return strictMultilineParsing;
}
/**
- * A convenience method to send the FTP QUIT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
+ * Return whether strict non-multiline parsing is enabled, as per RFC 959, section 4.2.
+ * <p>
+ * The default is true, which requires the 3 digit code be followed by space and some text.
+ * <br>
+ * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
+ * <br>
+ * @return True if strict (default), false if additional checks are not made
+ * @since 3.6
*/
- public int quit() throws IOException
- {
- return sendCommand(FTPCmd.QUIT);
+ public boolean isStrictReplyParsing() {
+ return strictReplyParsing;
}
- /**
- * A convenience method to send the FTP REIN command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int rein() throws IOException
- {
- return sendCommand(FTPCmd.REIN);
+ // The strict check is too strong a condition because of non-conforming ftp
+ // servers like ftp.funet.fi which sent 226 as the last line of a
+ // 426 multi-line reply in response to ls /. We relax the condition to
+ // test that the line starts with a digit rather than starting with
+ // the code.
+ private boolean lenientCheck(final String line) {
+ return !(line.length() > REPLY_CODE_LEN&& line.charAt(REPLY_CODE_LEN) != '-' &&
+ Character.isDigit(line.charAt(0)));
}
/**
- * A convenience method to send the FTP SMNT command to the server,
- * receive the reply, and return the reply code.
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param dir The directory name.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -935,56 +946,53 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int smnt(final String dir) throws IOException
+ public int list() throws IOException
{
- return sendCommand(FTPCmd.SMNT, dir);
+ return sendCommand(FTPCmd.LIST);
}
/**
- * A convenience method to send the FTP PORT command to the server,
- * receive the reply, and return the reply code.
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param host The host owning the port.
- * @param port The new port.
+ * @param pathname The pathname to list,
+ * may be {@code null} in which case the command is sent with no parameters
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
* to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int port(final InetAddress host, final int port) throws IOException
- {
- int num;
- final StringBuilder info = new StringBuilder(24);
-
- info.append(host.getHostAddress().replace('.', ','));
- num = port >>> 8;
- info.append(',');
- info.append(num);
- info.append(',');
- num = port & 0xff;
- info.append(num);
-
- return sendCommand(FTPCmd.PORT, info.toString());
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int list(final String pathname) throws IOException
+ {
+ return sendCommand(FTPCmd.LIST, pathname);
}
/**
- * A convenience method to send the FTP EPRT command to the server,
- * receive the reply, and return the reply code.
- *
- * Examples:
- * <ul>
- * <li>EPRT |1|132.235.1.2|6275|</li>
- * <li>EPRT |2|1080::8:800:200C:417A|5282|</li>
- * </ul>
+ * Sends the MDTM command for the given file.
*
- * @see "http://www.faqs.org/rfcs/rfc2428.html"
+ * @param file name of file
+ * @return the status
+ * @throws IOException on error
+ * @since 2.0
+ **/
+ public int mdtm(final String file) throws IOException
+ {
+ return sendCommand(FTPCmd.MDTM, file);
+ }
+
+ /**
+ * A convenience method to send the FTP MFMT command to the server,
+ * receive the reply, and return the reply code.
*
- * @param host The host owning the port.
- * @param port The new port.
+ * @param pathname The pathname for which mtime is to be changed
+ * @param timeval Timestamp in <code>YYYYMMDDhhmmss</code> format
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -994,42 +1002,18 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
* @since 2.2
- */
- public int eprt(final InetAddress host, final int port) throws IOException
+ * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
+ **/
+ public int mfmt(final String pathname, final String timeval) throws IOException
{
- final int num;
- final StringBuilder info = new StringBuilder();
- String h;
-
- // If IPv6, trim the zone index
- h = host.getHostAddress();
- num = h.indexOf('%');
- if (num > 0) {
- h = h.substring(0, num);
- }
-
- info.append("|");
-
- if (host instanceof Inet4Address) {
- info.append("1");
- } else if (host instanceof Inet6Address) {
- info.append("2");
- }
- info.append("|");
- info.append(h);
- info.append("|");
- info.append(port);
- info.append("|");
-
- return sendCommand(FTPCmd.EPRT, info.toString());
+ return sendCommand(FTPCmd.MFMT, timeval + " " + pathname);
}
/**
- * A convenience method to send the FTP PASV command to the server,
- * receive the reply, and return the reply code. Remember, it's up
- * to you to interpret the reply string containing the host/port
- * information.
+ * A convenience method to send the FTP MKD command to the server,
+ * receive the reply, and return the reply code.
*
+ * @param pathname The pathname of the new directory to create.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1039,16 +1023,18 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int pasv() throws IOException
+ public int mkd(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.PASV);
+ return sendCommand(FTPCmd.MKD, pathname);
}
- /**
- * A convenience method to send the FTP EPSV command to the server,
- * receive the reply, and return the reply code. Remember, it's up
- * to you to interpret the reply string containing the host/port
- * information.
+
+ /**
+ * A convenience method to send the FTP MLSD command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
@@ -1058,22 +1044,23 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 2.2
+ * @since 3.0
*/
- public int epsv() throws IOException
+ public int mlsd() throws IOException
{
- return sendCommand(FTPCmd.EPSV);
+ return sendCommand(FTPCmd.MLSD);
}
/**
- * A convenience method to send the FTP TYPE command for text files
- * to the server, receive the reply, and return the reply code.
- * @param fileType The type of the file (one of the <code>FILE_TYPE</code>
- * constants).
- * @param formatOrByteSize The format of the file (one of the
- * <code>_FORMAT</code> constants. In the case of
- * <code>LOCAL_FILE_TYPE</code>, the byte size.
- * @return The reply code received from the server.
+ * A convenience method to send the FTP MLSD command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param path the path to report on
+ * @return The reply code received from the server,
+ * may be {@code null} in which case the command is sent with no parameters
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1081,29 +1068,20 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @since 3.0
*/
- public int type(final int fileType, final int formatOrByteSize) throws IOException
+ public int mlsd(final String path) throws IOException
{
- final StringBuilder arg = new StringBuilder();
-
- arg.append(modes.charAt(fileType));
- arg.append(' ');
- if (fileType == LOCAL_FILE_TYPE) {
- arg.append(formatOrByteSize);
- } else {
- arg.append(modes.charAt(formatOrByteSize));
- }
-
- return sendCommand(FTPCmd.TYPE, arg.toString());
+ return sendCommand(FTPCmd.MLSD, path);
}
-
/**
- * A convenience method to send the FTP TYPE command to the server,
- * receive the reply, and return the reply code.
+ * A convenience method to send the FTP MLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param fileType The type of the file (one of the <code>FILE_TYPE</code>
- * constants).
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1112,20 +1090,23 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @since 3.0
*/
- public int type(final int fileType) throws IOException
+ public int mlst() throws IOException
{
- return sendCommand(FTPCmd.TYPE,
- modes.substring(fileType, fileType + 1));
+ return sendCommand(FTPCmd.MLST);
}
/**
- * A convenience method to send the FTP STRU command to the server,
- * receive the reply, and return the reply code.
+ * A convenience method to send the FTP MLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param structure The structure of the file (one of the
- * <code>_STRUCTURE</code> constants).
- * @return The reply code received from the server.
+ * @param path the path to report on
+ * @return The reply code received from the server,
+ * may be {@code null} in which case the command is sent with no parameters
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1133,11 +1114,11 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @since 3.0
*/
- public int stru(final int structure) throws IOException
+ public int mlst(final String path) throws IOException
{
- return sendCommand(FTPCmd.STRU,
- modes.substring(structure, structure + 1));
+ return sendCommand(FTPCmd.MLST, path);
}
/**
@@ -1162,13 +1143,12 @@ public class FTP extends SocketClient
}
/**
- * A convenience method to send the FTP RETR command to the server,
+ * A convenience method to send the FTP NLST command to the server,
* receive the reply, and return the reply code. Remember, it is up
* to you to manage the data connection. If you don't need this low
* level of access, use {@link org.apache.commons.net.ftp.FTPClient}
* , which will handle all low level details for you.
*
- * @param pathname The pathname of the file to retrieve.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1178,20 +1158,20 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int retr(final String pathname) throws IOException
+ public int nlst() throws IOException
{
- return sendCommand(FTPCmd.RETR, pathname);
+ return sendCommand(FTPCmd.NLST);
}
/**
- * A convenience method to send the FTP STOR command to the server,
+ * A convenience method to send the FTP NLST command to the server,
* receive the reply, and return the reply code. Remember, it is up
* to you to manage the data connection. If you don't need this low
* level of access, use {@link org.apache.commons.net.ftp.FTPClient}
* , which will handle all low level details for you.
*
- * @param pathname The pathname to use for the file when stored at
- * the remote end of the transfer.
+ * @param pathname The pathname to list,
+ * may be {@code null} in which case the command is sent with no parameters
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1201,17 +1181,14 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int stor(final String pathname) throws IOException
+ public int nlst(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.STOR, pathname);
+ return sendCommand(FTPCmd.NLST, pathname);
}
/**
- * A convenience method to send the FTP STOU command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP NOOP command to the server,
+ * receive the reply, and return the reply code.
*
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
@@ -1222,20 +1199,15 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int stou() throws IOException
+ public int noop() throws IOException
{
- return sendCommand(FTPCmd.STOU);
+ return sendCommand(FTPCmd.NOOP);
}
/**
- * A convenience method to send the FTP STOU command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- * @param pathname The base pathname to use for the file when stored at
- * the remote end of the transfer. Some FTP servers
- * require this.
+ * A convenience method to send the FTP PASS command to the server,
+ * receive the reply, and return the reply code.
+ * @param password The plain text password of the username being logged into.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1245,20 +1217,17 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int stou(final String pathname) throws IOException
+ public int pass(final String password) throws IOException
{
- return sendCommand(FTPCmd.STOU, pathname);
+ return sendCommand(FTPCmd.PASS, password);
}
/**
- * A convenience method to send the FTP APPE command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP PASV command to the server,
+ * receive the reply, and return the reply code. Remember, it's up
+ * to you to interpret the reply string containing the host/port
+ * information.
*
- * @param pathname The pathname to use for the file when stored at
- * the remote end of the transfer.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1268,16 +1237,17 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int appe(final String pathname) throws IOException
+ public int pasv() throws IOException
{
- return sendCommand(FTPCmd.APPE, pathname);
+ return sendCommand(FTPCmd.PASV);
}
/**
- * A convenience method to send the FTP ALLO command to the server,
+ * A convenience method to send the FTP PORT command to the server,
* receive the reply, and return the reply code.
*
- * @param bytes The number of bytes to allocate.
+ * @param host The host owning the port.
+ * @param port The new port.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1287,49 +1257,44 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int allo(final int bytes) throws IOException
+ public int port(final InetAddress host, final int port) throws IOException
{
- return sendCommand(FTPCmd.ALLO, Integer.toString(bytes));
+ int num;
+ final StringBuilder info = new StringBuilder(24);
+
+ info.append(host.getHostAddress().replace('.', ','));
+ num = port >>> 8;
+ info.append(',');
+ info.append(num);
+ info.append(',');
+ num = port & 0xff;
+ info.append(num);
+
+ return sendCommand(FTPCmd.PORT, info.toString());
}
/**
- * A convenience method to send the FTP ALLO command to the server,
+ * A convenience method to send the FTP PWD command to the server,
* receive the reply, and return the reply code.
*
- * @param bytes The number of bytes to allocate.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int allo(final long bytes) throws IOException
- {
- return sendCommand(FTPCmd.ALLO, Long.toString(bytes));
- }
-
- /**
- * A convenience method to send the FTP FEAT command to the server, receive the reply,
- * and return the reply code.
- * @return The reply code received by the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 2.2
*/
- public int feat() throws IOException
+ public int pwd() throws IOException
{
- return sendCommand(FTPCmd.FEAT);
+ return sendCommand(FTPCmd.PWD);
}
/**
- * A convenience method to send the FTP ALLO command to the server,
+ * A convenience method to send the FTP QUIT command to the server,
* receive the reply, and return the reply code.
*
- * @param bytes The number of bytes to allocate.
- * @param recordSize The size of a record.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1339,18 +1304,15 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int allo(final int bytes, final int recordSize) throws IOException
+ public int quit() throws IOException
{
- return sendCommand(FTPCmd.ALLO, Integer.toString(bytes) + " R " +
- Integer.toString(recordSize));
+ return sendCommand(FTPCmd.QUIT);
}
/**
- * A convenience method to send the FTP ALLO command to the server,
+ * A convenience method to send the FTP REIN command to the server,
* receive the reply, and return the reply code.
*
- * @param bytes The number of bytes to allocate.
- * @param recordSize The size of a record.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1360,12 +1322,12 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int allo(final long bytes, final int recordSize) throws IOException
+ public int rein() throws IOException
{
- return sendCommand(FTPCmd.ALLO, Long.toString(bytes) + " R " +
- Integer.toString(recordSize));
+ return sendCommand(FTPCmd.REIN);
}
+
/**
* A convenience method to send the FTP REST command to the server,
* receive the reply, and return the reply code.
@@ -1387,25 +1349,33 @@ public class FTP extends SocketClient
/**
- * Sends the MDTM command for the given file.
+ * A convenience method to send the FTP RETR command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
*
- * @param file name of file
- * @return the status
- * @throws IOException on error
- * @since 2.0
- **/
- public int mdtm(final String file) throws IOException
+ * @param pathname The pathname of the file to retrieve.
+ * @return The reply code received from the server.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int retr(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.MDTM, file);
+ return sendCommand(FTPCmd.RETR, pathname);
}
/**
- * A convenience method to send the FTP MFMT command to the server,
+ * A convenience method to send the FTP RMD command to the server,
* receive the reply, and return the reply code.
*
- * @param pathname The pathname for which mtime is to be changed
- * @param timeval Timestamp in <code>YYYYMMDDhhmmss</code> format
+ * @param pathname The pathname of the directory to remove.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1414,15 +1384,12 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 2.2
- * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
- **/
- public int mfmt(final String pathname, final String timeval) throws IOException
+ */
+ public int rmd(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.MFMT, timeval + " " + pathname);
+ return sendCommand(FTPCmd.RMD, pathname);
}
-
/**
* A convenience method to send the FTP RNFR command to the server,
* receive the reply, and return the reply code.
@@ -1461,12 +1428,33 @@ public class FTP extends SocketClient
return sendCommand(FTPCmd.RNTO, pathname);
}
+ private void send(final String message) throws IOException,
+ FTPConnectionClosedException, SocketException {
+ try{
+ _controlOutput_.write(message);
+ _controlOutput_.flush();
+ }
+ catch (final SocketException e)
+ {
+ if (!isConnected())
+ {
+ throw new FTPConnectionClosedException("Connection unexpectedly closed.");
+ }
+ throw e;
+ }
+ }
+
/**
- * A convenience method to send the FTP DELE command to the server,
- * receive the reply, and return the reply code.
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
*
- * @param pathname The pathname to delete.
- * @return The reply code received from the server.
+ * @param command The FTPCmd enum corresponding to the FTP command
+ * to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1474,18 +1462,75 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @since 3.3
*/
- public int dele(final String pathname) throws IOException
+ public int sendCommand(final FTPCmd command) throws IOException{
+ return sendCommand(command, null);
+ }
+
+ /**
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCmd enum corresponding to the FTP command
+ * to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ * @since 3.3
+ */
+ public int sendCommand(final FTPCmd command, final String args) throws IOException{
+ return sendCommand(command.getCommand(), args);
+ }
+
+ /**
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @throws FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @throws IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int sendCommand(final int command) throws IOException
{
- return sendCommand(FTPCmd.DELE, pathname);
+ return sendCommand(command, null);
}
/**
- * A convenience method to send the FTP RMD command to the server,
- * receive the reply, and return the reply code.
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
*
- * @param pathname The pathname of the directory to remove.
- * @return The reply code received from the server.
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1493,18 +1538,24 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @deprecated (3.3) Use {@link #sendCommand(FTPCmd, String)} instead
*/
- public int rmd(final String pathname) throws IOException
+ @Deprecated
+ public int sendCommand(final int command, final String args) throws IOException
{
- return sendCommand(FTPCmd.RMD, pathname);
+ return sendCommand(FTPCommand.getCommand(command), args);
}
/**
- * A convenience method to send the FTP MKD command to the server,
- * receive the reply, and return the reply code.
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
*
- * @param pathname The pathname of the new directory to create.
- * @return The reply code received from the server.
+ * @param command The text representation of the FTP command to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1513,16 +1564,23 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int mkd(final String pathname) throws IOException
+ public int sendCommand(final String command) throws IOException
{
- return sendCommand(FTPCmd.MKD, pathname);
+ return sendCommand(command, null);
}
/**
- * A convenience method to send the FTP PWD command to the server,
- * receive the reply, and return the reply code.
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
*
- * @return The reply code received from the server.
+ * @param command The text representation of the FTP command to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1531,18 +1589,65 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int pwd() throws IOException
+ public int sendCommand(final String command, final String args) throws IOException
{
- return sendCommand(FTPCmd.PWD);
+ if (_controlOutput_ == null) {
+ throw new IOException("Connection is not open");
+ }
+
+ final String message = buildMessage(command, args);
+
+ send(message);
+
+ fireCommandSent(command, message);
+
+ return getReply();
}
/**
- * A convenience method to send the FTP LIST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * Saves the character encoding to be used by the FTP control connection.
+ * Some FTP servers require that commands be issued in a non-ASCII
+ * encoding like UTF-8 so that file names with multi-byte character
+ * representations (e.g, Big 8) can be specified.
+ * <p>
+ * Please note that this has to be set before the connection is established.
+ *
+ * @param encoding The new character encoding for the control connection.
+ */
+ public void setControlEncoding(final String encoding) {
+ _controlEncoding = encoding;
+ }
+
+ /**
+ * Set strict multiline parsing.
+ * @param strictMultilineParsing the setting
+ * @since 2.0
+ */
+ public void setStrictMultilineParsing(final boolean strictMultilineParsing) {
+ this.strictMultilineParsing = strictMultilineParsing;
+ }
+
+ /**
+ * Set strict non-multiline parsing.
+ * <p>
+ * If true, it requires the 3 digit code be followed by space and some text.
+ * <br>
+ * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
+ * <p>
+ * <b>This should not be required by a well-behaved FTP server</b>
+ * <br>
+ * @param strictReplyParsing the setting
+ * @since 3.6
+ */
+ public void setStrictReplyParsing(final boolean strictReplyParsing) {
+ this.strictReplyParsing = strictReplyParsing;
+ }
+
+ /**
+ * A convenience method to send the FTP SITE command to the server,
+ * receive the reply, and return the reply code.
*
+ * @param parameters The site parameters to send.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1552,20 +1657,16 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int list() throws IOException
+ public int site(final String parameters) throws IOException
{
- return sendCommand(FTPCmd.LIST);
+ return sendCommand(FTPCmd.SITE, parameters);
}
/**
- * A convenience method to send the FTP LIST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP SIZE command to the server,
+ * receive the reply, and return the reply code.
*
- * @param pathname The pathname to list,
- * may be {@code null} in which case the command is sent with no parameters
+ * @param parameters The site parameters to send.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1574,19 +1675,18 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
+ * @since 3.7
*/
- public int list(final String pathname) throws IOException
+ public int size(final String parameters) throws IOException
{
- return sendCommand(FTPCmd.LIST, pathname);
+ return sendCommand(FTPCmd.SIZE, parameters);
}
/**
- * A convenience method to send the FTP MLSD command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP SMNT command to the server,
+ * receive the reply, and return the reply code.
*
+ * @param dir The directory name.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1595,23 +1695,17 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.0
*/
- public int mlsd() throws IOException
+ public int smnt(final String dir) throws IOException
{
- return sendCommand(FTPCmd.MLSD);
+ return sendCommand(FTPCmd.SMNT, dir);
}
/**
- * A convenience method to send the FTP MLSD command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
*
- * @param path the path to report on
- * @return The reply code received from the server,
- * may be {@code null} in which case the command is sent with no parameters
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1619,20 +1713,17 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.0
*/
- public int mlsd(final String path) throws IOException
+ public int stat() throws IOException
{
- return sendCommand(FTPCmd.MLSD, path);
+ return sendCommand(FTPCmd.STAT);
}
/**
- * A convenience method to send the FTP MLST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
*
+ * @param pathname A pathname to list.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1641,23 +1732,22 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.0
*/
- public int mlst() throws IOException
+ public int stat(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.MLST);
+ return sendCommand(FTPCmd.STAT, pathname);
}
/**
- * A convenience method to send the FTP MLST command to the server,
+ * A convenience method to send the FTP STOR command to the server,
* receive the reply, and return the reply code. Remember, it is up
* to you to manage the data connection. If you don't need this low
* level of access, use {@link org.apache.commons.net.ftp.FTPClient}
* , which will handle all low level details for you.
*
- * @param path the path to report on
- * @return The reply code received from the server,
- * may be {@code null} in which case the command is sent with no parameters
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
* of the client being idle or some other reason causing the server
@@ -1665,15 +1755,14 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.0
*/
- public int mlst(final String path) throws IOException
+ public int stor(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.MLST, path);
+ return sendCommand(FTPCmd.STOR, pathname);
}
/**
- * A convenience method to send the FTP NLST command to the server,
+ * A convenience method to send the FTP STOU command to the server,
* receive the reply, and return the reply code. Remember, it is up
* to you to manage the data connection. If you don't need this low
* level of access, use {@link org.apache.commons.net.ftp.FTPClient}
@@ -1688,20 +1777,20 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int nlst() throws IOException
+ public int stou() throws IOException
{
- return sendCommand(FTPCmd.NLST);
+ return sendCommand(FTPCmd.STOU);
}
/**
- * A convenience method to send the FTP NLST command to the server,
+ * A convenience method to send the FTP STOU command to the server,
* receive the reply, and return the reply code. Remember, it is up
* to you to manage the data connection. If you don't need this low
* level of access, use {@link org.apache.commons.net.ftp.FTPClient}
* , which will handle all low level details for you.
- *
- * @param pathname The pathname to list,
- * may be {@code null} in which case the command is sent with no parameters
+ * @param pathname The base pathname to use for the file when stored at
+ * the remote end of the transfer. Some FTP servers
+ * require this.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1711,35 +1800,22 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int nlst(final String pathname) throws IOException
+ public int stou(final String pathname) throws IOException
{
- return sendCommand(FTPCmd.NLST, pathname);
+ return sendCommand(FTPCmd.STOU, pathname);
}
- /**
- * A convenience method to send the FTP SITE command to the server,
- * receive the reply, and return the reply code.
- *
- * @param parameters The site parameters to send.
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int site(final String parameters) throws IOException
- {
- return sendCommand(FTPCmd.SITE, parameters);
+ // The RFC-compliant multiline termination check
+ private boolean strictCheck(final String line, final String code) {
+ return !(line.startsWith(code) && line.charAt(REPLY_CODE_LEN) == ' ');
}
/**
- * A convenience method to send the FTP SIZE command to the server,
+ * A convenience method to send the FTP STRU command to the server,
* receive the reply, and return the reply code.
*
- * @param parameters The site parameters to send.
+ * @param structure The structure of the file (one of the
+ * <code>_STRUCTURE</code> constants).
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1748,11 +1824,11 @@ public class FTP extends SocketClient
* as an IOException or independently as itself.
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
- * @since 3.7
*/
- public int size(final String parameters) throws IOException
+ public int stru(final int structure) throws IOException
{
- return sendCommand(FTPCmd.SIZE, parameters);
+ return sendCommand(FTPCmd.STRU,
+ modes.substring(structure, structure + 1));
}
/**
@@ -1774,9 +1850,11 @@ public class FTP extends SocketClient
}
/**
- * A convenience method to send the FTP STAT command to the server,
+ * A convenience method to send the FTP TYPE command to the server,
* receive the reply, and return the reply code.
*
+ * @param fileType The type of the file (one of the <code>FILE_TYPE</code>
+ * constants).
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1786,16 +1864,20 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int stat() throws IOException
+ public int type(final int fileType) throws IOException
{
- return sendCommand(FTPCmd.STAT);
+ return sendCommand(FTPCmd.TYPE,
+ modes.substring(fileType, fileType + 1));
}
/**
- * A convenience method to send the FTP STAT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname A pathname to list.
+ * A convenience method to send the FTP TYPE command for text files
+ * to the server, receive the reply, and return the reply code.
+ * @param fileType The type of the file (one of the <code>FILE_TYPE</code>
+ * constants).
+ * @param formatOrByteSize The format of the file (one of the
+ * <code>_FORMAT</code> constants. In the case of
+ * <code>LOCAL_FILE_TYPE</code>, the byte size.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1805,52 +1887,26 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int stat(final String pathname) throws IOException
+ public int type(final int fileType, final int formatOrByteSize) throws IOException
{
- return sendCommand(FTPCmd.STAT, pathname);
- }
+ final StringBuilder arg = new StringBuilder();
- /**
- * A convenience method to send the FTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int help() throws IOException
- {
- return sendCommand(FTPCmd.HELP);
- }
+ arg.append(modes.charAt(fileType));
+ arg.append(' ');
+ if (fileType == LOCAL_FILE_TYPE) {
+ arg.append(formatOrByteSize);
+ } else {
+ arg.append(modes.charAt(formatOrByteSize));
+ }
- /**
- * A convenience method to send the FTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @param command The command name on which to request help.
- * @return The reply code received from the server.
- * @throws FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @throws IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int help(final String command) throws IOException
- {
- return sendCommand(FTPCmd.HELP, command);
+ return sendCommand(FTPCmd.TYPE, arg.toString());
}
/**
- * A convenience method to send the FTP NOOP command to the server,
+ * A convenience method to send the FTP USER command to the server,
* receive the reply, and return the reply code.
*
+ * @param username The username to login under.
* @return The reply code received from the server.
* @throws FTPConnectionClosedException
* If the FTP server prematurely closes the connection as a result
@@ -1860,64 +1916,8 @@ public class FTP extends SocketClient
* @throws IOException If an I/O error occurs while either sending the
* command or receiving the server reply.
*/
- public int noop() throws IOException
+ public int user(final String username) throws IOException
{
- return sendCommand(FTPCmd.NOOP);
- }
-
- /**
- * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2.
- * @return True if strict, false if lenient
- * @since 2.0
- */
- public boolean isStrictMultilineParsing() {
- return strictMultilineParsing;
- }
-
- /**
- * Set strict multiline parsing.
- * @param strictMultilineParsing the setting
- * @since 2.0
- */
- public void setStrictMultilineParsing(final boolean strictMultilineParsing) {
- this.strictMultilineParsing = strictMultilineParsing;
- }
-
- /**
- * Return whether strict non-multiline parsing is enabled, as per RFC 959, section 4.2.
- * <p>
- * The default is true, which requires the 3 digit code be followed by space and some text.
- * <br>
- * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
- * <br>
- * @return True if strict (default), false if additional checks are not made
- * @since 3.6
- */
- public boolean isStrictReplyParsing() {
- return strictReplyParsing;
- }
-
- /**
- * Set strict non-multiline parsing.
- * <p>
- * If true, it requires the 3 digit code be followed by space and some text.
- * <br>
- * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
- * <p>
- * <b>This should not be required by a well-behaved FTP server</b>
- * <br>
- * @param strictReplyParsing the setting
- * @since 3.6
- */
- public void setStrictReplyParsing(final boolean strictReplyParsing) {
- this.strictReplyParsing = strictReplyParsing;
- }
-
- /**
- * Provide command support to super-class
- */
- @Override
- protected ProtocolCommandSupport getCommandSupport() {
- return _commandSupport_;
+ return sendCommand(FTPCmd.USER, username);
}
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java b/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java
index eaf97a4..8790167 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java
@@ -219,17 +219,142 @@ public class FTPClientConfig
// Full string is "MACOS Peter's Server"; the substring below should be enough
public static final String SYST_MACOS_PETER = "MACOS PETER"; // NET-436
+ private static final Map<String, Object> LANGUAGE_CODE_MAP = new TreeMap<>();
+ static {
+
+ // if there are other commonly used month name encodings which
+ // correspond to particular locales, please add them here.
+
+
+
+ // many locales code short names for months as all three letters
+ // these we handle simply.
+ LANGUAGE_CODE_MAP.put("en", Locale.ENGLISH);
+ LANGUAGE_CODE_MAP.put("de",Locale.GERMAN);
+ LANGUAGE_CODE_MAP.put("it",Locale.ITALIAN);
+ LANGUAGE_CODE_MAP.put("es", new Locale("es", "", "")); // spanish
+ LANGUAGE_CODE_MAP.put("pt", new Locale("pt", "", "")); // portuguese
+ LANGUAGE_CODE_MAP.put("da", new Locale("da", "", "")); // danish
+ LANGUAGE_CODE_MAP.put("sv", new Locale("sv", "", "")); // swedish
+ LANGUAGE_CODE_MAP.put("no", new Locale("no", "", "")); // norwegian
+ LANGUAGE_CODE_MAP.put("nl", new Locale("nl", "", "")); // dutch
+ LANGUAGE_CODE_MAP.put("ro", new Locale("ro", "", "")); // romanian
+ LANGUAGE_CODE_MAP.put("sq", new Locale("sq", "", "")); // albanian
+ LANGUAGE_CODE_MAP.put("sh", new Locale("sh", "", "")); // serbo-croatian
+ LANGUAGE_CODE_MAP.put("sk", new Locale("sk", "", "")); // slovak
+ LANGUAGE_CODE_MAP.put("sl", new Locale("sl", "", "")); // slovenian
+
+
+ // some don't
+ LANGUAGE_CODE_MAP.put("fr",
+ "jan|f\u00e9v|mar|avr|mai|jun|jui|ao\u00fb|sep|oct|nov|d\u00e9c"); //french
+
+ }
+ /**
+ * Returns a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ * @param shortmonths This should be as described in
+ * {@link #setShortMonthNames(String) shortMonthNames}
+ * @return a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ */
+ public static DateFormatSymbols getDateFormatSymbols(final String shortmonths)
+ {
+ final String[] months = splitShortMonthString(shortmonths);
+ final DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+ dfs.setShortMonths(months);
+ return dfs;
+ }
+ /**
+ * Returns a Collection of all the language codes currently supported
+ * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * for a functional descrption of language codes within this system.
+ *
+ * @return a Collection of all the language codes currently supported
+ * by this class
+ */
+ public static Collection<String> getSupportedLanguageCodes() {
+ return LANGUAGE_CODE_MAP.keySet();
+ }
+ /**
+ * Looks up the supplied language code in the internally maintained table of
+ * language codes. Returns a DateFormatSymbols object configured with
+ * short month names corresponding to the code. If there is no corresponding
+ * entry in the table, the object returned will be that for
+ * <code>Locale.US</code>
+ * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * @return a DateFormatSymbols object configured with short month names
+ * corresponding to the supplied code, or with month names for
+ * <code>Locale.US</code> if there is no corresponding entry in the internal
+ * table.
+ */
+ public static DateFormatSymbols lookupDateFormatSymbols(final String languageCode)
+ {
+ final Object lang = LANGUAGE_CODE_MAP.get(languageCode);
+ if (lang != null) {
+ if (lang instanceof Locale) {
+ return new DateFormatSymbols((Locale) lang);
+ } else if (lang instanceof String){
+ return getDateFormatSymbols((String) lang);
+ }
+ }
+ return new DateFormatSymbols(Locale.US);
+ }
+ private static String[] splitShortMonthString(final String shortmonths) {
+ final StringTokenizer st = new StringTokenizer(shortmonths, "|");
+ final int monthcnt = st.countTokens();
+ if (12 != monthcnt) {
+ throw new IllegalArgumentException(
+ "expecting a pipe-delimited string containing 12 tokens");
+ }
+ final String[] months = new String[13];
+ int pos = 0;
+ while(st.hasMoreTokens()) {
+ months[pos++] = st.nextToken();
+ }
+ months[pos]="";
+ return months;
+ }
private final String serverSystemKey;
private String defaultDateFormatStr;
+
+
private String recentDateFormatStr;
+
private boolean lenientFutureDates = true; // NET-407
+
private String serverLanguageCode;
+
private String shortMonthNames;
+
private String serverTimeZoneId;
+
private boolean saveUnparseableEntries;
+ /**
+ * Convenience constructor mainly for use in testing.
+ * Constructs a UNIX configuration.
+ */
+ public FTPClientConfig() {
+ this(SYST_UNIX);
+ }
/**
+ * Copy constructor
+ * @param config source
+ * @since 3.6
+ */
+ public FTPClientConfig(final FTPClientConfig config) {
+ this.serverSystemKey = config.serverSystemKey;
+ this.defaultDateFormatStr = config.defaultDateFormatStr;
+ this.lenientFutureDates = config.lenientFutureDates;
+ this.recentDateFormatStr = config.recentDateFormatStr;
+ this.saveUnparseableEntries = config.saveUnparseableEntries;
+ this.serverLanguageCode = config.serverLanguageCode;
+ this.serverTimeZoneId = config.serverTimeZoneId;
+ this.shortMonthNames = config.shortMonthNames;
+ }
+ /**
* The main constructor for an FTPClientConfig object
* @param systemKey key representing system type of the server being
* connected to. See {@link #getServerSystemKey() serverSystemKey}
@@ -241,12 +366,16 @@ public class FTPClientConfig
this.serverSystemKey = systemKey;
}
- /**
- * Convenience constructor mainly for use in testing.
- * Constructs a UNIX configuration.
- */
- public FTPClientConfig() {
- this(SYST_UNIX);
+ // Copy constructor, intended for use by FTPClient only
+ FTPClientConfig(final String systemKey, final FTPClientConfig config) {
+ this.serverSystemKey = systemKey;
+ this.defaultDateFormatStr = config.defaultDateFormatStr;
+ this.lenientFutureDates = config.lenientFutureDates;
+ this.recentDateFormatStr = config.recentDateFormatStr;
+ this.saveUnparseableEntries = config.saveUnparseableEntries;
+ this.serverLanguageCode = config.serverLanguageCode;
+ this.serverTimeZoneId = config.serverTimeZoneId;
+ this.shortMonthNames = config.shortMonthNames;
}
/**
@@ -339,67 +468,34 @@ public class FTPClientConfig
this.serverTimeZoneId = serverTimeZoneId;
}
- // Copy constructor, intended for use by FTPClient only
- FTPClientConfig(final String systemKey, final FTPClientConfig config) {
- this.serverSystemKey = systemKey;
- this.defaultDateFormatStr = config.defaultDateFormatStr;
- this.lenientFutureDates = config.lenientFutureDates;
- this.recentDateFormatStr = config.recentDateFormatStr;
- this.saveUnparseableEntries = config.saveUnparseableEntries;
- this.serverLanguageCode = config.serverLanguageCode;
- this.serverTimeZoneId = config.serverTimeZoneId;
- this.shortMonthNames = config.shortMonthNames;
- }
-
/**
- * Copy constructor
- * @param config source
- * @since 3.6
+ * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
+ * property.
+ * @return Returns the defaultDateFormatStr property.
*/
- public FTPClientConfig(final FTPClientConfig config) {
- this.serverSystemKey = config.serverSystemKey;
- this.defaultDateFormatStr = config.defaultDateFormatStr;
- this.lenientFutureDates = config.lenientFutureDates;
- this.recentDateFormatStr = config.recentDateFormatStr;
- this.saveUnparseableEntries = config.saveUnparseableEntries;
- this.serverLanguageCode = config.serverLanguageCode;
- this.serverTimeZoneId = config.serverTimeZoneId;
- this.shortMonthNames = config.shortMonthNames;
+ public String getDefaultDateFormatStr() {
+ return defaultDateFormatStr;
}
- private static final Map<String, Object> LANGUAGE_CODE_MAP = new TreeMap<>();
- static {
-
- // if there are other commonly used month name encodings which
- // correspond to particular locales, please add them here.
-
-
-
- // many locales code short names for months as all three letters
- // these we handle simply.
- LANGUAGE_CODE_MAP.put("en", Locale.ENGLISH);
- LANGUAGE_CODE_MAP.put("de",Locale.GERMAN);
- LANGUAGE_CODE_MAP.put("it",Locale.ITALIAN);
- LANGUAGE_CODE_MAP.put("es", new Locale("es", "", "")); // spanish
- LANGUAGE_CODE_MAP.put("pt", new Locale("pt", "", "")); // portuguese
- LANGUAGE_CODE_MAP.put("da", new Locale("da", "", "")); // danish
- LANGUAGE_CODE_MAP.put("sv", new Locale("sv", "", "")); // swedish
- LANGUAGE_CODE_MAP.put("no", new Locale("no", "", "")); // norwegian
- LANGUAGE_CODE_MAP.put("nl", new Locale("nl", "", "")); // dutch
- LANGUAGE_CODE_MAP.put("ro", new Locale("ro", "", "")); // romanian
- LANGUAGE_CODE_MAP.put("sq", new Locale("sq", "", "")); // albanian
- LANGUAGE_CODE_MAP.put("sh", new Locale("sh", "", "")); // serbo-croatian
- LANGUAGE_CODE_MAP.put("sk", new Locale("sk", "", "")); // slovak
- LANGUAGE_CODE_MAP.put("sl", new Locale("sl", "", "")); // slovenian
-
-
- // some don't
- LANGUAGE_CODE_MAP.put("fr",
- "jan|f\u00e9v|mar|avr|mai|jun|jui|ao\u00fb|sep|oct|nov|d\u00e9c"); //french
+ /**
+ * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property.
+ * @return Returns the recentDateFormatStr property.
+ */
+ public String getRecentDateFormatStr() {
+ return recentDateFormatStr;
}
/**
+ * <p>
+ * getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property.
+ * </p>
+ * @return Returns the serverLanguageCode property.
+ */
+ public String getServerLanguageCode() {
+ return serverLanguageCode;
+ }
+ /**
* Getter for the serverSystemKey property. This property
* specifies the general type of server to which the client connects.
* Should be either one of the <code>FTPClientConfig.SYST_*</code> codes
@@ -413,24 +509,6 @@ public class FTPClientConfig
}
/**
- * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
- * property.
- * @return Returns the defaultDateFormatStr property.
- */
- public String getDefaultDateFormatStr() {
- return defaultDateFormatStr;
- }
-
- /**
- * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property.
- * @return Returns the recentDateFormatStr property.
- */
-
- public String getRecentDateFormatStr() {
- return recentDateFormatStr;
- }
-
- /**
* getter for the {@link #setServerTimeZoneId(String) serverTimeZoneId} property.
* @return Returns the serverTimeZoneId property.
*/
@@ -448,15 +526,15 @@ public class FTPClientConfig
public String getShortMonthNames() {
return shortMonthNames;
}
-
/**
+ * @return true if list parsing should return FTPFile entries even for unparseable response lines
* <p>
- * getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property.
- * </p>
- * @return Returns the serverLanguageCode property.
+ * If true, the FTPFile for any unparseable entries will contain only the unparsed entry
+ * {@link FTPFile#getRawListing()} and {@link FTPFile#isValid()} will return {@code false}
+ * @since 3.4
*/
- public String getServerLanguageCode() {
- return serverLanguageCode;
+ public boolean getUnparseableEntries() {
+ return this.saveUnparseableEntries;
}
/**
@@ -469,6 +547,7 @@ public class FTPClientConfig
public boolean isLenientFutureDates() {
return lenientFutureDates;
}
+
/**
* <p>
* setter for the defaultDateFormatStr property. This property
@@ -489,27 +568,6 @@ public class FTPClientConfig
/**
* <p>
- * setter for the recentDateFormatStr property. This property
- * specifies a secondary date format that will be used by a parser
- * configured by this configuration to parse file timestamps, typically
- * those less than a year old. If this is not specified, such a parser
- * will not attempt to parse using an alternate format.
- * </p>
- * <p>
- * This is used primarily in unix-based systems.
- * </p>
- * <p>
- * This should be in the format described for
- * <code>java.text.SimpleDateFormat</code>.
- * </p>
- * @param recentDateFormatStr The recentDateFormatStr to set.
- */
- public void setRecentDateFormatStr(final String recentDateFormatStr) {
- this.recentDateFormatStr = recentDateFormatStr;
- }
-
- /**
- * <p>
* setter for the lenientFutureDates property. This boolean property
* (default: true) only has meaning when a
* {@link #setRecentDateFormatStr(String) recentDateFormatStr} property
@@ -531,43 +589,26 @@ public class FTPClientConfig
public void setLenientFutureDates(final boolean lenientFutureDates) {
this.lenientFutureDates = lenientFutureDates;
}
+
/**
* <p>
- * setter for the serverTimeZoneId property. This property
- * allows a time zone to be specified corresponding to that known to be
- * used by an FTP server in file listings. This might be particularly
- * useful to clients such as Ant that try to use these timestamps for
- * dependency checking.
- * </p><p>
- * This should be one of the identifiers used by
- * <code>java.util.TimeZone</code> to refer to time zones, for example,
- * <code>America/Chicago</code> or <code>Asia/Rangoon</code>.
+ * setter for the recentDateFormatStr property. This property
+ * specifies a secondary date format that will be used by a parser
+ * configured by this configuration to parse file timestamps, typically
+ * those less than a year old. If this is not specified, such a parser
+ * will not attempt to parse using an alternate format.
* </p>
- * @param serverTimeZoneId The serverTimeZoneId to set.
- */
- public void setServerTimeZoneId(final String serverTimeZoneId) {
- this.serverTimeZoneId = serverTimeZoneId;
- }
-
- /**
* <p>
- * setter for the shortMonthNames property.
- * This property allows the user to specify a set of month names
- * used by the server that is different from those that may be
- * specified using the {@link #setServerLanguageCode(String) serverLanguageCode}
- * property.
- * </p><p>
- * This should be a string containing twelve strings each composed of
- * three characters, delimited by pipe (|) characters. Currently,
- * only 8-bit ASCII characters are known to be supported. For example,
- * a set of month names used by a hypothetical Icelandic FTP server might
- * conceivably be specified as
- * <code>"jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des"</code>.
+ * This is used primarily in unix-based systems.
* </p>
- * @param shortMonthNames The value to set to the shortMonthNames property.
+ * <p>
+ * This should be in the format described for
+ * <code>java.text.SimpleDateFormat</code>.
+ * </p>
+ * @param recentDateFormatStr The recentDateFormatStr to set.
*/
- public void setShortMonthNames(final String shortMonthNames) {
- this.shortMonthNames = shortMonthNames;
+ public void setRecentDateFormatStr(final String recentDateFormatStr) {
+ this.recentDateFormatStr = recentDateFormatStr;
}
/**
@@ -615,72 +656,42 @@ public class FTPClientConfig
}
/**
- * Looks up the supplied language code in the internally maintained table of
- * language codes. Returns a DateFormatSymbols object configured with
- * short month names corresponding to the code. If there is no corresponding
- * entry in the table, the object returned will be that for
- * <code>Locale.US</code>
- * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode}
- * @return a DateFormatSymbols object configured with short month names
- * corresponding to the supplied code, or with month names for
- * <code>Locale.US</code> if there is no corresponding entry in the internal
- * table.
- */
- public static DateFormatSymbols lookupDateFormatSymbols(final String languageCode)
- {
- final Object lang = LANGUAGE_CODE_MAP.get(languageCode);
- if (lang != null) {
- if (lang instanceof Locale) {
- return new DateFormatSymbols((Locale) lang);
- } else if (lang instanceof String){
- return getDateFormatSymbols((String) lang);
- }
- }
- return new DateFormatSymbols(Locale.US);
- }
-
- /**
- * Returns a DateFormatSymbols object configured with short month names
- * as in the supplied string
- * @param shortmonths This should be as described in
- * {@link #setShortMonthNames(String) shortMonthNames}
- * @return a DateFormatSymbols object configured with short month names
- * as in the supplied string
+ * <p>
+ * setter for the serverTimeZoneId property. This property
+ * allows a time zone to be specified corresponding to that known to be
+ * used by an FTP server in file listings. This might be particularly
+ * useful to clients such as Ant that try to use these timestamps for
+ * dependency checking.
+ * </p><p>
+ * This should be one of the identifiers used by
+ * <code>java.util.TimeZone</code> to refer to time zones, for example,
+ * <code>America/Chicago</code> or <code>Asia/Rangoon</code>.
+ * </p>
+ * @param serverTimeZoneId The serverTimeZoneId to set.
*/
- public static DateFormatSymbols getDateFormatSymbols(final String shortmonths)
- {
- final String[] months = splitShortMonthString(shortmonths);
- final DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
- dfs.setShortMonths(months);
- return dfs;
- }
-
- private static String[] splitShortMonthString(final String shortmonths) {
- final StringTokenizer st = new StringTokenizer(shortmonths, "|");
- final int monthcnt = st.countTokens();
- if (12 != monthcnt) {
- throw new IllegalArgumentException(
- "expecting a pipe-delimited string containing 12 tokens");
- }
- final String[] months = new String[13];
- int pos = 0;
- while(st.hasMoreTokens()) {
- months[pos++] = st.nextToken();
- }
- months[pos]="";
- return months;
+ public void setServerTimeZoneId(final String serverTimeZoneId) {
+ this.serverTimeZoneId = serverTimeZoneId;
}
/**
- * Returns a Collection of all the language codes currently supported
- * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode}
- * for a functional descrption of language codes within this system.
- *
- * @return a Collection of all the language codes currently supported
- * by this class
+ * <p>
+ * setter for the shortMonthNames property.
+ * This property allows the user to specify a set of month names
+ * used by the server that is different from those that may be
+ * specified using the {@link #setServerLanguageCode(String) serverLanguageCode}
+ * property.
+ * </p><p>
+ * This should be a string containing twelve strings each composed of
+ * three characters, delimited by pipe (|) characters. Currently,
+ * only 8-bit ASCII characters are known to be supported. For example,
+ * a set of month names used by a hypothetical Icelandic FTP server might
+ * conceivably be specified as
+ * <code>"jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des"</code>.
+ * </p>
+ * @param shortMonthNames The value to set to the shortMonthNames property.
*/
- public static Collection<String> getSupportedLanguageCodes() {
- return LANGUAGE_CODE_MAP.keySet();
+ public void setShortMonthNames(final String shortMonthNames) {
+ this.shortMonthNames = shortMonthNames;
}
/**
@@ -695,15 +706,4 @@ public class FTPClientConfig
this.saveUnparseableEntries = saveUnparseable;
}
- /**
- * @return true if list parsing should return FTPFile entries even for unparseable response lines
- * <p>
- * If true, the FTPFile for any unparseable entries will contain only the unparsed entry
- * {@link FTPFile#getRawListing()} and {@link FTPFile#isValid()} will return {@code false}
- * @since 3.4
- */
- public boolean getUnparseableEntries() {
- return this.saveUnparseableEntries;
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPCommand.java b/src/main/java/org/apache/commons/net/ftp/FTPCommand.java
index 0b69b92..528f679 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPCommand.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPCommand.java
@@ -134,10 +134,6 @@ public final class FTPCommand
/** @since 2.2 */
public static final int SET_MOD_TIME = MFMT;
- // Cannot be instantiated
- private FTPCommand()
- {}
-
private static final String[] _commands = {
"USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "REIN", "QUIT", "PORT",
"PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO",
@@ -145,17 +141,17 @@ public final class FTPCommand
"NLST", "SITE", "SYST", "STAT", "HELP", "NOOP", "MDTM", "FEAT", "MFMT",
"EPSV", "EPRT", "MLSD", "MLST" };
-
-
// default access needed for Unit test
- static void checkArray(){
- final int expectedLength = LAST+1;
+ static void checkArray() {
+ final int expectedLength = LAST + 1;
if (_commands.length != expectedLength) {
- throw new RuntimeException("Incorrect _commands array. Should have length "
- +expectedLength+" found "+_commands.length);
+ throw new RuntimeException(
+ "Incorrect _commands array. Should have length " + expectedLength + " found " + _commands.length);
}
}
+
+
/**
* Retrieve the FTP protocol command string corresponding to a specified
* command code.
@@ -168,4 +164,8 @@ public final class FTPCommand
{
return _commands[command];
}
+
+ // Cannot be instantiated
+ private FTPCommand()
+ {}
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParser.java b/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParser.java
index 8ff1afb..9fa7987 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParser.java
@@ -92,21 +92,6 @@ public interface FTPFileEntryParser
FTPFile parseFTPEntry(String listEntry);
/**
- * Reads the next entry using the supplied BufferedReader object up to
- * whatever delemits one entry from the next. Implementors must define
- * this for the particular ftp system being parsed. In many but not all
- * cases, this can be defined simply by calling BufferedReader.readLine().
- *
- * @param reader The BufferedReader object from which entries are to be
- * read.
- *
- * @return A string representing the next ftp entry or null if none found.
- * @throws IOException thrown on any IO Error reading from the reader.
- */
- String readNextEntry(BufferedReader reader) throws IOException;
-
-
- /**
* This method is a hook for those implementors (such as
* VMSVersioningFTPEntryParser, and possibly others) which need to
* perform some action upon the FTPFileList after it has been created
@@ -121,4 +106,19 @@ public interface FTPFileEntryParser
List<String> preParse(List<String> original);
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delemits one entry from the next. Implementors must define
+ * this for the particular ftp system being parsed. In many but not all
+ * cases, this can be defined simply by calling BufferedReader.readLine().
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @throws IOException thrown on any IO Error reading from the reader.
+ */
+ String readNextEntry(BufferedReader reader) throws IOException;
+
+
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java b/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
index 4240b95..f76722a 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
@@ -37,22 +37,6 @@ public abstract class FTPFileEntryParserImpl
}
/**
- * Reads the next entry using the supplied BufferedReader object up to
- * whatever delimits one entry from the next. This default implementation
- * simply calls BufferedReader.readLine().
- *
- * @param reader The BufferedReader object from which entries are to be
- * read.
- *
- * @return A string representing the next ftp entry or null if none found.
- * @throws java.io.IOException thrown on any IO Error reading from the reader.
- */
- @Override
- public String readNextEntry(final BufferedReader reader) throws IOException
- {
- return reader.readLine();
- }
- /**
* This method is a hook for those implementors (such as
* VMSVersioningFTPEntryParser, and possibly others) which need to
* perform some action upon the FTPFileList after it has been created
@@ -68,4 +52,20 @@ public abstract class FTPFileEntryParserImpl
public List<String> preParse(final List<String> original) {
return original;
}
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delimits one entry from the next. This default implementation
+ * simply calls BufferedReader.readLine().
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @throws java.io.IOException thrown on any IO Error reading from the reader.
+ */
+ @Override
+ public String readNextEntry(final BufferedReader reader) throws IOException
+ {
+ return reader.readLine();
+ }
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPHTTPClient.java b/src/main/java/org/apache/commons/net/ftp/FTPHTTPClient.java
index b51d046..8e1ab42 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPHTTPClient.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPHTTPClient.java
@@ -40,68 +40,68 @@ import org.apache.commons.net.util.Base64;
* @since 2.2
*/
public class FTPHTTPClient extends FTPClient {
+ private static final byte[] CRLF={'\r', '\n'};
private final String proxyHost;
private final int proxyPort;
private final String proxyUsername;
private final String proxyPassword;
- private final Charset charset;
- private static final byte[] CRLF={'\r', '\n'};
+ private final Charset charset;
private final Base64 base64 = new Base64();
private String tunnelHost; // Save the host when setting up a tunnel (needed for EPSV)
/**
- * Create an instance with the specified encoding
+ * Create an instance using the UTF-8 encoding, with no proxy credentials.
*
* @param proxyHost the hostname to use
* @param proxyPort the port to use
- * @param proxyUser the user name for the proxy
- * @param proxyPass the password for the proxy
- * @param encoding the encoding to use
*/
- public FTPHTTPClient(final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPass,
- final Charset encoding) {
- this.proxyHost = proxyHost;
- this.proxyPort = proxyPort;
- this.proxyUsername = proxyUser;
- this.proxyPassword = proxyPass;
- this.tunnelHost = null;
- this.charset = encoding;
+ public FTPHTTPClient(final String proxyHost, final int proxyPort) {
+ this(proxyHost, proxyPort, null, null);
}
/**
- * Create an instance using the UTF-8 encoding
+ * Create an instance using the specified encoding, with no proxy credentials.
*
* @param proxyHost the hostname to use
* @param proxyPort the port to use
- * @param proxyUser the user name for the proxy
- * @param proxyPass the password for the proxy
+ * @param encoding the encoding to use
*/
- public FTPHTTPClient(final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPass) {
- this(proxyHost, proxyPort, proxyUser, proxyPass, StandardCharsets.UTF_8);
+ public FTPHTTPClient(final String proxyHost, final int proxyPort, final Charset encoding) {
+ this(proxyHost, proxyPort, null, null, encoding);
}
/**
- * Create an instance using the UTF-8 encoding, with no proxy credentials.
+ * Create an instance using the UTF-8 encoding
*
* @param proxyHost the hostname to use
* @param proxyPort the port to use
+ * @param proxyUser the user name for the proxy
+ * @param proxyPass the password for the proxy
*/
- public FTPHTTPClient(final String proxyHost, final int proxyPort) {
- this(proxyHost, proxyPort, null, null);
+ public FTPHTTPClient(final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPass) {
+ this(proxyHost, proxyPort, proxyUser, proxyPass, StandardCharsets.UTF_8);
}
/**
- * Create an instance using the specified encoding, with no proxy credentials.
+ * Create an instance with the specified encoding
*
* @param proxyHost the hostname to use
* @param proxyPort the port to use
+ * @param proxyUser the user name for the proxy
+ * @param proxyPass the password for the proxy
* @param encoding the encoding to use
*/
- public FTPHTTPClient(final String proxyHost, final int proxyPort, final Charset encoding) {
- this(proxyHost, proxyPort, null, null, encoding);
+ public FTPHTTPClient(final String proxyHost, final int proxyPort, final String proxyUser, final String proxyPass,
+ final Charset encoding) {
+ this.proxyHost = proxyHost;
+ this.proxyPort = proxyPort;
+ this.proxyUsername = proxyUser;
+ this.proxyPassword = proxyPass;
+ this.tunnelHost = null;
+ this.charset = encoding;
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java b/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
index 5ffe0c7..44abe3c 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
@@ -75,18 +75,18 @@ import org.apache.commons.net.util.Charsets;
* uses this class transparently.
*/
public class FTPListParseEngine {
+ /**
+ * An empty immutable {@code FTPFile} array.
+ */
+ private static final FTPFile[] EMPTY_FTP_FILE_ARRAY = new FTPFile[0];
private List<String> entries = new LinkedList<>();
- private ListIterator<String> internalIterator = entries.listIterator();
+ private ListIterator<String> internalIterator = entries.listIterator();
private final FTPFileEntryParser parser;
+
// Should invalid files (parse failures) be allowed?
private final boolean saveUnparseableEntries;
- /**
- * An empty immutable {@code FTPFile} array.
- */
- private static final FTPFile[] EMPTY_FTP_FILE_ARRAY = new FTPFile[0];
-
public FTPListParseEngine(final FTPFileEntryParser parser) {
this(parser, null);
}
@@ -105,44 +105,55 @@ public class FTPListParseEngine {
}
/**
- * Reads (and closes) the initial reading and preparsing of the list returned by the server. After this method has
- * completed, this object will contain a list of unparsed entries (Strings) each referring to a unique file on the
- * server.
- *
- * @param inputStream input stream provided by the server socket.
- * @param charsetName the encoding to be used for reading the stream
+ * Returns an array of FTPFile objects containing the whole list of
+ * files returned by the server as read by this object's parser.
*
- * @throws IOException thrown on any failure to read from the sever.
+ * @return an array of FTPFile objects containing the whole list of
+ * files returned by the server as read by this object's parser.
+ * None of the entries will be null
+ * @throws IOException - not ever thrown, may be removed in a later release
*/
- public void readServerList(final InputStream inputStream, final String charsetName) throws IOException {
- this.entries = new LinkedList<>();
- read(inputStream, charsetName);
- this.parser.preParse(this.entries);
- resetIterator();
+ public FTPFile[] getFiles()
+ throws IOException // TODO remove; not actually thrown
+ {
+ return getFiles(FTPFileFilters.NON_NULL);
}
/**
- * Internal method for reading (and closing) the input into the <code>entries</code> list. After this method has
- * completed, <code>entries</code> will contain a collection of entries (as defined by
- * <code>FTPFileEntryParser.readNextEntry()</code>), but this may contain various non-entry preliminary lines from
- * the server output, duplicates, and other data that will not be part of the final listing.
+ * Returns an array of FTPFile objects containing the whole list of
+ * files returned by the server as read by this object's parser.
+ * The files are filtered before being added to the array.
*
- * @param inputStream The socket stream on which the input will be read.
- * @param charsetName The encoding to use.
+ * @param filter FTPFileFilter, must not be <code>null</code>.
*
- * @throws IOException thrown on any failure to read the stream
+ * @return an array of FTPFile objects containing the whole list of
+ * files returned by the server as read by this object's parser.
+ * <p><b>
+ * NOTE:</b> This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it, or use the
+ * a filter such as {@link FTPFileFilters#NON_NULL} which does not
+ * allow null entries.
+ * @since 2.2
+ * @throws IOException - not ever thrown, may be removed in a later release
*/
- private void read(final InputStream inputStream, final String charsetName) throws IOException {
- try (final BufferedReader reader = new BufferedReader(
- new InputStreamReader(inputStream, Charsets.toCharset(charsetName)))) {
-
- String line = this.parser.readNextEntry(reader);
-
- while (line != null) {
- this.entries.add(line);
- line = this.parser.readNextEntry(reader);
+ public FTPFile[] getFiles(final FTPFileFilter filter)
+ throws IOException // TODO remove; not actually thrown
+ {
+ final List<FTPFile> tmpResults = new ArrayList<>();
+ final Iterator<String> iter = this.entries.iterator();
+ while (iter.hasNext()) {
+ final String entry = iter.next();
+ FTPFile temp = this.parser.parseFTPEntry(entry);
+ if (temp == null && saveUnparseableEntries) {
+ temp = new FTPFile(entry);
+ }
+ if (filter.accept(temp)) {
+ tmpResults.add(temp);
}
}
+ return tmpResults.toArray(EMPTY_FTP_FILE_ARRAY);
+
}
/**
@@ -226,58 +237,6 @@ public class FTPListParseEngine {
}
/**
- * Returns an array of FTPFile objects containing the whole list of
- * files returned by the server as read by this object's parser.
- *
- * @return an array of FTPFile objects containing the whole list of
- * files returned by the server as read by this object's parser.
- * None of the entries will be null
- * @throws IOException - not ever thrown, may be removed in a later release
- */
- public FTPFile[] getFiles()
- throws IOException // TODO remove; not actually thrown
- {
- return getFiles(FTPFileFilters.NON_NULL);
- }
-
- /**
- * Returns an array of FTPFile objects containing the whole list of
- * files returned by the server as read by this object's parser.
- * The files are filtered before being added to the array.
- *
- * @param filter FTPFileFilter, must not be <code>null</code>.
- *
- * @return an array of FTPFile objects containing the whole list of
- * files returned by the server as read by this object's parser.
- * <p><b>
- * NOTE:</b> This array may contain null members if any of the
- * individual file listings failed to parse. The caller should
- * check each entry for null before referencing it, or use the
- * a filter such as {@link FTPFileFilters#NON_NULL} which does not
- * allow null entries.
- * @since 2.2
- * @throws IOException - not ever thrown, may be removed in a later release
- */
- public FTPFile[] getFiles(final FTPFileFilter filter)
- throws IOException // TODO remove; not actually thrown
- {
- final List<FTPFile> tmpResults = new ArrayList<>();
- final Iterator<String> iter = this.entries.iterator();
- while (iter.hasNext()) {
- final String entry = iter.next();
- FTPFile temp = this.parser.parseFTPEntry(entry);
- if (temp == null && saveUnparseableEntries) {
- temp = new FTPFile(entry);
- }
- if (filter.accept(temp)) {
- tmpResults.add(temp);
- }
- }
- return tmpResults.toArray(EMPTY_FTP_FILE_ARRAY);
-
- }
-
- /**
* convenience method to allow clients to know whether this object's
* internal iterator's current position is at the end of the list.
*
@@ -300,13 +259,28 @@ public class FTPListParseEngine {
}
/**
- * resets this object's internal iterator to the beginning of the list.
+ * Internal method for reading (and closing) the input into the <code>entries</code> list. After this method has
+ * completed, <code>entries</code> will contain a collection of entries (as defined by
+ * <code>FTPFileEntryParser.readNextEntry()</code>), but this may contain various non-entry preliminary lines from
+ * the server output, duplicates, and other data that will not be part of the final listing.
+ *
+ * @param inputStream The socket stream on which the input will be read.
+ * @param charsetName The encoding to use.
+ *
+ * @throws IOException thrown on any failure to read the stream
*/
- public void resetIterator() {
- this.internalIterator = this.entries.listIterator();
- }
+ private void read(final InputStream inputStream, final String charsetName) throws IOException {
+ try (final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(inputStream, Charsets.toCharset(charsetName)))) {
- // DEPRECATED METHODS - for API compatibility only - DO NOT USE
+ String line = this.parser.readNextEntry(reader);
+
+ while (line != null) {
+ this.entries.add(line);
+ line = this.parser.readNextEntry(reader);
+ }
+ }
+ }
/**
* Do not use.
@@ -319,4 +293,30 @@ public class FTPListParseEngine {
readServerList(inputStream, null);
}
+ /**
+ * Reads (and closes) the initial reading and preparsing of the list returned by the server. After this method has
+ * completed, this object will contain a list of unparsed entries (Strings) each referring to a unique file on the
+ * server.
+ *
+ * @param inputStream input stream provided by the server socket.
+ * @param charsetName the encoding to be used for reading the stream
+ *
+ * @throws IOException thrown on any failure to read from the sever.
+ */
+ public void readServerList(final InputStream inputStream, final String charsetName) throws IOException {
+ this.entries = new LinkedList<>();
+ read(inputStream, charsetName);
+ this.parser.preParse(this.entries);
+ resetIterator();
+ }
+
+ // DEPRECATED METHODS - for API compatibility only - DO NOT USE
+
+ /**
+ * resets this object's internal iterator to the beginning of the list.
+ */
+ public void resetIterator() {
+ this.internalIterator = this.entries.listIterator();
+ }
+
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPReply.java b/src/main/java/org/apache/commons/net/ftp/FTPReply.java
index 30db15e..70aff16 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPReply.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPReply.java
@@ -99,25 +99,34 @@ public final class FTPReply
/** @since 2.2 */
public static final int EXTENDED_PORT_FAILURE = 522;
- // Cannot be instantiated
- private FTPReply()
- {}
+ /**
+ * Determine if a reply code is a negative permanent response. All
+ * codes beginning with a 5 are negative permanent responses.
+ * The FTP server will send a negative permanent response on the
+ * failure of a command that cannot be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative permanent response, false
+ * if not.
+ */
+ public static boolean isNegativePermanent(final int reply)
+ {
+ return reply >= 500 && reply < 600;
+ }
/**
- * Determine if a reply code is a positive preliminary response. All
- * codes beginning with a 1 are positive preliminary responses.
- * Postitive preliminary responses are used to indicate tentative success.
- * No further commands can be issued to the FTP server after a positive
- * preliminary response until a follow up response is received from the
- * server.
+ * Determine if a reply code is a negative transient response. All
+ * codes beginning with a 4 are negative transient responses.
+ * The FTP server will send a negative transient response on the
+ * failure of a command that can be reattempted with success.
*
* @param reply The reply code to test.
- * @return True if a reply code is a positive preliminary response, false
+ * @return True if a reply code is a negative transient response, false
* if not.
*/
- public static boolean isPositivePreliminary(final int reply)
+ public static boolean isNegativeTransient(final int reply)
{
- return reply >= 100 && reply < 200;
+ return reply >= 400 && reply < 500;
}
/**
@@ -154,33 +163,20 @@ public final class FTPReply
}
/**
- * Determine if a reply code is a negative transient response. All
- * codes beginning with a 4 are negative transient responses.
- * The FTP server will send a negative transient response on the
- * failure of a command that can be reattempted with success.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative transient response, false
- * if not.
- */
- public static boolean isNegativeTransient(final int reply)
- {
- return reply >= 400 && reply < 500;
- }
-
- /**
- * Determine if a reply code is a negative permanent response. All
- * codes beginning with a 5 are negative permanent responses.
- * The FTP server will send a negative permanent response on the
- * failure of a command that cannot be reattempted with success.
+ * Determine if a reply code is a positive preliminary response. All
+ * codes beginning with a 1 are positive preliminary responses.
+ * Postitive preliminary responses are used to indicate tentative success.
+ * No further commands can be issued to the FTP server after a positive
+ * preliminary response until a follow up response is received from the
+ * server.
*
* @param reply The reply code to test.
- * @return True if a reply code is a negative permanent response, false
+ * @return True if a reply code is a positive preliminary response, false
* if not.
*/
- public static boolean isNegativePermanent(final int reply)
+ public static boolean isPositivePreliminary(final int reply)
{
- return reply >= 500 && reply < 600;
+ return reply >= 100 && reply < 200;
}
/**
@@ -197,5 +193,9 @@ public final class FTPReply
return reply >= 600 && reply < 700;
}
+ // Cannot be instantiated
+ private FTPReply()
+ {}
+
}
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPSClient.java b/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
index 9f50584..d5e863c 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
@@ -83,6 +83,18 @@ public class FTPSClient extends FTPClient {
/** The CCC (Clear Command Channel) command. */
private static final String CMD_CCC = "CCC";
+ /** @deprecated - not used - may be removed in a future release */
+ @Deprecated
+ public static String KEYSTORE_ALGORITHM;
+ /** @deprecated - not used - may be removed in a future release */
+ @Deprecated
+ public static String TRUSTSTORE_ALGORITHM;
+ /** @deprecated - not used - may be removed in a future release */
+ @Deprecated
+ public static String PROVIDER;
+ /** @deprecated - not used - may be removed in a future release */
+ @Deprecated
+ public static String STORE_TYPE;
/** The security mode. (True - Implicit Mode / False - Explicit Mode) */
private final boolean isImplicit;
/** The secure socket protocol to be used, e.g. SSL/TLS. */
@@ -97,12 +109,16 @@ public class FTPSClient extends FTPClient {
private boolean isCreation = true;
/** The use client mode flag. */
private boolean isClientMode = true;
+
/** The need client auth flag. */
private boolean isNeedClientAuth;
+
/** The want client auth flag. */
private boolean isWantClientAuth;
+
/** The cipher suites */
private String[] suites;
+
/** The protocol versions */
private String[] protocols;
@@ -138,30 +154,6 @@ public class FTPSClient extends FTPClient {
this(DEFAULT_PROTOCOL, isImplicit);
}
- /**
- * Constructor for FTPSClient, using explict mode, calls {@link #FTPSClient(String, boolean)}.
- *
- * @param protocol the protocol to use
- */
- public FTPSClient(final String protocol) {
- this(protocol, false);
- }
-
- /**
- * Constructor for FTPSClient allowing specification of protocol
- * and security mode. If isImplicit is true, the port is set to
- * {@link #DEFAULT_FTPS_PORT} i.e. 990.
- * The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
- * @param protocol the protocol
- * @param isImplicit The security mode(Implicit/Explicit).
- */
- public FTPSClient(final String protocol, final boolean isImplicit) {
- this.protocol = protocol;
- this.isImplicit = isImplicit;
- if (isImplicit) {
- setDefaultPort(DEFAULT_FTPS_PORT);
- }
- }
/**
* Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS
@@ -186,23 +178,30 @@ public class FTPSClient extends FTPClient {
/**
- * Set AUTH command use value.
- * This processing is done before connected processing.
- * @param auth AUTH command use value.
+ * Constructor for FTPSClient, using explict mode, calls {@link #FTPSClient(String, boolean)}.
+ *
+ * @param protocol the protocol to use
*/
- public void setAuthValue(final String auth) {
- this.auth = auth;
+ public FTPSClient(final String protocol) {
+ this(protocol, false);
}
/**
- * Return AUTH command use value.
- * @return AUTH command use value.
+ * Constructor for FTPSClient allowing specification of protocol
+ * and security mode. If isImplicit is true, the port is set to
+ * {@link #DEFAULT_FTPS_PORT} i.e. 990.
+ * The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
+ * @param protocol the protocol
+ * @param isImplicit The security mode(Implicit/Explicit).
*/
- public String getAuthValue() {
- return this.auth;
+ public FTPSClient(final String protocol, final boolean isImplicit) {
+ this.protocol = protocol;
+ this.isImplicit = isImplicit;
+ if (isImplicit) {
+ setDefaultPort(DEFAULT_FTPS_PORT);
+ }
}
-
/**
* Because there are so many connect() methods,
* the _connectAction_() method is provided as a means of performing
@@ -227,227 +226,256 @@ public class FTPSClient extends FTPClient {
}
/**
- * AUTH command.
- * @throws SSLException If it server reply code not equal "234" and "334".
- * @throws IOException If an I/O error occurs while either sending
- * the command.
- */
- protected void execAUTH() throws SSLException, IOException {
- final int replyCode = sendCommand(CMD_AUTH, auth);
- if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
- // replyCode = 334
- // I carry out an ADAT command.
- } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
- throw new SSLException(getReplyString());
- }
- }
-
- /**
- * Performs a lazy init of the SSL context
- * @throws IOException
+ * Returns a socket of the data connection.
+ * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
+ * @param command The int representation of the FTP command to send.
+ * @param arg The arguments to the FTP command.
+ * If this parameter is set to null, then the command is sent with
+ * no arguments.
+ * @return corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at any point
+ * during the establishment and initialization of the connection.
+ * @throws IOException If there is any problem with the connection.
+ * @see FTPClient#_openDataConnection_(int, String)
+ * @deprecated (3.3) Use {@link FTPClient#_openDataConnection_(FTPCmd, String)} instead
*/
- private void initSslContext() throws IOException {
- if (context == null) {
- context = SSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
- }
+ @Override
+ // Strictly speaking this is not needed, but it works round a Clirr bug
+ // So rather than invoke the parent code, we do it here
+ @Deprecated
+ protected Socket _openDataConnection_(final int command, final String arg)
+ throws IOException {
+ return _openDataConnection_(FTPCommand.getCommand(command), arg);
}
/**
- * SSL/TLS negotiation. Acquires an SSL socket of a control
- * connection and carries out handshake processing.
- * @throws IOException If server negotiation fails
- */
- protected void sslNegotiation() throws IOException {
- plainSocket = _socket_;
- initSslContext();
- final SSLSocket socket = createSSLSocket(_socket_);
- socket.setEnableSessionCreation(isCreation);
- socket.setUseClientMode(isClientMode);
-
- // client mode
- if (isClientMode) {
- if (tlsEndpointChecking) {
- SSLSocketUtils.enableEndpointNameVerification(socket);
+ * Returns a socket of the data connection.
+ * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
+ * @param command The textual representation of the FTP command to send.
+ * @param arg The arguments to the FTP command.
+ * If this parameter is set to null, then the command is sent with
+ * no arguments.
+ * @return corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at any point
+ * during the establishment and initialization of the connection.
+ * @throws IOException If there is any problem with the connection.
+ * @see FTPClient#_openDataConnection_(int, String)
+ * @since 3.2
+ */
+ @Override
+ protected Socket _openDataConnection_(final String command, final String arg)
+ throws IOException {
+ final Socket socket = super._openDataConnection_(command, arg);
+ _prepareDataSocket_(socket);
+ if (socket instanceof SSLSocket) {
+ final SSLSocket sslSocket = (SSLSocket)socket;
+
+ sslSocket.setUseClientMode(isClientMode);
+ sslSocket.setEnableSessionCreation(isCreation);
+
+ // server mode
+ if (!isClientMode) {
+ sslSocket.setNeedClientAuth(isNeedClientAuth);
+ sslSocket.setWantClientAuth(isWantClientAuth);
+ }
+ if (suites != null) {
+ sslSocket.setEnabledCipherSuites(suites);
+ }
+ if (protocols != null) {
+ sslSocket.setEnabledProtocols(protocols);
+ }
+ sslSocket.startHandshake();
}
- } else { // server mode
- socket.setNeedClientAuth(isNeedClientAuth);
- socket.setWantClientAuth(isWantClientAuth);
- }
- if (protocols != null) {
- socket.setEnabledProtocols(protocols);
- }
- if (suites != null) {
- socket.setEnabledCipherSuites(suites);
+ return socket;
}
- socket.startHandshake();
- // TODO the following setup appears to duplicate that in the super class methods
- _socket_ = socket;
- _controlInput_ = new BufferedReader(new InputStreamReader(
- socket .getInputStream(), getControlEncoding()));
- _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
- socket.getOutputStream(), getControlEncoding()));
+ /**
+ * Performs any custom initialization for a newly created SSLSocket (before
+ * the SSL handshake happens).
+ * Called by {@link #_openDataConnection_(int, String)} immediately
+ * after creating the socket.
+ * The default implementation is a no-op
+ * @param socket the socket to set up
+ * @throws IOException on error
+ * @since 3.1
+ */
+ protected void _prepareDataSocket_(final Socket socket)
+ throws IOException {
+ }
- if (isClientMode) {
- if (hostnameVerifier != null &&
- !hostnameVerifier.verify(_hostname_, socket.getSession())) {
- throw new SSLHandshakeException("Hostname doesn't match certificate");
+ /**
+ * Check the value that can be set in PROT Command value.
+ * @param prot Data Channel Protection Level.
+ * @return True - A set point is right / False - A set point is not right
+ */
+ private boolean checkPROTValue(final String prot) {
+ for (final String element : PROT_COMMAND_VALUE)
+ {
+ if (element.equals(prot)) {
+ return true;
}
}
+ return false;
}
/**
- * Get the {@link KeyManager} instance.
- * @return The {@link KeyManager} instance
+ * Create SSL socket from plain socket.
+ *
+ * @param socket
+ * @return SSL Socket
+ * @throws IOException
*/
- private KeyManager getKeyManager() {
- return keyManager;
+ private SSLSocket createSSLSocket(final Socket socket) throws IOException {
+ if (socket != null) {
+ final SSLSocketFactory f = context.getSocketFactory();
+ return (SSLSocket) f.createSocket(socket, _hostname_, socket.getPort(), false);
+ }
+ return null;
}
/**
- * Set a {@link KeyManager} to use
- *
- * @param keyManager The KeyManager implementation to set.
- * @see org.apache.commons.net.util.KeyManagerUtils
- */
- public void setKeyManager(final KeyManager keyManager) {
- this.keyManager = keyManager;
+ * Closes the connection to the FTP server and restores
+ * connection parameters to the default values.
+ * <p>
+ * Calls {@code setSocketFactory(null)} and {@code setServerSocketFactory(null)}
+ * to reset the factories that may have been changed during the session,
+ * e.g. by {@link #execPROT(String)}
+ * @throws IOException If an error occurs while disconnecting.
+ * @since 3.0
+ */
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ if (plainSocket != null) {
+ plainSocket.close();
+ }
+ setSocketFactory(null);
+ setServerSocketFactory(null);
}
/**
- * Controls whether a new SSL session may be established by this socket.
- * @param isCreation The established socket flag.
+ * Send the ADAT command with the specified authentication data.
+ * @param data The data to send with the command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public void setEnabledSessionCreation(final boolean isCreation) {
- this.isCreation = isCreation;
+ public int execADAT(final byte[] data) throws IOException
+ {
+ if (data != null)
+ {
+ return sendCommand(CMD_ADAT, Base64.encodeBase64StringUnChunked(data));
+ }
+ return sendCommand(CMD_ADAT);
}
/**
- * Returns true if new SSL sessions may be established by this socket.
- * When the underlying {@link Socket} instance is not SSL-enabled (i.e. an
- * instance of {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled,
- * this returns False.
- * @return true - Indicates that sessions may be created;
- * this is the default.
- * false - indicates that an existing session must be resumed.
+ * AUTH command.
+ * @throws SSLException If it server reply code not equal "234" and "334".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
*/
- public boolean getEnableSessionCreation() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getEnableSessionCreation();
+ protected void execAUTH() throws SSLException, IOException {
+ final int replyCode = sendCommand(CMD_AUTH, auth);
+ if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
+ // replyCode = 334
+ // I carry out an ADAT command.
+ } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
+ throw new SSLException(getReplyString());
}
- return false;
}
/**
- * Configures the socket to require client authentication.
- * @param isNeedClientAuth The need client auth flag.
+ * Send the AUTH command with the specified mechanism.
+ * @param mechanism The mechanism name to send with the command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public void setNeedClientAuth(final boolean isNeedClientAuth) {
- this.isNeedClientAuth = isNeedClientAuth;
+ public int execAUTH(final String mechanism) throws IOException
+ {
+ return sendCommand(CMD_AUTH, mechanism);
}
/**
- * Returns true if the socket will require client authentication.
- * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
- * @return true - If the server mode socket should request
- * that the client authenticate itself.
- */
- public boolean getNeedClientAuth() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getNeedClientAuth();
- }
- return false;
- }
-
- /**
- * Configures the socket to request client authentication,
- * but only if such a request is appropriate to the cipher
- * suite negotiated.
- * @param isWantClientAuth The want client auth flag.
- */
- public void setWantClientAuth(final boolean isWantClientAuth) {
- this.isWantClientAuth = isWantClientAuth;
- }
-
- /**
- * Returns true if the socket will request client authentication.
- * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
- * @return true - If the server mode socket should request
- * that the client authenticate itself.
- */
- public boolean getWantClientAuth() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getWantClientAuth();
- }
- return false;
- }
-
- /**
- * Configures the socket to use client (or server) mode in its first
- * handshake.
- * @param isClientMode The use client mode flag.
+ * Send the CCC command to the server.
+ * The CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned
+ * to a plain {@link Socket} instances
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public void setUseClientMode(final boolean isClientMode) {
- this.isClientMode = isClientMode;
+ public int execCCC() throws IOException
+ {
+ final int repCode = sendCommand(CMD_CCC);
+// This will be performed by sendCommand(String, String)
+// if (FTPReply.isPositiveCompletion(repCode)) {
+// _socket_.close();
+// _socket_ = plainSocket;
+// _controlInput_ = new BufferedReader(
+// new InputStreamReader(
+// _socket_.getInputStream(), getControlEncoding()));
+// _controlOutput_ = new BufferedWriter(
+// new OutputStreamWriter(
+// _socket_.getOutputStream(), getControlEncoding()));
+// }
+ return repCode;
}
/**
- * Returns true if the socket is set to use client mode
- * in its first handshake.
- * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
- * @return true - If the socket should start its first handshake
- * in "client" mode.
+ * Send the CONF command with the specified data.
+ * @param data The data to send with the command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public boolean getUseClientMode() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getUseClientMode();
+ public int execCONF(final byte[] data) throws IOException
+ {
+ if (data != null)
+ {
+ return sendCommand(CMD_CONF, Base64.encodeBase64StringUnChunked(data));
}
- return false;
- }
-
- /**
- * Controls which particular cipher suites are enabled for use on this
- * connection. Called before server negotiation.
- * @param cipherSuites The cipher suites.
- */
- public void setEnabledCipherSuites(final String[] cipherSuites) {
- suites = cipherSuites.clone();
+ return sendCommand(CMD_CONF, ""); // perhaps "=" or just sendCommand(String)?
}
/**
- * Returns the names of the cipher suites which could be enabled
- * for use on this connection.
- * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
- * @return An array of cipher suite names, or <code>null</code>
+ * Send the ENC command with the specified data.
+ * @param data The data to send with the command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public String[] getEnabledCipherSuites() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getEnabledCipherSuites();
+ public int execENC(final byte[] data) throws IOException
+ {
+ if (data != null)
+ {
+ return sendCommand(CMD_ENC, Base64.encodeBase64StringUnChunked(data));
}
- return null;
- }
-
- /**
- * Controls which particular protocol versions are enabled for use on this
- * connection. I perform setting before a server negotiation.
- * @param protocolVersions The protocol versions.
- */
- public void setEnabledProtocols(final String[] protocolVersions) {
- protocols = protocolVersions.clone();
+ return sendCommand(CMD_ENC, ""); // perhaps "=" or just sendCommand(String)?
}
/**
- * Returns the names of the protocol versions which are currently
- * enabled for use on this connection.
- * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
- * @return An array of protocols, or <code>null</code>
+ * Send the MIC command with the specified data.
+ * @param data The data to send with the command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while sending
+ * the command.
+ * @since 3.0
*/
- public String[] getEnabledProtocols() {
- if (_socket_ instanceof SSLSocket) {
- return ((SSLSocket)_socket_).getEnabledProtocols();
+ public int execMIC(final byte[] data) throws IOException
+ {
+ if (data != null)
+ {
+ return sendCommand(CMD_MIC, Base64.encodeBase64StringUnChunked(data));
}
- return null;
+ return sendCommand(CMD_MIC, ""); // perhaps "=" or just sendCommand(String)?
}
/**
@@ -469,31 +497,6 @@ public class FTPSClient extends FTPClient {
}
/**
- * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
- * Issues the command and parses the response to return the negotiated value.
- *
- * @param pbsz Protection Buffer Size.
- * @throws SSLException If the server reply code does not equal "200".
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @return the negotiated value.
- * @see #execPBSZ(long)
- * @since 3.0
- */
- public long parsePBSZ(final long pbsz) throws SSLException, IOException {
- execPBSZ(pbsz);
- long minvalue = pbsz;
- final String remainder = extractPrefixedData("PBSZ=", getReplyString());
- if (remainder != null) {
- final long replysz = Long.parseLong(remainder);
- if (replysz < minvalue) {
- minvalue = replysz;
- }
- }
- return minvalue;
- }
-
- /**
* PROT command.
* <ul>
* <li>C - Clear</li>
@@ -531,129 +534,100 @@ public class FTPSClient extends FTPClient {
}
/**
- * Check the value that can be set in PROT Command value.
- * @param prot Data Channel Protection Level.
- * @return True - A set point is right / False - A set point is not right
+ * Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234
+ * @param prefix the prefix to find
+ * @param reply where to find the prefix
+ * @return the remainder of the string after the prefix, or null if the prefix was not present.
*/
- private boolean checkPROTValue(final String prot) {
- for (final String element : PROT_COMMAND_VALUE)
- {
- if (element.equals(prot)) {
- return true;
- }
+ private String extractPrefixedData(final String prefix, final String reply) {
+ final int idx = reply.indexOf(prefix);
+ if (idx == -1) {
+ return null;
}
- return false;
+ // N.B. Cannot use trim before substring as leading space would affect the offset.
+ return reply.substring(idx+prefix.length()).trim();
}
/**
- * Send an FTP command.
- * A successful CCC (Clear Command Channel) command causes the underlying {@link SSLSocket}
- * instance to be assigned to a plain {@link Socket}
- * @param command The FTP command.
- * @return server reply.
- * @throws IOException If an I/O error occurs while sending the command.
- * @throws SSLException if a CCC command fails
- * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String)
+ * Return AUTH command use value.
+ * @return AUTH command use value.
*/
- // Would like to remove this method, but that will break any existing clients that are using CCC
- @Override
- public int sendCommand(final String command, final String args) throws IOException {
- final int repCode = super.sendCommand(command, args);
- /* If CCC is issued, restore socket i/o streams to unsecured versions */
- if (CMD_CCC.equals(command)) {
- if (FTPReply.COMMAND_OK == repCode) {
- _socket_.close();
- _socket_ = plainSocket;
- _controlInput_ = new BufferedReader(
- new InputStreamReader(
- _socket_ .getInputStream(), getControlEncoding()));
- _controlOutput_ = new BufferedWriter(
- new OutputStreamWriter(
- _socket_.getOutputStream(), getControlEncoding()));
- } else {
- throw new SSLException(getReplyString());
- }
- }
- return repCode;
+ public String getAuthValue() {
+ return this.auth;
}
/**
- * Returns a socket of the data connection.
- * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
- * @param command The int representation of the FTP command to send.
- * @param arg The arguments to the FTP command.
- * If this parameter is set to null, then the command is sent with
- * no arguments.
- * @return corresponding to the established data connection.
- * Null is returned if an FTP protocol error is reported at any point
- * during the establishment and initialization of the connection.
- * @throws IOException If there is any problem with the connection.
- * @see FTPClient#_openDataConnection_(int, String)
- * @deprecated (3.3) Use {@link FTPClient#_openDataConnection_(FTPCmd, String)} instead
+ * Returns the names of the cipher suites which could be enabled
+ * for use on this connection.
+ * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
+ * @return An array of cipher suite names, or <code>null</code>
*/
- @Override
- // Strictly speaking this is not needed, but it works round a Clirr bug
- // So rather than invoke the parent code, we do it here
- @Deprecated
- protected Socket _openDataConnection_(final int command, final String arg)
- throws IOException {
- return _openDataConnection_(FTPCommand.getCommand(command), arg);
+ public String[] getEnabledCipherSuites() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getEnabledCipherSuites();
+ }
+ return null;
}
- /**
- * Returns a socket of the data connection.
- * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
- * @param command The textual representation of the FTP command to send.
- * @param arg The arguments to the FTP command.
- * If this parameter is set to null, then the command is sent with
- * no arguments.
- * @return corresponding to the established data connection.
- * Null is returned if an FTP protocol error is reported at any point
- * during the establishment and initialization of the connection.
- * @throws IOException If there is any problem with the connection.
- * @see FTPClient#_openDataConnection_(int, String)
- * @since 3.2
+ /**
+ * Returns the names of the protocol versions which are currently
+ * enabled for use on this connection.
+ * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
+ * @return An array of protocols, or <code>null</code>
*/
- @Override
- protected Socket _openDataConnection_(final String command, final String arg)
- throws IOException {
- final Socket socket = super._openDataConnection_(command, arg);
- _prepareDataSocket_(socket);
- if (socket instanceof SSLSocket) {
- final SSLSocket sslSocket = (SSLSocket)socket;
-
- sslSocket.setUseClientMode(isClientMode);
- sslSocket.setEnableSessionCreation(isCreation);
-
- // server mode
- if (!isClientMode) {
- sslSocket.setNeedClientAuth(isNeedClientAuth);
- sslSocket.setWantClientAuth(isWantClientAuth);
- }
- if (suites != null) {
- sslSocket.setEnabledCipherSuites(suites);
- }
- if (protocols != null) {
- sslSocket.setEnabledProtocols(protocols);
- }
- sslSocket.startHandshake();
+ public String[] getEnabledProtocols() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getEnabledProtocols();
}
+ return null;
+ }
- return socket;
+ /**
+ * Returns true if new SSL sessions may be established by this socket.
+ * When the underlying {@link Socket} instance is not SSL-enabled (i.e. an
+ * instance of {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled,
+ * this returns False.
+ * @return true - Indicates that sessions may be created;
+ * this is the default.
+ * false - indicates that an existing session must be resumed.
+ */
+ public boolean getEnableSessionCreation() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getEnableSessionCreation();
+ }
+ return false;
}
/**
- * Performs any custom initialization for a newly created SSLSocket (before
- * the SSL handshake happens).
- * Called by {@link #_openDataConnection_(int, String)} immediately
- * after creating the socket.
- * The default implementation is a no-op
- * @param socket the socket to set up
- * @throws IOException on error
- * @since 3.1
- */
- protected void _prepareDataSocket_(final Socket socket)
- throws IOException {
+ * Get the currently configured {@link HostnameVerifier}.
+ * The verifier is only used on client mode connections.
+ * @return A HostnameVerifier instance.
+ * @since 3.4
+ */
+ public HostnameVerifier getHostnameVerifier()
+ {
+ return hostnameVerifier;
+ }
+
+ /**
+ * Get the {@link KeyManager} instance.
+ * @return The {@link KeyManager} instance
+ */
+private KeyManager getKeyManager() {
+ return keyManager;
+}
+
+ /**
+ * Returns true if the socket will require client authentication.
+ * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
+ */
+ public boolean getNeedClientAuth() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getNeedClientAuth();
+ }
+ return false;
}
/**
@@ -666,36 +640,40 @@ public class FTPSClient extends FTPClient {
}
/**
- * Override the default {@link TrustManager} to use; if set to {@code null},
- * the default TrustManager from the JVM will be used.
- *
- * @param trustManager The TrustManager implementation to set, may be {@code null}
- * @see org.apache.commons.net.util.TrustManagerUtils
+ * Returns true if the socket is set to use client mode
+ * in its first handshake.
+ * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
+ * @return true - If the socket should start its first handshake
+ * in "client" mode.
*/
- public void setTrustManager(final TrustManager trustManager) {
- this.trustManager = trustManager;
+ public boolean getUseClientMode() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getUseClientMode();
+ }
+ return false;
}
/**
- * Get the currently configured {@link HostnameVerifier}.
- * The verifier is only used on client mode connections.
- * @return A HostnameVerifier instance.
- * @since 3.4
+ * Returns true if the socket will request client authentication.
+ * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
*/
- public HostnameVerifier getHostnameVerifier()
- {
- return hostnameVerifier;
+ public boolean getWantClientAuth() {
+ if (_socket_ instanceof SSLSocket) {
+ return ((SSLSocket)_socket_).getWantClientAuth();
+ }
+ return false;
}
/**
- * Override the default {@link HostnameVerifier} to use.
- * The verifier is only used on client mode connections.
- * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable.
- * @since 3.4
+ * Performs a lazy init of the SSL context
+ * @throws IOException
*/
- public void setHostnameVerifier(final HostnameVerifier newHostnameVerifier)
- {
- hostnameVerifier = newHostnameVerifier;
+ private void initSslContext() throws IOException {
+ if (context == null) {
+ context = SSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
+ }
}
/**
@@ -713,208 +691,230 @@ public class FTPSClient extends FTPClient {
}
/**
- * Automatic endpoint identification checking using the HTTPS algorithm
- * is supported on Java 1.7+. The default behavior is for this to be disabled.
- *
- * This check is only performed on client mode connections.
- *
- * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+.
- * @since 3.4
- */
- public void setEndpointCheckingEnabled(final boolean enable)
- {
- tlsEndpointChecking = enable;
- }
-
- /**
- * Closes the connection to the FTP server and restores
- * connection parameters to the default values.
- * <p>
- * Calls {@code setSocketFactory(null)} and {@code setServerSocketFactory(null)}
- * to reset the factories that may have been changed during the session,
- * e.g. by {@link #execPROT(String)}
- * @throws IOException If an error occurs while disconnecting.
+ * Parses the given ADAT response line and base64-decodes the data.
+ * @param reply The ADAT reply to parse.
+ * @return the data in the reply, base64-decoded.
* @since 3.0
*/
- @Override
- public void disconnect() throws IOException
+ public byte[] parseADATReply(final String reply)
{
- super.disconnect();
- if (plainSocket != null) {
- plainSocket.close();
+ if (reply == null) {
+ return null;
}
- setSocketFactory(null);
- setServerSocketFactory(null);
+ return Base64.decodeBase64(extractPrefixedData("ADAT=", reply));
}
/**
- * Send the AUTH command with the specified mechanism.
- * @param mechanism The mechanism name to send with the command.
- * @return server reply.
+ * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
+ * Issues the command and parses the response to return the negotiated value.
+ *
+ * @param pbsz Protection Buffer Size.
+ * @throws SSLException If the server reply code does not equal "200".
* @throws IOException If an I/O error occurs while sending
* the command.
+ * @return the negotiated value.
+ * @see #execPBSZ(long)
* @since 3.0
*/
- public int execAUTH(final String mechanism) throws IOException
- {
- return sendCommand(CMD_AUTH, mechanism);
+ public long parsePBSZ(final long pbsz) throws SSLException, IOException {
+ execPBSZ(pbsz);
+ long minvalue = pbsz;
+ final String remainder = extractPrefixedData("PBSZ=", getReplyString());
+ if (remainder != null) {
+ final long replysz = Long.parseLong(remainder);
+ if (replysz < minvalue) {
+ minvalue = replysz;
+ }
+ }
+ return minvalue;
}
/**
- * Send the ADAT command with the specified authentication data.
- * @param data The data to send with the command.
+ * Send an FTP command.
+ * A successful CCC (Clear Command Channel) command causes the underlying {@link SSLSocket}
+ * instance to be assigned to a plain {@link Socket}
+ * @param command The FTP command.
* @return server reply.
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @since 3.0
+ * @throws IOException If an I/O error occurs while sending the command.
+ * @throws SSLException if a CCC command fails
+ * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String)
*/
- public int execADAT(final byte[] data) throws IOException
- {
- if (data != null)
- {
- return sendCommand(CMD_ADAT, Base64.encodeBase64StringUnChunked(data));
+ // Would like to remove this method, but that will break any existing clients that are using CCC
+ @Override
+ public int sendCommand(final String command, final String args) throws IOException {
+ final int repCode = super.sendCommand(command, args);
+ /* If CCC is issued, restore socket i/o streams to unsecured versions */
+ if (CMD_CCC.equals(command)) {
+ if (FTPReply.COMMAND_OK == repCode) {
+ _socket_.close();
+ _socket_ = plainSocket;
+ _controlInput_ = new BufferedReader(
+ new InputStreamReader(
+ _socket_ .getInputStream(), getControlEncoding()));
+ _controlOutput_ = new BufferedWriter(
+ new OutputStreamWriter(
+ _socket_.getOutputStream(), getControlEncoding()));
+ } else {
+ throw new SSLException(getReplyString());
+ }
}
- return sendCommand(CMD_ADAT);
+ return repCode;
}
/**
- * Send the CCC command to the server.
- * The CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned
- * to a plain {@link Socket} instances
- * @return server reply.
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @since 3.0
+ * Set AUTH command use value.
+ * This processing is done before connected processing.
+ * @param auth AUTH command use value.
*/
- public int execCCC() throws IOException
- {
- final int repCode = sendCommand(CMD_CCC);
-// This will be performed by sendCommand(String, String)
-// if (FTPReply.isPositiveCompletion(repCode)) {
-// _socket_.close();
-// _socket_ = plainSocket;
-// _controlInput_ = new BufferedReader(
-// new InputStreamReader(
-// _socket_.getInputStream(), getControlEncoding()));
-// _controlOutput_ = new BufferedWriter(
-// new OutputStreamWriter(
-// _socket_.getOutputStream(), getControlEncoding()));
-// }
- return repCode;
+ public void setAuthValue(final String auth) {
+ this.auth = auth;
}
/**
- * Send the MIC command with the specified data.
- * @param data The data to send with the command.
- * @return server reply.
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @since 3.0
+ * Controls which particular cipher suites are enabled for use on this
+ * connection. Called before server negotiation.
+ * @param cipherSuites The cipher suites.
*/
- public int execMIC(final byte[] data) throws IOException
- {
- if (data != null)
- {
- return sendCommand(CMD_MIC, Base64.encodeBase64StringUnChunked(data));
- }
- return sendCommand(CMD_MIC, ""); // perhaps "=" or just sendCommand(String)?
+ public void setEnabledCipherSuites(final String[] cipherSuites) {
+ suites = cipherSuites.clone();
}
/**
- * Send the CONF command with the specified data.
- * @param data The data to send with the command.
- * @return server reply.
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @since 3.0
+ * Controls which particular protocol versions are enabled for use on this
+ * connection. I perform setting before a server negotiation.
+ * @param protocolVersions The protocol versions.
*/
- public int execCONF(final byte[] data) throws IOException
- {
- if (data != null)
- {
- return sendCommand(CMD_CONF, Base64.encodeBase64StringUnChunked(data));
- }
- return sendCommand(CMD_CONF, ""); // perhaps "=" or just sendCommand(String)?
+ public void setEnabledProtocols(final String[] protocolVersions) {
+ protocols = protocolVersions.clone();
}
/**
- * Send the ENC command with the specified data.
- * @param data The data to send with the command.
- * @return server reply.
- * @throws IOException If an I/O error occurs while sending
- * the command.
- * @since 3.0
+ * Controls whether a new SSL session may be established by this socket.
+ * @param isCreation The established socket flag.
*/
- public int execENC(final byte[] data) throws IOException
+ public void setEnabledSessionCreation(final boolean isCreation) {
+ this.isCreation = isCreation;
+ }
+
+ /**
+ * Automatic endpoint identification checking using the HTTPS algorithm
+ * is supported on Java 1.7+. The default behavior is for this to be disabled.
+ *
+ * This check is only performed on client mode connections.
+ *
+ * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+.
+ * @since 3.4
+ */
+ public void setEndpointCheckingEnabled(final boolean enable)
{
- if (data != null)
- {
- return sendCommand(CMD_ENC, Base64.encodeBase64StringUnChunked(data));
- }
- return sendCommand(CMD_ENC, ""); // perhaps "=" or just sendCommand(String)?
+ tlsEndpointChecking = enable;
}
/**
- * Parses the given ADAT response line and base64-decodes the data.
- * @param reply The ADAT reply to parse.
- * @return the data in the reply, base64-decoded.
- * @since 3.0
+ * Override the default {@link HostnameVerifier} to use.
+ * The verifier is only used on client mode connections.
+ * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable.
+ * @since 3.4
*/
- public byte[] parseADATReply(final String reply)
+ public void setHostnameVerifier(final HostnameVerifier newHostnameVerifier)
{
- if (reply == null) {
- return null;
- }
- return Base64.decodeBase64(extractPrefixedData("ADAT=", reply));
+ hostnameVerifier = newHostnameVerifier;
}
/**
- * Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234
- * @param prefix the prefix to find
- * @param reply where to find the prefix
- * @return the remainder of the string after the prefix, or null if the prefix was not present.
+ * Set a {@link KeyManager} to use
+ *
+ * @param keyManager The KeyManager implementation to set.
+ * @see org.apache.commons.net.util.KeyManagerUtils
+ */
+ public void setKeyManager(final KeyManager keyManager) {
+ this.keyManager = keyManager;
+ }
+
+ /**
+ * Configures the socket to require client authentication.
+ * @param isNeedClientAuth The need client auth flag.
*/
- private String extractPrefixedData(final String prefix, final String reply) {
- final int idx = reply.indexOf(prefix);
- if (idx == -1) {
- return null;
- }
- // N.B. Cannot use trim before substring as leading space would affect the offset.
- return reply.substring(idx+prefix.length()).trim();
+ public void setNeedClientAuth(final boolean isNeedClientAuth) {
+ this.isNeedClientAuth = isNeedClientAuth;
}
+ // DEPRECATED - for API compatibility only - DO NOT USE
+
/**
- * Create SSL socket from plain socket.
+ * Override the default {@link TrustManager} to use; if set to {@code null},
+ * the default TrustManager from the JVM will be used.
*
- * @param socket
- * @return SSL Socket
- * @throws IOException
+ * @param trustManager The TrustManager implementation to set, may be {@code null}
+ * @see org.apache.commons.net.util.TrustManagerUtils
*/
- private SSLSocket createSSLSocket(final Socket socket) throws IOException {
- if (socket != null) {
- final SSLSocketFactory f = context.getSocketFactory();
- return (SSLSocket) f.createSocket(socket, _hostname_, socket.getPort(), false);
- }
- return null;
+ public void setTrustManager(final TrustManager trustManager) {
+ this.trustManager = trustManager;
}
- // DEPRECATED - for API compatibility only - DO NOT USE
+ /**
+ * Configures the socket to use client (or server) mode in its first
+ * handshake.
+ * @param isClientMode The use client mode flag.
+ */
+ public void setUseClientMode(final boolean isClientMode) {
+ this.isClientMode = isClientMode;
+ }
- /** @deprecated - not used - may be removed in a future release */
- @Deprecated
- public static String KEYSTORE_ALGORITHM;
+ /**
+ * Configures the socket to request client authentication,
+ * but only if such a request is appropriate to the cipher
+ * suite negotiated.
+ * @param isWantClientAuth The want client auth flag.
+ */
+ public void setWantClientAuth(final boolean isWantClientAuth) {
+ this.isWantClientAuth = isWantClientAuth;
+ }
- /** @deprecated - not used - may be removed in a future release */
- @Deprecated
- public static String TRUSTSTORE_ALGORITHM;
+ /**
+ * SSL/TLS negotiation. Acquires an SSL socket of a control
+ * connection and carries out handshake processing.
+ * @throws IOException If server negotiation fails
+ */
+ protected void sslNegotiation() throws IOException {
+ plainSocket = _socket_;
+ initSslContext();
+ final SSLSocket socket = createSSLSocket(_socket_);
+ socket.setEnableSessionCreation(isCreation);
+ socket.setUseClientMode(isClientMode);
- /** @deprecated - not used - may be removed in a future release */
- @Deprecated
- public static String PROVIDER;
+ // client mode
+ if (isClientMode) {
+ if (tlsEndpointChecking) {
+ SSLSocketUtils.enableEndpointNameVerification(socket);
+ }
+ } else { // server mode
+ socket.setNeedClientAuth(isNeedClientAuth);
+ socket.setWantClientAuth(isWantClientAuth);
+ }
- /** @deprecated - not used - may be removed in a future release */
- @Deprecated
- public static String STORE_TYPE;
+ if (protocols != null) {
+ socket.setEnabledProtocols(protocols);
+ }
+ if (suites != null) {
+ socket.setEnabledCipherSuites(suites);
+ }
+ socket.startHandshake();
+
+ // TODO the following setup appears to duplicate that in the super class methods
+ _socket_ = socket;
+ _controlInput_ = new BufferedReader(new InputStreamReader(
+ socket .getInputStream(), getControlEncoding()));
+ _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
+ socket.getOutputStream(), getControlEncoding()));
+
+ if (isClientMode) {
+ if (hostnameVerifier != null &&
+ !hostnameVerifier.verify(_hostname_, socket.getSession())) {
+ throw new SSLHandshakeException("Hostname doesn't match certificate");
+ }
+ }
+ }
}
/* kate: indent-width 4; replace-tabs on; */
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java b/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java
index 3beaaa1..211d747 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java
@@ -39,36 +39,6 @@ public class FTPSSocketFactory extends SocketFactory {
this.context = context;
}
- // Override the default implementation
- @Override
- public Socket createSocket() throws IOException{
- return this.context.getSocketFactory().createSocket();
- }
-
- @Override
- public Socket createSocket(final String address, final int port) throws UnknownHostException, IOException {
- return this.context.getSocketFactory().createSocket(address, port);
- }
-
- @Override
- public Socket createSocket(final InetAddress address, final int port) throws IOException {
- return this.context.getSocketFactory().createSocket(address, port);
- }
-
- @Override
- public Socket createSocket(final String address, final int port, final InetAddress localAddress, final int localPort)
- throws UnknownHostException, IOException {
- return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
- }
-
- @Override
- public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress,
- final int localPort) throws IOException {
- return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
- }
-
- // DEPRECATED METHODS - for API compatibility only - DO NOT USE
-
/** @param port the port
* @return the socket
* @throws IOException on error
@@ -100,6 +70,36 @@ public class FTPSSocketFactory extends SocketFactory {
return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress));
}
+ // Override the default implementation
+ @Override
+ public Socket createSocket() throws IOException{
+ return this.context.getSocketFactory().createSocket();
+ }
+
+ @Override
+ public Socket createSocket(final InetAddress address, final int port) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ // DEPRECATED METHODS - for API compatibility only - DO NOT USE
+
+ @Override
+ public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress,
+ final int localPort) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
+ @Override
+ public Socket createSocket(final String address, final int port) throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ @Override
+ public Socket createSocket(final String address, final int port, final InetAddress localAddress, final int localPort)
+ throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
/** @param socket the socket
* @return the socket
* @throws IOException on error
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java b/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
index 6e30a77..ac88607 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
@@ -71,22 +71,6 @@ implements Configurable
}
/**
- * This method is called by the concrete parsers to delegate
- * timestamp parsing to the timestamp parser.
- *
- * @param timestampStr the timestamp string pulled from the
- * file listing by the regular expression parser, to be submitted
- * to the <code>timestampParser</code> for extracting the timestamp.
- * @return a <code>java.util.Calendar</code> containing results of the
- * timestamp parse.
- * @throws ParseException on parse error
- */
- public Calendar parseTimestamp(final String timestampStr) throws ParseException {
- return this.timestampParser.parseTimestamp(timestampStr);
- }
-
-
- /**
* Implementation of the {@link Configurable Configurable}
* interface. Configures this parser by delegating to the
* underlying Configurable FTPTimestampParser implementation, '
@@ -117,6 +101,7 @@ implements Configurable
}
}
+
/**
* Each concrete subclass must define this member to create
* a default configuration to be used when that subclass is
@@ -125,4 +110,19 @@ implements Configurable
* @return the default configuration for the subclass.
*/
protected abstract FTPClientConfig getDefaultConfiguration();
+
+ /**
+ * This method is called by the concrete parsers to delegate
+ * timestamp parsing to the timestamp parser.
+ *
+ * @param timestampStr the timestamp string pulled from the
+ * file listing by the regular expression parser, to be submitted
+ * to the <code>timestampParser</code> for extracting the timestamp.
+ * @return a <code>java.util.Calendar</code> containing results of the
+ * timestamp parse.
+ * @throws ParseException on parse error
+ */
+ public Calendar parseTimestamp(final String timestampStr) throws ParseException {
+ return this.timestampParser.parseTimestamp(timestampStr);
+ }
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java b/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
index de72eb2..7981293 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
@@ -46,6 +46,35 @@ public class DefaultFTPFileEntryParserFactory
private static final Pattern JAVA_QUALIFIED_NAME_PATTERN = Pattern.compile(JAVA_QUALIFIED_NAME);
/**
+ * <p>Implementation extracts a key from the supplied
+ * {@link FTPClientConfig FTPClientConfig}
+ * parameter and creates an object implementing the
+ * interface FTPFileEntryParser and uses the supplied configuration
+ * to configure it.
+ * </p><p>
+ * Note that this method will generally not be called in scenarios
+ * that call for autodetection of parser type but rather, for situations
+ * where the user knows that the server uses a non-default configuration
+ * and knows what that configuration is.
+ * </p>
+ * @param config A {@link FTPClientConfig FTPClientConfig}
+ * used to configure the parser created
+ *
+ * @return the @link FTPFileEntryParser FTPFileEntryParser} so created.
+ * @throws ParserInitializationException
+ * Thrown on any exception in instantiation
+ * @throws NullPointerException if {@code config} is {@code null}
+ * @since 1.4
+ */
+ @Override
+ public FTPFileEntryParser createFileEntryParser(final FTPClientConfig config)
+ throws ParserInitializationException
+ {
+ final String key = config.getServerSystemKey();
+ return createFileEntryParser(key, config);
+ }
+
+ /**
* This default implementation of the FTPFileEntryParserFactory
* interface works according to the following logic:
* First it attempts to interpret the supplied key as a fully
@@ -175,44 +204,10 @@ public class DefaultFTPFileEntryParserFactory
return parser;
}
- /**
- * <p>Implementation extracts a key from the supplied
- * {@link FTPClientConfig FTPClientConfig}
- * parameter and creates an object implementing the
- * interface FTPFileEntryParser and uses the supplied configuration
- * to configure it.
- * </p><p>
- * Note that this method will generally not be called in scenarios
- * that call for autodetection of parser type but rather, for situations
- * where the user knows that the server uses a non-default configuration
- * and knows what that configuration is.
- * </p>
- * @param config A {@link FTPClientConfig FTPClientConfig}
- * used to configure the parser created
- *
- * @return the @link FTPFileEntryParser FTPFileEntryParser} so created.
- * @throws ParserInitializationException
- * Thrown on any exception in instantiation
- * @throws NullPointerException if {@code config} is {@code null}
- * @since 1.4
- */
- @Override
- public FTPFileEntryParser createFileEntryParser(final FTPClientConfig config)
- throws ParserInitializationException
- {
- final String key = config.getServerSystemKey();
- return createFileEntryParser(key, config);
- }
-
-
- public FTPFileEntryParser createUnixFTPEntryParser()
- {
- return new UnixFTPEntryParser();
- }
- public FTPFileEntryParser createVMSVersioningFTPEntryParser()
+ public FTPFileEntryParser createMVSEntryParser()
{
- return new VMSVersioningFTPEntryParser();
+ return new MVSFTPEntryParser();
}
public FTPFileEntryParser createNetwareFTPEntryParser() {
@@ -248,12 +243,12 @@ public class DefaultFTPFileEntryParserFactory
});
}
- public FTPFileEntryParser createOS2FTPEntryParser()
+ public FTPFileEntryParser createOS2FTPEntryParser()
{
return new OS2FTPEntryParser();
}
- public FTPFileEntryParser createOS400FTPEntryParser()
+ public FTPFileEntryParser createOS400FTPEntryParser()
{
return createOS400FTPEntryParser(null);
}
@@ -282,9 +277,14 @@ public class DefaultFTPFileEntryParserFactory
});
}
- public FTPFileEntryParser createMVSEntryParser()
+ public FTPFileEntryParser createUnixFTPEntryParser()
{
- return new MVSFTPEntryParser();
+ return new UnixFTPEntryParser();
+ }
+
+ public FTPFileEntryParser createVMSVersioningFTPEntryParser()
+ {
+ return new VMSVersioningFTPEntryParser();
}
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java b/src/main/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
index 59b711a..c99386a 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
@@ -26,21 +26,6 @@ import org.apache.commons.net.ftp.FTPFileEntryParser;
public interface FTPFileEntryParserFactory
{
/**
- * Implementation should be a method that decodes the
- * supplied key and creates an object implementing the
- * interface FTPFileEntryParser.
- *
- * @param key A string that somehow identifies an
- * FTPFileEntryParser to be created.
- *
- * @return the FTPFileEntryParser created.
- * @throws ParserInitializationException
- * Thrown on any exception in instantiation
- */
- FTPFileEntryParser createFileEntryParser(String key)
- throws ParserInitializationException;
-
- /**
*<p>
* Implementation should be a method that extracts
* a key from the supplied {@link FTPClientConfig FTPClientConfig}
@@ -65,4 +50,19 @@ public interface FTPFileEntryParserFactory
FTPFileEntryParser createFileEntryParser(FTPClientConfig config)
throws ParserInitializationException;
+ /**
+ * Implementation should be a method that decodes the
+ * supplied key and creates an object implementing the
+ * interface FTPFileEntryParser.
+ *
+ * @param key A string that somehow identifies an
+ * FTPFileEntryParser to be created.
+ *
+ * @return the FTPFileEntryParser created.
+ * @throws ParserInitializationException
+ * Thrown on any exception in instantiation
+ */
+ FTPFileEntryParser createFileEntryParser(String key)
+ throws ParserInitializationException;
+
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
index 99761e9..648fd5a 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
@@ -41,18 +41,6 @@ public class FTPTimestampParserImpl implements
{
- /** The date format for all dates, except possibly recent dates. Assumed to include the year. */
- private SimpleDateFormat defaultDateFormat;
- /* The index in CALENDAR_UNITS of the smallest time unit in defaultDateFormat */
- private int defaultDateSmallestUnitIndex;
-
- /** The format used for recent dates (which don't have the year). May be null. */
- private SimpleDateFormat recentDateFormat;
- /* The index in CALENDAR_UNITS of the smallest time unit in recentDateFormat */
- private int recentDateSmallestUnitIndex;
-
- private boolean lenientFutureDates;
-
/*
* List of units in order of increasing significance.
* This allows the code to clear all units in the Calendar until it
@@ -73,7 +61,6 @@ public class FTPTimestampParserImpl implements
Calendar.DAY_OF_MONTH,
Calendar.MONTH,
Calendar.YEAR};
-
/*
* Return the index to the array representing the least significant
* unit found in the date format.
@@ -118,7 +105,6 @@ public class FTPTimestampParserImpl implements
}
return 0;
}
-
/*
* Sets the Calendar precision (used by FTPFile#toFormattedDate) by clearing
* the immediately preceeding unit (if any).
@@ -139,6 +125,20 @@ public class FTPTimestampParserImpl implements
}
}
+ /** The date format for all dates, except possibly recent dates. Assumed to include the year. */
+ private SimpleDateFormat defaultDateFormat;
+
+ /* The index in CALENDAR_UNITS of the smallest time unit in defaultDateFormat */
+ private int defaultDateSmallestUnitIndex;
+
+ /** The format used for recent dates (which don't have the year). May be null. */
+ private SimpleDateFormat recentDateFormat;
+
+ /* The index in CALENDAR_UNITS of the smallest time unit in recentDateFormat */
+ private int recentDateSmallestUnitIndex;
+
+ private boolean lenientFutureDates;
+
/**
* The only constructor for this class.
*/
@@ -148,6 +148,103 @@ public class FTPTimestampParserImpl implements
}
/**
+ * Implementation of the {@link Configurable Configurable}
+ * interface. Configures this <code>FTPTimestampParser</code> according
+ * to the following logic:
+ * <p>
+ * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
+ * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
+ * to values supplied in the config based on month names configured as follows:
+ * </p>
+ * <ul>
+ * <li>If a {@link FTPClientConfig#setShortMonthNames(String) shortMonthString}
+ * has been supplied in the <code>config</code>, use that to parse parse timestamps.</li>
+ * <li>Otherwise, if a {@link FTPClientConfig#setServerLanguageCode(String) serverLanguageCode}
+ * has been supplied in the <code>config</code>, use the month names represented
+ * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
+ * to parse timestamps.</li>
+ * <li>otherwise use default English month names</li>
+ * </ul><p>
+ * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
+ * has been supplied via the config, set that into all date formats that have
+ * been configured.
+ * </p>
+ */
+ @Override
+ public void configure(final FTPClientConfig config) {
+ DateFormatSymbols dfs = null;
+
+ final String languageCode = config.getServerLanguageCode();
+ final String shortmonths = config.getShortMonthNames();
+ if (shortmonths != null) {
+ dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
+ } else if (languageCode != null) {
+ dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
+ } else {
+ dfs = FTPClientConfig.lookupDateFormatSymbols("en");
+ }
+
+
+ final String recentFormatString = config.getRecentDateFormatStr();
+ setRecentDateFormat(recentFormatString, dfs);
+
+ final String defaultFormatString = config.getDefaultDateFormatStr();
+ if (defaultFormatString == null) {
+ throw new IllegalArgumentException("defaultFormatString cannot be null");
+ }
+ setDefaultDateFormat(defaultFormatString, dfs);
+
+ setServerTimeZone(config.getServerTimeZoneId());
+
+ this.lenientFutureDates = config.isLenientFutureDates();
+ }
+
+ /**
+ * @return Returns the defaultDateFormat.
+ */
+ public SimpleDateFormat getDefaultDateFormat() {
+ return defaultDateFormat;
+ }
+
+ /**
+ * @return Returns the defaultDateFormat pattern string.
+ */
+ public String getDefaultDateFormatString() {
+ return defaultDateFormat.toPattern();
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public SimpleDateFormat getRecentDateFormat() {
+ return recentDateFormat;
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public String getRecentDateFormatString() {
+ return recentDateFormat.toPattern();
+ }
+ /**
+ * @return Returns the serverTimeZone used by this parser.
+ */
+ public TimeZone getServerTimeZone() {
+ return this.defaultDateFormat.getTimeZone();
+ }
+ /**
+ * @return returns an array of 12 strings representing the short
+ * month names used by this parse.
+ */
+ public String[] getShortMonths() {
+ return defaultDateFormat.getDateFormatSymbols().getShortMonths();
+ }
+ /**
+ * @return Returns the lenientFutureDates.
+ */
+ boolean isLenientFutureDates() {
+ return lenientFutureDates;
+ }
+
+ /**
* Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
* in the {@link FTPTimestampParser FTPTimestampParser} interface
* according to this algorithm:
@@ -170,6 +267,7 @@ public class FTPTimestampParserImpl implements
return parseTimestamp(timestampStr, now);
}
+
/**
* If the recentDateFormat member has been defined, try to parse the
* supplied string with that. If that parse fails, or if the recentDateFormat
@@ -248,19 +346,6 @@ public class FTPTimestampParserImpl implements
setPrecision(defaultDateSmallestUnitIndex, working);
return working;
}
-
- /**
- * @return Returns the defaultDateFormat.
- */
- public SimpleDateFormat getDefaultDateFormat() {
- return defaultDateFormat;
- }
- /**
- * @return Returns the defaultDateFormat pattern string.
- */
- public String getDefaultDateFormatString() {
- return defaultDateFormat.toPattern();
- }
/**
* @param format The defaultDateFormat to be set.
* @param dfs the symbols to use (may be null)
@@ -278,17 +363,12 @@ public class FTPTimestampParserImpl implements
}
this.defaultDateSmallestUnitIndex = getEntry(this.defaultDateFormat);
}
+
/**
- * @return Returns the recentDateFormat.
- */
- public SimpleDateFormat getRecentDateFormat() {
- return recentDateFormat;
- }
- /**
- * @return Returns the recentDateFormat.
+ * @param lenientFutureDates The lenientFutureDates to set.
*/
- public String getRecentDateFormatString() {
- return recentDateFormat.toPattern();
+ void setLenientFutureDates(final boolean lenientFutureDates) {
+ this.lenientFutureDates = lenientFutureDates;
}
/**
* @param format The recentDateFormat to set.
@@ -307,22 +387,6 @@ public class FTPTimestampParserImpl implements
}
this.recentDateSmallestUnitIndex = getEntry(this.recentDateFormat);
}
-
- /**
- * @return returns an array of 12 strings representing the short
- * month names used by this parse.
- */
- public String[] getShortMonths() {
- return defaultDateFormat.getDateFormatSymbols().getShortMonths();
- }
-
-
- /**
- * @return Returns the serverTimeZone used by this parser.
- */
- public TimeZone getServerTimeZone() {
- return this.defaultDateFormat.getTimeZone();
- }
/**
* sets a TimeZone represented by the supplied ID string into all
* of the parsers used by this server.
@@ -339,68 +403,4 @@ public class FTPTimestampParserImpl implements
this.recentDateFormat.setTimeZone(serverTimeZone);
}
}
-
- /**
- * Implementation of the {@link Configurable Configurable}
- * interface. Configures this <code>FTPTimestampParser</code> according
- * to the following logic:
- * <p>
- * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
- * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
- * to values supplied in the config based on month names configured as follows:
- * </p>
- * <ul>
- * <li>If a {@link FTPClientConfig#setShortMonthNames(String) shortMonthString}
- * has been supplied in the <code>config</code>, use that to parse parse timestamps.</li>
- * <li>Otherwise, if a {@link FTPClientConfig#setServerLanguageCode(String) serverLanguageCode}
- * has been supplied in the <code>config</code>, use the month names represented
- * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
- * to parse timestamps.</li>
- * <li>otherwise use default English month names</li>
- * </ul><p>
- * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
- * has been supplied via the config, set that into all date formats that have
- * been configured.
- * </p>
- */
- @Override
- public void configure(final FTPClientConfig config) {
- DateFormatSymbols dfs = null;
-
- final String languageCode = config.getServerLanguageCode();
- final String shortmonths = config.getShortMonthNames();
- if (shortmonths != null) {
- dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
- } else if (languageCode != null) {
- dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
- } else {
- dfs = FTPClientConfig.lookupDateFormatSymbols("en");
- }
-
-
- final String recentFormatString = config.getRecentDateFormatStr();
- setRecentDateFormat(recentFormatString, dfs);
-
- final String defaultFormatString = config.getDefaultDateFormatStr();
- if (defaultFormatString == null) {
- throw new IllegalArgumentException("defaultFormatString cannot be null");
- }
- setDefaultDateFormat(defaultFormatString, dfs);
-
- setServerTimeZone(config.getServerTimeZoneId());
-
- this.lenientFutureDates = config.isLenientFutureDates();
- }
- /**
- * @return Returns the lenientFutureDates.
- */
- boolean isLenientFutureDates() {
- return lenientFutureDates;
- }
- /**
- * @param lenientFutureDates The lenientFutureDates to set.
- */
- void setLenientFutureDates(final boolean lenientFutureDates) {
- this.lenientFutureDates = lenientFutureDates;
- }
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java
index 841d327..d0c6cd5 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/MLSxEntryParser.java
@@ -88,96 +88,12 @@ public class MLSxEntryParser extends FTPFileEntryParserImpl
/* 7 */ {FTPFile.READ_PERMISSION, FTPFile.WRITE_PERMISSION, FTPFile.EXECUTE_PERMISSION},
};
- /**
- * Create the parser for MSLT and MSLD listing entries
- * This class is immutable, so one can use {@link #getInstance()} instead.
- */
- public MLSxEntryParser()
- {
+ public static MLSxEntryParser getInstance() {
+ return INSTANCE;
}
- @Override
- public FTPFile parseFTPEntry(final String entry) {
- if (entry.startsWith(" ")) {// leading space means no facts are present
- if (entry.length() > 1) { // is there a path name?
- final FTPFile file = new FTPFile();
- file.setRawListing(entry);
- file.setName(entry.substring(1));
- return file;
- }
- return null; // Invalid - no pathname
-
- }
- final String parts[] = entry.split(" ",2); // Path may contain space
- if (parts.length != 2 || parts[1].isEmpty()) {
- return null; // no space found or no file name
- }
- final String factList = parts[0];
- if (!factList.endsWith(";")) {
- return null;
- }
- final FTPFile file = new FTPFile();
- file.setRawListing(entry);
- file.setName(parts[1]);
- final String[] facts = factList.split(";");
- final boolean hasUnixMode = parts[0].toLowerCase(Locale.ENGLISH).contains("unix.mode=");
- for(final String fact : facts) {
- final String []factparts = fact.split("=", -1); // Don't drop empty values
-// Sample missing permission
-// drwx------ 2 mirror mirror 4096 Mar 13 2010 subversion
-// modify=20100313224553;perm=;type=dir;unique=811U282598;UNIX.group=500;UNIX.mode=0700;UNIX.owner=500; subversion
- if (factparts.length != 2) {
- return null; // invalid - there was no "=" sign
- }
- final String factname = factparts[0].toLowerCase(Locale.ENGLISH);
- final String factvalue = factparts[1];
- if (factvalue.isEmpty()) {
- continue; // nothing to see here
- }
- final String valueLowerCase = factvalue.toLowerCase(Locale.ENGLISH);
- if ("size".equals(factname) || "sizd".equals(factname)) {
- file.setSize(Long.parseLong(factvalue));
- }
- else if ("modify".equals(factname)) {
- final Calendar parsed = parseGMTdateTime(factvalue);
- if (parsed == null) {
- return null;
- }
- file.setTimestamp(parsed);
- }
- else if ("type".equals(factname)) {
- final Integer intType = TYPE_TO_INT.get(valueLowerCase);
- if (intType == null) {
- file.setType(FTPFile.UNKNOWN_TYPE);
- } else {
- file.setType(intType.intValue());
- }
- }
- else if (factname.startsWith("unix.")) {
- final String unixfact = factname.substring("unix.".length()).toLowerCase(Locale.ENGLISH);
- if ("group".equals(unixfact)){
- file.setGroup(factvalue);
- } else if ("owner".equals(unixfact)){
- file.setUser(factvalue);
- } else if ("mode".equals(unixfact)){ // e.g. 0[1]755
- final int off = factvalue.length()-3; // only parse last 3 digits
- for(int i=0; i < 3; i++){
- final int ch = factvalue.charAt(off+i)-'0';
- if (ch >= 0 && ch <= 7) { // Check it's valid octal
- for(final int p : UNIX_PERMS[ch]) {
- file.setPermission(UNIX_GROUPS[i], p, true);
- }
- } else {
- // TODO should this cause failure, or can it be reported somehow?
- }
- } // digits
- } // mode
- } // unix.
- else if (!hasUnixMode && "perm".equals(factname)) { // skip if we have the UNIX.mode
- doUnixPerms(file, valueLowerCase);
- } // process "perm"
- } // each fact
- return file;
+ public static FTPFile parseEntry(final String entry) {
+ return INSTANCE.parseFTPEntry(entry);
}
/**
@@ -225,6 +141,14 @@ public class MLSxEntryParser extends FTPFileEntryParserImpl
return parseGMTdateTime(timestamp).toInstant();
}
+ /**
+ * Create the parser for MSLT and MSLD listing entries
+ * This class is immutable, so one can use {@link #getInstance()} instead.
+ */
+ public MLSxEntryParser()
+ {
+ }
+
// perm-fact = "Perm" "=" *pvals
// pvals = "a" / "c" / "d" / "e" / "f" /
// "l" / "m" / "p" / "r" / "w"
@@ -269,11 +193,87 @@ public class MLSxEntryParser extends FTPFileEntryParserImpl
} // each char
}
- public static FTPFile parseEntry(final String entry) {
- return INSTANCE.parseFTPEntry(entry);
- }
+ @Override
+ public FTPFile parseFTPEntry(final String entry) {
+ if (entry.startsWith(" ")) {// leading space means no facts are present
+ if (entry.length() > 1) { // is there a path name?
+ final FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ file.setName(entry.substring(1));
+ return file;
+ }
+ return null; // Invalid - no pathname
- public static MLSxEntryParser getInstance() {
- return INSTANCE;
+ }
+ final String parts[] = entry.split(" ",2); // Path may contain space
+ if (parts.length != 2 || parts[1].isEmpty()) {
+ return null; // no space found or no file name
+ }
+ final String factList = parts[0];
+ if (!factList.endsWith(";")) {
+ return null;
+ }
+ final FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ file.setName(parts[1]);
+ final String[] facts = factList.split(";");
+ final boolean hasUnixMode = parts[0].toLowerCase(Locale.ENGLISH).contains("unix.mode=");
+ for(final String fact : facts) {
+ final String []factparts = fact.split("=", -1); // Don't drop empty values
+// Sample missing permission
+// drwx------ 2 mirror mirror 4096 Mar 13 2010 subversion
+// modify=20100313224553;perm=;type=dir;unique=811U282598;UNIX.group=500;UNIX.mode=0700;UNIX.owner=500; subversion
+ if (factparts.length != 2) {
+ return null; // invalid - there was no "=" sign
+ }
+ final String factname = factparts[0].toLowerCase(Locale.ENGLISH);
+ final String factvalue = factparts[1];
+ if (factvalue.isEmpty()) {
+ continue; // nothing to see here
+ }
+ final String valueLowerCase = factvalue.toLowerCase(Locale.ENGLISH);
+ if ("size".equals(factname) || "sizd".equals(factname)) {
+ file.setSize(Long.parseLong(factvalue));
+ }
+ else if ("modify".equals(factname)) {
+ final Calendar parsed = parseGMTdateTime(factvalue);
+ if (parsed == null) {
+ return null;
+ }
+ file.setTimestamp(parsed);
+ }
+ else if ("type".equals(factname)) {
+ final Integer intType = TYPE_TO_INT.get(valueLowerCase);
+ if (intType == null) {
+ file.setType(FTPFile.UNKNOWN_TYPE);
+ } else {
+ file.setType(intType.intValue());
+ }
+ }
+ else if (factname.startsWith("unix.")) {
+ final String unixfact = factname.substring("unix.".length()).toLowerCase(Locale.ENGLISH);
+ if ("group".equals(unixfact)){
+ file.setGroup(factvalue);
+ } else if ("owner".equals(unixfact)){
+ file.setUser(factvalue);
+ } else if ("mode".equals(unixfact)){ // e.g. 0[1]755
+ final int off = factvalue.length()-3; // only parse last 3 digits
+ for(int i=0; i < 3; i++){
+ final int ch = factvalue.charAt(off+i)-'0';
+ if (ch >= 0 && ch <= 7) { // Check it's valid octal
+ for(final int p : UNIX_PERMS[ch]) {
+ file.setPermission(UNIX_GROUPS[i], p, true);
+ }
+ } else {
+ // TODO should this cause failure, or can it be reported somehow?
+ }
+ } // digits
+ } // mode
+ } // unix.
+ else if (!hasUnixMode && "perm".equals(factname)) { // skip if we have the UNIX.mode
+ doUnixPerms(file, valueLowerCase);
+ } // process "perm"
+ } // each fact
+ return file;
}
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
index 7dce7db..fa06533 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
@@ -39,13 +39,6 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
static final int JES_LEVEL_1_LIST_TYPE = 3;
static final int JES_LEVEL_2_LIST_TYPE = 4;
- private int isType = UNKNOWN_LIST_TYPE;
-
- /**
- * Fallback parser for Unix-style listings
- */
- private UnixFTPEntryParser unixFTPEntryParser;
-
/**
* Dates are ignored for file lists, but are used for member lists where
* possible
@@ -156,6 +149,13 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
"(\\S+).*" // rest ignored
;
+ private int isType = UNKNOWN_LIST_TYPE;
+
+ /**
+ * Fallback parser for Unix-style listings
+ */
+ private UnixFTPEntryParser unixFTPEntryParser;
+
/*
* ---------------------------------------------------------------------
* Very brief and incomplete description of the zOS/MVS-file system. (Note:
@@ -252,32 +252,13 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
super.configure(null); // configure parser with default configurations
}
- /**
- * Parses a line of an z/OS - MVS FTP server file listing and converts it
- * into a usable format in the form of an <code> FTPFile </code> instance.
- * If the file listing line doesn't describe a file, then
- * <code> null </code> is returned. Otherwise a <code> FTPFile </code>
- * instance representing the file is returned.
- *
- * @param entry
- * A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
+ /*
+ * @return
*/
@Override
- public FTPFile parseFTPEntry(final String entry) {
- if (isType == FILE_LIST_TYPE) {
- return parseFileList(entry);
- } else if (isType == MEMBER_LIST_TYPE) {
- return parseMemberList(entry);
- } else if (isType == UNIX_LIST_TYPE) {
- return unixFTPEntryParser.parseFTPEntry(entry);
- } else if (isType == JES_LEVEL_1_LIST_TYPE) {
- return parseJeslevel1List(entry);
- } else if (isType == JES_LEVEL_2_LIST_TYPE) {
- return parseJeslevel2List(entry);
- }
-
- return null;
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(FTPClientConfig.SYST_MVS,
+ DEFAULT_DATE_FORMAT, null);
}
/**
@@ -330,59 +311,30 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
}
/**
- * Parse entries within a partitioned dataset.
- *
- * Format of a memberlist within a PDS:
- * <pre>
- * 0 1 2 3 4 5 6 7 8
- * Name VV.MM Created Changed Size Init Mod Id
- * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001
- * TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001
- *
- * -------------------------------------------
- * [1] Name
- * [2] VV.MM: Version . modification
- * [3] Created: yyyy / MM / dd
- * [4,5] Changed: yyyy / MM / dd HH:mm
- * [6] Size: number of lines
- * [7] Init: number of lines when first created
- * [8] Mod: number of modified lines a last save
- * [9] Id: User id for last update
- * </pre>
+ * Parses a line of an z/OS - MVS FTP server file listing and converts it
+ * into a usable format in the form of an <code> FTPFile </code> instance.
+ * If the file listing line doesn't describe a file, then
+ * <code> null </code> is returned. Otherwise a <code> FTPFile </code>
+ * instance representing the file is returned.
*
- * @param entry zosDirectoryEntry
- * @return null: entry was not parsed.
+ * @param entry
+ * A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
*/
- private FTPFile parseMemberList(final String entry) {
- final FTPFile file = new FTPFile();
- if (matches(entry)) {
- file.setRawListing(entry);
- final String name = group(1);
- final String datestr = group(2) + " " + group(3);
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- try {
- file.setTimestamp(super.parseTimestamp(datestr));
- } catch (final ParseException e) {
- // just ignore parsing errors.
- // TODO check this is ok
- // Drop thru to try simple parser
- }
- return file;
+ @Override
+ public FTPFile parseFTPEntry(final String entry) {
+ if (isType == FILE_LIST_TYPE) {
+ return parseFileList(entry);
+ } else if (isType == MEMBER_LIST_TYPE) {
+ return parseMemberList(entry);
+ } else if (isType == UNIX_LIST_TYPE) {
+ return unixFTPEntryParser.parseFTPEntry(entry);
+ } else if (isType == JES_LEVEL_1_LIST_TYPE) {
+ return parseJeslevel1List(entry);
+ } else if (isType == JES_LEVEL_2_LIST_TYPE) {
+ return parseJeslevel2List(entry);
}
- /*
- * Assigns the name to the first word of the entry. Only to be used from a
- * safe context, for example from a memberlist, where the regex for some
- * reason fails. Then just assign the name field of FTPFile.
- */
- if (entry != null && !entry.trim().isEmpty()) {
- file.setRawListing(entry);
- final String name = entry.split(" ")[0];
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- return file;
- }
return null;
}
@@ -458,6 +410,63 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
}
/**
+ * Parse entries within a partitioned dataset.
+ *
+ * Format of a memberlist within a PDS:
+ * <pre>
+ * 0 1 2 3 4 5 6 7 8
+ * Name VV.MM Created Changed Size Init Mod Id
+ * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001
+ * TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001
+ *
+ * -------------------------------------------
+ * [1] Name
+ * [2] VV.MM: Version . modification
+ * [3] Created: yyyy / MM / dd
+ * [4,5] Changed: yyyy / MM / dd HH:mm
+ * [6] Size: number of lines
+ * [7] Init: number of lines when first created
+ * [8] Mod: number of modified lines a last save
+ * [9] Id: User id for last update
+ * </pre>
+ *
+ * @param entry zosDirectoryEntry
+ * @return null: entry was not parsed.
+ */
+ private FTPFile parseMemberList(final String entry) {
+ final FTPFile file = new FTPFile();
+ if (matches(entry)) {
+ file.setRawListing(entry);
+ final String name = group(1);
+ final String datestr = group(2) + " " + group(3);
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ try {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ } catch (final ParseException e) {
+ // just ignore parsing errors.
+ // TODO check this is ok
+ // Drop thru to try simple parser
+ }
+ return file;
+ }
+
+ /*
+ * Assigns the name to the first word of the entry. Only to be used from a
+ * safe context, for example from a memberlist, where the regex for some
+ * reason fails. Then just assign the name field of FTPFile.
+ */
+ if (entry != null && !entry.trim().isEmpty()) {
+ file.setRawListing(entry);
+ final String name = entry.split(" ")[0];
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return file;
+ }
+ return null;
+ }
+
+ /**
* preParse is called as part of the interface. Per definition is is called
* before the parsing takes place.
* Three kind of lists is recognize:
@@ -509,13 +518,4 @@ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
isType = type;
}
- /*
- * @return
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(FTPClientConfig.SYST_MVS,
- DEFAULT_DATE_FORMAT, null);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
index bcd5c24..d2200f2 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
@@ -115,6 +115,20 @@ public class MacOsPeterFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
}
/**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ DEFAULT_DATE_FORMAT,
+ DEFAULT_RECENT_DATE_FORMAT);
+ }
+
+ /**
* Parses a line of a unix (standard) FTP server file listing and converts
* it into a usable format in the form of an <code> FTPFile </code>
* instance. If the file listing line doesn't describe a file,
@@ -260,18 +274,4 @@ public class MacOsPeterFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
return null;
}
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_UNIX,
- DEFAULT_DATE_FORMAT,
- DEFAULT_RECENT_DATE_FORMAT);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
index 31570b6..3ce5d30 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
@@ -37,8 +37,6 @@ public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
private static final String DEFAULT_DATE_FORMAT2
= "MM-dd-yy kk:mm"; //11-09-01 18:30
- private final FTPTimestampParser timestampParser;
-
/**
* this is the regular expression used by this parser.
*/
@@ -47,6 +45,8 @@ public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+ "(?:(<DIR>)|([0-9]+))\\s+" // <DIR> or ddddd; swallow trailing spaces
+ "(\\S.*)"; // First non-space followed by rest of line (name)
+ private final FTPTimestampParser timestampParser;
+
/**
* The sole constructor for an NTFTPEntryParser object.
*
@@ -86,6 +86,20 @@ public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
}
/**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ public FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_NT,
+ DEFAULT_DATE_FORMAT,
+ null);
+ }
+
+ /**
* Parses a line of an NT FTP server file listing and converts it into a
* usable format in the form of an <code> FTPFile </code> instance. If the
* file listing line doesn't describe a file, <code> null </code> is
@@ -149,18 +163,4 @@ public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
return null;
}
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- public FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_NT,
- DEFAULT_DATE_FORMAT,
- null);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
index 67f66a9..808ed2b 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
@@ -84,6 +84,18 @@ public class NetwareFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
}
/**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
+ DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT);
+ }
+
+ /**
* Parses a line of an NetwareFTP server file listing and converts it into a
* usable format in the form of an <code> FTPFile </code> instance. If the
* file listing line doesn't describe a file, <code> null </code> is
@@ -161,16 +173,4 @@ public class NetwareFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
}
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
- DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
index 33dfc96..1cc6333 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
@@ -74,6 +74,20 @@ public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
}
/**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS2,
+ DEFAULT_DATE_FORMAT,
+ null);
+ }
+
+ /**
* Parses a line of an OS2 FTP server file listing and converts it into a
* usable format in the form of an <code> FTPFile </code> instance. If the
* file listing line doesn't describe a file, <code> null </code> is
@@ -128,18 +142,4 @@ public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
}
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_OS2,
- DEFAULT_DATE_FORMAT,
- null);
- }
-
}
diff --git a/src/main/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
index 437ab0c..3e15035 100644
--- a/src/main/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
+++ b/src/main/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
@@ -278,6 +278,34 @@ public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
}
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS400,
+ DEFAULT_DATE_FORMAT,
+ null);
+ }
+
+ /**
+ *
+ * @param string String value that is checked for <code>null</code>
+ * or empty.
+ * @return <code>true</code> for <code>null</code> or empty values,
+ * else <code>false</code>.
+ */
+ private boolean isNullOrEmpty(final String string) {
+ if (string == null || string.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
@Override
... 29022 lines suppressed ...