001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider.ftp;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.OutputStream;
022import java.time.Instant;
023
024import org.apache.commons.net.ftp.FTPFile;
025import org.apache.commons.net.ftp.FTPReply;
026import org.apache.commons.vfs2.FileSystemException;
027
028/**
029 * What VFS expects from an FTP client to provide.
030 */
031public interface FtpClient {
032
033    /**
034     * Aborts the current operation.
035     *
036     * @return true if aborted.
037     * @throws IOException If an I/O error occurs
038     */
039    boolean abort() throws IOException;
040
041    /**
042     * Returns an OutputStream through which data can be written to append to a file on the server with the given name.
043     *
044     * @param relPath The name of the remote file.
045     * @return An OutputStream through which the remote file can be appended.
046     * @throws IOException If an I/O error occurs.
047     */
048    OutputStream appendFileStream(String relPath) throws IOException;
049
050    /**
051     * There are a few FTPClient methods that do not complete the entire sequence of FTP commands to complete a transaction.
052     * These commands require some action by the programmer after the reception of a positive intermediate command. After
053     * the programmer's code completes its actions, it must call this method to receive the completion reply from the server
054     * and verify the success of the entire transaction.
055     *
056     * @return true if successfully completed, false if not.
057     * @throws IOException If an I/O error occurs.
058     */
059    boolean completePendingCommand() throws IOException;
060
061    /**
062     * Deletes a file on the FTP server.
063     *
064     * @param relPath The relPath of the file to be deleted.
065     * @return true if successfully completed, false if not.
066     * @throws IOException If an I/O error occurs.
067     */
068    boolean deleteFile(String relPath) throws IOException;
069
070    /**
071     * Sends the FTP QUIT command to the server, receive the reply, and return the reply code.
072     *
073     * @throws IOException If an I/O error occurs.
074     */
075    void disconnect() throws IOException;
076
077    /**
078     * Gets the integer value of the reply code of the last FTP reply.
079     *
080     * @return The integer value of the reply code of the last FTP reply.
081     * @throws IOException If an I/O error occurs.
082     */
083    @SuppressWarnings("unused")
084    default int getReplyCode() throws IOException {
085        return FTPReply.COMMAND_OK;
086    }
087
088    /**
089     * Gets the entire text of the last FTP server response exactly as it was received, including all end of line markers in
090     * NETASCII format.
091     *
092     * @return The entire text from the last FTP response as a String.
093     * @throws IOException If an I/O error occurs.
094     */
095    String getReplyString() throws IOException;
096
097    /**
098     * Queries the server for a supported feature.
099     *
100     * @param feature the name of the feature, converted to upper case.
101     * @return {@code true} if the feature is present, {@code false} if the feature is not present or the FTP command
102     *         failed.
103     *
104     * @throws IOException If an I/O error occurs.
105     * @since 2.8.0
106     */
107    boolean hasFeature(String feature) throws IOException;
108
109    /**
110     * Tests if the client is currently connected to a server.
111     *
112     * @return true if the client is currently connected to a server, false otherwise.
113     * @throws FileSystemException If an I/O error occurs.
114     */
115    boolean isConnected() throws FileSystemException;
116
117    /**
118     * Using the default system autodetect mechanism, obtain a list of file information for the current working directory or
119     * for just a single file.
120     * <p>
121     * TODO This interface should not leak Apache Commons NET types like FTPFile
122     * </p>
123     *
124     * @param relPath The file or directory to list.
125     * @return an array of FTPFile.
126     * @throws IOException If an I/O error occurs.
127     */
128    FTPFile[] listFiles(String relPath) throws IOException;
129
130    /**
131     * Creates a new subdirectory on the FTP server in the current directory (if a relative pathname is given) or where
132     * specified (if an absolute pathname is given).
133     *
134     * @param relPath The pathname of the directory to create.
135     * @return true if successfully completed, false if not.
136     * @throws IOException If an I/O error occurs.
137     */
138    boolean makeDirectory(String relPath) throws IOException;
139
140    /**
141     * Sends the MDTM command to get a file's date and time information after file transfer. It is typically more accurate
142     * than the {@code "LIST"} command response. Time values are always represented in UTC (GMT), and in the Gregorian
143     * calendar regardless of what calendar may have been in use at the date and time the file was last modified.
144     * <p>
145     * NOTE: not all remote FTP servers support {@code MDTM}.
146     * </p>
147     *
148     * @param relPath The relative path of the file object to execute {@code MDTM} command against
149     * @return new {@code Instant} object containing the {@code MDTM} timestamp.
150     * @throws IOException If an I/O error occurs.
151     * @since 2.8.0
152     */
153    @SuppressWarnings("unused")
154    default Instant mdtmInstant(final String relPath) throws IOException {
155        return null;
156    }
157
158    /**
159     * Removes a directory on the FTP server (if empty).
160     *
161     * @param relPath The pathname of the directory to remove.
162     * @return true if successfully completed, false if not.
163     * @throws IOException If an I/O error occurs.
164     */
165    boolean removeDirectory(String relPath) throws IOException;
166
167    /**
168     * Renames a remote file.
169     *
170     * @param from The name of the remote file to rename.
171     * @param to The new name of the remote file.
172     * @return true if successfully completed, false if not.
173     * @throws IOException If an I/O error occurs.
174     */
175    boolean rename(String from, String to) throws IOException;
176
177    /**
178     * Returns an InputStream from which a named file from the server can be read.
179     *
180     * @param relPath The name of the remote file.
181     * @return An InputStream from which the remote file can be read.
182     * @throws IOException If an I/O error occurs.
183     */
184    InputStream retrieveFileStream(String relPath) throws IOException;
185
186    /**
187     * Returns an InputStream from which a named file from the server can be read.
188     *
189     * @param relPath The name of the remote file.
190     * @param bufferSize buffer size.
191     * @return An InputStream from which the remote file can be read.
192     * @throws IOException If an I/O error occurs.
193     */
194    default InputStream retrieveFileStream(final String relPath, final int bufferSize) throws IOException {
195        // Backward compatibility: no buffer size.
196        return retrieveFileStream(relPath);
197    }
198
199    /**
200     * Returns an InputStream from which a named file from the server can be read.
201     *
202     * @param relPath The name of the remote file.
203     * @param restartOffset restart offset.
204     * @return An InputStream from which the remote file can be read.
205     * @throws IOException If an I/O error occurs.
206     */
207    InputStream retrieveFileStream(String relPath, long restartOffset) throws IOException;
208
209    /**
210     * Sets the buffer size for buffered data streams.
211     *
212     * @param bufferSize The size of the buffer.
213     * @throws FileSystemException If an I/O error occurs.
214     */
215    @SuppressWarnings("unused")
216    default void setBufferSize(final int bufferSize) throws FileSystemException {
217        // Backward compatibility: do nothing.
218    }
219
220    /**
221     * Returns an OutputStream through which data can be written to store a file on the server using the given name.
222     *
223     * @param relPath The name to give the remote file.
224     * @return An OutputStream through which the remote file can be written.
225     * @throws IOException If an I/O error occurs.
226     */
227    OutputStream storeFileStream(String relPath) throws IOException;
228
229}