diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cf4617 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.iml +*.xml diff --git a/Shell/src/CdCommand.java b/Shell/src/CdCommand.java new file mode 100644 index 0000000..a0295ea --- /dev/null +++ b/Shell/src/CdCommand.java @@ -0,0 +1,38 @@ +import java.io.File; +import java.util.Arrays; + +public class CdCommand implements Command { + + private File curDirectory; + private String path; + + CdCommand(File directory, String path) { + curDirectory = directory; + this.path = path; + } + + @Override + public File execute() throws WrongCommand { + if (path.equals("..")) { + return new File(curDirectory.getParent()); + } else { + for (String name : Arrays.asList(curDirectory.list())) { + if (path.equals(name) && new File(curDirectory + File.separator + name).isDirectory()) { + return new File(curDirectory.toString() + File.separator + name); + } + } + throw new WrongCommand("No directory named " + path); + } + } + + @Override + public File cancel() { + return curDirectory; + } + + @Override + public String name() { + return "cd"; + } + +} diff --git a/Shell/src/Command.java b/Shell/src/Command.java new file mode 100644 index 0000000..ecc28a7 --- /dev/null +++ b/Shell/src/Command.java @@ -0,0 +1,7 @@ +import java.io.File; + +public interface Command { + File execute() throws WrongCommand, SessionClosed; + File cancel() throws WrongCommand; + String name(); +} diff --git a/Shell/src/CommandManager.java b/Shell/src/CommandManager.java new file mode 100644 index 0000000..a7cdcc4 --- /dev/null +++ b/Shell/src/CommandManager.java @@ -0,0 +1,83 @@ +import java.io.File; +import java.util.*; +import java.util.stream.Collectors; + +public class CommandManager { + + private LinkedList HISTORY; + private LinkedList TRASH; + private File curDirectory; + + private CommandManager(String home) throws WrongCommand { + HISTORY = new LinkedList<>(); + TRASH = new LinkedList<>(); + File homeDirectory = new File(home); + if ((!homeDirectory.exists()) || (homeDirectory.isFile())) { + throw new WrongCommand("Incorrect home directory"); + } + curDirectory = homeDirectory; + } + + private Command getCommand(String command) throws WrongCommand { + List parseCommand = Arrays.stream(command.split(" ")) + .filter((w) -> w.length() > 0) + .collect(Collectors.toList()); + switch (parseCommand.get(0)) { + case "cd": + return new CdCommand(curDirectory, parseCommand.get(1)); + case "cp": + return new CpCommand(curDirectory, parseCommand.get(1), parseCommand.get(2)); + case "mv": + return new MvCommand(curDirectory, parseCommand.get(1), parseCommand.get(2)); + case "mkdir": + return new MkdirCommand(curDirectory, parseCommand.get(1)); + case "redo": + return new RedoCommand(curDirectory, TRASH.removeLast(), HISTORY); + case "undo": + return new UndoCommand(curDirectory, HISTORY.removeLast(), TRASH); + case "history": + return new HistoryCommand(curDirectory, HISTORY); + case "exit": + return new ExitCommand(curDirectory); + default: + throw new WrongCommand("Wrong command"); + } + } + + private void doSession() throws SessionClosed, WrongCommand { + Scanner scanner = new Scanner(System.in); + System.out.println(curDirectory + "$"); + while (true) { + String curCommandName = scanner.nextLine(); + try { + Command curCommand = getCommand(curCommandName); + curDirectory = curCommand.execute(); + if (!curCommand.getClass().equals(RedoCommand.class) && + !curCommand.getClass().equals(UndoCommand.class) && + !curCommand.getClass().equals(HistoryCommand.class) && + !curCommand.getClass().equals(ExitCommand.class)) { + HISTORY.add(curCommand); + } + System.out.println(curDirectory); + } catch (WrongCommand e) { + System.out.println(e.getMessage()); + System.out.println(curDirectory); + } catch (SessionClosed e) { + System.out.println(e.getMessage()); + break; + } + } + } + + public static void main(String... args) { + + CommandManager manager; + try { + manager = new CommandManager(System.getProperty("user.dir")); + manager.doSession(); + } catch (WrongCommand | SessionClosed e) { + System.out.println(e.getMessage()); + } + } + +} diff --git a/Shell/src/CpCommand.java b/Shell/src/CpCommand.java new file mode 100644 index 0000000..983a336 --- /dev/null +++ b/Shell/src/CpCommand.java @@ -0,0 +1,77 @@ +import java.io.File; +import java.io.IOException; + +public class CpCommand implements Command { + + private File curDirectory; + private String destination; + private String source; + private boolean alreadyExist; + + CpCommand(File directory, String destination, String source) { + curDirectory = directory; + this.destination = destination; + this.source = source; + alreadyExist = false; + } + + @Override + public File execute() throws WrongCommand { + File folder = new File(destination); + //folder is absolute path + if (!folder.exists()) { + throw new WrongCommand("Directory does not exist"); + } + if (folder.isFile()) { + throw new WrongCommand("Destination is not a directory"); + } + + //source is absolute path + File file = new File(source); + try { + if (file.isDirectory() && file.list().length > 0) { + throw new WrongCommand("Folder is a non-empty directory."); + } + } catch (NullPointerException e) { + //do nothing + } + + File newFile = new File(destination + File.separator + file.getName()); + if (file.isFile()) { + try { + if (newFile.createNewFile()) { + System.out.println("File " + file.getName() + " copied"); + } else { + System.out.println("File already exist"); + alreadyExist = true; + } + } catch (IOException e) { + e.printStackTrace(); + } + } else if (file.isDirectory()) { + if (newFile.mkdir()) { + System.out.println("Directory " + file.getName() + " copied"); + } else { + System.out.println("Directory already exist"); + alreadyExist = true; + } + } + return curDirectory; + } + + @Override + public File cancel() throws WrongCommand { + File newFile = new File(destination + File.separator + new File(source).getName()); + if (!alreadyExist) { + newFile.delete(); + System.out.println("File " + newFile.getName() + " has been deleted."); + } + return curDirectory; + } + + @Override + public String name() { + return "cp"; + } + +} diff --git a/Shell/src/ExitCommand.java b/Shell/src/ExitCommand.java new file mode 100644 index 0000000..3528d43 --- /dev/null +++ b/Shell/src/ExitCommand.java @@ -0,0 +1,27 @@ +import java.io.File; + +public class ExitCommand implements Command { + + private File curDirectory; + + ExitCommand(File directory) { + curDirectory = directory; + } + + @Override + public File execute() throws SessionClosed { + throw new SessionClosed("Session Closed"); + } + + @Override + public File cancel() { + return curDirectory; + //do nothing + } + + @Override + public String name() { + return "exit"; + } + +} diff --git a/Shell/src/HistoryCommand.java b/Shell/src/HistoryCommand.java new file mode 100644 index 0000000..cf72865 --- /dev/null +++ b/Shell/src/HistoryCommand.java @@ -0,0 +1,36 @@ +import java.io.File; +import java.util.LinkedList; + +public class HistoryCommand implements Command { + + private File curDirectory; + private LinkedList history; + + HistoryCommand(File curDirectory, LinkedList history) { + this.curDirectory = curDirectory; + this.history = history; + } + + @Override + public File execute() { + System.out.println("HISTORY OF COMMANDS:"); + int counter = 0; + for (Command command : history) { + ++counter; + System.out.println(counter + " " + command.name()); + } + return curDirectory; + } + + @Override + public File cancel() { + return curDirectory; + //do nothing + } + + @Override + public String name() { + return "undo"; + } + +} diff --git a/Shell/src/MkdirCommand.java b/Shell/src/MkdirCommand.java new file mode 100644 index 0000000..0aa0d79 --- /dev/null +++ b/Shell/src/MkdirCommand.java @@ -0,0 +1,39 @@ +import java.io.File; + +public class MkdirCommand implements Command { + + private File curDirectory; + private String nameOfNewDirectory; + private boolean alreadyExist; + + MkdirCommand(File directory, String name) { + curDirectory = directory; + nameOfNewDirectory = name; + alreadyExist = false; + } + + @Override + public File execute() throws WrongCommand { + File file = new File(curDirectory.toString() + File.separator + nameOfNewDirectory); + alreadyExist = !file.mkdir(); + if (alreadyExist) { + System.out.println("Directory already exists. Nothing to be done."); + } + return curDirectory; + } + + @Override + public File cancel() { + if (!alreadyExist) { + File file = new File(curDirectory.toString() + File.separator + nameOfNewDirectory); + file.delete(); + } + return curDirectory; + } + + @Override + public String name() { + return "mkdir"; + } + +} diff --git a/Shell/src/MvCommand.java b/Shell/src/MvCommand.java new file mode 100644 index 0000000..5e1fc2a --- /dev/null +++ b/Shell/src/MvCommand.java @@ -0,0 +1,50 @@ +import java.io.File; +import java.io.IOException; + +public class MvCommand implements Command { + + private File curDirectory; + private String source; + private CpCommand copying; + + MvCommand(File directory, String destination, String source) { + curDirectory = directory; + this.source = source; + copying = new CpCommand(curDirectory, destination, source); + } + + @Override + public File execute() throws WrongCommand { + try { + copying.execute(); + new File(source).delete(); + System.out.println("Original source has been deleted."); + } catch (WrongCommand e) { + System.out.println(e.getMessage()); + } + return curDirectory; + } + + @Override + public File cancel() throws WrongCommand { + copying.cancel(); + File file = new File(source); + if (file.isDirectory()) { + file.mkdir(); + } else { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + System.out.println(file.getName() + " file has been recovered."); + return curDirectory; + } + + @Override + public String name() { + return "mv"; + } + +} diff --git a/Shell/src/RedoCommand.java b/Shell/src/RedoCommand.java new file mode 100644 index 0000000..d538ba6 --- /dev/null +++ b/Shell/src/RedoCommand.java @@ -0,0 +1,33 @@ +import java.io.File; +import java.util.LinkedList; + +public class RedoCommand implements Command { + + private File curDirectory; + private Command prevCommand; + private LinkedList history; + + RedoCommand(File directory, Command command, LinkedList commands) { + curDirectory = directory; + prevCommand = command; + history = commands; + } + + @Override + public File execute() throws WrongCommand, SessionClosed { + history.add(prevCommand); + return prevCommand.execute(); + } + + @Override + public File cancel() { + //do nothing + return curDirectory; + } + + @Override + public String name() { + return "redo"; + } + +} diff --git a/Shell/src/SessionClosed.java b/Shell/src/SessionClosed.java new file mode 100644 index 0000000..dda69c9 --- /dev/null +++ b/Shell/src/SessionClosed.java @@ -0,0 +1,5 @@ +class SessionClosed extends Exception { + SessionClosed(String message) { + super(message); + } +} diff --git a/Shell/src/UndoCommand.java b/Shell/src/UndoCommand.java new file mode 100644 index 0000000..9c17898 --- /dev/null +++ b/Shell/src/UndoCommand.java @@ -0,0 +1,33 @@ +import java.io.File; +import java.util.LinkedList; + +public class UndoCommand implements Command { + + private File curDirectory; + private Command prevCommand; + private LinkedList trash; + + UndoCommand(File directory, Command command, LinkedList commands) { + curDirectory = directory; + prevCommand = command; + trash = commands; + } + + @Override + public File execute() throws WrongCommand { + trash.add(prevCommand); + return prevCommand.cancel(); + } + + @Override + public File cancel() { + //do nothing + return curDirectory; + } + + @Override + public String name() { + return "undo"; + } + +} diff --git a/Shell/src/WrongCommand.java b/Shell/src/WrongCommand.java new file mode 100644 index 0000000..33131a4 --- /dev/null +++ b/Shell/src/WrongCommand.java @@ -0,0 +1,5 @@ +class WrongCommand extends Exception { + WrongCommand(String message) { + super(message); + } +}