001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.plugins.transfer; 019 020import java.io.File; 021import java.util.Map; 022 023import org.syncany.plugins.transfer.files.DatabaseRemoteFile; 024import org.syncany.plugins.transfer.files.MultichunkRemoteFile; 025import org.syncany.plugins.transfer.files.RemoteFile; 026import org.syncany.plugins.transfer.files.SyncanyRemoteFile; 027 028/** 029 * The transfer manager synchronously connects to the remote storage. It is 030 * responsible for file upload, download and deletion. 031 * 032 * <p>All its operations are strictly <b>synchronous</b> and throw a 033 * {@code StorageException} if they fail. The implementations have to make sure 034 * that 035 * <ul> 036 * <li>the repository is not corrupted, e.g. duplicate files or corrupt files 037 * <li>files matching the specified file format are complete, i.e. fully uploaded 038 * <li>methods that need an established connections re-connect if necessary 039 * </ul> 040 * 041 * <p>A transfer manager may organize files according to their type or name as 042 * it is optimal for the given storage. {@link RemoteFile}s can be classified 043 * by their sub-type. For network-transfer optimization reasons, it might be 044 * useful to place {@link MultichunkRemoteFile}s and {@link DatabaseRemoteFile}s 045 * in a separate sub-folder on the remote storage. 046 * 047 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 048 */ 049public interface TransferManager { 050 /** 051 * Establish a connection with the remote storage. 052 * 053 * <p>This method does not validate the correctness of the repository and 054 * it does not create any folders. The former is done by {@link #test(boolean)}, the 055 * latter is done by {@link #init(boolean)}. 056 * 057 * @throws StorageException If the connection fails due to no Internet connection, 058 * authentication errors, etc. 059 */ 060 public void connect() throws StorageException; 061 062 /** 063 * Disconnect from the remote storage. 064 * 065 * @throws StorageException If the connection fails due to no Internet connection, 066 * authentication errors, etc. 067 */ 068 public void disconnect() throws StorageException; 069 070 /** 071 * Initialize remote storage. This method is called to set up a new repository. 072 * 073 * @param createIfRequired true if the method should handle repo creation 074 * @throws StorageException If the connection drops, or any other 075 * exception occurs. 076 */ 077 public void init(boolean createIfRequired) throws StorageException; 078 079 /** 080 * Download an existing remote file to the local disk. 081 * 082 * <p>The file is either downloaded completely or nothing at all. In the latter 083 * case, a {@code StorageException} is thrown. 084 * 085 * <p>Implementations must make sure that if a file matches the specified name 086 * schema, it must be complete and consistent. 087 * 088 * <p>If remoteFile does not exist, a {@link StorageFileNotFoundException} is thrown. 089 * 090 * @param remoteFile Existing source file on the remote storage. 091 * The only required property of the remote file is the name. 092 * @param localFile Not existing local file to which the remote file is 093 * going to be downloaded. 094 * @throws StorageException If the connection fails due to no Internet connection, 095 * authentication errors, etc. 096 */ 097 public void download(RemoteFile remoteFile, File localFile) throws StorageException; 098 099 /** 100 * Update an existing local file to the online storage. 101 * 102 * <p>The file is either uploaded completely or nothing at all. In the latter 103 * case, a {@code StorageException} is thrown. 104 * 105 * <p>Implementations must make sure that if a file matches the specified name 106 * schema, it must be complete and consistent. 107 * 108 * <p>Implementations must NOT upload a file if it already exists and has 109 * the same file size as the local file. 110 * 111 * @param localFile Existing local file that is going to be uploaded. 112 * @param remoteFile Not existing destination file on the remote storage. 113 * The only required property of the remote file is the name. 114 * @throws StorageException If the connection fails due to no Internet connection, 115 * authentication errors, etc. 116 */ 117 public void upload(File localFile, RemoteFile remoteFile) throws StorageException; 118 119 /** 120 * Moves an existing file in the online storage. 121 * 122 * <p> If the sourceFile does not exists, a {@link StorageMoveException} is thrown. 123 * 124 * @param sourceFile Existing remote file that is to be moved. 125 * @param targetFile Destination for the remote file. 126 * @throws StorageException If the connection fails due to no Internet connection, 127 * authentication errors, etc. 128 */ 129 public void move(RemoteFile sourceFile, RemoteFile targetFile) throws StorageException; 130 131 /** 132 * Deletes an existing file from the remote storage permanently. 133 * 134 * <p>In case the remote file does not exist, it returns immediately without 135 * any notice. If the file cannot be deleted or the connection breaks, 136 * a {@code StorageException} is thrown. 137 * 138 * @param remoteFile Existing remote file to be deleted. 139 * The only required property of the remote file is the name. 140 * @throws StorageException If the connection fails due to no Internet connection, 141 * authentication errors, etc 142 */ 143 public boolean delete(RemoteFile remoteFile) throws StorageException; 144 145 /** 146 * Retrieves a list of all files in the remote repository, filtered by 147 * the type of the desired file, i.e. by a sub-class of {@link RemoteFile}. 148 * 149 * @param remoteFileClass Filter class: <code>RemoteFile</code> or a sub-type thereof 150 * @return Returns a list of remote files. In the map, the key is the file name, 151 * the value the entire {@link RemoteFile} object. 152 * @throws StorageException If the connection fails due to no Internet connection, 153 * authentication errors, etc 154 */ 155 public <T extends RemoteFile> Map<String, T> list(Class<T> remoteFileClass) throws StorageException; 156 157 /** 158 * Tests whether the repository parameters are valid. In particular, the method tests 159 * whether a target (folder, bucket, etc.) exists or, if not, whether it can be created. 160 * It furthermore tests whether a repository at the target already exists by checking if the 161 * {@link SyncanyRemoteFile} exists. 162 * 163 * <p>The relevant result is determined by the following methods: 164 * 165 * <ul> 166 * <li>{@link #testTargetExists()}: Tests whether the target exists.</li> 167 * <li>{@link #testTargetCanWrite()}: Tests whether the target is writable.</li> 168 * <li>{@link #testTargetCanCreate()}: Tests whether the target can be created if it does not 169 * exist already. This is only called if <code>testCreateTarget</code> is set.</li> 170 * <li>{@link #testRepoFileExists()}: Tests whether the repo file exists.</li> 171 * </ul> 172 * 173 * @return Returns the result of testing the repository. 174 * @param testCreateTarget If <code>true</code>, the test will test if the target can be created in case 175 * it does not exist. If <code>false</code>, this test will be skipped. 176 * @see StorageTestResult 177 */ 178 public StorageTestResult test(boolean testCreateTarget); 179 180 /** 181 * Tests whether the target path/folder <b>exists</b>. This might be done by listing the parent path/folder 182 * or by retrieving metadata about the target. The method returns <code>true</code> if the target exists, 183 * <code>false</code> otherwise. 184 * 185 * <p>This method is called by the {@link #test(boolean)} method (only during repository initialization 186 * or initial connection). 187 * 188 * @return Returns <code>true</code> if the target exists, <code>false</code> otherwise 189 * @throws StorageException If the test cannot be performed, e.g. due to a connection failure 190 */ 191 public boolean testTargetExists() throws StorageException; 192 193 /** 194 * Tests whether the target path/folder is <b>writable</b> by the application. This method may either 195 * check the write permissions of the target or actually write a test file to check write access. If the 196 * target does not exist, <code>false</code> is returned. If the target exists and is writable, <code>true</code> 197 * is returned. 198 * 199 * <p>This method is called by the {@link #test(boolean)} method (only during repository initialization 200 * or initial connection). 201 * 202 * @return Returns <code>true</code> if the target can be written to, <code>false</code> otherwise 203 * @throws StorageException If the test cannot be performed, e.g. due to a connection failure 204 */ 205 public boolean testTargetCanWrite() throws StorageException; 206 207 /** 208 * Tests whether the target path/folder <b>can be created</b> (if it <b>does not exist already</b>). This method 209 * may either check the permissions of the parent path/folder or actually create and delete the target to 210 * determine create permissions. 211 * 212 * <p>If the target already exists, the method returns <code>true</code>. If it does not, but it can be created 213 * (according to tests of this method), it also returns <code>true</code>. In all other cases, <code>false</code> is returned. 214 * 215 * <p>This method is called by the {@link #test(boolean)} method, <b>but only if</b> the <code>testCreateTarget</code> flag 216 * is set to <code>true</code>! 217 * 218 * @return Returns <code>true</code> if the target can be created or already exists, <code>false</code> otherwise 219 * @throws StorageException If the test cannot be performed, e.g. due to a connection failure 220 */ 221 public boolean testTargetCanCreate() throws StorageException; 222 223 /** 224 * Tests whether the <b>repository file exists</b> (see {@link SyncanyRemoteFile}). This method is called by the {@link #test(boolean)} method 225 * (only during repository initialization (or initial connection). 226 * 227 * <p>This method is called by the {@link #test(boolean)} method (only during repository initialization 228 * or initial connection). 229 * 230 * @return Returns <code>true</code> if the repository is valid, <code>false</code> otherwise 231 * @throws StorageException If the test cannot be performed, e.g. due to a connection failure 232 */ 233 public boolean testRepoFileExists() throws StorageException; 234 235 /** 236 * Return the path for a concrete {@link org.syncany.plugins.transfer.files.RemoteFile} implementation as it is stored on the 237 * remote side 238 * * 239 * @param remoteFileClass The class to provide the path for 240 * @return A string pointing to the folder where a file is stored 241 */ 242 public String getRemoteFilePath(Class<? extends RemoteFile> remoteFileClass); 243 244}