diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b8dde0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: java +jdk: + - oraclejdk8 +os: + - linux +script: + - chmod +x buildscript.sh && ./buildscript.sh diff --git a/04.FTP_GUI/pom.xml b/04.FTP_GUI/pom.xml new file mode 100644 index 0000000..59da308 --- /dev/null +++ b/04.FTP_GUI/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + 04 + FTP_GUI + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + junit + junit + 4.12 + + + + + \ No newline at end of file diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/Main.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/Main.java new file mode 100644 index 0000000..335ebac --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/Main.java @@ -0,0 +1,26 @@ +package ru.spbau.mit.alyokhina; + +import javafx.application.Application; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.layout.GridPane; +import javafx.stage.Stage; +import ru.spbau.mit.alyokhina.ui.*; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setTitle("Крестики - Нолики"); + GridPane gridPane = new GridPane(); + gridPane.setAlignment(Pos.CENTER); + CreateNewElements.createMainActivity(gridPane); + primaryStage.setScene(new Scene(gridPane, 600, 400)); + primaryStage.show(); + + } + + public static void main(String[] args) { + launch(args); + } +} \ No newline at end of file diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/client/Client.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/client/Client.java new file mode 100644 index 0000000..8dbfc96 --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/client/Client.java @@ -0,0 +1,99 @@ +package ru.spbau.mit.alyokhina.client; + +import javafx.util.Pair; +import ru.spbau.mit.alyokhina.server.Server; + + +import java.io.*; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +/** + * Client, which allows you to execute the requests list and get + */ +public class Client { + /** + * OutputStream from Socket + */ + private DataOutputStream dataOutputStream; + /** + * InputStream from Socket + */ + private DataInputStream dataInputStream; + + /** + * Constructor + * + * @throws IOException if Socket or Stream can't be created + */ + public Client(String host, int port) throws IOException { + Socket clientSocket = new Socket(host, port); + dataInputStream = new DataInputStream(clientSocket.getInputStream()); + dataOutputStream = new DataOutputStream(clientSocket.getOutputStream()); + + } + + + /** + * Listing files in the directory on the server + * + * @param path directory path + * @return list of Pair. Fist value - name of file. Second value - type of file ( if file is directory - true, else false) + * Count files in directory = length of list + * @throws IOException if we can't read/write in InputStream/OutputStream + */ + public List> list(String path) throws IOException { + List> listFiles = new ArrayList<>(); + dataOutputStream.writeInt(Server.LIST_REQUEST); + dataOutputStream.writeUTF(path); + dataOutputStream.flush(); + int count = dataInputStream.readInt(); + for (int i = 0; i < count; i++) { + String fileName = dataInputStream.readUTF(); + Boolean isDirectory = dataInputStream.readBoolean(); + listFiles.add(new Pair<>(fileName, isDirectory)); + } + return listFiles; + } + + /** + * Сopy the file from the server to the file + * + * @param path path of the file from server + * @param nameFileForSave the name of the file into which the content will be copied + * @return file into which the content will be copied + * @throws IOException if we can't read/write in InputStream/OutputStream + */ + public File get(String path, String nameFileForSave) throws IOException { + dataOutputStream.writeInt(Server.GET_REQUEST); + dataOutputStream.writeUTF(path); + dataOutputStream.flush(); + File fileForSave = new File(nameFileForSave); + int count = dataInputStream.readInt(); + if (count != 0) { + byte[] bytes = new byte[count]; + int countReadBytes = dataInputStream.read(bytes); + if (countReadBytes != count) { + throw new IOException("Impossible to read all data"); + } + DataOutputStream dataOutputStreamForSave = new DataOutputStream(new FileOutputStream(fileForSave)); + dataOutputStreamForSave.write(bytes); + } + return fileForSave; + } + + /** + * check file in server for existence + * + * @param path path of the file, that we want to check + * @return true - is exists, false - else + * @throws IOException if we can't write in dataOutputStream + */ + public boolean isExists(String path) throws IOException { + dataOutputStream.writeInt(Server.IS_EXISTS_REQUEST); + dataOutputStream.writeUTF(path); + dataOutputStream.flush(); + return dataInputStream.readBoolean(); + } +} \ No newline at end of file diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/server/Server.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/server/Server.java new file mode 100644 index 0000000..0fbcfb1 --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/server/Server.java @@ -0,0 +1,131 @@ +package ru.spbau.mit.alyokhina.server; + +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * A server that processes two list requests and receives + */ +public class Server { + /** + * Value for request list + */ + public static int LIST_REQUEST = 1; + /** + * Value for request get + */ + public static int GET_REQUEST = 2; + /** + * Value for request is exist file + */ + public static int IS_EXISTS_REQUEST = 3; + /** + * Socket for connection with this server + */ + private ServerSocket serverSocket; + + /** + * Constructor + * + * @param port port of connection + * @throws IOException if Socket can't be created + */ + public Server(int port) throws IOException { + serverSocket = new ServerSocket(port); + + } + + /** + * Start of the server + */ + public void start() { + while (true) { + try { + final Socket socket = serverSocket.accept(); + Thread thread = new Thread(() -> { + try (DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); + DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) { + while (!Thread.interrupted()) { + int requestType = dataInputStream.readInt(); + String path = dataInputStream.readUTF(); + if (requestType == LIST_REQUEST) { + list(path, dataOutputStream); + } else if (requestType == GET_REQUEST) { + get(path, dataOutputStream); + } else if (requestType == IS_EXISTS_REQUEST) { + isExist(path, dataOutputStream); + } + } + } catch (IOException e) { + System.out.println(e.getMessage()); + } + }); + thread.start(); + } catch (IOException ignored) { + break; + } + } + } + + /** + * Write count files, names of files and their types from input directory to dataOutputStream + * + * @param path directory path + * @param dataOutputStream stream for write result + * @throws IOException if it is impossible to write in dataOutputStream + */ + private void list(String path, DataOutputStream dataOutputStream) throws IOException { + File directory = new File(path); + File[] files = directory.listFiles(); + dataOutputStream.writeInt(files == null ? 0 : files.length); + if (files != null) { + for (File file : files) { + dataOutputStream.writeUTF(file.getName()); + dataOutputStream.writeBoolean(file.isDirectory()); + } + } + dataOutputStream.flush(); + } + + /** + * Write file contents in dataOutputStream + * + * @param path name of file + * @param dataOutputStream OutputStream for write result + * @throws IOException if it is impossible to write in dataOutputStream + */ + private void get(String path, DataOutputStream dataOutputStream) throws IOException { + File file = new File(path); + int length = (int) file.length(); + if (length != 0) { + DataInputStream dataInputStreamForRequest = new DataInputStream(new FileInputStream(file)); + byte[] bytes = new byte[length]; + + if (dataInputStreamForRequest.read(bytes) == length) { + dataOutputStream.writeInt(length); + dataOutputStream.write(bytes); + } else { + throw new IOException("Impossible to read all data"); + } + dataInputStreamForRequest.close(); + } else { + dataOutputStream.writeInt(length); + } + } + + /** + * check file for existence + * + * @param path path of the file, that we want to check + * @throws IOException if we can't write in dataOutputStream or create + */ + private void isExist(String path, DataOutputStream dataOutputStream) throws IOException { + File file = new File(path); + dataOutputStream.writeBoolean(file.exists()); + } +} + + + + diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ClientUI.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ClientUI.java new file mode 100644 index 0000000..b9af4ad --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ClientUI.java @@ -0,0 +1,183 @@ +package ru.spbau.mit.alyokhina.ui; + +import javafx.application.Platform; +import javafx.scene.control.ListView; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import javafx.util.Pair; +import ru.spbau.mit.alyokhina.client.Client; + +import java.io.IOException; +import java.util.HashSet; +import java.util.List; + + +/** + * UI for Client + */ +public class ClientUI { + /** + * Constructor + * + * @param gridPane on which objects will be placed + */ + public ClientUI(GridPane gridPane) { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 50, 300, 0, 0, "Введите порт"); + TextField textFieldForPort = CreateNewElements.createTextField(gridPane, 50, 300, 0, 1); + CreateNewElements.createLabel(gridPane, 50, 300, 0, 2, "Введите хост"); + TextField textFieldForHost = CreateNewElements.createTextField(gridPane, 50, 300, 0, 3); + CreateNewElements.createLabel(gridPane, 50, 300, 0, 4, "Введите путь"); + TextField textFieldForPath = CreateNewElements.createTextField(gridPane, 50, 300, 0, 5); + + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 100, 1, 6, "OK"), + actionEvent -> startClient(gridPane, textFieldForPort.getText(), textFieldForHost.getText(), textFieldForPath.getText())); + + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 100, 1, 0, "Назад"), + actionEvent -> CreateNewElements.createMainActivity(gridPane)); + } + + /** + * Print files from the server on this path + * + * @param gridPane on which objects will be placed + * @param client to communicate with the server + * @param path on which we want to get the files + */ + public void printFiles(GridPane gridPane, Client client, String path) { + + try { + if (!client.isExists(path)) { + CreateNewElements.createLabel(gridPane, 50, 100, 0, 6, "Такого пути не существует"); + } else { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 50, 100, 0, 0, path); + List> files = client.list(path); + HashSet dir = new HashSet<>(); + for (Pair file : files) { + if (file.getValue()) { + dir.add(file.getKey()); + } + } + ListView listView = CreateNewElements.createListView(gridPane, files, dir); + listView.setOnMouseClicked(event -> { + if (dir.contains(listView.getSelectionModel().getSelectedItem())) { + printFiles(gridPane, client, path + '/' + listView.getSelectionModel().getSelectedItem()); + } else { + agreement(gridPane, client, path + '/' + listView.getSelectionModel().getSelectedItem()); + } + }); + + } + } catch (IOException e) { + CreateNewElements.createLabel(gridPane, 50, 100, 0, 6, e.getMessage(), "#ff0000"); + } + CreateNewElements.createBackButton(gridPane, 100, 100, 1, 0, "Назад", path, client, this); + + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 100, 150, 2, 0, "В главное меню"), + actionEvent -> CreateNewElements.createMainActivity(gridPane)); + } + + /** + * Get an agreement to download a file + * + * @param gridPane on which objects will be placed + * @param client to communicate with the server + * @param path path of the file, that we want to download + */ + private void agreement(GridPane gridPane, Client client, String path) { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 50, 200, 1, 0, "Вы уверены, что хотите скачать?"); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 50, 0, 1, "Да"), + actionEvent -> download(gridPane, client, path) + ); + + CreateNewElements.createBackButton(gridPane, 50, 50, 2, 1, "Нет", path, client, this); + } + + /** + * Download file from server + * + * @param gridPane on which objects will be placed + * @param client to communicate with the server + * @param path path of the file, that would be download + */ + private void download(GridPane gridPane, Client client, String path) { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 50, 300, 0, 0, "Введите путь для сохранения"); + TextField textFieldForDowloadPath = CreateNewElements.createTextField(gridPane, 50, 300, 0, 1); + CreateNewElements.createBackButton(gridPane, 50, 100, 1, 0, "Назад", path, client, this); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 100, 1, 2, "OK"), + actionEvent -> { + try { + client.get(path, textFieldForDowloadPath.getText()); + afterDownload(gridPane, client, path); + } catch (IOException e) { + if (gridPane.getChildren().size() > 4) { + for (int i = 4; i < gridPane.getChildren().size(); i++) { + gridPane.getChildren().remove(i); + } + } + CreateNewElements.createLabel(gridPane, 50, 300, 0, 2, e.getMessage(), "#ff0000"); + } + }); + + + } + + + /** + * Selecting the transition after downloading the file + * + * @param gridPane on which objects will be placed + * @param client to communicate with the server + * @param path of the file, that was downloaded + */ + private void afterDownload(GridPane gridPane, Client client, String path) { + gridPane.getChildren().clear(); + CreateNewElements.createBackButton(gridPane, 100, 200, 0, 0, "Продолжить", path, client, this); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 100, 200, 0, 1, "В главное меню"), + actionEvent -> CreateNewElements.createMainActivity(gridPane) + ); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 100, 200, 0, 2, "Выход"), + actionEvent -> Platform.exit() + ); + + } + + /** + * Start client work + * + * @param gridPane on which objects will be placed + * @param namePort for create client + * @param host gor create client + * @param path of the current directory + */ + private void startClient(GridPane gridPane, String namePort, String host, String path) { + if (gridPane.getChildren().size() > 8) { + for (int i = 8; i < gridPane.getChildren().size(); i++) { + gridPane.getChildren().remove(i); + } + } + Integer port; + try { + port = Integer.parseInt(namePort); + } catch (NumberFormatException e) { + CreateNewElements.createLabel(gridPane, 50, 300, 0, 6, "Неккоректный порт. \nПопробуйте еще раз", "#ff0000"); + return; + } + try { + Client client = new Client(host, port); + printFiles(gridPane, client, path); + } catch (IOException e) { + CreateNewElements.createLabel(gridPane, 50, 300, 0, 6, e.getMessage(), "#ff0000"); + } + } +} diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/CreateNewElements.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/CreateNewElements.java new file mode 100644 index 0000000..7c3630d --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/CreateNewElements.java @@ -0,0 +1,215 @@ +package ru.spbau.mit.alyokhina.ui; + +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.GridPane; +import javafx.scene.paint.Color; + +import javafx.event.EventHandler; +import javafx.util.Pair; +import ru.spbau.mit.alyokhina.client.Client; + +import java.io.File; +import java.net.MalformedURLException; +import java.util.HashSet; +import java.util.List; + +public class CreateNewElements { + + /** + * Create button + * + * @param height height of the button + * @param width width of the button + * @param x abscissa coordinate + * @param y ordinate coordinate + * @param text this text will be on the button + * @return new button + */ + public static Button createButton(GridPane gridPane, double height, double width, int x, int y, String text) { + Button button = new Button(); + gridPane.add(button, x, y); + button.setText(text); + button.setPrefHeight(height); + button.setPrefWidth(width); + button.setLayoutX(x); + button.setLayoutY(y); + return button; + } + + /** + * Create label + * + * @param height height of the label + * @param width width of the label + * @param x abscissa coordinate + * @param y ordinate coordinate + * @param text this text will be on the label + * @return new label + */ + public static Label createLabel(GridPane gridPane, double height, double width, int x, int y, String text) { + Label label = new Label(); + gridPane.add(label, x, y); + label.setText(text); + label.setPrefHeight(height); + label.setPrefWidth(width); + label.setAlignment(Pos.CENTER); + label.setWrapText(true); + return label; + } + + /** + * Create label + * + * @param height height of the label + * @param width width of the label + * @param x abscissa coordinate + * @param y ordinate coordinate + * @param text this text will be on the label + * @param color color of the text + */ + public static void createLabel(GridPane gridPane, double height, double width, int x, int y, String text, String color) { + Label label = createLabel(gridPane, height, width, x, y, text); + label.setTextFill(Color.web(color)); + } + + /** + * Create TextField + * + * @param height height of the textField + * @param width width of the textField + * @param x abscissa coordinate + * @param y ordinate coordinate + * @return new textField + */ + public static TextField createTextField(GridPane gridPane, double height, double width, int x, int y) { + TextField textField = new TextField(); + textField.setPrefHeight(height); + textField.setPrefWidth(width); + gridPane.add(textField, x, y); + return textField; + } + + + /** + * Add an action to click a button + * @param button add action to this button + * @param actionEvent this action will be after click + */ + public static void addActionToButton(Button button, EventHandler actionEvent) { + button.setOnAction(actionEvent); + } + + + /** + * Create ListView + * @param gridPane on which objects will be placed + * @param files list all files will be printed. First parameter is files name, second - true, if directory, else - false + * @param dir set of name of files, which is directory + * @return ListView + */ + public static ListView createListView(GridPane gridPane, List> files, HashSet dir) { + ListView listView = new ListView<>(); + ObservableList items = FXCollections.observableArrayList(); + for (Pair file : files) { + items.add(file.getKey()); + } + listView.setItems(items); + + listView.setCellFactory(param -> new ListCell() { + private ImageView imageView = new ImageView(); + + @Override + public void updateItem(String name, boolean empty) { + super.updateItem(name, empty); + if (empty) { + setText(null); + setGraphic(null); + } else { + try { + if (dir.contains(name)) { + imageView.setImage(new Image(new File("src/main/resources/directory.png").toURI().toURL().toExternalForm())); + } else { + imageView.setImage(new Image(new File("src/main/resources/file.png").toURI().toURL().toExternalForm())); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } + setText(name); + imageView.setFitHeight(25); + imageView.setFitWidth(25); + setGraphic(imageView); + } + } + }); + gridPane.add(listView, 0, 1); + return listView; + } + + + /** + * Create Main Activity. 3 buttons : create server, create client, exit + * @param gridPane on which objects will be placed + */ + public static void createMainActivity(GridPane gridPane) { + gridPane.getChildren().clear(); + addActionToButton( + createButton(gridPane, 50, 200, 0, 0, "Создать сервер"), + actionEvent -> new ServerUI(gridPane) + ); + addActionToButton( + createButton(gridPane, 50, 200, 0, 1, "Новый клиент"), + actionEvent -> new ClientUI(gridPane) + ); + addActionToButton( + createButton(gridPane, 50, 200, 0, 2, "Выход"), + actionEvent -> Platform.exit() + ); + } + + + /** + * Create button for back + * @param gridPane on which objects will be placed + * @param height height of the button + * @param width width of the button + * @param x abscissa coordinate + * @param y ordinate coordinate + * @param text this text will be on the button + * @param path path for back from the current directory + * @param client to communicate with the server + * @param clientUI for print result + */ + public static void createBackButton(GridPane gridPane, double height, double width, int x, int y, String text, String path, Client client, ClientUI clientUI) { + addActionToButton( + createButton(gridPane, height, width, x, y, text), + actionEvent -> { + if (path.equals("/")) { + createMainActivity(gridPane); + } else { + int end = 0; + for (int i = path.length() - 1; i >= 0; i--) { + if (path.charAt(i) == '/') { + end = i; + break; + } + } + if (end == 0) { + clientUI.printFiles(gridPane, client, "/"); + } else { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < end; i++) { + stringBuilder.append(path.charAt(i)); + } + clientUI.printFiles(gridPane, client, stringBuilder.toString()); + } + } + }); + } +} diff --git a/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ServerUI.java b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ServerUI.java new file mode 100644 index 0000000..fde6667 --- /dev/null +++ b/04.FTP_GUI/src/main/java/ru/spbau/mit/alyokhina/ui/ServerUI.java @@ -0,0 +1,66 @@ +package ru.spbau.mit.alyokhina.ui; + +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import ru.spbau.mit.alyokhina.server.Server; + +import java.io.IOException; + +public class ServerUI { + + public ServerUI(GridPane gridPane) { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 50, 400, 0, 0, "Введите порт"); + TextField port = CreateNewElements.createTextField(gridPane, 100, 200, 0, 2); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 100, 1, 3, "OK"), + actionEvent -> { + createServer(gridPane, port.getText()); + } + ); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 100, 1, 0, "Назад"), + actionEvent -> { + CreateNewElements.createMainActivity(gridPane); + } + ); + } + + private void result(GridPane gridPane) { + gridPane.getChildren().clear(); + CreateNewElements.createLabel(gridPane, 100, 200, 0, 0, "Сервер создан"); + CreateNewElements.addActionToButton( + CreateNewElements.createButton(gridPane, 50, 200, 0, 1, "Назад"), + actionEvent -> { + CreateNewElements.createMainActivity(gridPane); + } + ); + } + + + private void createServer(GridPane gridPane, String namePort) { + if (gridPane.getChildren().size() > 4) { + for (int i = 4; i < gridPane.getChildren().size();i++) { + gridPane.getChildren().remove(i); + } + } + Integer port; + try{ + port = Integer.parseInt(namePort); + } + catch (NumberFormatException e) { + CreateNewElements.createLabel(gridPane, 50, 400, 0, 3, "Неккоректный порт. \nПопробуйте еще раз", "#ff0000"); + return; + } + try { + Server server = new Server(port); + Thread thread = new Thread(server::start); + thread.start(); + result(gridPane); + } + catch (IOException | IllegalArgumentException e) { + CreateNewElements.createLabel(gridPane, 50, 400, 0, 3, e.getMessage(), "#ff0000"); + } + + } +} diff --git a/04.FTP_GUI/src/main/resources/directory.png b/04.FTP_GUI/src/main/resources/directory.png new file mode 100644 index 0000000..ada21cb Binary files /dev/null and b/04.FTP_GUI/src/main/resources/directory.png differ diff --git a/04.FTP_GUI/src/main/resources/file.png b/04.FTP_GUI/src/main/resources/file.png new file mode 100644 index 0000000..7c0209a Binary files /dev/null and b/04.FTP_GUI/src/main/resources/file.png differ diff --git a/04.FTP_GUI/src/resources/testGet1/copyFile1 b/04.FTP_GUI/src/resources/testGet1/copyFile1 new file mode 100644 index 0000000..4d20f7a --- /dev/null +++ b/04.FTP_GUI/src/resources/testGet1/copyFile1 @@ -0,0 +1,8 @@ +Я вас любил: любовь еще, быть может, +В душе моей угасла не совсем; +Но пусть она вас больше не тревожит; +Я не хочу печалить вас ничем. +Я вас любил безмолвно, безнадежно, +То робостью, то ревностью томим; +Я вас любил так искренно, так нежно, +Как дай вам бог любимой быть другим. \ No newline at end of file diff --git a/04.FTP_GUI/src/resources/testGet1/copyFile2 b/04.FTP_GUI/src/resources/testGet1/copyFile2 new file mode 100644 index 0000000..9d57e16 --- /dev/null +++ b/04.FTP_GUI/src/resources/testGet1/copyFile2 @@ -0,0 +1,9 @@ +Я выжила… Отчаянно, ознобно, +Легко. Светает. Снег сошёл на нет. +Не слышен плач, не ослепляет свет. +Глаза пусты, глаза беззлобны. + +Недостающий воздух – чушь, пустяк, +Совпал с полночным и привычным зноем. +А если будет что-нибудь не так… +Ты мне поможешь? Нас пока что двое? \ No newline at end of file diff --git a/04.FTP_GUI/src/resources/testGet1/file1 b/04.FTP_GUI/src/resources/testGet1/file1 new file mode 100644 index 0000000..4d20f7a --- /dev/null +++ b/04.FTP_GUI/src/resources/testGet1/file1 @@ -0,0 +1,8 @@ +Я вас любил: любовь еще, быть может, +В душе моей угасла не совсем; +Но пусть она вас больше не тревожит; +Я не хочу печалить вас ничем. +Я вас любил безмолвно, безнадежно, +То робостью, то ревностью томим; +Я вас любил так искренно, так нежно, +Как дай вам бог любимой быть другим. \ No newline at end of file diff --git a/04.FTP_GUI/src/resources/testGet1/file2 b/04.FTP_GUI/src/resources/testGet1/file2 new file mode 100644 index 0000000..9d57e16 --- /dev/null +++ b/04.FTP_GUI/src/resources/testGet1/file2 @@ -0,0 +1,9 @@ +Я выжила… Отчаянно, ознобно, +Легко. Светает. Снег сошёл на нет. +Не слышен плач, не ослепляет свет. +Глаза пусты, глаза беззлобны. + +Недостающий воздух – чушь, пустяк, +Совпал с полночным и привычным зноем. +А если будет что-нибудь не так… +Ты мне поможешь? Нас пока что двое? \ No newline at end of file diff --git a/04.FTP_GUI/src/resources/testList1/dir1/1 b/04.FTP_GUI/src/resources/testList1/dir1/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList1/dir2/1 b/04.FTP_GUI/src/resources/testList1/dir2/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList1/file1 b/04.FTP_GUI/src/resources/testList1/file1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList1/file2 b/04.FTP_GUI/src/resources/testList1/file2 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList1/file3 b/04.FTP_GUI/src/resources/testList1/file3 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/dir1/1 b/04.FTP_GUI/src/resources/testList2/dir1/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/dir2/1 b/04.FTP_GUI/src/resources/testList2/dir2/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/dir3/1 b/04.FTP_GUI/src/resources/testList2/dir3/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/dir4/1 b/04.FTP_GUI/src/resources/testList2/dir4/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/dir5/1 b/04.FTP_GUI/src/resources/testList2/dir5/1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/file1 b/04.FTP_GUI/src/resources/testList2/file1 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/resources/testList2/file2 b/04.FTP_GUI/src/resources/testList2/file2 new file mode 100644 index 0000000..e69de29 diff --git a/04.FTP_GUI/src/test/java/ru/spbau/mit/alyokhina/client/ClientTest.java b/04.FTP_GUI/src/test/java/ru/spbau/mit/alyokhina/client/ClientTest.java new file mode 100644 index 0000000..f7128cb --- /dev/null +++ b/04.FTP_GUI/src/test/java/ru/spbau/mit/alyokhina/client/ClientTest.java @@ -0,0 +1,231 @@ +package ru.spbau.mit.alyokhina.client; + +import javafx.util.Pair; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import ru.spbau.mit.alyokhina.server.Server; + +import static org.junit.Assert.assertEquals; + + +/** + * Test for client-server connection + */ +public class ClientTest { + /** + * If a server was created, this flag will be true + */ + private static boolean isCreateServer = false; + + + @Test + public void testCreateClientAndServer() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client = new Client("localhost", 1408); + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + @Test + public void testListWithOneClient() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client = new Client("localhost", 1408); + List> files = client.list("src/resources/testList1"); + List> rightAnswer = new ArrayList<>(); + rightAnswer.add(new Pair<>("dir1", true)); + rightAnswer.add(new Pair<>("dir2", true)); + rightAnswer.add(new Pair<>("file3", false)); + rightAnswer.add(new Pair<>("file1", false)); + rightAnswer.add(new Pair<>("file2", false)); + assertEquals(rightAnswer.size(), equalLists(rightAnswer, files)); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + + @Test + public void testListWithTwoClients() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client1 = new Client("localhost", 1408); + Client client2 = new Client("localhost", 1408); + List> files1 = client1.list("src/resources/testList1"); + List> files2 = client2.list("src/resources/testList2"); + List> rightAnswer1 = new ArrayList<>(); + rightAnswer1.add(new Pair<>("dir1", true)); + rightAnswer1.add(new Pair<>("dir2", true)); + rightAnswer1.add(new Pair<>("file3", false)); + rightAnswer1.add(new Pair<>("file1", false)); + rightAnswer1.add(new Pair<>("file2", false)); + assertEquals(rightAnswer1.size(), equalLists(rightAnswer1, files1)); + + List> rightAnswer2 = new ArrayList<>(); + rightAnswer2.add(new Pair<>("dir1", true)); + rightAnswer2.add(new Pair<>("dir2", true)); + rightAnswer2.add(new Pair<>("dir3", true)); + rightAnswer2.add(new Pair<>("dir4", true)); + rightAnswer2.add(new Pair<>("dir5", true)); + rightAnswer2.add(new Pair<>("file1", false)); + rightAnswer2.add(new Pair<>("file2", false)); + assertEquals(rightAnswer2.size(), equalLists(files2, rightAnswer2)); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + @Test + public void testCreateWithNonexistentDirectory() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client = new Client("localhost", 1408); + List> files = client.list("src/resources/testList3"); + assertEquals(0, files.size()); + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + + @Test + public void testGetWithOneClient() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client = new Client("localhost", 1408); + File copyFile = client.get("src/resources/testGet1/file1", "src/resources/testGet1/copyFile1"); + File file = new File("src/resources/testGet1/file1"); + assertEquals(true, equalFiles(file, copyFile)); + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + + @Test + public void testGetWithTwoClients() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client1 = new Client("localhost", 1408); + File copyFile1 = client1.get("src/resources/testGet1/file1", "src/resources/testGet1/copyFile1"); + File file1 = new File("src/resources/testGet1/file1"); + assertEquals(true, equalFiles(file1, copyFile1)); + + Client client2 = new Client("localhost", 1408); + File copyFile2 = client2.get("src/resources/testGet1/file2", "src/resources/testGet1/copyFile2"); + File file2 = new File("src/resources/testGet1/file2"); + assertEquals(true, equalFiles(file2, copyFile2)); + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + @Test + public void testGetWithNonexistentFiles() { + try { + if (!isCreateServer) { + final Server server = new Server(1408); + Thread thread = new Thread(server::start); + thread.start(); + isCreateServer = true; + } + Client client = new Client("localhost", 1408); + File file = client.get("src/resources/testGet1/file3", "src/resources/testGet1/copyFile3"); + assertEquals(0, file.length()); + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + + /** + * Compare two List> + */ + private static int equalLists(List> a, List> b) { + if (a.size() != b.size()) { + return -1; + } + int i = 0; + for (Pair elem1 : a) { + boolean flag = false; + for (Pair elem2 : b) { + if (elem1.getKey().equals(elem2.getKey()) && elem1.getValue() == elem2.getValue()) { + flag = true; + } + } + if (!flag) { + return i; + } + i++; + } + return a.size(); + } + + /** + * Compare files + */ + private static boolean equalFiles(File file, File copyFile) throws IOException { + if (file.length() != copyFile.length()) { + return false; + } + byte[] data1 = new byte[(int) file.length()]; + byte[] data2 = new byte[(int) file.length()]; + FileInputStream fisForFile = new FileInputStream(file); + FileInputStream fisForCopyFile = new FileInputStream(copyFile); + if (fisForFile.read(data1) != file.length()) { + throw new IOException("Can't read file"); + } + if (fisForCopyFile.read(data2) != copyFile.length()) { + throw new IOException("Can't read file"); + } + for (int i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) { + return false; + } + } + return true; + } + +} \ No newline at end of file diff --git a/buildscript.sh b/buildscript.sh new file mode 100755 index 0000000..1cc07e7 --- /dev/null +++ b/buildscript.sh @@ -0,0 +1,9 @@ +#!/bin/bash +files=$(find . -maxdepth 1 -type d | grep "./0.*") +for file in $files +do + cd $file + mvn test -B + cd ../ +done +