Implemented DownloadWorkflowStep

- DownloadWorkflowStep still calls next step as connection needs to be
   closed
 - Added more debug logging
This commit is contained in:
Josh Stark 2015-10-17 17:14:55 +01:00
parent 455b074bd4
commit 5debe9aebd
13 changed files with 298 additions and 45 deletions

View File

@ -6,6 +6,7 @@ import java.util.List;
import org.joda.time.DateTime;
import io.linuxserver.davos.schedule.workflow.actions.PostDownloadAction;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
import io.linuxserver.davos.transfer.ftp.TransferProtocol;
import io.linuxserver.davos.transfer.ftp.client.UserCredentials;
@ -21,9 +22,10 @@ public class ScheduleConfiguration {
private List<String> filters = new ArrayList<String>();
private List<PostDownloadAction> actions = new ArrayList<PostDownloadAction>();
private DateTime lastRun = DateTime.now();
private FileTransferType transferType;
public ScheduleConfiguration(final String scheduleName, final TransferProtocol protocol, final String hostname,
final int port, final UserCredentials credentials, final String remoteFilePath, final String localFilePath) {
final int port, final UserCredentials credentials, final String remoteFilePath, final String localFilePath, FileTransferType transferType) {
this.scheduleName = scheduleName;
this.connectionType = protocol;
@ -32,6 +34,7 @@ public class ScheduleConfiguration {
this.credentials = credentials;
this.localFilePath = localFilePath;
this.remoteFilePath = remoteFilePath;
this.transferType = transferType;
}
public TransferProtocol getConnectionType() {
@ -85,4 +88,8 @@ public class ScheduleConfiguration {
public void setLastRun(DateTime lastRun) {
this.lastRun = lastRun;
}
public FileTransferType getTransferType() {
return transferType;
}
}

View File

@ -3,18 +3,49 @@ package io.linuxserver.davos.schedule.workflow;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.linuxserver.davos.schedule.ScheduleConfiguration;
import io.linuxserver.davos.schedule.workflow.transfer.TransferStrategy;
import io.linuxserver.davos.schedule.workflow.transfer.TransferStrategyFactory;
import io.linuxserver.davos.transfer.ftp.FTPFile;
import io.linuxserver.davos.transfer.ftp.exception.FTPException;
public class DownloadFilesWorkflowStep extends WorkflowStep {
private static final Logger LOGGER = LoggerFactory.getLogger(DownloadFilesWorkflowStep.class);
private List<FTPFile> filesToDownload = new ArrayList<FTPFile>();
private TransferStrategyFactory transferStrategyFactory = new TransferStrategyFactory();
public DownloadFilesWorkflowStep() {
this.nextStep = new DisconnectWorkflowStep();
}
@Override
public void runStep(ScheduleWorkflow schedule) {
ScheduleConfiguration config = schedule.getConfig();
TransferStrategy strategyToUse = transferStrategyFactory.getStrategy(config.getTransferType(), schedule.getConnection());
LOGGER.debug("Strategy chosen for downloads is {}, selected {}", config.getTransferType(), strategyToUse);
try {
for (FTPFile file : filesToDownload)
strategyToUse.transferFile(file, config.getLocalFilePath());
LOGGER.info("Successfully downloaded all files. Moving onto next step");
} catch (FTPException e) {
LOGGER.error("Unable to complete download. Error was: {}", e.getMessage());
LOGGER.debug("Stacktrace", e);
LOGGER.info("Will still continue to next step");
}
nextStep.runStep(schedule);
}
public void setFilesToDownload(List<FTPFile> filesToDownload) {

View File

@ -58,6 +58,8 @@ public class FilterFilesWorkflowStep extends WorkflowStep {
}
private Predicate<? super FTPFile> after(DateTime lastRun) {
LOGGER.debug("Filtering initial set of files by lastRun. Last run was {}", lastRun);
return f -> f.getLastModified().isAfter(lastRun);
}

View File

@ -3,14 +3,14 @@ package io.linuxserver.davos.schedule.workflow.transfer;
import io.linuxserver.davos.transfer.ftp.FTPFile;
import io.linuxserver.davos.transfer.ftp.connection.Connection;
public class FilesAndFoldersTranferStrategies extends TransferStrategy {
public class FilesAndFoldersTranferStrategy extends TransferStrategy {
public FilesAndFoldersTranferStrategies(Connection connection) {
public FilesAndFoldersTranferStrategy(Connection connection) {
super(connection);
}
@Override
public void transfer(FTPFile fileToTransfer, String destination) {
public void transferFile(FTPFile fileToTransfer, String destination) {
// TODO Auto-generated method stub
}
}

View File

@ -10,7 +10,7 @@ public class FilesOnlyTransferStrategy extends TransferStrategy {
}
@Override
public void transfer(FTPFile fileToTransfer, String destination) {
public void transferFile(FTPFile fileToTransfer, String destination) {
// TODO Auto-generated method stub
}
}

View File

@ -11,5 +11,10 @@ public abstract class TransferStrategy {
this.connection = connection;
}
public abstract void transfer(FTPFile fileToTransfer, String destination);
public abstract void transferFile(FTPFile fileToTransfer, String destination);
@Override
public String toString() {
return getClass().getSimpleName();
}
}

View File

@ -0,0 +1,15 @@
package io.linuxserver.davos.schedule.workflow.transfer;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
import io.linuxserver.davos.transfer.ftp.connection.Connection;
public class TransferStrategyFactory {
public TransferStrategy getStrategy(FileTransferType type, Connection connection) {
if (FileTransferType.FILES_ONLY.equals(type))
return new FilesOnlyTransferStrategy(connection);
return new FilesAndFoldersTranferStrategy(connection);
}
}

View File

@ -1,5 +1,5 @@
package io.linuxserver.davos.transfer.ftp;
public enum FileTransferType {
FILES_ONLY, FILE_RECURSIVE, INCLUDE_FOLDERS;
FILES_ONLY, INCLUDE_FOLDERS;
}

View File

@ -15,6 +15,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import io.linuxserver.davos.schedule.ScheduleConfiguration;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
import io.linuxserver.davos.transfer.ftp.TransferProtocol;
import io.linuxserver.davos.transfer.ftp.client.Client;
import io.linuxserver.davos.transfer.ftp.client.ClientFactory;
@ -32,7 +33,7 @@ public class ConnectWorkflowStepTest {
@Mock
private Client mockClient;
@Mock
private WorkflowStep mockNextStep;
@ -48,7 +49,7 @@ public class ConnectWorkflowStepTest {
public void runStepShouldCreateNewClient() {
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
workflowStep.runStep(new ScheduleWorkflow(config));
@ -59,7 +60,7 @@ public class ConnectWorkflowStepTest {
public void runStepShouldSetClientIntoWorkflow() {
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
workflowStep.runStep(schedule);
@ -71,7 +72,7 @@ public class ConnectWorkflowStepTest {
public void runStepShouldConnectToNewlyCreatedClient() {
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
workflowStep.runStep(new ScheduleWorkflow(config));
@ -86,7 +87,7 @@ public class ConnectWorkflowStepTest {
UserCredentials credentials = new UserCredentials(hostIP, hostIP);
ScheduleConfiguration config = new ScheduleConfiguration("scheduleName", TransferProtocol.SFTP, hostIP, port, credentials,
"remotePath", "localPath");
"remotePath", "localPath", FileTransferType.FILES_ONLY);
workflowStep.runStep(new ScheduleWorkflow(config));
@ -103,22 +104,22 @@ public class ConnectWorkflowStepTest {
Connection mockConnection = mock(Connection.class);
when(mockClient.connect()).thenReturn(mockConnection);
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
workflowStep.runStep(schedule);
assertThat(schedule.getConnection()).isEqualTo(mockConnection);
}
@Test
public void runStepShouldCallOnNextStepWhenComplete() {
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
workflowStep.runStep(schedule);
@ -127,15 +128,15 @@ public class ConnectWorkflowStepTest {
inOrder.verify(mockClient).connect();
inOrder.verify(mockNextStep).runStep(schedule);
}
@Test
public void ifClientCannotConnectThenDoNotCallNextStep() {
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "");
"", "", FileTransferType.FILES_ONLY);
when(mockClient.connect()).thenThrow(new ClientConnectionException());
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
workflowStep.runStep(schedule);
@ -143,6 +144,6 @@ public class ConnectWorkflowStepTest {
inOrder.verify(mockClient).connect();
inOrder.verify(mockNextStep, never()).runStep(schedule);
}
}

View File

@ -0,0 +1,126 @@
package io.linuxserver.davos.schedule.workflow;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import io.linuxserver.davos.schedule.ScheduleConfiguration;
import io.linuxserver.davos.schedule.workflow.transfer.TransferStrategy;
import io.linuxserver.davos.schedule.workflow.transfer.TransferStrategyFactory;
import io.linuxserver.davos.transfer.ftp.FTPFile;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
import io.linuxserver.davos.transfer.ftp.TransferProtocol;
import io.linuxserver.davos.transfer.ftp.client.UserCredentials;
import io.linuxserver.davos.transfer.ftp.connection.Connection;
import io.linuxserver.davos.transfer.ftp.exception.DownloadFailedException;
public class DownloadFilesWorkflowStepTest {
@InjectMocks
private DownloadFilesWorkflowStep workflowStep = new DownloadFilesWorkflowStep();
@Mock
private WorkflowStep mockNextStep;
@Mock
private Connection mockConnection;
@Mock
private TransferStrategyFactory mockTransferStrategyFactory;
private TransferStrategy mockTransferStrategy;
@Before
public void setUp() {
initMocks(this);
mockTransferStrategy = mock(TransferStrategy.class);
when(mockTransferStrategyFactory.getStrategy(any(FileTransferType.class), eq(mockConnection)))
.thenReturn(mockTransferStrategy);
}
@Test
public void shouldCallStrategyFactoryToGetCorrectStrategyAndPassFileThrough() {
ArrayList<FTPFile> filesToDownload = new ArrayList<FTPFile>();
FTPFile file = new FTPFile("", 0, "", 0, false);
FTPFile file2 = new FTPFile("", 0, "", 0, false);
filesToDownload.add(file);
filesToDownload.add(file2);
workflowStep.setFilesToDownload(filesToDownload);
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "local/", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
schedule.setConnection(mockConnection);
workflowStep.runStep(schedule);
verify(mockTransferStrategyFactory).getStrategy(FileTransferType.FILES_ONLY, mockConnection);
verify(mockTransferStrategy).transferFile(file, "local/");
verify(mockTransferStrategy).transferFile(file2, "local/");
}
@Test
public void shouldCallOnNextStepWhenFinished() {
ArrayList<FTPFile> filesToDownload = new ArrayList<FTPFile>();
FTPFile file = new FTPFile("", 0, "", 0, false);
filesToDownload.add(file);
workflowStep.setFilesToDownload(filesToDownload);
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "local/", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
schedule.setConnection(mockConnection);
workflowStep.runStep(schedule);
InOrder inOrder = Mockito.inOrder(mockTransferStrategy, mockNextStep);
inOrder.verify(mockTransferStrategy).transferFile(file, "local/");
inOrder.verify(mockNextStep).runStep(schedule);
}
@Test
public void ifStrategyTranferFailsThenShouldStillCallNextStep() {
ArrayList<FTPFile> filesToDownload = new ArrayList<FTPFile>();
FTPFile file = new FTPFile("", 0, "", 0, false);
filesToDownload.add(file);
workflowStep.setFilesToDownload(filesToDownload);
ScheduleConfiguration config = new ScheduleConfiguration("", TransferProtocol.SFTP, "", 0, new UserCredentials("", ""),
"", "local/", FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
schedule.setConnection(mockConnection);
doThrow(new DownloadFailedException()).when(mockTransferStrategy).transferFile(file, "local/");
workflowStep.runStep(schedule);
verify(mockNextStep).runStep(schedule);
}
}

View File

@ -18,6 +18,7 @@ import org.mockito.Mockito;
import io.linuxserver.davos.schedule.ScheduleConfiguration;
import io.linuxserver.davos.transfer.ftp.FTPFile;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
import io.linuxserver.davos.transfer.ftp.connection.Connection;
import io.linuxserver.davos.transfer.ftp.exception.FileListingException;
@ -40,7 +41,8 @@ public class FilterFilesWorkflowStepTest {
@Test
public void workflowStepShouldListFilesInTheRemoteDirectory() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
schedule.setConnection(mockConnection);
@ -53,7 +55,8 @@ public class FilterFilesWorkflowStepTest {
@Test
public void workflowStepShouldFilterOutAnyFilesThatAreNotInTheGivenConfigList() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
config.setFilters(Arrays.asList("file1", "file2", "file4"));
config.setLastRun(DateTime.now().minusDays(1));
@ -84,7 +87,8 @@ public class FilterFilesWorkflowStepTest {
@Test
public void workflowStepShouldFilterOutAnyFilesThatAreNotInTheGivenConfigListAndWereModifiedBeforeLastRun() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
config.setFilters(Arrays.asList("file1", "file2", "file4"));
config.setLastRun(DateTime.now().minusDays(1));
@ -115,7 +119,8 @@ public class FilterFilesWorkflowStepTest {
@Test
public void workflowStepShouldFilterOutAnyFilesThatDoNotMatchTheWildcards() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
config.setFilters(Arrays.asList("file1?and?Stuff", "file2*something", "file4*", "file5"));
config.setLastRun(DateTime.now().minusDays(1));
@ -142,11 +147,12 @@ public class FilterFilesWorkflowStepTest {
verify(mockNextStep).setFilesToDownload(Arrays.asList(file2, file4));
}
@Test
public void workflowStepShouldCallNextStepRunMethodOnceSettingFilters() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
config.setFilters(Arrays.asList("file1", "file2", "file4"));
config.setLastRun(DateTime.now().minusDays(1));
@ -164,15 +170,16 @@ public class FilterFilesWorkflowStepTest {
workflowStep.runStep(schedule);
InOrder inOrder = Mockito.inOrder(mockNextStep);
inOrder.verify(mockNextStep).setFilesToDownload(Arrays.asList(file1));
inOrder.verify(mockNextStep).runStep(schedule);
}
@Test
public void ifFilterListIsInitiallyEmptyThenAssumeThatAllFilesAfterLastRunShouldBeDownloaded() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
config.setLastRun(DateTime.now().minusDays(1));
ArrayList<FTPFile> files = new ArrayList<FTPFile>();
@ -198,21 +205,20 @@ public class FilterFilesWorkflowStepTest {
verify(mockNextStep).setFilesToDownload(Arrays.asList(file2, file5));
}
@Test
public void ifListingFilesIsUnsuccessfulThenDoNotCallNextStep() {
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/");
ScheduleConfiguration config = new ScheduleConfiguration(null, null, null, 0, null, "remote/", "local/",
FileTransferType.FILES_ONLY);
when(mockConnection.listFiles("remote/")).thenThrow(new FileListingException());
ScheduleWorkflow schedule = new ScheduleWorkflow(config);
schedule.setConnection(mockConnection);
workflowStep.runStep(schedule);
verify(mockNextStep, never()).runStep(schedule);
}
}

View File

@ -0,0 +1,20 @@
package io.linuxserver.davos.schedule.workflow.transfer;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import io.linuxserver.davos.transfer.ftp.FileTransferType;
public class TransferStrategyFactoryTest {
@Test
public void shouldReturnCorrectStrategies() {
assertThat(new TransferStrategyFactory().getStrategy(FileTransferType.FILES_ONLY, null))
.isInstanceOf(FilesOnlyTransferStrategy.class);
assertThat(new TransferStrategyFactory().getStrategy(FileTransferType.INCLUDE_FOLDERS, null))
.isInstanceOf(FilesAndFoldersTranferStrategy.class);
}
}

View File

@ -0,0 +1,40 @@
package io.linuxserver.davos.schedule.workflow.transfer;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import io.linuxserver.davos.transfer.ftp.FTPFile;
import io.linuxserver.davos.transfer.ftp.connection.Connection;
public class TransferStrategyTest {
@Test
public void toStringShouldPrintClassName() {
assertThat(new TestTransferStrategy(null).toString()).isEqualTo("TestTransferStrategy");
assertThat(new AnotherTestTransferStrategy(null).toString()).isEqualTo("AnotherTestTransferStrategy");
}
class TestTransferStrategy extends TransferStrategy {
public TestTransferStrategy(Connection connection) {
super(connection);
}
@Override
public void transferFile(FTPFile fileToTransfer, String destination) {
}
}
class AnotherTestTransferStrategy extends TransferStrategy {
public AnotherTestTransferStrategy(Connection connection) {
super(connection);
}
@Override
public void transferFile(FTPFile fileToTransfer, String destination) {
}
}
}