diff --git a/.gitignore b/.gitignore index eef38ee..f10f6f5 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,6 @@ bin/ ### Build ### target -*.scr \ No newline at end of file +*.scr + +DB/* \ No newline at end of file diff --git a/Client.jpg b/Client.jpg deleted file mode 100644 index 9a90710..0000000 Binary files a/Client.jpg and /dev/null differ diff --git a/Domain.jpg b/Domain.jpg deleted file mode 100644 index da7e2a4..0000000 Binary files a/Domain.jpg and /dev/null differ diff --git a/Lab.Client/pom.xml b/Lab.Client/pom.xml index 0a63c58..91a47d2 100644 --- a/Lab.Client/pom.xml +++ b/Lab.Client/pom.xml @@ -3,11 +3,11 @@ 4.0.0 me.zinch - Lab6-Client + Lab7-Client 1.0 jar - Lab6-Client + Lab7-Client UTF-8 @@ -43,8 +43,8 @@ me.zinch - Lab6-Domain - 1.0-SNAPSHOT + Lab7-Domain + 1.0 compile @@ -58,7 +58,7 @@ - me.zinch.Lab6.Client.App + me.zinch.Lab7.Client.App diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/files/ScriptLoader.java b/Lab.Client/src/main/java/me/zinch/Lab6/Client/files/ScriptLoader.java deleted file mode 100644 index 0b22840..0000000 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/files/ScriptLoader.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.zinch.Lab6.Client.files; - -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; - -/** - * The ScriptLoader class provides methods to load scripts from files. - */ -public class ScriptLoader { - public static List loadList(String path) throws IOException { - try { - BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(path)); - Scanner scanner = new Scanner(bufferedInputStream); - List list = new ArrayList<>(); - while (scanner.hasNextLine()) { - list.add(scanner.nextLine()); - } - bufferedInputStream.close(); - scanner.close(); - return list; - } catch (FileNotFoundException e) { - throw new FileNotFoundException(String.format("Файл %s не найден.", path)); - } catch (IOException e) { - throw new IOException("Произошла неожиданная ошибка во время работы с файлом!"); - } - } -} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/App.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/App.java similarity index 61% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/App.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/App.java index 94332ae..8484277 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/App.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/App.java @@ -1,7 +1,7 @@ -package me.zinch.Lab6.Client; +package me.zinch.Lab7.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.console.ShutdownHook; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.console.ShutdownHook; /** * Main class for running the application. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/client/Client.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/client/Client.java similarity index 73% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/client/Client.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/client/Client.java index 6a1e4b4..47754fe 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/client/Client.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/client/Client.java @@ -1,11 +1,12 @@ -package me.zinch.Lab6.Client.client; +package me.zinch.Lab7.Client.client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.ConnectionErrorException; -import me.zinch.Lab6.Client.exceptions.ResponseException; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.Message; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.ConnectionErrorException; +import me.zinch.Lab7.Client.exceptions.ResponseException; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.Message; +import me.zinch.Lab7.Domain.net.MessageType; +import me.zinch.Lab7.Domain.net.User; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; @@ -17,6 +18,7 @@ import java.net.Socket; public class Client { private final String address; private final int port; + private User user; public Client(String address, int port) throws ConnectionErrorException, ResponseException { this.address = address; @@ -37,6 +39,8 @@ public class Client { var byteArrayOutputStream = new ByteArrayOutputStream(); var objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { + if (user != null) message.setUser(user); + objectOutputStream.writeObject(message); objectOutputStream.flush(); bufferedSocketOutputStream.write(byteArrayOutputStream.toByteArray()); @@ -49,4 +53,12 @@ public class Client { throw new IOException("Сервер не доступен"); } } + + public void setUser(User user) { + this.user = user; + } + + public boolean isLogin() { + return user != null; + } } diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Add.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Add.java similarity index 71% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Add.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Add.java index c827016..d78d6fa 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Add.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Add.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMax.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMax.java similarity index 75% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMax.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMax.java index e6e38d3..61813e9 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMax.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMax.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMin.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMin.java similarity index 74% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMin.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMin.java index 409c368..5471d93 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/AddIfMin.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/AddIfMin.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/CheckProductOwner.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/CheckProductOwner.java new file mode 100644 index 0000000..cbca0f2 --- /dev/null +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/CheckProductOwner.java @@ -0,0 +1,28 @@ +package me.zinch.Lab7.Client.commands; + +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; + +import java.io.IOException; + +public class CheckProductOwner extends Command { + public CheckProductOwner() { + super("check_product_owner", ""); + } + + @Override + public String action(Client client) throws CommandActionException { + try { + Long id = Long.parseLong(Console.getLastCommand().split(" ")[1]); + var response = (BodylessMessage) client.sendMessage(new BodyfulMessage(MessageType.POST, Console.getLastCommand(), id)); + if (response.getType() == MessageType.ERROR) throw new CommandActionException(response.getBody().toString()); + return response.getBody().toString(); + } catch (IOException | ClassNotFoundException e) { + throw new CommandActionException(e); + } + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Clear.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Clear.java similarity index 85% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Clear.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Clear.java index 7d0f300..cb86505 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Clear.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Clear.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * The Clear class represents a command to clear a collection. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Command.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Command.java similarity index 84% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Command.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Command.java index 99c0fe8..dc6acec 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Command.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Command.java @@ -1,9 +1,9 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/ExecuteScript.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/ExecuteScript.java similarity index 89% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/ExecuteScript.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/ExecuteScript.java index 7ae3de7..2d6a638 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/ExecuteScript.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/ExecuteScript.java @@ -1,8 +1,8 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.files.ScriptLoader; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.files.ScriptLoader; import java.io.IOException; import java.util.ArrayList; @@ -41,7 +41,7 @@ public class ExecuteScript extends Command { var commandList = ScriptLoader.loadList(scriptFile); for (var input : commandList) { input = input.trim(); - var command = CommandManager.getCommandByInput(input); + var command = MainCommandManager.getCommandByInput(input); if (command.isPresent()) { Console.appendHistory(input); if (command.get() instanceof ExecuteScript) { diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Exit.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Exit.java similarity index 50% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Exit.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Exit.java index 83dd029..7da8cae 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Exit.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Exit.java @@ -1,14 +1,14 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; /** * A command to exit the program without saving to a file. */ public class Exit extends Command { public Exit() { - super("exit", "завершить программу (без сохранения в файл)"); + super("exit", "завершить программу"); } @Override diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/FilterContainsName.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/FilterContainsName.java similarity index 73% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/FilterContainsName.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/FilterContainsName.java index f61c58c..ee24aa2 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/FilterContainsName.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/FilterContainsName.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/GetProductById.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/GetProductById.java similarity index 70% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/GetProductById.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/GetProductById.java index 73dc7db..ca7a876 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/GetProductById.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/GetProductById.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Help.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Help.java similarity index 57% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Help.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Help.java index 10845ec..90a739c 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Help.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Help.java @@ -1,6 +1,6 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; +import me.zinch.Lab7.Client.client.Client; /** * A command to display help for available commands. @@ -12,6 +12,6 @@ public class Help extends Command { @Override public String action(Client client) { - return CommandManager.getRegisteredCommand(); + return client.isLogin() ? MainCommandManager.getRegisteredCommand() : UserCommandManager.getRegisteredCommand(); } } diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Info.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Info.java similarity index 91% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Info.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Info.java index aa70245..e63867c 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Info.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Info.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * A command to display information about the collection (type, initialization date, number of elements, etc.) to the standard output stream. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/IsIdExists.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/IsIdExists.java similarity index 69% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/IsIdExists.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/IsIdExists.java index 04a81fc..7444d44 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/IsIdExists.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/IsIdExists.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Login.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Login.java new file mode 100644 index 0000000..2a454ea --- /dev/null +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Login.java @@ -0,0 +1,30 @@ +package me.zinch.Lab7.Client.commands; + +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.MessageType; + +import java.io.IOException; + +public class Login extends Command { + + public Login() { + super("login", "войти в систему"); + } + + @Override + public String action(Client client) throws CommandActionException { + var user = Console.readUser(); + try { + var response = client.sendMessage(new BodyfulMessage(MessageType.POST, Console.getLastCommand(), user)); + if (response.getType() == MessageType.OK) { + client.setUser(user); + } + return response.getBody().toString(); + } catch (ClassNotFoundException | IOException e) { + throw new CommandActionException(e.getMessage()); + } + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Logout.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Logout.java new file mode 100644 index 0000000..eb2a53c --- /dev/null +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Logout.java @@ -0,0 +1,16 @@ +package me.zinch.Lab7.Client.commands; + +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.exceptions.CommandActionException; + +public class Logout extends Command { + public Logout() { + super("logout", "выйти из текущего пользователя"); + } + + @Override + public String action(Client client) throws CommandActionException { + client.setUser(null); + return "Успешно!"; + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/CommandManager.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/MainCommandManager.java similarity index 92% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/CommandManager.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/MainCommandManager.java index 65804d3..657aba5 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/CommandManager.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/MainCommandManager.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; import java.util.ArrayList; import java.util.List; @@ -7,7 +7,7 @@ import java.util.Optional; /** * Manages the registration and retrieval of commands. */ -public class CommandManager { +public class MainCommandManager { private static final List commandList = new ArrayList<>(); static { @@ -25,6 +25,7 @@ public class CommandManager { registerCommand(new AddIfMin()); registerCommand(new RemoveLower()); registerCommand(new ExecuteScript()); + registerCommand(new Logout()); registerCommand(new Help()); } diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintAscending.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintAscending.java similarity index 88% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintAscending.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintAscending.java index 724c624..4d51e72 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintAscending.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintAscending.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * A command to print the elements of the collection in ascending order. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintUniqueManufactureCost.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintUniqueManufactureCost.java similarity index 90% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintUniqueManufactureCost.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintUniqueManufactureCost.java index 9ffb3db..aab44ab 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/PrintUniqueManufactureCost.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/PrintUniqueManufactureCost.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * A command to print the unique values of the 'manufactureCost' field of all elements in the collection. diff --git a/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Register.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Register.java new file mode 100644 index 0000000..3bd00ea --- /dev/null +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Register.java @@ -0,0 +1,31 @@ +package me.zinch.Lab7.Client.commands; + +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.MessageType; +import me.zinch.Lab7.Domain.net.User; + +import java.io.IOException; + +public class Register extends Command { + + public Register() { + super("register", "зарегистрироваться в системе"); + } + + @Override + public String action(Client client) throws CommandActionException { + var user = Console.readUser(); + try { + var response = client.sendMessage(new BodyfulMessage(MessageType.POST, Console.getLastCommand(), user)); + if (response.getType() == MessageType.OK) { + client.setUser(new User(user.getLogin(), user.getPassword())); + } + return response.getBody().toString(); + } catch (ClassNotFoundException | IOException e) { + throw new CommandActionException(e.getMessage()); + } + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Remove.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Remove.java similarity index 73% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Remove.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Remove.java index 33dbc54..eaba824 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Remove.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Remove.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/RemoveLower.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/RemoveLower.java similarity index 74% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/RemoveLower.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/RemoveLower.java index 7f92f1f..fe6de46 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/RemoveLower.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/RemoveLower.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Save.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Save.java similarity index 81% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Save.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Save.java index e0d2d3e..24fdfc9 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Save.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Save.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * A command to save the collection to a file. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Show.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Show.java similarity index 90% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Show.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Show.java index 321c843..6c33ebd 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Show.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Show.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; /** * A command to display all elements of the collection in string representation to the standard output stream. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/UnknownCommand.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UnknownCommand.java similarity index 75% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/UnknownCommand.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UnknownCommand.java index 246796c..1be5fc2 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/UnknownCommand.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UnknownCommand.java @@ -1,6 +1,6 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; +import me.zinch.Lab7.Client.client.Client; /** * Represents an unknown command. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Update.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Update.java similarity index 72% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Update.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Update.java index 545681b..dc61a3a 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/commands/Update.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/Update.java @@ -1,12 +1,12 @@ -package me.zinch.Lab6.Client.commands; +package me.zinch.Lab7.Client.commands; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.console.Console; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Domain.dto.BodyfulMessage; -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.MessageBody; -import me.zinch.Lab6.Domain.dto.MessageType; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.console.Console; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.BodyfulMessage; +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.MessageBody; +import me.zinch.Lab7.Domain.net.MessageType; import java.io.IOException; import java.util.regex.Pattern; @@ -25,6 +25,10 @@ public class Update extends Command { var command = Console.getLastCommand(); Long id = Long.parseLong(command.split(" ")[1]); + var checkProductOwner = new CheckProductOwner(); + Console.appendHistory(String.format("%s %s", checkProductOwner.getSignature(), id)); + checkProductOwner.action(client); + var isIdExists = new IsIdExists(); Console.appendHistory(String.format("%s %s", isIdExists.getSignature(), id)); isIdExists.action(client); diff --git a/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UserCommandManager.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UserCommandManager.java new file mode 100644 index 0000000..c6735c4 --- /dev/null +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/commands/UserCommandManager.java @@ -0,0 +1,32 @@ +package me.zinch.Lab7.Client.commands; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class UserCommandManager { + private static final List commandList = new ArrayList<>(); + + static { + registerCommand(new Login()); + registerCommand(new Register()); + registerCommand(new Exit()); + + registerCommand(new Help()); + } + + public static void registerCommand(Command command) { + commandList.add(command); + } + + public static String getRegisteredCommand() { + return String.join("\n", commandList + .stream() + .map(command -> String.format("%s - %s", command.getName(), command.getDescription())) + .toList()); + } + + public static Optional getCommandByInput(String input) { + return commandList.stream().filter(command -> command.checkPattern(input)).findFirst(); + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/console/Console.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/console/Console.java similarity index 81% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/console/Console.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/console/Console.java index dbe187e..7f776d3 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/console/Console.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/console/Console.java @@ -1,22 +1,26 @@ -package me.zinch.Lab6.Client.console; +package me.zinch.Lab7.Client.console; -import me.zinch.Lab6.Client.client.Client; -import me.zinch.Lab6.Client.commands.CommandManager; -import me.zinch.Lab6.Client.exceptions.ColorFormatException; -import me.zinch.Lab6.Client.exceptions.CommandActionException; -import me.zinch.Lab6.Client.exceptions.ConnectionErrorException; -import me.zinch.Lab6.Client.exceptions.ResponseException; -import me.zinch.Lab6.Client.exceptions.UnitOfMeasureFormatException; -import me.zinch.Lab6.Domain.models.Color; -import me.zinch.Lab6.Domain.models.Coordinates; -import me.zinch.Lab6.Domain.models.Location; -import me.zinch.Lab6.Domain.models.Person; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.models.UnitOfMeasure; +import me.zinch.Lab7.Client.client.Client; +import me.zinch.Lab7.Client.commands.MainCommandManager; +import me.zinch.Lab7.Client.commands.UserCommandManager; +import me.zinch.Lab7.Client.exceptions.ColorFormatException; +import me.zinch.Lab7.Client.exceptions.CommandActionException; +import me.zinch.Lab7.Client.exceptions.ConnectionErrorException; +import me.zinch.Lab7.Client.exceptions.ResponseException; +import me.zinch.Lab7.Client.exceptions.UnitOfMeasureFormatException; +import me.zinch.Lab7.Domain.models.Color; +import me.zinch.Lab7.Domain.models.Coordinates; +import me.zinch.Lab7.Domain.models.Location; +import me.zinch.Lab7.Domain.models.Person; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.models.UnitOfMeasure; +import me.zinch.Lab7.Domain.net.User; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Scanner; /** @@ -165,11 +169,28 @@ public class Console { return productDTO; } + public static String readPassword() { + var msg = "Пароль пользователя"; + var console = System.console(); + return Objects.isNull(console) ? readField(msg) : Arrays.toString(console.readPassword(msg + ": ")); + } + + public static User readUser() { + var user = new User(); + log("Заполните следующие поля: "); + + setField("Имя пользователя", () -> user.setLogin(readString())); + setField(() -> user.setPassword(readPassword())); + + return user; + } + public static void run() { while (client == null) { try { var address = readField("Хост"); int port = Integer.parseInt(readField("Порт")); + if (port > 65535 || port < 1) throw new NumberFormatException(); client = new Client(address, port); } catch (NumberFormatException e) { log("Порт должен быть числом от 1 до 65535"); @@ -185,7 +206,7 @@ public class Console { try { var input = scanner.nextLine().trim(); - var command = CommandManager.getCommandByInput(input); + var command = client.isLogin() ? MainCommandManager.getCommandByInput(input) : UserCommandManager.getCommandByInput(input); if (command.isPresent()) { appendHistory(input); diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/console/ShutdownHook.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/console/ShutdownHook.java similarity index 84% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/console/ShutdownHook.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/console/ShutdownHook.java index c04060e..4870b7c 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/console/ShutdownHook.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/console/ShutdownHook.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.console; +package me.zinch.Lab7.Client.console; /** * Represents a shutdown hook that is executed when the application is stopped. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ColorFormatException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ColorFormatException.java similarity index 82% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ColorFormatException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ColorFormatException.java index 6957daf..592f533 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ColorFormatException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ColorFormatException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; public class ColorFormatException extends IllegalArgumentException { public ColorFormatException() { diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/CommandActionException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/CommandActionException.java similarity index 91% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/CommandActionException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/CommandActionException.java index 0669f9d..f2adbfb 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/CommandActionException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/CommandActionException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; /** * Represents an exception that occurs during the execution of a command action. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ConnectionErrorException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ConnectionErrorException.java similarity index 85% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ConnectionErrorException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ConnectionErrorException.java index 7caf050..e0eb045 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ConnectionErrorException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ConnectionErrorException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; import java.io.IOException; diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/DbInitializationException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/DbInitializationException.java similarity index 91% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/DbInitializationException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/DbInitializationException.java index 6c20dce..8d2167f 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/DbInitializationException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/DbInitializationException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; import java.io.IOException; diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/IllegalProductDtoException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/IllegalProductDtoException.java similarity index 93% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/IllegalProductDtoException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/IllegalProductDtoException.java index 91e77de..9ea1638 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/IllegalProductDtoException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/IllegalProductDtoException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.exceptions; +package me.zinch.Lab7.Client.exceptions; /** * Represents an exception that occurs when an illegal product DTO is encountered during the creation or modification of a product. diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ResponseException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ResponseException.java similarity index 82% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ResponseException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ResponseException.java index a213292..4d28557 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/ResponseException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/ResponseException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; public class ResponseException extends ClassNotFoundException { public ResponseException() { diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/UnitOfMeasureFormatException.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/UnitOfMeasureFormatException.java similarity index 84% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/UnitOfMeasureFormatException.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/UnitOfMeasureFormatException.java index 8c84ca0..4804d6d 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/UnitOfMeasureFormatException.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/exceptions/UnitOfMeasureFormatException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Client.exceptions; public class UnitOfMeasureFormatException extends IllegalArgumentException { public UnitOfMeasureFormatException() { diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/files/ScriptLoader.java b/Lab.Client/src/main/java/me/zinch/Lab7/Client/files/ScriptLoader.java similarity index 96% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/files/ScriptLoader.java rename to Lab.Client/src/main/java/me/zinch/Lab7/Client/files/ScriptLoader.java index 9dce936..0f7e99e 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/files/ScriptLoader.java +++ b/Lab.Client/src/main/java/me/zinch/Lab7/Client/files/ScriptLoader.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.files; +package me.zinch.Lab7.Client.files; import java.io.BufferedInputStream; import java.io.FileInputStream; diff --git a/Lab.Domain/pom.xml b/Lab.Domain/pom.xml index ded39f3..fa349f1 100644 --- a/Lab.Domain/pom.xml +++ b/Lab.Domain/pom.xml @@ -5,8 +5,8 @@ 4.0.0 me.zinch - Lab6-Domain - 1.0-SNAPSHOT + Lab7-Domain + 1.0 17 diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/wrapper/IStorage.java b/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/wrapper/IStorage.java deleted file mode 100644 index 8d6dfa6..0000000 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/wrapper/IStorage.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zinch.Lab6.Domain.wrapper; - -import me.zinch.Lab6.Domain.models.Product; -import me.zinch.Lab6.Domain.models.ProductDTO; - -import java.util.List; - -public interface IStorage { - public Product getProductById(Long id); - - public Product addProduct(ProductDTO productDTO); - - public Product updateProduct(Long id, ProductDTO productDTO); - - public Product removeProduct(Long id); - - public String getInfo(); - - public void clear(); - - public Long getMaxPrice(); - - public Long getMinPrice(); - - public boolean isProductIdExists(Long id); - - public Integer removeLover(Long id); - - public String filterContainsName(String name); - - public String getUniqueManufactureCost(); - - public List toList(); -} diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/exceptions/ValidationException.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/exceptions/ValidationException.java similarity index 88% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/exceptions/ValidationException.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/exceptions/ValidationException.java index 076f346..e5e2e6b 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/exceptions/ValidationException.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/exceptions/ValidationException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.exceptions; +package me.zinch.Lab7.Domain.exceptions; /** * Represents an exception related to validation errors. diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Color.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Color.java similarity index 97% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Color.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Color.java index 22f5bb2..4b3a5b8 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Color.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Color.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import java.io.Serializable; import java.util.Arrays; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Coordinates.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Coordinates.java similarity index 95% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Coordinates.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Coordinates.java index e2574ce..4397198 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Coordinates.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Coordinates.java @@ -1,10 +1,10 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; -import me.zinch.Lab6.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; import java.io.Serializable; import java.util.Objects; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Location.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Location.java similarity index 83% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Location.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Location.java index 49dc700..dda4484 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Location.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Location.java @@ -1,8 +1,8 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; -import me.zinch.Lab6.Domain.validator.NotEmpty; +import me.zinch.Lab7.Domain.validator.NotEmpty; import java.io.Serializable; import java.util.Objects; @@ -64,4 +64,16 @@ public class Location implements Serializable { public int hashCode() { return Objects.hash(x, y, name); } + + public float getX() { + return x; + } + + public @NotNull(message = "Location: Координата y не может быть null") Integer getY() { + return y; + } + + public String getName() { + return name; + } } diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Person.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Person.java similarity index 81% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Person.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Person.java index 86f53c6..bcd4b7e 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Person.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Person.java @@ -1,10 +1,10 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import me.zinch.Lab6.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; import java.io.Serializable; import java.util.Objects; @@ -80,4 +80,20 @@ public class Person implements Serializable { public int hashCode() { return Objects.hash(name, passportID, hairColor, location); } + + public @NotBlank(message = "Person: Имя персоны не может быть пустым или null") String getName() { + return name; + } + + public @NotNull(message = "Person: Поле passportID не может быть null") @Size(min = 5, max = 22, message = "Длина строки passportID должна быть не меньше 5 и не должна быть больше 22") String getPassportID() { + return passportID; + } + + public Color getHairColor() { + return hairColor; + } + + public Location getLocation() { + return location; + } } diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Product.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Product.java similarity index 98% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Product.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Product.java index e7e4290..27190ee 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/Product.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/Product.java @@ -1,11 +1,11 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import me.zinch.Lab6.Domain.validator.NotEmpty; +import me.zinch.Lab7.Domain.validator.NotEmpty; import java.io.Serializable; import java.time.ZonedDateTime; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/ProductDTO.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/ProductDTO.java similarity index 97% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/ProductDTO.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/ProductDTO.java index 2d7a2a7..b608e62 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/ProductDTO.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/ProductDTO.java @@ -1,12 +1,12 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.validator.NotEmpty; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.validator.NotEmpty; import java.io.Serializable; import java.time.ZonedDateTime; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/UnitOfMeasure.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/UnitOfMeasure.java similarity index 97% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/UnitOfMeasure.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/UnitOfMeasure.java index bf713a3..d865347 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/models/UnitOfMeasure.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/models/UnitOfMeasure.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.models; +package me.zinch.Lab7.Domain.models; import java.io.Serializable; import java.util.Arrays; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodyfulMessage.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodyfulMessage.java similarity index 50% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodyfulMessage.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodyfulMessage.java index 6f372c1..cb3d60d 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodyfulMessage.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodyfulMessage.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; import java.io.Serializable; @@ -7,4 +7,10 @@ public class BodyfulMessage extends Message { this.setType(type); this.setBody(new MessageBody(command, body)); } + + public BodyfulMessage(MessageType type, String command, Serializable body, User user) { + this.setType(type); + this.setBody(new MessageBody(command, body)); + this.setUser(user); + } } diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodylessMessage.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodylessMessage.java similarity index 56% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodylessMessage.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodylessMessage.java index cc2c479..158ce78 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/BodylessMessage.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/BodylessMessage.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; public class BodylessMessage extends Message { public BodylessMessage(MessageType type) { @@ -9,4 +9,10 @@ public class BodylessMessage extends Message { this.setType(type); this.setBody(command); } + + public BodylessMessage(MessageType type, String command, User user) { + this.setType(type); + this.setBody(command); + this.setUser(user); + } } diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/Message.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/Message.java similarity index 74% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/Message.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/Message.java index f45162f..c72defd 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/Message.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/Message.java @@ -1,10 +1,11 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; import java.io.Serializable; public abstract class Message implements Serializable { private MessageType type; private Serializable body; + private Serializable user; public final MessageType getType() { return type; @@ -22,6 +23,14 @@ public abstract class Message implements Serializable { this.body = body; } + public Serializable getUser() { + return user; + } + + public void setUser(Serializable user) { + this.user = user; + } + @Override public String toString() { return "Message{" + diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageBody.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageBody.java similarity index 93% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageBody.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageBody.java index f038b33..8096d45 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageBody.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageBody.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; import java.io.Serializable; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageType.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageType.java similarity index 78% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageType.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageType.java index d4f40aa..7ab4678 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/MessageType.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/MessageType.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; import java.io.Serializable; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/UpdateBody.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/UpdateBody.java similarity index 86% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/UpdateBody.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/UpdateBody.java index 2748136..38c8f2f 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/dto/UpdateBody.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/UpdateBody.java @@ -1,6 +1,6 @@ -package me.zinch.Lab6.Domain.dto; +package me.zinch.Lab7.Domain.net; -import me.zinch.Lab6.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.models.ProductDTO; import java.io.Serializable; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/User.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/User.java new file mode 100644 index 0000000..0da2c37 --- /dev/null +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/net/User.java @@ -0,0 +1,58 @@ +package me.zinch.Lab7.Domain.net; + +import jakarta.validation.constraints.NotNull; + +import java.io.Serializable; +import java.util.Objects; + +public class User implements Serializable { + @NotNull + private String login; + @NotNull + private String password; + + public User() { + } + + public User(String login, String password) { + this.login = login; + this.password = password; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "User{" + + "login='" + login + '\'' + + ", password='" + password + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(login, user.login) && Objects.equals(password, user.password); + } + + @Override + public int hashCode() { + return Objects.hash(login, password); + } +} diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmpty.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmpty.java similarity index 94% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmpty.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmpty.java index 65f3db4..f2fc4e8 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmpty.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmpty.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.validator; +package me.zinch.Lab7.Domain.validator; import jakarta.validation.Constraint; import jakarta.validation.Payload; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmptyValidator.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmptyValidator.java similarity index 91% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmptyValidator.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmptyValidator.java index bcb817f..b5285d9 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/NotEmptyValidator.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/NotEmptyValidator.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Domain.validator; +package me.zinch.Lab7.Domain.validator; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/ValidateResult.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/ValidateResult.java similarity index 91% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/ValidateResult.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/ValidateResult.java index 23ecb03..4825103 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/ValidateResult.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/ValidateResult.java @@ -1,7 +1,7 @@ -package me.zinch.Lab6.Domain.validator; +package me.zinch.Lab7.Domain.validator; import jakarta.validation.ConstraintViolation; -import me.zinch.Lab6.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; import java.util.Set; diff --git a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/Validators.java b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/Validators.java similarity index 94% rename from Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/Validators.java rename to Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/Validators.java index 93c48e1..86bd4dc 100644 --- a/Lab.Domain/src/main/java/me/zinch/Lab6/Domain/validator/Validators.java +++ b/Lab.Domain/src/main/java/me/zinch/Lab7/Domain/validator/Validators.java @@ -1,9 +1,9 @@ -package me.zinch.Lab6.Domain.validator; +package me.zinch.Lab7.Domain.validator; import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; -import me.zinch.Lab6.Domain.models.Product; +import me.zinch.Lab7.Domain.models.Product; import org.hibernate.validator.HibernateValidator; import java.util.List; diff --git a/Lab.Server/pom.xml b/Lab.Server/pom.xml index 3bb7508..5011095 100644 --- a/Lab.Server/pom.xml +++ b/Lab.Server/pom.xml @@ -3,11 +3,11 @@ 4.0.0 me.zinch - Lab6-Server + Lab7-Server 1.0 jar - Lab6-Server + Lab7-Server UTF-8 @@ -16,11 +16,6 @@ - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - 2.15.0 - com.fasterxml.jackson.datatype jackson-datatype-jsr310 @@ -53,8 +48,8 @@ me.zinch - Lab6-Domain - 1.0-SNAPSHOT + Lab7-Domain + 1.0 compile @@ -68,6 +63,11 @@ jline 3.26.1 + + org.postgresql + postgresql + 42.7.3 + @@ -79,7 +79,7 @@ - me.zinch.Lab6.Server.App + me.zinch.Lab7.Server.App diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/App.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/App.java deleted file mode 100644 index 7f8b8a7..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/App.java +++ /dev/null @@ -1,14 +0,0 @@ -package me.zinch.Lab6.Server; - -import me.zinch.Lab6.Server.console.Console; - -import java.io.IOException; - -/** - * Main class for running the application. - */ -public class App { - public static void main(String[] args) throws IOException { - Console.run(); - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/Server.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/Server.java deleted file mode 100644 index 6072db7..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/Server.java +++ /dev/null @@ -1,185 +0,0 @@ -package me.zinch.Lab6.Server; - -import me.zinch.Lab6.Domain.dto.BodylessMessage; -import me.zinch.Lab6.Domain.dto.Message; -import me.zinch.Lab6.Domain.dto.MessageBody; -import me.zinch.Lab6.Domain.dto.MessageType; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.commands.CommandManager; -import me.zinch.Lab6.Server.commands.GetCommand; -import me.zinch.Lab6.Server.commands.PostCommand; -import me.zinch.Lab6.Server.exceptions.CommandActionException; -import me.zinch.Lab6.Server.files.DbController; -import me.zinch.Lab6.Server.wrapper.ProductCollection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class Server { - private static final Logger log = LoggerFactory.getLogger(Server.class); - private final Selector selector; - private final ServerSocketChannel serverSocketChannel; - private final Map usersMessages = new HashMap<>(); - private final IStorage storage; - private boolean isRunning = false; - - public Server(int port, IStorage collection) throws IOException { - selector = Selector.open(); - serverSocketChannel = ServerSocketChannel.open(); - serverSocketChannel.bind(new InetSocketAddress(port)); - serverSocketChannel.configureBlocking(false); - serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); - isRunning = true; - - if (collection == null) collection = new ProductCollection(new ArrayList<>()); - storage = collection; - - log.info("The server has been assigned to port {}", port); - } - - public static ByteBuffer serialize(Serializable obj) throws IOException { - try (var bOut = new ByteArrayOutputStream(); - var oOut = new ObjectOutputStream(bOut)) { - oOut.writeObject(obj); - oOut.flush(); - return ByteBuffer.wrap(bOut.toByteArray()); - } - } - - public void run() throws IOException { - run(() -> { - }); - } - - public void run(Runnable middleware) throws IOException { - log.info("The server is running"); - - while (isRunning) { - selector.select(this::handleKey); - middleware.run(); - } - } - - private void handleKey(SelectionKey key) { - try { - if (key.isAcceptable()) handleAccept(key); - if (key.isReadable()) handleRead(key); - if (key.isWritable()) handleWrite(key); - } catch (IOException | ClassNotFoundException e) { - log.error(e.getMessage(), e); - key.cancel(); - } - } - - private void handleAccept(SelectionKey key) throws IOException { - var server = (ServerSocketChannel) key.channel(); - var client = server.accept(); - if (client != null) { - client.configureBlocking(false); - client.register(selector, SelectionKey.OP_READ); - log.info("Received connection from {}", client.getRemoteAddress()); - } - } - - private void handleRead(SelectionKey key) throws IOException, ClassNotFoundException { - var client = (SocketChannel) key.channel(); - var buffer = ByteBuffer.allocate(8192); - int bytesRead = client.read(buffer); - if (bytesRead == -1) { - client.close(); - } else { - buffer.flip(); - var oIn = new ObjectInputStream(new ByteArrayInputStream(buffer.array())); - var msg = (Message) oIn.readObject(); - log.info("Received message {} from {}", msg, client.getRemoteAddress()); - usersMessages.put(client.getRemoteAddress(), msg); - client.register(selector, SelectionKey.OP_WRITE); - oIn.close(); - } - } - - private void handleWrite(SelectionKey key) throws IOException { - var client = (SocketChannel) key.channel(); - var message = usersMessages.get(client.getRemoteAddress()); - if (message == null) { - log.error("Message for {} not found", client.getRemoteAddress()); - client.close(); - return; - } - - ByteBuffer responseBuffer = createResponse(message); - if (responseBuffer != null) { - client.write(responseBuffer); - log.info("Sent message to {}", client.getRemoteAddress()); - } - - client.close(); - } - - private ByteBuffer createResponse(Message message) throws IOException { - return switch (message.getType()) { - case HELLO -> serialize(new BodylessMessage(MessageType.HELLO)); - case GET -> handleGetCommand((String) message.getBody()); - case POST -> handlePostCommand((MessageBody) message.getBody()); - default -> { - log.error("Message type not supported"); - yield null; - } - }; - } - - private ByteBuffer handleGetCommand(String inputCommand) throws IOException { - var command = CommandManager.getCommandByInput(inputCommand); - if (command.isEmpty()) { - log.error("Command {} not found", inputCommand); - return serialize(new BodylessMessage(MessageType.ERROR, String.format("Command %s not found", inputCommand))); - } - try { - var action = (GetCommand) command.get(); - return serialize(new BodylessMessage(MessageType.OK, action.action(storage))); - } catch (CommandActionException e) { - return serialize(new BodylessMessage(MessageType.ERROR, e.getMessage())); - } - } - - private ByteBuffer handlePostCommand(MessageBody request) throws IOException { - var inputCommand = request.getCommand(); - var body = request.getBody(); - - var command = CommandManager.getCommandByInput(inputCommand); - if (command.isEmpty()) { - log.error("Command {} not found", inputCommand); - return serialize(new BodylessMessage(MessageType.ERROR, String.format("Command %s not found", inputCommand))); - } - - try { - var action = (PostCommand) command.get(); - return serialize(new BodylessMessage(MessageType.OK, action.action(storage, body))); - } catch (CommandActionException e) { - return serialize(new BodylessMessage(MessageType.ERROR, e.getMessage())); - } - } - - public void stop() throws IOException { - isRunning = false; - serverSocketChannel.close(); - selector.close(); - DbController.saveDb(storage.toList()); - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/ServerBuilder.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/ServerBuilder.java deleted file mode 100644 index 39bf27b..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/ServerBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zinch.Lab6.Server; - -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.configs.ServerConfig; -import me.zinch.Lab6.Server.wrapper.ProductCollection; - -import java.io.IOException; -import java.util.ArrayList; - -public class ServerBuilder { - private ServerConfig serverConfig = new ServerConfig(); - - public ServerBuilder() { - serverConfig.setPort(3000); - serverConfig.setCollection(new ProductCollection(new ArrayList<>())); - } - - public ServerBuilder(ServerConfig serverConfig) { - this.serverConfig = serverConfig; - } - - public ServerBuilder setPort(int port) { - if (port < 1 || port > 65535) throw new IllegalArgumentException("Port must be between 1 and 65535"); - serverConfig.setPort(port); - return new ServerBuilder(serverConfig); - } - - public ServerBuilder setCollection(IStorage collection) { - serverConfig.setCollection(collection); - return new ServerBuilder(serverConfig); - } - - public Server build() throws IOException { - return new Server(serverConfig.getPort(), - serverConfig.getCollection()); - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Clear.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Clear.java deleted file mode 100644 index 9b21263..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Clear.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zinch.Lab6.Server.commands; - -import me.zinch.Lab6.Domain.wrapper.IStorage; - -/** - * The Clear class represents a command to clear a collection. - * It extends the Command class. - */ -public class Clear extends GetCommand { - public Clear() { - super("clear", "очистить коллекцию"); - } - - @Override - public String action(IStorage productCollection) { - productCollection.clear(); - return "Коллекция была очищена"; - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Exit.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Exit.java deleted file mode 100644 index 2683839..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Exit.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zinch.Lab6.Server.commands; - -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.console.Console; - -/** - * A command to exit the program without saving to a file. - */ -public class Exit extends GetCommand { - public Exit() { - super("exit", "terminate the program (without saving to a file)"); - } - - @Override - public String action(IStorage productCollection) { - Console.stopApp(); - return ""; - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Save.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Save.java deleted file mode 100644 index 211dd34..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Save.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.zinch.Lab6.Server.commands; - -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; -import me.zinch.Lab6.Server.files.DbController; - -import java.io.IOException; - -/** - * A command to save the collection to a file. - */ -public class Save extends GetCommand { - public Save() { - super("save", "сохранить коллекцию в файл"); - } - - @Override - public String action(IStorage productCollection) throws CommandActionException { - try { - DbController.saveDb(productCollection.toList()); - return "Коллекция была сохранена"; - } catch (IOException e) { - throw new CommandActionException(e.getMessage()); - } - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/configs/ServerConfig.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/configs/ServerConfig.java deleted file mode 100644 index 4829db9..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/configs/ServerConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zinch.Lab6.Server.configs; - -import me.zinch.Lab6.Domain.wrapper.IStorage; - -public class ServerConfig { - private Integer port; - private IStorage collection; - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public IStorage getCollection() { - return collection; - } - - public void setCollection(IStorage collection) { - this.collection = collection; - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/DbInitializationException.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/DbInitializationException.java deleted file mode 100644 index c055e44..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/DbInitializationException.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.zinch.Lab6.Server.exceptions; - -import java.io.IOException; - -/** - * Represents an exception that occurs when the database initialization fails. - */ -public class DbInitializationException extends IOException { - public DbInitializationException() { - super("Ошибка! Не удалось инициализировать БД. Проверьте, что структура БД верна."); - } - - public DbInitializationException(String message) { - super(message); - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/files/DbController.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/files/DbController.java deleted file mode 100644 index 4b482ea..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/files/DbController.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zinch.Lab6.Server.files; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import me.zinch.Lab6.Domain.models.Product; - -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * The DbController class provides methods for loading and saving product data to a database file. - */ -public class DbController { - private static final XmlMapper xmlMapper = XmlMapper.builder().addModule(new JavaTimeModule()).build(); - private static final String path; - - static { - Map env = System.getenv(); - path = env.getOrDefault("DB_FILE", "db.xml"); - xmlMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); - } - - public static List loadDb() { - try { - BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(path)); - List collection = xmlMapper.readValue(bufferedInputStream, Products.class).getProducts(); - bufferedInputStream.close(); - if (collection == null) return new ArrayList<>(); - return collection; - } catch (IOException e) { - return new ArrayList<>(); - } - } - - public static void saveDb(List list) throws IOException { - try { - OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path)); - xmlMapper.writeValue(outputStreamWriter, new Products(list)); - outputStreamWriter.close(); - } catch (IOException e) { - throw new IOException("Не удалось записать в файл"); - } - } - - /** - * Represents a collection of products. - */ - private static class Products { - @JacksonXmlElementWrapper(useWrapping = false) - @JacksonXmlProperty(localName = "Product") - private List products; - - public Products() { - } - - public Products(List list) { - this.products = list; - } - - public List getProducts() { - return products; - } - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/wrapper/ProductCollection.java b/Lab.Server/src/main/java/me/zinch/Lab6/Server/wrapper/ProductCollection.java deleted file mode 100644 index bf3a70e..0000000 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/wrapper/ProductCollection.java +++ /dev/null @@ -1,134 +0,0 @@ -package me.zinch.Lab6.Server.wrapper; - -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.models.Product; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.wrapper.IStorage; - -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; - -/** - * Represents a collection of products. - */ -public class ProductCollection implements IStorage { - private final TreeSet productList; - private Long idIncrementor; - - public ProductCollection(List list) throws ValidationException { - productList = new TreeSet<>((o1, o2) -> { - var o1Length = o1.getCoordinates().getX() * o1.getCoordinates().getX() + o1.getCoordinates().getY() * o1.getCoordinates().getY(); - var o2Length = o2.getCoordinates().getX() * o2.getCoordinates().getX() + o2.getCoordinates().getY() * o2.getCoordinates().getY(); - return Math.toIntExact(o1Length - o2Length); - }); - productList.addAll(list); - idIncrementor = productList.isEmpty() ? 1L : productList.last().getId() + 1; - } - - private Long generateId() { - return idIncrementor++; - } - - public Product getProductById(Long id) { - Optional product = productList.stream().filter(i -> Objects.equals(i.getId(), id)).findFirst(); - return product.orElse(null); - } - - public Product addProduct(ProductDTO productDTO) { - var product = productDTO.buildProduct(generateId(), ZonedDateTime.now()); - productList.add(product); - return product; - } - - private Product addProduct(ProductDTO productDTO, Long id, ZonedDateTime creationDate) { - var product = productDTO.buildProduct(id, creationDate); - productList.add(product); - return product; - } - - public Product updateProduct(Long id, ProductDTO productDTO) { - var product = getProductById(id); - productList.remove(product); - return addProduct(productDTO, product.getId(), product.getCreationDate()); - } - - public Product removeProduct(Long id) { - var product = getProductById(id); - productList.remove(product); - return product; - } - - public String getInfo() { - var optionalInitDate = productList.stream().map(Product::getCreationDate).sorted().findFirst(); - ZonedDateTime initDate = optionalInitDate.orElse(ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.systemDefault())); - return String.format("Структура: TreeSet%nДата инициализации: %s%nКоличество элементов: %s", initDate, productList.size()); - } - - public void clear() { - productList.clear(); - } - - - public Long getMaxPrice() { - return productList.stream().max(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null); - } - - public Long getMinPrice() { - return productList.stream().min(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null); - } - - public boolean isProductIdExists(Long id) { - return getProductById(id) != null; - } - - public Integer removeLover(Long id) { - var size = productList.size(); - productList.headSet(getProductById(id)).stream().toList().forEach(productList::remove); - return size - productList.size(); - } - - public String filterContainsName(String name) { - return String.join("\n", productList.stream() - .filter(product -> product.getName().toLowerCase().contains(name.toLowerCase())) - .map(Product::toString) - .toList()); - } - - public String getUniqueManufactureCost() { - return String.join(", ", Set.copyOf(productList.stream() - .map(Product::getManufactureCost) - .toList()) - .stream() - .map(Object::toString) - .toList()); - } - - public List toList() { - return productList.stream().toList(); - } - - @Override - public String toString() { - return String.join("\n", productList.stream().map(Product::toString).toList()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ProductCollection that = (ProductCollection) o; - return Objects.equals(productList, that.productList) && Objects.equals(idIncrementor, that.idIncrementor); - } - - @Override - public int hashCode() { - return Objects.hash(productList, idIncrementor); - } -} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/App.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/App.java new file mode 100644 index 0000000..6203d6a --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/App.java @@ -0,0 +1,13 @@ +package me.zinch.Lab7.Server; + +import me.zinch.Lab7.Server.console.Console; +import me.zinch.Lab7.Server.utils.SHA256; + +/** + * Main class for running the application. + */ +public class App { + public static void main(String[] args) throws Exception { + Console.run(); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/Server.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/Server.java new file mode 100644 index 0000000..2cfaf69 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/Server.java @@ -0,0 +1,167 @@ +package me.zinch.Lab7.Server.Server; + +import me.zinch.Lab7.Domain.net.BodylessMessage; +import me.zinch.Lab7.Domain.net.Message; +import me.zinch.Lab7.Domain.net.MessageBody; +import me.zinch.Lab7.Domain.net.MessageType; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.utils.SHA256; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.commands.CommandManager; +import me.zinch.Lab7.Server.commands.GetCommand; +import me.zinch.Lab7.Server.commands.PostCommand; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.ProductCollection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class Server { + private static final Logger log = LoggerFactory.getLogger(Server.class); + private final ServerSocket serverSocket; + private final IStorage storage; + private boolean isRunning; + private final ExecutorService requestReadPool = Executors.newCachedThreadPool(); + private final ExecutorService requestProcessPool = Executors.newCachedThreadPool(); + private final ExecutorService responseSendPool = Executors.newFixedThreadPool(12); + + public Server(int port, IStorage collection) throws IOException { + serverSocket = new ServerSocket(port); + isRunning = true; + + if (collection == null) collection = new ProductCollection(new ArrayList<>()); + storage = collection; + + log.info("The server has been assigned to port {}", port); + } + + public static byte[] serialize(Serializable obj) throws IOException { + try (var bOut = new ByteArrayOutputStream(); + var oOut = new ObjectOutputStream(bOut)) { + oOut.writeObject(obj); + oOut.flush(); + return bOut.toByteArray(); + } + } + + public void run() { + log.info("The server is running"); + + while (isRunning) { + try { + var clientSocket = serverSocket.accept(); + log.info("Received connection from {}", clientSocket.getRemoteSocketAddress()); + requestReadPool.execute(() -> { + try { + handleClient(clientSocket); + } catch (IOException | ClassNotFoundException e) { + log.error(e.getMessage(), e); + } + }); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + } + + private void handleClient(Socket clientSocket) throws IOException, ClassNotFoundException { + var inputStream = clientSocket.getInputStream(); + + var buffer = new byte[8192]; + inputStream.read(buffer); + + var oIn = new ObjectInputStream(new ByteArrayInputStream(buffer)); + var msg = (Message) oIn.readObject(); + log.info("Received message {} from {}", msg, clientSocket.getRemoteSocketAddress()); + + responseSendPool.execute(() -> handleWrite(clientSocket, msg, inputStream)); + } + + private void handleWrite(Socket clientSocket, Message msg, InputStream inputStream) { + try { + var response = requestProcessPool.submit(() -> createResponse(msg)); + var responseBuffer = response.get(); + if (responseBuffer != null) { + try { + var outputStream = clientSocket.getOutputStream(); + outputStream.write(responseBuffer); + outputStream.flush(); + log.info("Sent message to {}", clientSocket.getRemoteSocketAddress()); + outputStream.close(); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + inputStream.close(); + } catch (IOException | InterruptedException | ExecutionException e) { + log.error(e.getMessage(), e); + } + } + + private byte[] createResponse(Message message) throws IOException { + var user = (User) message.getUser(); + if (user != null) user.setPassword(SHA256.hash(user.getPassword())); + return switch (message.getType()) { + case HELLO -> serialize(new BodylessMessage(MessageType.HELLO)); + case GET -> handleGetCommand((String) message.getBody(), user); + case POST -> handlePostCommand((MessageBody) message.getBody(), user); + default -> { + log.error("Message type not supported"); + yield null; + } + }; + } + + private byte[] handleGetCommand(String inputCommand, User user) throws IOException { + var command = CommandManager.getCommandByInput(inputCommand); + if (command.isEmpty()) { + log.error("Command {} not found", inputCommand); + return serialize(new BodylessMessage(MessageType.ERROR, String.format("Command %s not found", inputCommand))); + } + try { + var action = (GetCommand) command.get(); + return serialize(new BodylessMessage(MessageType.OK, action.action(storage, user))); + } catch (CommandActionException e) { + return serialize(new BodylessMessage(MessageType.ERROR, e.getMessage())); + } + } + + private byte[] handlePostCommand(MessageBody request, User user) throws IOException { + var inputCommand = request.getCommand(); + var body = request.getBody(); + + var command = CommandManager.getCommandByInput(inputCommand); + if (command.isEmpty()) { + log.error("Command {} not found", inputCommand); + return serialize(new BodylessMessage(MessageType.ERROR, String.format("Command %s not found", inputCommand))); + } + + try { + var action = (PostCommand) command.get(); + return serialize(new BodylessMessage(MessageType.OK, action.action(storage, body, user))); + } catch (CommandActionException e) { + return serialize(new BodylessMessage(MessageType.ERROR, e.getMessage())); + } + } + + public void stop() throws IOException { + isRunning = false; + serverSocket.close(); + requestReadPool.shutdown(); + requestProcessPool.shutdown(); + responseSendPool.shutdown(); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/ServerBuilder.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/ServerBuilder.java new file mode 100644 index 0000000..e11d5fc --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/Server/ServerBuilder.java @@ -0,0 +1,56 @@ +package me.zinch.Lab7.Server.Server; + +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.wrapper.ProductCollection; + +import java.io.IOException; +import java.util.ArrayList; + +public class ServerBuilder { + private static class Config { + private int port = 3000; + private IStorage collection = new ProductCollection(); + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public IStorage getCollection() { + return collection; + } + + public void setCollection(IStorage collection) { + this.collection = collection; + } + } + + private Config config = new Config(); + + public ServerBuilder() { + config.setPort(3000); + config.setCollection(new ProductCollection(new ArrayList<>())); + } + + private ServerBuilder(Config config) { + this.config = config; + } + + public ServerBuilder setPort(int port) { + if (port < 1 || port > 65535) throw new IllegalArgumentException("Port must be between 1 and 65535"); + config.setPort(port); + return new ServerBuilder(config); + } + + public ServerBuilder setCollection(IStorage collection) { + config.setCollection(collection); + return new ServerBuilder(config); + } + + public Server build() throws IOException { + return new Server(config.getPort(), config.getCollection()); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Add.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Add.java similarity index 59% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Add.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Add.java index b538e79..ecfa55d 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Add.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Add.java @@ -1,11 +1,13 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.validator.Validators; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Domain.validator.Validators; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -18,13 +20,13 @@ public class Add extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) throws CommandActionException { + public String action(IStorage productCollection, Object object, User user) throws CommandActionException { var productDTO = (ProductDTO) object; try { Validators.validateObject(productDTO).throwIfNotValid(); - var product = productCollection.addProduct(productDTO); + var product = productCollection.addProduct(productDTO, user); return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId()); - } catch (ValidationException e) { + } catch (ValidationException | SQLException e) { throw new CommandActionException(String.format("Произошла ошибка при добавлении%n%s", e.getMessage())); } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMax.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMax.java similarity index 70% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMax.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMax.java index a2aa3e4..172d8d9 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMax.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMax.java @@ -1,11 +1,13 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.validator.Validators; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Domain.validator.Validators; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -18,17 +20,17 @@ public class AddIfMax extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) throws CommandActionException { + public String action(IStorage productCollection, Object object, User user) throws CommandActionException { try { var productDTO = (ProductDTO) object; try { Validators.validateObject(productDTO).throwIfNotValid(); if (productCollection.getMaxPrice() == null || productCollection.getMaxPrice() < productDTO.getPrice()) { - var product = productCollection.addProduct(productDTO); + var product = productCollection.addProduct(productDTO, user); return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId()); } return "Продукт не подходит под условие"; - } catch (ValidationException e) { + } catch (ValidationException | SQLException e) { throw new CommandActionException(e.getMessage()); } } catch (NumberFormatException e) { diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMin.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMin.java similarity index 71% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMin.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMin.java index 2cf05a8..f95a616 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/AddIfMin.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/AddIfMin.java @@ -1,11 +1,13 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.validator.Validators; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Domain.validator.Validators; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -18,17 +20,17 @@ public class AddIfMin extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) { + public String action(IStorage productCollection, Object object, User user) { try { var productDTO = (ProductDTO) object; try { Validators.validateObject(productDTO).throwIfNotValid(); if (productCollection.getMinPrice() == null || productCollection.getMinPrice() > productDTO.getPrice()) { - var product = productCollection.addProduct(productDTO); + var product = productCollection.addProduct(productDTO, user); return String.format("Продукт %s был добавлен под id %d", product.getName(), product.getId()); } return "Продукт не подходит под условие"; - } catch (ValidationException e) { + } catch (ValidationException | SQLException e) { throw new CommandActionException(e.getMessage()); } } catch (NumberFormatException e) { diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CheckProductOwner.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CheckProductOwner.java new file mode 100644 index 0000000..2dfe15d --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CheckProductOwner.java @@ -0,0 +1,29 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +import java.sql.SQLException; +import java.util.regex.Pattern; + +public class CheckProductOwner extends PostCommand { + public CheckProductOwner() { + super("check_product_owner", "", Pattern.compile("^check_product_owner .+")); + } + + @Override + public String action(IStorage productCollection, Object obj, User user) throws CommandActionException { + try { + var id = (long) obj; + if (DbWrapper.hasAccess(id, user, DbController.getConnection())) return "Это ваш продукт"; + throw new CommandActionException("У вас нет прав на изменение данного продукта"); + } catch (ClassCastException e) { + throw new CommandActionException(e); + } catch (SQLException e) { + throw new CommandActionException("У вас нет прав на изменение данного продукта"); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Clear.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Clear.java new file mode 100644 index 0000000..38722c0 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Clear.java @@ -0,0 +1,27 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.IStorage; + +import java.sql.SQLException; + +/** + * The Clear class represents a command to clear a collection. + * It extends the Command class. + */ +public class Clear extends GetCommand { + public Clear() { + super("clear", "очистить коллекцию"); + } + + @Override + public String action(IStorage productCollection, User user) { + try { + productCollection.clear(user); + return "Были удалены ваши продукты"; + } catch (SQLException e) { + throw new CommandActionException("Ошибка при отчистке коллекции"); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Command.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Command.java similarity index 95% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Command.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Command.java index 8f8733d..9390ed8 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Command.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Command.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; import java.util.regex.Pattern; diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/CommandManager.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CommandManager.java similarity index 89% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/CommandManager.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CommandManager.java index 2f6d97f..63e6696 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/CommandManager.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/CommandManager.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; import java.util.ArrayList; import java.util.List; @@ -25,8 +25,10 @@ public class CommandManager { registerCommand(new AddIfMax()); registerCommand(new AddIfMin()); registerCommand(new RemoveLower()); - registerCommand(new Save()); registerCommand(new GetProduct()); + registerCommand(new Login()); + registerCommand(new Register()); + registerCommand(new CheckProductOwner()); registerCommand(new Help()); } diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Drop.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Drop.java new file mode 100644 index 0000000..e830b22 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Drop.java @@ -0,0 +1,18 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +public class Drop extends GetCommand{ + public Drop() { + super("drop", "Init db"); + } + + @Override + public String action(IStorage productCollection, User user) throws CommandActionException { + DbWrapper.dropDb(); + return "Dropped 💀"; + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Exit.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Exit.java new file mode 100644 index 0000000..fc6cd22 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Exit.java @@ -0,0 +1,20 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.console.Console; + +/** + * A command to exit the program without saving to a file. + */ +public class Exit extends GetCommand { + public Exit() { + super("exit", "terminate the program"); + } + + @Override + public String action(IStorage productCollection, User user) { + Console.stopApp(); + return ""; + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/FilterContainsName.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/FilterContainsName.java similarity index 83% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/FilterContainsName.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/FilterContainsName.java index f595fdf..dab6cee 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/FilterContainsName.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/FilterContainsName.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; import java.util.regex.Pattern; @@ -13,7 +14,7 @@ public class FilterContainsName extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) { + public String action(IStorage productCollection, Object object, User user) { String name = object.toString(); var result = productCollection.filterContainsName(name); return result.isEmpty() ? "Таких элементов не найдено" : result; diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetCommand.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetCommand.java similarity index 50% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetCommand.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetCommand.java index a32c07d..8d60a91 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetCommand.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetCommand.java @@ -1,7 +1,8 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; import java.util.regex.Pattern; @@ -14,5 +15,5 @@ public abstract class GetCommand extends Command { super(name, description); } - public abstract String action(IStorage productCollection) throws CommandActionException; + public abstract String action(IStorage productCollection, User user) throws CommandActionException; } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetProduct.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetProduct.java similarity index 59% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetProduct.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetProduct.java index b6d5f2c..81b3f3b 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/GetProduct.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/GetProduct.java @@ -1,7 +1,8 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; import java.util.regex.Pattern; @@ -11,7 +12,7 @@ public class GetProduct extends PostCommand { } @Override - public String action(IStorage productCollection, Object obj) throws CommandActionException { + public String action(IStorage productCollection, Object obj, User user) throws CommandActionException { if (!productCollection.isProductIdExists((Long) obj)) throw new CommandActionException("Продукт с таким ID не существует"); return productCollection.getProductById((Long) obj).toString(); diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Help.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Help.java similarity index 57% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Help.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Help.java index ffcb379..512f0db 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Help.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Help.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * A command to display help for available commands. @@ -11,7 +12,7 @@ public class Help extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { return SystemCommandManager.getRegisteredCommand(); } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Info.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Info.java similarity index 72% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Info.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Info.java index 90e6cc0..3df9867 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Info.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Info.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * A command to display information about the collection (type, initialization date, number of elements, etc.) to the standard output stream. @@ -11,7 +12,7 @@ public class Info extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { return productCollection.getInfo(); } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Init.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Init.java new file mode 100644 index 0000000..6452d61 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Init.java @@ -0,0 +1,26 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.DbInitializer; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +import java.sql.SQLException; + +public class Init extends GetCommand{ + public Init() { + super("init", "Delete all db"); + } + + @Override + public String action(IStorage productCollection, User user) throws CommandActionException { + try { + DbInitializer.initializeDb(DbController.getConnection()); + return "Initialized 😇"; + } catch (SQLException e) { + throw new CommandActionException(e); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/IsIdExists.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/IsIdExists.java similarity index 56% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/IsIdExists.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/IsIdExists.java index 9772a3c..033af60 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/IsIdExists.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/IsIdExists.java @@ -1,7 +1,8 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; import java.util.regex.Pattern; @@ -11,7 +12,7 @@ public class IsIdExists extends PostCommand { } @Override - public String action(IStorage productCollection, Object obj) throws CommandActionException { + public String action(IStorage productCollection, Object obj, User user) throws CommandActionException { if (!productCollection.isProductIdExists((Long) obj)) throw new CommandActionException("Продукт с таким ID не существует"); return "Exists"; diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Login.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Login.java new file mode 100644 index 0000000..eb007b7 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Login.java @@ -0,0 +1,28 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.utils.SHA256; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +import java.sql.SQLException; + +public class Login extends PostCommand { + public Login() { + super("login", ""); + } + + @Override + public String action(IStorage productCollection, Object obj, User user) throws CommandActionException { + try { + var loginUser = (User) obj; + if (DbWrapper.isUserExists(loginUser.getLogin(), SHA256.hash(loginUser.getPassword()), DbController.getConnection())) + return "Здравствуйте, " + loginUser.getLogin() + "!"; + throw new CommandActionException("Ошибка в логине или пароле"); + } catch (SQLException e) { + throw new CommandActionException(e); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PostCommand.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PostCommand.java similarity index 60% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PostCommand.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PostCommand.java index f72e3cb..515ffe8 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PostCommand.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PostCommand.java @@ -1,7 +1,8 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; import java.util.regex.Pattern; @@ -14,5 +15,5 @@ public abstract class PostCommand extends Command { super(name, description); } - public abstract String action(IStorage productCollection, Object obj) throws CommandActionException; + public abstract String action(IStorage productCollection, Object obj, User user) throws CommandActionException; } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintAscending.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintAscending.java similarity index 69% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintAscending.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintAscending.java index d2a22ca..6006d61 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintAscending.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintAscending.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * A command to print the elements of the collection in ascending order. @@ -11,7 +12,7 @@ public class PrintAscending extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { var result = productCollection.toString(); return result.isEmpty() ? "Коллекция пуста" : result; } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintUniqueManufactureCost.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintUniqueManufactureCost.java similarity index 74% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintUniqueManufactureCost.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintUniqueManufactureCost.java index 1269891..ab221f4 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/PrintUniqueManufactureCost.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/PrintUniqueManufactureCost.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * A command to print the unique values of the 'manufactureCost' field of all elements in the collection. @@ -11,7 +12,7 @@ public class PrintUniqueManufactureCost extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { var result = productCollection.getUniqueManufactureCost(); return result.isEmpty() ? "Коллекция пуста" : result; } diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Register.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Register.java new file mode 100644 index 0000000..49c01ef --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Register.java @@ -0,0 +1,28 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.utils.SHA256; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +import java.sql.SQLException; + +public class Register extends PostCommand { + public Register() { + super("register", ""); + } + + @Override + public String action(IStorage productCollection, Object obj, User user) throws CommandActionException { + try { + var newUser = (User) obj; + newUser.setPassword(SHA256.hash(newUser.getPassword())); + DbWrapper.createUser(newUser, DbController.getConnection()); + return "Пользователь создан"; + } catch (ClassCastException | SQLException e) { + throw new CommandActionException("Пользователь уже существует"); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Remove.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Remove.java similarity index 66% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Remove.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Remove.java index e4088a0..4907eb6 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Remove.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Remove.java @@ -1,8 +1,10 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -14,16 +16,18 @@ public class Remove extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) throws CommandActionException { + public String action(IStorage productCollection, Object object, User user) throws CommandActionException { try { Long id = (Long) object; if (productCollection.isProductIdExists(id)) { - var product = productCollection.removeProduct(id); + var product = productCollection.removeProduct(id, user); return String.format("Продукт %s был удалён", product.getName()); } return "Продукта с таким id не существует"; } catch (NumberFormatException e) { return "Неверный аргумент, id может быть только число"; + } catch (SQLException e) { + throw new CommandActionException(e.getMessage()); } } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/RemoveLower.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/RemoveLower.java similarity index 66% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/RemoveLower.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/RemoveLower.java index 35b18e3..ebf3c21 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/RemoveLower.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/RemoveLower.java @@ -1,7 +1,10 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.IStorage; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -13,13 +16,15 @@ public class RemoveLower extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) { + public String action(IStorage productCollection, Object object, User user) { try { Long id = (Long) object; - var size = productCollection.removeLover(id); + var size = productCollection.removeLover(id, user); return String.format("Было удалено %d продуктов", size); } catch (NumberFormatException e) { return "Неверный аргумент, id может быть только число"; + } catch (SQLException e) { + throw new CommandActionException(e.getMessage()); } } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Seed.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Seed.java new file mode 100644 index 0000000..e66fa75 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Seed.java @@ -0,0 +1,18 @@ +package me.zinch.Lab7.Server.commands; + +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.wrapper.DbWrapper; +import me.zinch.Lab7.Server.wrapper.IStorage; + +public class Seed extends GetCommand{ + public Seed() { + super("seed", "Seed data"); + } + + @Override + public String action(IStorage productCollection, User user) throws CommandActionException { + DbWrapper.seedDb(); + return "Seeded 🌿"; + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Show.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Show.java similarity index 72% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Show.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Show.java index 53997ec..4fd6a0e 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Show.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Show.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * A command to display all elements of the collection in string representation to the standard output stream. @@ -11,7 +12,7 @@ public class Show extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { var result = productCollection.toString(); return result.isEmpty() ? "Коллекция пуста" : result; } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/SystemCommandManager.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/SystemCommandManager.java similarity index 85% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/SystemCommandManager.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/SystemCommandManager.java index 3f4e3ef..918cbc4 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/SystemCommandManager.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/SystemCommandManager.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; import java.util.ArrayList; import java.util.List; @@ -12,7 +12,9 @@ public class SystemCommandManager { static { registerCommand(new Exit()); - registerCommand(new Save()); + registerCommand(new Drop()); + registerCommand(new Init()); + registerCommand(new Seed()); registerCommand(new Help()); } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/UnknownCommand.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/UnknownCommand.java similarity index 53% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/UnknownCommand.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/UnknownCommand.java index b632dad..22e9043 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/UnknownCommand.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/UnknownCommand.java @@ -1,6 +1,7 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.wrapper.IStorage; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.wrapper.IStorage; /** * Represents an unknown command. @@ -11,7 +12,7 @@ public class UnknownCommand extends GetCommand { } @Override - public String action(IStorage productCollection) { + public String action(IStorage productCollection, User user) { return "Команда не распознана."; } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Update.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Update.java similarity index 69% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Update.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Update.java index 8d7802f..dd14724 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/commands/Update.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/commands/Update.java @@ -1,12 +1,14 @@ -package me.zinch.Lab6.Server.commands; +package me.zinch.Lab7.Server.commands; -import me.zinch.Lab6.Domain.dto.MessageBody; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.models.ProductDTO; -import me.zinch.Lab6.Domain.validator.Validators; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Domain.net.MessageBody; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Domain.validator.Validators; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -18,7 +20,7 @@ public class Update extends PostCommand { } @Override - public String action(IStorage productCollection, Object object) throws CommandActionException { + public String action(IStorage productCollection, Object object, User user) throws CommandActionException { try { var body = (MessageBody) object; var id = Long.parseLong(body.getCommand().split(" ")[1]); @@ -26,7 +28,7 @@ public class Update extends PostCommand { var productDTO = (ProductDTO) body.getBody(); try { Validators.validateObject(productDTO).throwIfNotValid(); - var product = productCollection.updateProduct(id, productDTO); + var product = productCollection.updateProduct(id, productDTO, user); return String.format("Продукт %s был изменён", product.getName()); } catch (ValidationException e) { throw new CommandActionException(e.getMessage()); @@ -35,6 +37,8 @@ public class Update extends PostCommand { return "Продукта с таким id не существует"; } catch (NumberFormatException e) { return "Неверный аргумент, id может быть только число"; + } catch (SQLException e) { + throw new CommandActionException(e.getMessage()); } } } diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/configs/ServerConfig.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/configs/ServerConfig.java new file mode 100644 index 0000000..b82ec95 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/configs/ServerConfig.java @@ -0,0 +1,60 @@ +package me.zinch.Lab7.Server.configs; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Properties; + +public class ServerConfig { + private static final Logger log = LoggerFactory.getLogger(ServerConfig.class); + private static final Properties properties = new Properties(); + + static { + var settingsFile = new File("server.properties"); + if (settingsFile.isFile() && settingsFile.exists()) { + try { + properties.load(new FileReader(settingsFile)); + } catch (IOException e) { + log.error(e.getMessage()); + } + } else { + var classLoader = ServerConfig.class.getClassLoader(); + try (var inputStream = classLoader.getResourceAsStream("server.properties")) { + properties.load(inputStream); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + } + + public static int getPort() { + return Integer.parseInt(properties.getProperty("server-port", "3000")); + } + + public static String getDbHost() { + return properties.getProperty("db-host", "localhost"); + } + + public static int getDbPort() { + return Integer.parseInt(properties.getProperty("db-port", "5432")); + } + + public static String getDbName() { + return properties.getProperty("db-name", "studs"); + } + + public static String getDbScheme() { + return properties.getProperty("db-scheme", "s408657"); + } + + public static String getDbUsername() { + return properties.getProperty("db-username", "postgres"); + } + + public static String getDbPassword() { + return properties.getProperty("db-password", "postgres"); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/console/Console.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/console/Console.java similarity index 64% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/console/Console.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/console/Console.java index 9ec97b9..11c019e 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/console/Console.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/console/Console.java @@ -1,13 +1,16 @@ -package me.zinch.Lab6.Server.console; +package me.zinch.Lab7.Server.console; -import me.zinch.Lab6.Domain.exceptions.ValidationException; -import me.zinch.Lab6.Domain.wrapper.IStorage; -import me.zinch.Lab6.Server.ServerBuilder; -import me.zinch.Lab6.Server.commands.GetCommand; -import me.zinch.Lab6.Server.commands.SystemCommandManager; -import me.zinch.Lab6.Server.exceptions.CommandActionException; -import me.zinch.Lab6.Server.files.DbController; -import me.zinch.Lab6.Server.wrapper.ProductCollection; +import me.zinch.Lab7.Domain.exceptions.ValidationException; +import me.zinch.Lab7.Server.wrapper.IStorage; +import me.zinch.Lab7.Server.Server.ServerBuilder; +import me.zinch.Lab7.Server.commands.GetCommand; +import me.zinch.Lab7.Server.commands.SystemCommandManager; +import me.zinch.Lab7.Server.configs.ServerConfig; +import me.zinch.Lab7.Server.exceptions.CommandActionException; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.exceptions.DbConnectionException; +import me.zinch.Lab7.Server.wrapper.DbInitializer; +import me.zinch.Lab7.Server.wrapper.ProductCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,11 +40,14 @@ public class Console { isExitMessageShowed = true; } - public static void run() throws IOException, ValidationException { - collection = new ProductCollection(DbController.loadDb()); + public static void run() throws IOException, ValidationException, DbConnectionException { + DbController.initConnection(); + DbInitializer.initializeDb(DbController.getConnection()); + + collection = new ProductCollection(DbController.getConnection()); var server = new ServerBuilder() - .setPort(3000) + .setPort(ServerConfig.getPort()) .setCollection(collection) .build(); @@ -69,12 +75,12 @@ public class Console { if (command.isPresent()) { var action = (GetCommand) command.get(); try { - log.info(action.action(collection)); + System.out.println(action.action(collection, null)); } catch (CommandActionException e) { - log.info(e.getMessage()); + System.out.println(e.getMessage()); } } else { - log.info("This command does not exist. Write help to see a list of available commands."); + System.out.println("This command does not exist. Write help to see a list of available commands."); } } catch (NoSuchElementException e) { stopApp(); diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/console/ShutdownHook.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/console/ShutdownHook.java similarity index 82% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/console/ShutdownHook.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/console/ShutdownHook.java index 2439529..5b6af28 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/console/ShutdownHook.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/console/ShutdownHook.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.console; +package me.zinch.Lab7.Server.console; /** * Represents a shutdown hook that is executed when the application is stopped. diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/db/DbController.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/db/DbController.java new file mode 100644 index 0000000..bfef534 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/db/DbController.java @@ -0,0 +1,51 @@ +package me.zinch.Lab7.Server.db; + +import me.zinch.Lab7.Server.configs.ServerConfig; +import me.zinch.Lab7.Server.exceptions.DbConnectionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +/** + * The DbController class provides methods for loading and saving product data to a database file. + */ +public class DbController { + private static final Logger log = LoggerFactory.getLogger(DbController.class); + private static Connection connection; + + public static void initConnection() throws DbConnectionException { + var url = String.format("jdbc:postgresql://%s:%s/%s?currentSchema=%s", + ServerConfig.getDbHost(), + ServerConfig.getDbPort(), + ServerConfig.getDbName(), + ServerConfig.getDbScheme()); + var props = new Properties(); + props.setProperty("user", ServerConfig.getDbUsername()); + props.setProperty("password", ServerConfig.getDbPassword()); + try { + connection = DriverManager.getConnection(url, props); + log.info("Connection to the database has been successfully established"); + } catch (SQLException e) { + log.error(e.getMessage()); + throw new DbConnectionException("Failed to connect to the database"); + } + } + + public static Connection getConnection() throws DbConnectionException { + if (connection == null) initConnection(); + return connection; + } + + public static void closeConnection() throws DbConnectionException { + try { + connection.close(); + } catch (SQLException e) { + log.error(e.getMessage()); + throw new DbConnectionException("Failed to close the connection to the database"); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/ColorFormatException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/ColorFormatException.java similarity index 82% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/ColorFormatException.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/ColorFormatException.java index 6341563..7bb81ba 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/ColorFormatException.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/ColorFormatException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.exceptions; +package me.zinch.Lab7.Server.exceptions; public class ColorFormatException extends IllegalArgumentException { public ColorFormatException() { diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/CommandActionException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/CommandActionException.java similarity index 91% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/CommandActionException.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/CommandActionException.java index 2e9ed82..dbc30c0 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/CommandActionException.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/CommandActionException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.exceptions; +package me.zinch.Lab7.Server.exceptions; /** * Represents an exception that occurs during the execution of a command action. diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbConnectionException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbConnectionException.java new file mode 100644 index 0000000..954c316 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbConnectionException.java @@ -0,0 +1,17 @@ +package me.zinch.Lab7.Server.exceptions; + +import java.io.IOException; +import java.sql.SQLException; + +/** + * Represents an exception that occurs when the database initialization fails. + */ +public class DbConnectionException extends SQLException { + public DbConnectionException() { + super("Failed to connect to the database"); + } + + public DbConnectionException(String message) { + super(message); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbExecuteException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbExecuteException.java new file mode 100644 index 0000000..937fcec --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/DbExecuteException.java @@ -0,0 +1,17 @@ +package me.zinch.Lab7.Server.exceptions; + +import java.sql.SQLException; + +public class DbExecuteException extends SQLException { + public DbExecuteException() { + super("Error during sql command execution"); + } + + public DbExecuteException(String reason) { + super(reason); + } + + public DbExecuteException(Throwable cause) { + super(cause); + } +} diff --git a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/IllegalProductDtoException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/IllegalProductDtoException.java similarity index 93% rename from Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/IllegalProductDtoException.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/IllegalProductDtoException.java index 55413e6..2b3f062 100644 --- a/Lab.Client/src/main/java/me/zinch/Lab6/Client/exceptions/IllegalProductDtoException.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/IllegalProductDtoException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Client.exceptions; +package me.zinch.Lab7.Server.exceptions; /** * Represents an exception that occurs when an illegal product DTO is encountered during the creation or modification of a product. diff --git a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/UnitOfMeasureFormatException.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/UnitOfMeasureFormatException.java similarity index 84% rename from Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/UnitOfMeasureFormatException.java rename to Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/UnitOfMeasureFormatException.java index 98041be..0c26a86 100644 --- a/Lab.Server/src/main/java/me/zinch/Lab6/Server/exceptions/UnitOfMeasureFormatException.java +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/exceptions/UnitOfMeasureFormatException.java @@ -1,4 +1,4 @@ -package me.zinch.Lab6.Server.exceptions; +package me.zinch.Lab7.Server.exceptions; public class UnitOfMeasureFormatException extends IllegalArgumentException { public UnitOfMeasureFormatException() { diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/files/FileReader.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/files/FileReader.java new file mode 100644 index 0000000..af17623 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/files/FileReader.java @@ -0,0 +1,36 @@ +package me.zinch.Lab7.Server.files; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class FileReader { + private static final Logger log = LoggerFactory.getLogger(FileReader.class); + + public static String readFromInputStream(InputStream inputStream) { + StringBuilder resultStringBuilder = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while ((line = br.readLine()) != null) { + resultStringBuilder.append(line).append("\n"); + } + } catch (IOException e) { + log.error(e.getMessage()); + return ""; + } + return resultStringBuilder.toString(); + } + + public static String readFromResource(String fileName) throws FileNotFoundException { + try (var inputStream = FileReader.class.getClassLoader().getResourceAsStream(fileName)) { + return readFromInputStream(inputStream); + } catch (IOException e) { + throw new FileNotFoundException(); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/utils/SHA256.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/utils/SHA256.java new file mode 100644 index 0000000..11e8397 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/utils/SHA256.java @@ -0,0 +1,27 @@ +package me.zinch.Lab7.Server.utils; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class SHA256 { + public static String hash(String str) { + if (str == null) str = ""; + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + byte[] encodedhash = digest.digest(str.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(2 * encodedhash.length); + for (byte b : encodedhash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbInitializer.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbInitializer.java new file mode 100644 index 0000000..1f09651 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbInitializer.java @@ -0,0 +1,30 @@ +package me.zinch.Lab7.Server.wrapper; + +import me.zinch.Lab7.Server.exceptions.DbConnectionException; +import me.zinch.Lab7.Server.files.FileReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; + +public class DbInitializer { + private static final Logger log = LoggerFactory.getLogger(DbInitializer.class); + + public static void initializeDb(Connection connection) throws DbConnectionException { + try (var st = connection.createStatement(); + var inputStream = DbInitializer.class.getClassLoader().getResourceAsStream("migrations/init.sql")) { + try { + st.executeQuery("SELECT * FROM db_info WHERE db_info.migration_version >= 1"); + log.info("The database already exists"); + } catch (SQLException e) { + var initScript = FileReader.readFromInputStream(inputStream); + st.execute(initScript); + log.info("The database has been successfully initialized"); + } + } catch (SQLException | IOException e) { + log.error(e.getMessage()); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbWrapper.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbWrapper.java new file mode 100644 index 0000000..6036883 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/DbWrapper.java @@ -0,0 +1,283 @@ +package me.zinch.Lab7.Server.wrapper; + +import me.zinch.Lab7.Domain.models.Product; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import me.zinch.Lab7.Server.files.FileReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class DbWrapper { + private static final Logger log = LoggerFactory.getLogger(DbWrapper.class); + + public static List getProducts(Connection connection) throws SQLException, FileNotFoundException { + try (var st = connection.createStatement()) { + var productsResultSet = st.executeQuery(FileReader.readFromResource("migrations/getProducts.sql")); + var products = new ArrayList(); + while (productsResultSet.next()) { + products.add(Mapper.resultStateToProduct(productsResultSet)); + } + return products; + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + return new ArrayList<>(); + } + } + + public static Product getProductByDto(ProductDTO productDTO, Connection connection) { + try { + var createProductStatement = connection.prepareStatement(FileReader.readFromResource("migrations/getProductByDto.sql")); + + prepareProductDtoStatement(productDTO, createProductStatement); + createProductStatement.setString(8, productDTO.getOwner().getName()); + createProductStatement.setString(9, productDTO.getOwner().getPassportID()); + createProductStatement.setInt(10, productDTO.getOwner().getHairColor().ordinal()); + createProductStatement.setFloat(11, productDTO.getOwner().getLocation().getX()); + createProductStatement.setInt(12, productDTO.getOwner().getLocation().getY()); + createProductStatement.setString(13, productDTO.getOwner().getLocation().getName()); + + var rs = createProductStatement.executeQuery(); + if (rs.next()) + return Mapper.resultStateToProduct(rs); + return null; + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + return null; + } + } + + private static void prepareProductDtoStatement(ProductDTO productDTO, PreparedStatement createProductStatement) throws SQLException { + createProductStatement.setString(1, productDTO.getName()); + createProductStatement.setLong(2, productDTO.getCoordinates().getX()); + createProductStatement.setLong(3, productDTO.getCoordinates().getY()); + createProductStatement.setLong(4, productDTO.getPrice()); + createProductStatement.setString(5, productDTO.getPartNumber()); + createProductStatement.setLong(6, productDTO.getManufactureCost()); + createProductStatement.setInt(7, productDTO.getUnitOfMeasure().ordinal()); + } + + public static Product getProductById(long id, Connection connection) { + try(var st = connection.prepareStatement(FileReader.readFromResource("migrations/getProductById.sql"))) { + st.setLong(1, id); + + var rs = st.executeQuery(); + if (rs.next()) { + return Mapper.resultStateToProduct(rs); + } + return null; + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + return null; + } + } + + public static Product addProduct(ProductDTO productDTO, Connection connection, User user) throws SQLException { + try { + var createProductStatement = connection.prepareStatement(FileReader.readFromResource("migrations/createProduct.sql"), PreparedStatement.RETURN_GENERATED_KEYS); + prepareProductObjectCreation(productDTO, connection); + + createProductStatement.setString(1, productDTO.getName()); + createProductStatement.setLong(2, productDTO.getCoordinates().getX()); + createProductStatement.setLong(3, productDTO.getCoordinates().getY()); + createProductStatement.setTimestamp(4, Timestamp.valueOf(LocalDateTime.now())); + createProductStatement.setLong(5, productDTO.getPrice()); + createProductStatement.setString(6, productDTO.getPartNumber()); + createProductStatement.setLong(7, productDTO.getManufactureCost()); + createProductStatement.setInt(8, productDTO.getUnitOfMeasure().ordinal()); + createProductStatement.setString(9, productDTO.getOwner().getPassportID()); + + createProductStatement.executeUpdate(); + var generatedKeys = createProductStatement.getGeneratedKeys(); + generatedKeys.next(); + + var product = getProductById(generatedKeys.getLong(1), connection); + + var createProductOwnersStatement = connection.prepareStatement(FileReader.readFromResource("migrations/createProductOwners.sql")); + createProductOwnersStatement.setLong(1, product.getId()); + createProductOwnersStatement.setLong(2, getUserId(user, connection)); + + createProductOwnersStatement.execute(); + + return product; + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static Product updateProduct(long id, ProductDTO productDTO, Connection connection, User user) throws SQLException { + try { + if (!hasAccess(id, user, connection)) throw new SQLException("У вас нет прав на этот продукт"); + + var updateProductStatement = connection.prepareStatement(FileReader.readFromResource("migrations/updateProduct.sql")); + prepareProductObjectCreation(productDTO, connection); + + prepareProductDtoStatement(productDTO, updateProductStatement); + updateProductStatement.setString(8, productDTO.getOwner().getPassportID()); + updateProductStatement.setLong(9, id); + + updateProductStatement.execute(); + + return getProductByDto(productDTO, connection); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + private static void prepareProductObjectCreation(ProductDTO productDTO, Connection connection) throws SQLException, FileNotFoundException { + var updateCoordinateStatement = connection.prepareStatement(FileReader.readFromResource("migrations/createCoordinate.sql")); + var updateLocationStatement = connection.prepareStatement(FileReader.readFromResource("migrations/createLocation.sql")); + var updatePersonStatement = connection.prepareStatement(FileReader.readFromResource("migrations/createPerson.sql")); + + updateCoordinateStatement.setLong(1, productDTO.getCoordinates().getX()); + updateCoordinateStatement.setLong(2, productDTO.getCoordinates().getY()); + try { + updateCoordinateStatement.execute(); + } catch (SQLException e) { + log.error(e.getMessage()); + } + + updateLocationStatement.setFloat(1, productDTO.getOwner().getLocation().getX()); + updateLocationStatement.setInt(2, productDTO.getOwner().getLocation().getY()); + updateLocationStatement.setString(3, productDTO.getOwner().getLocation().getName()); + try { + updateLocationStatement.execute(); + } catch (SQLException e) { + log.error(e.getMessage()); + } + + updatePersonStatement.setString(1, productDTO.getOwner().getName()); + updatePersonStatement.setString(2, productDTO.getOwner().getPassportID()); + updatePersonStatement.setInt(3, productDTO.getOwner().getHairColor().ordinal()); + updatePersonStatement.setFloat(4, productDTO.getOwner().getLocation().getX()); + updatePersonStatement.setInt(5, productDTO.getOwner().getLocation().getY()); + try { + updatePersonStatement.execute(); + } catch (SQLException e) { + log.error(e.getMessage()); + } + } + + public static boolean removeProductById(long id, Connection connection, User user) throws SQLException { + if (!hasAccess(id, user, connection)) throw new SQLException("У вас нет прав на этот продукт"); + + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/deleteProductById.sql"))) { + st.setLong(1, id); + st.setLong(2, id); + return st.executeUpdate() > 0; + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static int removeLower(long id, Connection connection, User user) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/deleteLower.sql"))) { + st.setLong(1, getUserId(user, connection)); + st.setLong(2, id); + return st.executeUpdate(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static void clearProducts(User user, Connection connection) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/clearProducts.sql"))) { + st.setLong(1, getUserId(user, connection)); + st.executeUpdate(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static boolean isUserExists(User user, Connection connection) throws SQLException { + return isUserExists(user.getLogin(), user.getPassword(), connection); + } + + public static boolean isUserExists(String login, String passwordHash, Connection connection) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/isUserExists.sql"))) { + st.setString(1, login); + st.setString(2, passwordHash); + + var rs = st.executeQuery(); + return rs.next(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static long getUserId(User user, Connection connection) throws SQLException { + return getUserId(user.getLogin(), user.getPassword(), connection); + } + + public static long getUserId(String login, String passwordHash, Connection connection) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/isUserExists.sql"))) { + st.setString(1, login); + st.setString(2, passwordHash); + + var rs = st.executeQuery(); + if (rs.next()) return rs.getLong(1); + throw new SQLException("User not found"); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static User createUser(User userRegister, Connection connection) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/createUser.sql"))) { + st.setString(1, userRegister.getLogin()); + st.setString(2, userRegister.getPassword()); + + st.execute(); + return new User(userRegister.getLogin(), userRegister.getPassword()); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException(e); + } + } + + public static boolean hasAccess(long productId, User user, Connection connection) throws SQLException { + try (var st = connection.prepareStatement(FileReader.readFromResource("migrations/hasUserAccess.sql"))) { + st.setLong(1, productId); + st.setString(2, user.getLogin()); + st.setString(3, user.getPassword()); + + var rs = st.executeQuery(); + return rs.next(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + throw new SQLException("У вас нет прав на изменение данного продукта"); + } + } + + public static void dropDb() { + try (var st = DbController.getConnection().prepareStatement(FileReader.readFromResource("migrations/drop.sql"))) { + st.execute(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + } + } + + public static void seedDb() { + try (var st = DbController.getConnection().prepareStatement(FileReader.readFromResource("migrations/seed.sql"))) { + st.execute(); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + } + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/IStorage.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/IStorage.java new file mode 100644 index 0000000..8fb16d2 --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/IStorage.java @@ -0,0 +1,37 @@ +package me.zinch.Lab7.Server.wrapper; + +import me.zinch.Lab7.Domain.models.Product; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.exceptions.DbConnectionException; + +import java.sql.SQLException; +import java.util.List; + +public interface IStorage { + public Product getProductById(Long id); + + public Product addProduct(ProductDTO productDTO, User user) throws SQLException; + + public Product updateProduct(Long id, ProductDTO productDTO, User user) throws SQLException; + + public Product removeProduct(Long id, User user) throws SQLException; + + public String getInfo(); + + public void clear(User user) throws SQLException; + + public Long getMaxPrice(); + + public Long getMinPrice(); + + public boolean isProductIdExists(Long id); + + public Integer removeLover(Long id, User user) throws SQLException; + + public String filterContainsName(String name); + + public String getUniqueManufactureCost(); + + public List toList(); +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/Mapper.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/Mapper.java new file mode 100644 index 0000000..35f71af --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/Mapper.java @@ -0,0 +1,44 @@ +package me.zinch.Lab7.Server.wrapper; + +import me.zinch.Lab7.Domain.models.Color; +import me.zinch.Lab7.Domain.models.Coordinates; +import me.zinch.Lab7.Domain.models.Location; +import me.zinch.Lab7.Domain.models.Person; +import me.zinch.Lab7.Domain.models.Product; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.models.UnitOfMeasure; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public class Mapper { + public static Product resultStateToProduct(ResultSet resultSet) throws SQLException { + var productDto = new ProductDTO(); + var coordinates = new Coordinates(); + var person = new Person(); + var location = new Location(); + productDto.setName(resultSet.getString(2)); + coordinates.setX(resultSet.getLong(3)); + coordinates.setY(resultSet.getLong(4)); + productDto.setPrice(resultSet.getLong(6)); + productDto.setPartNumber(resultSet.getString(7)); + productDto.setManufactureCost(resultSet.getLong(8)); + productDto.setUnitOfMeasure(UnitOfMeasure.create(resultSet.getInt(9))); + person.setName(resultSet.getString(10)); + person.setPassportID(resultSet.getString(11)); + person.setHairColor(Color.create(resultSet.getInt(12))); + location.setX(resultSet.getLong(13)); + location.setY(resultSet.getInt(14)); + location.setName(resultSet.getString(15)); + + person.setLocation(location); + productDto.setOwner(person); + productDto.setCoordinates(coordinates); + + var id = resultSet.getLong(1); + var date = ZonedDateTime.parse(String.join("T", resultSet.getString(5).split(" ")), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + return productDto.buildProduct(id, date); + } +} diff --git a/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/ProductCollection.java b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/ProductCollection.java new file mode 100644 index 0000000..9cf2f0a --- /dev/null +++ b/Lab.Server/src/main/java/me/zinch/Lab7/Server/wrapper/ProductCollection.java @@ -0,0 +1,234 @@ +package me.zinch.Lab7.Server.wrapper; + +import me.zinch.Lab7.Domain.models.Product; +import me.zinch.Lab7.Domain.models.ProductDTO; +import me.zinch.Lab7.Domain.net.User; +import me.zinch.Lab7.Server.db.DbController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.SQLException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; + +public class ProductCollection implements IStorage { + private static final Logger log = LoggerFactory.getLogger(ProductCollection.class); + private TreeSet productList; + private final Lock lock = new ReentrantLock(); + + private List fetchProductFromDb(Connection connection) { + try { + return DbWrapper.getProducts(connection); + } catch (SQLException | FileNotFoundException e) { + log.error(e.getMessage()); + return new ArrayList<>(); + } + } + + private void Initialize(List list) { + productList = new TreeSet<>((o1, o2) -> { + var o1Length = Math.sqrt(o1.getCoordinates().getX() * o1.getCoordinates().getX() + o1.getCoordinates().getY() * o1.getCoordinates().getY()); + var o2Length = Math.sqrt(o2.getCoordinates().getX() * o2.getCoordinates().getX() + o2.getCoordinates().getY() * o2.getCoordinates().getY()); + return Math.toIntExact((long) (o1Length - o2Length)); + }); + productList.addAll(list); + } + + public ProductCollection(List list) { + Initialize(list); + } + + public ProductCollection() { + Initialize(new ArrayList<>()); + } + + public ProductCollection(Connection connection) { + Initialize(fetchProductFromDb(connection)); + } + + public Product getProductById(Long id) { + lock.lock(); + try { + Optional product = productList.stream().filter(i -> Objects.equals(i.getId(), id)).findFirst(); + return product.orElse(null); + } finally { + lock.unlock(); + } + } + + public Product addProduct(ProductDTO productDTO, User user) throws SQLException { + lock.lock(); + try { + var product = DbWrapper.addProduct(productDTO, DbController.getConnection(), user); + productList.add(product); + return product; + } finally { + lock.unlock(); + } + } + + public Product updateProduct(Long id, ProductDTO productDTO, User user) throws SQLException { + lock.lock(); + try { + var product = DbWrapper.updateProduct(id, productDTO, DbController.getConnection(), user); + fetchProductFromDb(DbController.getConnection()); + return productDTO.buildProduct(product.getId(), product.getCreationDate()); + } finally { + lock.unlock(); + } + } + + public Product removeProduct(Long id, User user) throws SQLException { + lock.lock(); + try { + var product = getProductById(id); + if (DbWrapper.removeProductById(id, DbController.getConnection(), user)) { + productList.remove(product); + return product; + } + return null; + } finally { + lock.unlock(); + } + } + + public String getInfo() { + lock.lock(); + try { + var optionalInitDate = productList.stream().map(Product::getCreationDate).sorted().findFirst(); + ZonedDateTime initDate = optionalInitDate.orElse(ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.systemDefault())); + return String.format("Структура: TreeSet%nДата инициализации: %s%nКоличество элементов: %s", initDate, productList.size()); + } finally { + lock.unlock(); + } + } + + public void clear(User user) throws SQLException { + lock.lock(); + try { + DbWrapper.clearProducts(user, DbController.getConnection()); + fetchProductFromDb(DbController.getConnection()); + } finally { + lock.unlock(); + } + } + + public Long getMaxPrice() { + lock.lock(); + try { + return productList.stream().max(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null); + } finally { + lock.unlock(); + } + } + + public Long getMinPrice() { + lock.lock(); + try { + return productList.stream().min(Comparator.comparingLong(Product::getPrice)).map(Product::getPrice).orElse(null); + } finally { + lock.unlock(); + } + } + + public boolean isProductIdExists(Long id) { + lock.lock(); + try { + return getProductById(id) != null; + } finally { + lock.unlock(); + } + } + + public Integer removeLover(Long id, User user) throws SQLException { + lock.lock(); + try { + var size = productList.size(); + DbWrapper.removeLower(id, DbController.getConnection(), user); + fetchProductFromDb(DbController.getConnection()); + return size - productList.size(); + } finally { + lock.unlock(); + } + } + + public String filterContainsName(String name) { + lock.lock(); + try { + return String.join("\n", productList.stream() + .filter(product -> product.getName().toLowerCase().contains(name.toLowerCase())) + .map(Product::toString) + .toList()); + } finally { + lock.unlock(); + } + } + + public String getUniqueManufactureCost() { + lock.lock(); + try { + return String.join(", ", Set.copyOf(productList.stream() + .map(Product::getManufactureCost) + .toList()) + .stream() + .map(Object::toString) + .toList()); + } finally { + lock.unlock(); + } + } + + public List toList() { + lock.lock(); + try { + return productList.stream().toList(); + } finally { + lock.unlock(); + } + } + + @Override + public String toString() { + lock.lock(); + try { + return String.join("\n", productList.stream().map(Product::toString).toList()); + } finally { + lock.unlock(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProductCollection that = (ProductCollection) o; + lock.lock(); + try { + return Objects.equals(productList, that.productList); + } finally { + lock.unlock(); + } + } + + @Override + public int hashCode() { + lock.lock(); + try { + return Objects.hashCode(productList); + } finally { + lock.unlock(); + } + } +} diff --git a/Lab.Server/src/main/resources/migrations/clearProducts.sql b/Lab.Server/src/main/resources/migrations/clearProducts.sql new file mode 100644 index 0000000..7dd5fe3 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/clearProducts.sql @@ -0,0 +1,5 @@ +DELETE FROM products +WHERE id IN ( + SELECT product FROM products_owners + WHERE "user" = ? +); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/createCoordinate.sql b/Lab.Server/src/main/resources/migrations/createCoordinate.sql new file mode 100644 index 0000000..dda384a --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createCoordinate.sql @@ -0,0 +1 @@ +INSERT INTO coordinates(x, y) VALUES (?, ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/createLocation.sql b/Lab.Server/src/main/resources/migrations/createLocation.sql new file mode 100644 index 0000000..1a4bd76 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createLocation.sql @@ -0,0 +1 @@ +INSERT INTO locations(x, y, name) VALUES (?, ?, ?); diff --git a/Lab.Server/src/main/resources/migrations/createPerson.sql b/Lab.Server/src/main/resources/migrations/createPerson.sql new file mode 100644 index 0000000..5b36c48 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createPerson.sql @@ -0,0 +1,2 @@ +INSERT INTO persons(name, passport_id, color, location_x, location_y) +VALUES (?, ?, ?, ?, ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/createProduct.sql b/Lab.Server/src/main/resources/migrations/createProduct.sql new file mode 100644 index 0000000..b4181cd --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createProduct.sql @@ -0,0 +1,2 @@ +INSERT INTO products( name, coordinate_x, coordinate_y, creation_date, price, part_number, manufacture_cost, unit_of_measure, person) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/createProductOwners.sql b/Lab.Server/src/main/resources/migrations/createProductOwners.sql new file mode 100644 index 0000000..47b3ef6 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createProductOwners.sql @@ -0,0 +1 @@ +INSERT INTO products_owners(product, "user") VALUES (?, ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/createUser.sql b/Lab.Server/src/main/resources/migrations/createUser.sql new file mode 100644 index 0000000..19f7d28 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/createUser.sql @@ -0,0 +1,2 @@ +INSERT INTO users(login, password) +VALUES (?, ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/deleteLower.sql b/Lab.Server/src/main/resources/migrations/deleteLower.sql new file mode 100644 index 0000000..5e39090 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/deleteLower.sql @@ -0,0 +1,6 @@ +DELETE +FROM products +WHERE id IN (SELECT product + FROM products_owners + WHERE "user" = ? + AND id < ?); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/deleteProductById.sql b/Lab.Server/src/main/resources/migrations/deleteProductById.sql new file mode 100644 index 0000000..09204a3 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/deleteProductById.sql @@ -0,0 +1,2 @@ +DELETE FROM products_owners WHERE product = ?; +DELETE FROM products WHERE id = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/drop.sql b/Lab.Server/src/main/resources/migrations/drop.sql new file mode 100644 index 0000000..dac44bc --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/drop.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS coordinates CASCADE; +DROP TABLE IF EXISTS users CASCADE; +DROP TABLE IF EXISTS locations CASCADE; +DROP TABLE IF EXISTS db_info CASCADE; +DROP TABLE IF EXISTS persons CASCADE; +DROP TABLE IF EXISTS products_owners CASCADE; +DROP TABLE IF EXISTS products CASCADE; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/getProductByDto.sql b/Lab.Server/src/main/resources/migrations/getProductByDto.sql new file mode 100644 index 0000000..33b4a84 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/getProductByDto.sql @@ -0,0 +1,31 @@ +SELECT id, + products.name, + coordinate_x, + coordinate_y, + creation_date, + price, + part_number, + manufacture_cost, + unit_of_measure, + persons.name, + persons.passport_id, + persons.color, + locations.x, + locations.y, + locations.name +FROM products + LEFT JOIN persons ON person = persons.passport_id + LEFT JOIN locations on persons.location_x = locations.x and persons.location_y = locations.y +WHERE products.name = ? + AND coordinate_x = ? + AND coordinate_y = ? + AND price = ? + AND part_number = ? + AND manufacture_cost = ? + AND unit_of_measure = ? + AND persons.name = ? + AND persons.passport_id = ? + AND persons.color = ? + AND locations.x = ? + AND locations.y = ? + AND locations.name = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/getProductById.sql b/Lab.Server/src/main/resources/migrations/getProductById.sql new file mode 100644 index 0000000..acde603 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/getProductById.sql @@ -0,0 +1,19 @@ +SELECT id, + products.name, + coordinate_x, + coordinate_y, + creation_date, + price, + part_number, + manufacture_cost, + unit_of_measure, + persons.name, + persons.passport_id, + persons.color, + locations.x, + locations.y, + locations.name +FROM products + LEFT JOIN persons ON person = persons.passport_id + LEFT JOIN locations on persons.location_x = locations.x and persons.location_y = locations.y +WHERE id = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/getProducts.sql b/Lab.Server/src/main/resources/migrations/getProducts.sql new file mode 100644 index 0000000..682791f --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/getProducts.sql @@ -0,0 +1,18 @@ +SELECT id, + products.name, + coordinate_x, + coordinate_y, + creation_date, + price, + part_number, + manufacture_cost, + unit_of_measure, + persons.name, + persons.passport_id, + persons.color, + locations.x, + locations.y, + locations.name +FROM products + LEFT JOIN persons ON person = persons.passport_id + LEFT JOIN locations on persons.location_x = locations.x and persons.location_y = locations.y; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/hasUserAccess.sql b/Lab.Server/src/main/resources/migrations/hasUserAccess.sql new file mode 100644 index 0000000..118ad3d --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/hasUserAccess.sql @@ -0,0 +1,3 @@ +SELECT product, login, password FROM products_owners +LEFT JOIN users ON products_owners."user" = users.id +WHERE product = ? AND login = ? AND password = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/init.sql b/Lab.Server/src/main/resources/migrations/init.sql new file mode 100644 index 0000000..b480c66 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/init.sql @@ -0,0 +1,64 @@ +CREATE TABLE IF NOT EXISTS coordinates +( + x BIGINT NOT NULL, + y BIGINT NOT NULL, + PRIMARY KEY (x, y) +); + +CREATE TABLE IF NOT EXISTS locations +( + x float4 NOT NULL, + y INT NOT NULL, + name TEXT CHECK ( (length(name) > 0) or (name IS NULL) ), + PRIMARY KEY (x, y) +); + +CREATE TABLE IF NOT EXISTS persons +( + name TEXT NOT NULL, + passport_id TEXT PRIMARY KEY CHECK ( length(passport_id) BETWEEN 5 AND 22 ), + color INT, + location_x float4, + location_y INT, + FOREIGN KEY (location_x, location_y) REFERENCES locations (x, y) +); + +CREATE TABLE IF NOT EXISTS products +( + id SERIAL PRIMARY KEY, + name TEXT not null, + coordinate_x BIGINT NOT NULL, + coordinate_y BIGINT NOT NULL, + FOREIGN KEY (coordinate_x, coordinate_y) REFERENCES coordinates (x, y), + creation_date timestamptz not null, + price BIGINT NOT NULL CHECK ( price > 0 ), + part_number TEXT CHECK ( length(part_number) < 82 ) UNIQUE, + manufacture_cost BIGINT not null, + unit_of_measure int not null, + person TEXT REFERENCES persons (passport_id) NOT NULL +); + +CREATE TABLE IF NOT EXISTS users +( + id SERIAL PRIMARY KEY, + login TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + email TEXT +); + +CREATE TABLE IF NOT EXISTS products_owners +( + product SERIAL NOT NULL UNIQUE, + "user" SERIAL NOT NULL, + PRIMARY KEY (product, "user"), + FOREIGN KEY (product) REFERENCES products (id), + FOREIGN KEY ("user") REFERENCES users (id) +); + +CREATE TABLE IF NOT EXISTS db_info +( + migration_version serial PRIMARY KEY +); + +INSERT INTO db_info +VALUES (1); \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/isUserExists.sql b/Lab.Server/src/main/resources/migrations/isUserExists.sql new file mode 100644 index 0000000..37969bf --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/isUserExists.sql @@ -0,0 +1 @@ +SELECT id FROM users WHERE login = ? AND password = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/seed.sql b/Lab.Server/src/main/resources/migrations/seed.sql new file mode 100644 index 0000000..82c7485 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/seed.sql @@ -0,0 +1,36 @@ +INSERT INTO users(login, password) VALUES ('zinch', '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'); +INSERT INTO coordinates(x, y) VALUES (15, 15); +INSERT INTO locations(x, y, name) VALUES (16, 52, 'Танзания'); +INSERT INTO persons(name, passport_id, color, location_x, location_y) +VALUES ('Егор', '15к-337134', 1, 16, 52); +INSERT INTO products( name, coordinate_x, coordinate_y, creation_date, price, part_number, manufacture_cost, unit_of_measure, person) +VALUES ('Клубника', 15, 15, '2023-09-09', 1500, 'FUD1550', 570, 1, '15к-337134'); +INSERT INTO products_owners(product, "user") VALUES (1, 1); + +INSERT INTO users(login, password) VALUES ('anna', 'e99a18c428cb38d5f260853678922e03abd833d9d287c78c818b85321e19bfe7'); +INSERT INTO coordinates(x, y) VALUES (20, 35); +INSERT INTO locations(x, y, name) VALUES (20, 35, 'Индонезия'); +INSERT INTO persons(name, passport_id, color, location_x, location_y) +VALUES ('Анна', '30к-897234', 2, 20, 35); +INSERT INTO products(name, coordinate_x, coordinate_y, creation_date, price, part_number, manufacture_cost, unit_of_measure, person) +VALUES ('Манго', 20, 35, '2023-10-10', 2500, 'MNG2040', 850, 2, '30к-897234'); +INSERT INTO products_owners(product, "user") VALUES (2, 2); + + +INSERT INTO users(login, password) VALUES ('ivan', 'b6d767d2f8ed5d21a44b0e5886680cb9ec97e74ee3a8a85042bfc6fc78d51f6b'); +INSERT INTO coordinates(x, y) VALUES (45, 22); +INSERT INTO locations(x, y, name) VALUES (45, 22, 'Бразилия'); +INSERT INTO persons(name, passport_id, color, location_x, location_y) +VALUES ('Иван', '42к-569231', 1, 45, 22); +INSERT INTO products(name, coordinate_x, coordinate_y, creation_date, price, part_number, manufacture_cost, unit_of_measure, person) +VALUES ('Ананас', 45, 22, '2023-11-11', 3000, 'PNA4560', 1200, 0, '42к-569231'); +INSERT INTO products_owners(product, "user") VALUES (3, 3); + + +INSERT INTO coordinates(x, y) VALUES (30, 40); +INSERT INTO locations(x, y, name) VALUES (30, 40, 'Австралия'); +INSERT INTO persons(name, passport_id, color, location_x, location_y) +VALUES ('Ольга', '53к-128349', 0, 30, 40); +INSERT INTO products(name, coordinate_x, coordinate_y, creation_date, price, part_number, manufacture_cost, unit_of_measure, person) +VALUES ('Авокадо', 30, 40, '2023-12-12', 4000, 'AVO3000', 1500, 0, '53к-128349'); +INSERT INTO products_owners(product, "user") VALUES (4, 3); diff --git a/Lab.Server/src/main/resources/migrations/updateCoordinate.sql b/Lab.Server/src/main/resources/migrations/updateCoordinate.sql new file mode 100644 index 0000000..d5cdf81 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/updateCoordinate.sql @@ -0,0 +1,4 @@ +UPDATE coordinates +SET x = ?, + y = ? +WHERE x = ? AND y = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/updateLocation.sql b/Lab.Server/src/main/resources/migrations/updateLocation.sql new file mode 100644 index 0000000..937386e --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/updateLocation.sql @@ -0,0 +1,5 @@ +UPDATE locations +SET x = ?, + y = ?, + name = ? +WHERE x = ? AND y = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/updatePerson.sql b/Lab.Server/src/main/resources/migrations/updatePerson.sql new file mode 100644 index 0000000..c9a553d --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/updatePerson.sql @@ -0,0 +1,6 @@ +UPDATE persons +SET name = ?, + color = ?, + location_x = ?, + location_y = ? +WHERE passport_id = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/migrations/updateProduct.sql b/Lab.Server/src/main/resources/migrations/updateProduct.sql new file mode 100644 index 0000000..f94bd72 --- /dev/null +++ b/Lab.Server/src/main/resources/migrations/updateProduct.sql @@ -0,0 +1,10 @@ +UPDATE products +SET name = ?, + coordinate_x = ?, + coordinate_y = ?, + price = ?, + part_number = ?, + manufacture_cost = ?, + unit_of_measure = ?, + person = ? +WHERE id = ?; \ No newline at end of file diff --git a/Lab.Server/src/main/resources/server.properties b/Lab.Server/src/main/resources/server.properties new file mode 100644 index 0000000..5444900 --- /dev/null +++ b/Lab.Server/src/main/resources/server.properties @@ -0,0 +1,7 @@ +server-port=3000 +db-host=localhost +db-port=5432 +db-name=studs +db-scheme=s408657 +db-username=postgres +db-password=NHYOUX8VDGlSukoaX2ydo6rHrYYILZSZ diff --git a/README.md b/README.md index 7012984..8669dcf 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,86 @@ -# Лабораторная работа №6 +# Лабораторная работа №7 ## Выполнил > ФИ: Зинченко Иван > > ИСУ: 408657 > -> Вариант: 21290 \ No newline at end of file +> Вариант: 21210 + +Доработать программу из лабораторной работы №6 следующим образом: + +- Организовать хранение коллекции в реляционной СУБД (PostgresQL). Убрать хранение коллекции в файле. +- Для генерации поля id использовать средства базы данных (sequence). +- Обновлять состояние коллекции в памяти только при успешном добавлении объекта в БД +- Все команды получения данных должны работать с коллекцией в памяти, а не в БД +- Организовать возможность регистрации и авторизации пользователей. У пользователя есть возможность указать пароль. +- Пароли при хранении хэшировать алгоритмом SHA-256 +- Запретить выполнение команд не авторизованным пользователям. +- При хранении объектов сохранять информацию о пользователе, который создал этот объект. +- Пользователи должны иметь возможность просмотра всех объектов коллекции, но модифицировать могут только принадлежащие им. +- Для идентификации пользователя отправлять логин и пароль с каждым запросом. + +Необходимо реализовать многопоточную обработку запросов. + +- Для многопоточного чтения запросов использовать `Cached thread pool` +- Для многопоточной обработки полученного запроса использовать `Cached thread pool` +- Для многопоточной отправки ответа использовать `Fixed thread pool` +- Для синхронизации доступа к коллекции использовать синхронизацию чтения и записи с помощью `java.util.concurrent.locks.ReentrantLock` + +## Реализация + +### БД +```mermaid +erDiagram + users { + serial id PK + text login + text password "sha256" + } + + products { + serial id PK + text name + coorinates coorinates FK + DateTime creation_date + long price + text part_number + long manufacture_cost + int unit_of_measure + persons person FK + } + + coordinates { + int x PK + int y PK + } + + persons { + text name + text passport_id PK + int color + locations location FK + } + + locations { + int x PK + int y PK + text name + } + + products }|--|| coordinates : "" + products }|--|| persons : "" + persons }|--|| locations : "" + + products_owners { + products product PK,FK + users owner PK,FK + } + + products_owners ||--|| products : "" + products_owners }|--|| users : "" + + db_info { + int migration_version PK + } +``` \ No newline at end of file diff --git a/Server.jpg b/Server.jpg deleted file mode 100644 index 120d8dd..0000000 Binary files a/Server.jpg and /dev/null differ