├── .idea
├── .name
├── .gitignore
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── vcs.xml
├── compiler.xml
├── misc.xml
├── gradle.xml
├── runConfigurations
│ └── JunitTests.xml
├── jarRepositories.xml
└── uiDesigner.xml
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── crcCards
├── Constants.txt
├── Find.txt
├── PathHandler.txt
├── Tree.txt
├── Exit.txt
├── History.txt
├── Man.txt
├── CommandExecutor.txt
├── GetURL.txt
├── JShellState.txt
├── Mv.txt
├── Redirection
├── cp.txt
├── CommandDecorator
├── CommandReader.txt
├── Ls.txt
├── Pwd.txt
├── JShell.txt
├── File.txt
├── Mkdir.txt
├── FileSystemObject.txt
├── Cat.txt
├── RecursiveDecorator.txt
├── Cd.txt
├── Pushd.txt
├── Directory.txt
├── Popd.txt
├── Echo.txt
├── Command.txt
└── readMeForCrcCards.txt
├── src
├── main
│ └── java
│ │ ├── constants
│ │ ├── CommandException.java
│ │ ├── Exceptions.java
│ │ └── Constants.java
│ │ ├── commands
│ │ ├── RecursiveInterface.java
│ │ ├── Exit.java
│ │ ├── Echo.java
│ │ ├── Pwd.java
│ │ ├── Tree.java
│ │ ├── Mv.java
│ │ ├── Cd.java
│ │ ├── Cp.java
│ │ ├── Pushd.java
│ │ ├── Command.java
│ │ ├── Popd.java
│ │ ├── Man.java
│ │ ├── Cat.java
│ │ ├── Save.java
│ │ ├── History.java
│ │ ├── Get.java
│ │ ├── Mkdir.java
│ │ ├── Find.java
│ │ ├── Load.java
│ │ ├── CommandController.java
│ │ ├── CommandReader.java
│ │ └── Ls.java
│ │ ├── command_decorators
│ │ ├── CommandDecorator.java
│ │ ├── RecursiveDecorator.java
│ │ └── Redirection.java
│ │ ├── helper_classes
│ │ ├── CmdArgTuple.java
│ │ ├── DirectoryFileNameTuple.java
│ │ ├── StringHelper.java
│ │ └── PathHandler.java
│ │ ├── driver
│ │ ├── IShellState.java
│ │ ├── JShell.java
│ │ └── JShellState.java
│ │ └── file_system
│ │ ├── File.java
│ │ ├── FileSystemObject.java
│ │ ├── VirtualFileSystem.java
│ │ └── Directory.java
└── test
│ └── java
│ └── commands
│ └── MkdirTest.java
├── README.md
├── LICENSE
├── gradlew.bat
└── gradlew
/.idea/.name:
--------------------------------------------------------------------------------
1 | JavaShell
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'JavaShell'
2 |
3 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSC207-UofT/Java-Shell/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/crcCards/Constants.txt:
--------------------------------------------------------------------------------
1 | Class name: Constants
2 |
3 | Responsibilities:
4 | * Holds program constants
5 |
6 | Collaborators:
7 |
--------------------------------------------------------------------------------
/crcCards/Find.txt:
--------------------------------------------------------------------------------
1 | Class name: find
2 |
3 | Responsibilities:
4 | * Finds a specific file or directory
5 |
6 | Collaborators:
7 | * JShell
8 |
--------------------------------------------------------------------------------
/crcCards/PathHandler.txt:
--------------------------------------------------------------------------------
1 | Class name: PathHandler
2 |
3 | Responsibilities:
4 | * Handles path input
5 |
6 | Collaborators:
7 | * FileSystemObject
8 |
--------------------------------------------------------------------------------
/crcCards/Tree.txt:
--------------------------------------------------------------------------------
1 | Class name: tree
2 |
3 | Responsibilities:
4 | * Displays the entire filesystem as a tree
5 |
6 | Collaborators:
7 | * JShell
8 |
--------------------------------------------------------------------------------
/crcCards/Exit.txt:
--------------------------------------------------------------------------------
1 | Class name: Exit
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Quit the program
6 |
7 | Collaborators:
8 | * JShellState
9 |
--------------------------------------------------------------------------------
/crcCards/History.txt:
--------------------------------------------------------------------------------
1 | Class name: History
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Show recent commands
6 |
7 | Collaborators:
8 | * JShellState
9 |
--------------------------------------------------------------------------------
/crcCards/Man.txt:
--------------------------------------------------------------------------------
1 | Class name: Man
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Display documentations of the command
6 |
7 | Collaborators:
8 | * Command
9 |
--------------------------------------------------------------------------------
/crcCards/CommandExecutor.txt:
--------------------------------------------------------------------------------
1 | Class name: CommandExecutor
2 |
3 | Responsibilities:
4 | * Executes the command line
5 |
6 | Collaborators:
7 | * CommandReader
8 | * Command
9 |
--------------------------------------------------------------------------------
/crcCards/GetURL.txt:
--------------------------------------------------------------------------------
1 | Class name: getURL
2 |
3 | Responsibilities:
4 | * Retrieve file from URL and add to the current working directory
5 |
6 | Collaborators:
7 | * JShell
8 |
--------------------------------------------------------------------------------
/crcCards/JShellState.txt:
--------------------------------------------------------------------------------
1 | Class name: JShellState
2 |
3 | Responsibilities:
4 | * Hold state of JShell program
5 |
6 | Collaborators:
7 | * Directory
8 | * DirectoryStack
9 |
--------------------------------------------------------------------------------
/crcCards/Mv.txt:
--------------------------------------------------------------------------------
1 | Class name: mv
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Move the contents from a old path to a new path
6 |
7 | Collaborators:
8 | * JShell
9 | * rec
10 |
--------------------------------------------------------------------------------
/crcCards/Redirection:
--------------------------------------------------------------------------------
1 | Class name: Redirection
2 | Sub-classes: CommandDecorator
3 |
4 | Responsibilities:
5 | * Decorates command to redirect output into a file
6 |
7 | Collaborators:
8 | * Command
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/crcCards/cp.txt:
--------------------------------------------------------------------------------
1 | Class name: cp
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Copies all the items from old path to a new path
6 |
7 | Collaborators:
8 | * JShell
9 | * rec
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/crcCards/CommandDecorator:
--------------------------------------------------------------------------------
1 | Class name: CommandDecorator
2 | Sub-classes: Redirection, RecursiveDecorator
3 |
4 | Responsibilities:
5 | * Decorates command appropriately
6 |
7 | Collaborators:
8 | * Command
--------------------------------------------------------------------------------
/crcCards/CommandReader.txt:
--------------------------------------------------------------------------------
1 | Class name: CommandReader
2 |
3 | Responsibilities:
4 | * Read input line, separate arguments
5 | * Raise exception if invalid arguments are provided
6 |
7 | Collaborators:
8 |
--------------------------------------------------------------------------------
/crcCards/Ls.txt:
--------------------------------------------------------------------------------
1 | Class name: Ls
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Display all files and directories(in current directory) in the shell
6 |
7 | Collaborators:
8 | * FileSystemObject
9 |
--------------------------------------------------------------------------------
/crcCards/Pwd.txt:
--------------------------------------------------------------------------------
1 | Class name: Pwd
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Display the path of the current working directory
6 |
7 | Collaborators:
8 | * JShellState
9 | * Directory
10 |
--------------------------------------------------------------------------------
/src/main/java/constants/CommandException.java:
--------------------------------------------------------------------------------
1 | package constants;
2 |
3 | public class CommandException extends Exception {
4 | public CommandException(String msg) {
5 | super(msg);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/crcCards/JShell.txt:
--------------------------------------------------------------------------------
1 | Class name: JShell
2 |
3 | Responsibilities:
4 | * Run and terminate the program
5 | * Provide access to other classes
6 |
7 | Collaborators:
8 | * JShellState
9 | * CommandExecutor
10 |
--------------------------------------------------------------------------------
/crcCards/File.txt:
--------------------------------------------------------------------------------
1 | Class name: File
2 | Parent class: FileSystemObject
3 |
4 | Responsibilities:
5 | * Contain data, information
6 | * Can be opened, read, edited, deleted
7 |
8 | Collaborators:
9 | * Directory
10 |
--------------------------------------------------------------------------------
/crcCards/Mkdir.txt:
--------------------------------------------------------------------------------
1 | Class name: Mkdir
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Create a new directory relative to the current directory or its full path
6 |
7 | Collaborators:
8 | * Directory
9 |
10 |
--------------------------------------------------------------------------------
/crcCards/FileSystemObject.txt:
--------------------------------------------------------------------------------
1 | Class name: FileSystemObject
2 | Subclasses: Directory, File
3 |
4 | Responsibilities:
5 | * Is a file system object such as directory or file
6 | * Can be renamed, moved
7 |
8 | Collaborators:
9 |
--------------------------------------------------------------------------------
/crcCards/Cat.txt:
--------------------------------------------------------------------------------
1 | Class name: Cat
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Display the contents of a file and multiple files
6 | * Raise exception is file doesn't exist
7 |
8 | Collaborators:
9 | * File
10 |
--------------------------------------------------------------------------------
/crcCards/RecursiveDecorator.txt:
--------------------------------------------------------------------------------
1 | Class name: RecursiveDecorator
2 | Sub-classes: CommandDecorator
3 |
4 | Responsibilities:
5 | * Decorates command to be able to execute recursive calls appropriately
6 |
7 | Collaborators:
8 | * Command
--------------------------------------------------------------------------------
/crcCards/Cd.txt:
--------------------------------------------------------------------------------
1 | Class name: Cd
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Change current directory of the JShell
6 | * Raise exception if directory doesn't exist
7 |
8 | Collaborators:
9 | * JShellState
10 | * Directory
11 |
--------------------------------------------------------------------------------
/crcCards/Pushd.txt:
--------------------------------------------------------------------------------
1 | Class name: Pushd
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Save the current directory by pushing it into the directory stack
6 |
7 | Collaborators:
8 | * JShellState
9 | * DirectoryStack
10 | * Directory
11 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/crcCards/Directory.txt:
--------------------------------------------------------------------------------
1 | Class name: Directory
2 | Parent class: FileSystemObject
3 |
4 | Responsibilities:
5 | * Store file system objects
6 | * Show path to itself
7 | * Show file system object inside itself
8 |
9 | Collaborators:
10 | * FileSystemObject
11 |
--------------------------------------------------------------------------------
/crcCards/Popd.txt:
--------------------------------------------------------------------------------
1 | Class name: Popd
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Change the current directory in the program to the directory at the top of the directory stack
6 |
7 | Collaborators:
8 | * JShellState
9 | * DirectoryStack
10 | * Directory
11 |
--------------------------------------------------------------------------------
/crcCards/Echo.txt:
--------------------------------------------------------------------------------
1 | Class name: Echo
2 | Parent class: Command
3 |
4 | Responsibilities:
5 | * Replace the content of a given file (contains only string) with string
6 | * Create a new file that contains the string
7 | * Append a string to a file
8 |
9 | Collaborators:
10 | *File
11 |
--------------------------------------------------------------------------------
/crcCards/Command.txt:
--------------------------------------------------------------------------------
1 | Class name: Command
2 | Parent class: None
3 | Subclasses: Cat, Cd, Cp, Echo, Exit, GetURL, Ls, Mkdir, Mv, Pwd
4 |
5 | Responsibilities:
6 | * Execute a valid command
7 | * Raise exception if command is invalid
8 |
9 | Collaborators:
10 | * Shell
11 | * Exception
12 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/java/commands/RecursiveInterface.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 |
7 | /**
8 | * Interface for commands that can be executed recursively (have -R as an
9 | * optional parameter)
10 | */
11 | public interface RecursiveInterface {
12 | String executeRecursively
13 | (IShellState shellState, List arguments);
14 | }
15 |
--------------------------------------------------------------------------------
/crcCards/readMeForCrcCards.txt:
--------------------------------------------------------------------------------
1 | --All your crc cards will reside in here.
2 |
3 | --Your code structure MUST always reflect the design outlined in CRC Cards.
4 |
5 | --If at any point you change or modify your design:
6 | ----a) Change your CRC Cards to reflect the new design.
7 | ----b) Change your code sturcture so that it reflects the new design.
8 |
9 | --Follow the same format as in Assignment1 for crc cards.
10 |
--------------------------------------------------------------------------------
/src/main/java/command_decorators/CommandDecorator.java:
--------------------------------------------------------------------------------
1 | package command_decorators;
2 |
3 | import commands.Command;
4 |
5 |
6 | // This is a builder!
7 | /**
8 | * This is an abstract class that is a base for all decorators of the command
9 | */
10 | public abstract class CommandDecorator extends Command {
11 | final Command command;
12 |
13 | public CommandDecorator(Command command) {
14 | super(command.getMaxArg(), command.getMinArg());
15 | this.command = command;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/JunitTests.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/commands/Exit.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 |
7 | /**
8 | * This class is responsible for letting user to exit the program
9 | */
10 | public class Exit extends Command {
11 |
12 | public Exit() {
13 | super(0, 0);
14 | }
15 |
16 | /**
17 | * Stop the JShell program by changing its state
18 | * @param shellState is the object that holds JShell's state
19 | * @throws Exception if number of arguments provided is incorrect
20 | */
21 | public String executeCommand
22 | (IShellState shellState, List arguments) throws Exception{
23 | checkArgumentsNum(arguments);
24 | shellState.stopRunning();
25 | return "";
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/commands/Echo.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 |
7 | /**
8 | * This class reads the provided STRING argument
9 | */
10 | public class Echo extends Command {
11 |
12 | public Echo() {
13 | super(1, 1);
14 | }
15 |
16 | /**
17 | * Returns provided STRING argument.
18 | * @param shellState is the state of the program
19 | * @param arguments is list of arguments that were passed along with command
20 | * @throws Exception number of arguments provided is incorrect
21 | */
22 | public String executeCommand(IShellState shellState, List arguments)
23 | throws Exception {
24 | checkArgumentsNum(arguments);
25 | return arguments.get(0);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/helper_classes/CmdArgTuple.java:
--------------------------------------------------------------------------------
1 | package helper_classes;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * This is a class that mimics a tuple in python
7 | */
8 | public class CmdArgTuple {
9 | private final String command;
10 | private final List arguments;
11 |
12 | /**
13 | * Constructor for the tuple
14 | */
15 | public CmdArgTuple(String command, List arguments) {
16 | this.command = command;
17 | this.arguments = arguments;
18 | }
19 |
20 | /**
21 | * Return first object
22 | */
23 | public String getCommand() {
24 | return this.command;
25 | }
26 |
27 | /**
28 | * Return second object
29 | */
30 | public List getArguments() {
31 | return this.arguments;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/commands/Pwd.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 |
7 | /**
8 | * Display path of current directory in the program
9 | */
10 | public class Pwd extends Command {
11 |
12 | public Pwd() {
13 | super(0, 0);
14 | }
15 |
16 | /**
17 | * Print the current working directory (including the whole path).
18 | * @param shellState is the state of JShell program
19 | * @param arguments is list of arguments that were passed along with command
20 | * (includes the path of directory to be switched to)
21 | */
22 | public String executeCommand
23 | (IShellState shellState, List arguments) throws Exception{
24 | checkArgumentsNum(arguments);
25 | return shellState.getCurrentDir().getPath();
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/driver/IShellState.java:
--------------------------------------------------------------------------------
1 | package driver;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 | import java.util.Stack;
6 |
7 | import file_system.Directory;
8 | import file_system.VirtualFileSystem;
9 |
10 | public interface IShellState extends Serializable {
11 | boolean isRunning();
12 |
13 | void stopRunning();
14 |
15 | VirtualFileSystem getFileSystem();
16 |
17 | Directory getRootDir();
18 |
19 | Directory getCurrentDir();
20 |
21 | void setCurrentDir(Directory newCurrentDir);
22 |
23 | void addHistory(String inputLine);
24 |
25 | void removeHistory(int index);
26 |
27 | List getHistory();
28 |
29 | void addCorrectHistory(String inputLine);
30 |
31 | List getCorrectHistory();
32 |
33 | Stack getDirectoryStack();
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/helper_classes/DirectoryFileNameTuple.java:
--------------------------------------------------------------------------------
1 | package helper_classes;
2 |
3 | import file_system.Directory;
4 |
5 | /**
6 | * This is a class that mimics a tuple in python
7 | */
8 | public class DirectoryFileNameTuple {
9 | private final Directory directory;
10 | private final String fileName;
11 |
12 | /**
13 | * Constructor for a tuple
14 | */
15 | public DirectoryFileNameTuple(Directory directory, String fileName) {
16 | this.directory = directory;
17 | this.fileName = fileName;
18 | }
19 |
20 | /**
21 | * Return first object
22 | */
23 | public Directory getDirectory() {
24 | return this.directory;
25 | }
26 |
27 | /**
28 | * Return second object
29 | */
30 | public String getFileName() {
31 | return this.fileName;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/commands/Tree.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.VirtualFileSystem;
7 |
8 | /**
9 | * Display the entire file system as a tree
10 | */
11 | public class Tree extends Command {
12 |
13 | public Tree() {
14 | super(0, 0);
15 | }
16 |
17 | /**
18 | * Displays the entire file system as a tree
19 | * @param shellState the state of JShell program
20 | * @param arguments list of arguments that were passed along with command
21 | * @return Representation of the entire file system as a tree
22 | */
23 | @Override
24 | public String executeCommand(IShellState shellState, List arguments)
25 | throws Exception {
26 | checkArgumentsNum(arguments);
27 | VirtualFileSystem fs = shellState.getFileSystem();
28 | return fs.getTreeRepresentation();
29 | }
30 |
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java-Shell
2 |
3 | ## System Requirements
4 | Java (1.7 or later)
5 |
6 | ## Using the program
7 |
8 | ### Compiling
9 | * Open a terminal. (It's in the row of tabs at the bottom of this window.)
10 | * Copy and paste these two commands:
11 | ```
12 | cd src/main/java # This opens the src/main/java folder
13 | javac driver/*.java # This compiles the whole program.
14 | ```
15 |
16 | ### Starting the Program
17 | * Run the program:
18 | ```
19 | $ java driver/JShell
20 | ```
21 |
22 | ## Commands
23 | List of commands available
24 | * !
25 | * cat
26 | * cd
27 | * cp
28 | * echo
29 | * exit
30 | * find
31 | * get
32 | * history
33 | * load
34 | * ls
35 | * man
36 | * mkdir
37 | * mv
38 | * popd
39 | * pushd
40 | * pwd
41 |
42 | ## Example using the commands
43 |
44 | To read the documentation of a specific command
45 | ```
46 | $ man [command]
47 | #example:
48 | $ man ls
49 | ```
50 |
51 | To write to a file using echo:
52 | ```
53 | $ echo "hello world" > file1
54 | ```
55 |
56 | To append to a existing file:
57 | To write to a file using echo:
58 | ```
59 | $ echo "good bye" >> file1
60 | ```
61 |
--------------------------------------------------------------------------------
/src/main/java/commands/Mv.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.VirtualFileSystem;
7 |
8 | /**
9 | * Moves a file or directory from one path to another
10 | */
11 | public class Mv extends Command {
12 |
13 | public Mv() {
14 | super(2, 2);
15 | }
16 |
17 | /**
18 | * Moves a file or directory at one path to another path, possibly
19 | * overwritting a file or directory.
20 | * @param shellState is the state of the program
21 | * @param arguments is list of provided arguments
22 | * @throws Exception if given paths are invalid
23 | */
24 | @Override
25 | public String executeCommand(IShellState shellState, List arguments)
26 | throws Exception {
27 | checkArgumentsNum(arguments);
28 | VirtualFileSystem fs = shellState.getFileSystem();
29 | String oldPath = arguments.get(0);
30 | String newPath = arguments.get(1);
31 | fs.moveFsObject(shellState.getCurrentDir(), oldPath, newPath);
32 | return "";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/commands/Cd.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.Directory;
7 | import helper_classes.PathHandler;
8 |
9 | /**
10 | * This class allows user to move between directories
11 | */
12 | public class Cd extends Command {
13 |
14 | public Cd() {
15 | super(1, 1);
16 | }
17 |
18 | /**
19 | * Switches the current directory that JShell program is in to the one
20 | * defined by given path
21 | *
22 | * @param shellState is the state of JShell program
23 | * @param arguments is list of arguments that were passed along with command
24 | * (includes the path of directory to be switched to)
25 | */
26 | public String executeCommand(IShellState shellState, List arguments)
27 | throws Exception {
28 | checkArgumentsNum(arguments);
29 | String path = arguments.get(0);
30 | Directory target = PathHandler.getDirectoryByPath(shellState, path);
31 | shellState.setCurrentDir(target);
32 | return "";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/commands/Cp.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.VirtualFileSystem;
7 |
8 | /**
9 | * This class copies a file or directory from one place to another
10 | */
11 | public class Cp extends Command {
12 |
13 | public Cp() {
14 | super(2, 2);
15 | }
16 |
17 | /**
18 | * Copies a file or directory at one path to another path, possibly
19 | * overwritting a file or directory.
20 | * @param shellState is the state of the program
21 | * @param arguments is list of provided arguments
22 | * @throws Exception if given paths are invalid
23 | */
24 | @Override
25 | public String executeCommand(IShellState shellState, List arguments)
26 | throws Exception {
27 | checkArgumentsNum(arguments);
28 | VirtualFileSystem fs = shellState.getFileSystem();
29 | String oldPath = arguments.get(0);
30 | String newPath = arguments.get(1);
31 | fs.copyFsObject(shellState.getCurrentDir(), oldPath, newPath);
32 | return "";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Minh Hoang Nguyen and Nhi Nguyen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/commands/Pushd.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.Directory;
7 |
8 | public class Pushd extends Command {
9 |
10 | /**
11 | * Pushd class save the current working directory
12 | * to directory stack and switch to given dir
13 | *
14 | */
15 | public Pushd() {
16 | super(1, 1);
17 | }
18 |
19 | /**
20 | * Saves the current working directory to directory stack
21 | * and then changes the new current working directory to given directory
22 | * @param shellState is the state of JShell program
23 | * @param arguments is list of arguments that were passed along with command
24 | * (includes the path of directory to be switched to)
25 | */
26 | public String executeCommand(IShellState shellState, List arguments)
27 | throws Exception {
28 | checkArgumentsNum(arguments);
29 | Directory currentDir = shellState.getCurrentDir();
30 | Cd cd = new Cd();
31 | cd.executeCommand(shellState, arguments);
32 | shellState.getDirectoryStack().push(currentDir);
33 | return "";
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/src/main/java/driver/JShell.java:
--------------------------------------------------------------------------------
1 | package driver;
2 |
3 | import java.util.Scanner;
4 |
5 | import commands.CommandController;
6 |
7 | /**
8 | * This is the Shell that prompts user for input and prints the output
9 | * according to specified input
10 | */
11 | public class JShell {
12 |
13 | public static void main(String[] args) {
14 | JShellState shellState = new JShellState();
15 | CommandController commandExecutor = new CommandController();
16 | Scanner in = new Scanner(System.in);
17 | // keep reading the command and executing it until user exits the program
18 | while (shellState.isRunning()) {
19 | System.out.print("$ ");
20 | // read next input line parse it and check if it is valid
21 | String commandLine = in.nextLine();
22 | try {
23 | String output = commandExecutor.executeCommand(shellState, commandLine);
24 | if (!output.equals("")) {
25 | System.out.println(output);
26 | }
27 | }
28 | catch (Exception e) {
29 | // TODO: change to CommandException everywhere.
30 | System.out.println(e.getMessage());
31 | }
32 | }
33 | in.close();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/command_decorators/RecursiveDecorator.java:
--------------------------------------------------------------------------------
1 | package command_decorators;
2 |
3 | import java.util.List;
4 |
5 | import commands.Command;
6 | import commands.RecursiveInterface;
7 | import constants.Exceptions;
8 | import driver.IShellState;
9 |
10 | /**
11 | * This class is a decorator for command that can be executed recursively
12 | * (can take -R as an optional parameter)
13 | */
14 | public class RecursiveDecorator extends CommandDecorator {
15 |
16 | public RecursiveDecorator(Command command) {
17 | super(command);
18 | }
19 |
20 | /**
21 | * Checks if given command takes -R as an optional parameter. Then execute
22 | * accordingly
23 | * @param shellState is state of program
24 | * @param arguments are base arguments provided
25 | * @throws Exception if command doesn't take -R
26 | */
27 | @Override
28 | public String executeCommand(IShellState shellState, List arguments)
29 | throws Exception {
30 | // if command does not support -R as optional parameter
31 | if (!(command instanceof RecursiveInterface)) {
32 | throw new Exception(Exceptions.INVALID_OPTIONAL_PARAM);
33 | }
34 | return ((RecursiveInterface) command).
35 | executeRecursively(shellState, arguments);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/commands/Command.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import constants.CommandException;
6 | import driver.IShellState;
7 |
8 | /**
9 | * This is a base class for any commands that might be needed in the program
10 | */
11 | public abstract class Command {
12 | protected final int maxArguments;
13 | protected final int minArguments;
14 |
15 | public Command(int maxArguments, int minArguments) {
16 | this.maxArguments = maxArguments;
17 | this.minArguments = minArguments;
18 | }
19 |
20 | public int getMaxArg() {
21 | return maxArguments;
22 | }
23 |
24 | public int getMinArg() {
25 | return minArguments;
26 | }
27 |
28 | abstract public String executeCommand
29 | (IShellState shellState, List arguments) throws Exception;
30 |
31 | // TODO: write Javadoc
32 | protected void checkArgumentsNum(List arguments) throws Exception {
33 | if (arguments.size() > maxArguments) {
34 | // TODO: add this message to class constants.Exceptions
35 | throw new CommandException("too many arguments provided");
36 | }
37 | if (arguments.size() < minArguments) {
38 | throw new CommandException("too little arguments provided");
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/commands/Popd.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 | import java.util.Stack;
5 |
6 | import constants.Exceptions;
7 | import driver.IShellState;
8 | import file_system.Directory;
9 |
10 | /**
11 | * Pop class Remove the top entry from
12 | * the directory stack, and cd into it
13 | *
14 | */
15 | public class Popd extends Command {
16 | public Popd() {
17 | super(0, 0);
18 | }
19 |
20 | /**
21 | * Remove the top entry from the directory stack, and cd into it
22 | * @param shellState is the state of JShell program
23 | * @param arguments is list of arguments that were passed along with command
24 | * (includes the path of directory to be switched to)
25 | * @throws Exception if pop from empty directory stack
26 | */
27 | public String executeCommand(IShellState shellState, List arguments)
28 | throws Exception {
29 | checkArgumentsNum(arguments);
30 | Stack dirStack = shellState.getDirectoryStack();
31 | int stackLen = dirStack.size();
32 | if (stackLen == 0) {
33 | throw new Exception(Exceptions.POP_EMPTY_STACK);
34 | }
35 | // switch to last directory in the directoryStack(removing it from stack)
36 | shellState.setCurrentDir(dirStack.pop());
37 | return "";
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/helper_classes/StringHelper.java:
--------------------------------------------------------------------------------
1 | package helper_classes;
2 |
3 | /**
4 | * This class contains methods that help make operations with strings
5 | */
6 | public class StringHelper {
7 |
8 | /**
9 | * Method checks if a string contains any of the characters in the array
10 | * @param str is the string
11 | * @param charArray is an array of characters
12 | * @return boolean
13 | */
14 | public static boolean containsAny(String str, char[] charArray) {
15 | boolean result = false;
16 | for (int i = 0; i < str.length(); i++) {
17 | char currentChar = str.charAt(i);
18 | for (char c : charArray) {
19 | if (c == currentChar) {
20 | result = true;
21 | break;
22 | }
23 | }
24 | }
25 | return result;
26 | }
27 |
28 | /**
29 | * This method multiplies concatenates given string given number of times
30 | * @param str any string
31 | * @param numRepeat number of repetition
32 | * @return repeated string
33 | */
34 | public static String repeat(String str, int numRepeat) {
35 | StringBuilder output = new StringBuilder();
36 | for (int i = 0; i < numRepeat; i++) {
37 | output.append(str);
38 | i++;
39 | }
40 | return output.toString();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/commands/Man.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 | import constants.Constants;
5 | import driver.IShellState;
6 | /**
7 | * This class will get the documentation for a given command
8 | */
9 | public class Man extends Command {
10 |
11 | public Man() {
12 | super(1, 1);
13 | }
14 |
15 | /**
16 | * Prints the documentation for the given command
17 | * @param shellState is the current state of JShell program
18 | * @param arguments is the command that indicates what should be printed
19 | * @return the current FileSystemObject the path indicates
20 | * @throws Exception if command is invalid
21 | */
22 | @Override
23 | public String executeCommand(IShellState shellState, List arguments)
24 | throws Exception{
25 | checkArgumentsNum(arguments);
26 | String commandToPrint = arguments.get(0);
27 | if (!CommandReader.isValidCommand(commandToPrint)) {
28 | throw new Exception("command to print documentation not found");
29 | }
30 | return getDocumentation(commandToPrint);
31 | }
32 |
33 | /**
34 | * Gets the documentation for the given command
35 | * @param command is the command that indicates what documentation to get
36 | * @return the documentation of the given command
37 | */
38 | private String getDocumentation(String command) {
39 | return Constants.COMMAND_DOCUMENTATION.get(command);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/commands/MkdirTest.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import driver.JShellState;
4 | import file_system.Directory;
5 | import file_system.VirtualFileSystem;
6 | import org.junit.After;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | import java.util.List;
11 |
12 | import static org.junit.Assert.*;
13 |
14 | public class MkdirTest {
15 | JShellState shellState;
16 | CommandController commandExecutor;
17 |
18 | @Before
19 | public void setUp() throws Exception {
20 | VirtualFileSystem.resetFileSystemInstance();
21 | shellState = new JShellState();
22 | commandExecutor = new CommandController();
23 | }
24 |
25 | @After
26 | public void tearDown() throws Exception {
27 | }
28 |
29 | @Test
30 | public void testExecuteCommandHistory() {
31 | try {
32 | String output = commandExecutor.executeCommand(shellState, "mkdir test");
33 | List history = shellState.getHistory();
34 | assertEquals("mkdir test", history.get(0));
35 | } catch (Exception e) {
36 | e.printStackTrace();
37 | }
38 | }
39 |
40 |
41 | @Test
42 | public void testExecuteCommandNewDir() {
43 | try {
44 | String output = commandExecutor.executeCommand(shellState, "mkdir test");
45 | VirtualFileSystem fileSystem = shellState.getFileSystem();
46 | Directory newDir = fileSystem.getDirectoryByPath(fileSystem.getRoot(), "test");
47 | } catch (Exception e) {
48 | fail("Could not retrieve new directory using getDirectoryByPath");
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/java/commands/Cat.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.File;
7 | import helper_classes.PathHandler;
8 |
9 | /**
10 | * Cat class Returns content of the file(s) at path(s) that are provided
11 | */
12 | public class Cat extends Command {
13 |
14 | public Cat() {
15 | super(100, 1);
16 | }
17 |
18 | /**
19 | * Returns content of the file(s) at path(s) that are provided
20 | * @param shellState is the state of the program
21 | * @param arguments is list of arguments that were passed along with command
22 | * @throws Exception if path is invalid
23 | */
24 | public String executeCommand(IShellState shellState, List arguments)
25 | throws Exception {
26 | /*
27 | * loop through each path in the argument list
28 | * and get the directory of the requirement file and its name
29 | */
30 | checkArgumentsNum(arguments);
31 | StringBuilder output = new StringBuilder();
32 | for (String path: arguments) {
33 | try {
34 | File filetoCat = PathHandler.getFileByPath(shellState, path);
35 | /*
36 | * if this is the first file get cat, do not include line break
37 | * else concatenate the current file after the previous
38 | * file with 3 lines break
39 | */
40 | output.append((output.toString().equals("")) ?
41 | filetoCat.getContent() : ("\n\n" + filetoCat.getContent()));
42 | }
43 | catch (Exception e) {
44 | String errorString = "cannot view file " + path + ": " + e.getMessage();
45 | output.append((output.toString().equals("")) ?
46 | errorString : "\n\n" + errorString);
47 | }
48 | }
49 | return output.toString();
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/constants/Exceptions.java:
--------------------------------------------------------------------------------
1 | package constants;
2 |
3 | import java.lang.reflect.Field;
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * This class holds all the exception messages in the program
8 | */
9 | public class Exceptions {
10 | public static final String WRONG_PATH_INPUT_MSG = "No such file or directory";
11 | public static final String INVALID_STRING_MSG = "Invalid string input";
12 | public static final String POP_EMPTY_STACK =
13 | "cannot execute: use pushd to push a directory into the stack first ";
14 | public static final String FILE_EXISTS = "File/directory exists";
15 | public static final String COMMAND_NOT_FOUND = "command not found";
16 | public static final String OPTIONAL_PARAM_ERROR = "invalid option";
17 | public static final String INVALID_ARGUMENT = "invalid argument";
18 | public static final String MOVE_INTO_SUBCHILD_ERROR =
19 | "Can't move or copy into sub child";
20 | public static final String INVALID_OPTIONAL_PARAM =
21 | "this command doesn't support this optional parameter";
22 |
23 | public static final String NOT_A_FILE_ERROR = "Not a file";
24 | public static final String NOT_A_DIRECTORY_ERROR = "Not a file";
25 | public static final String INVALID_NAME =
26 | "name cannot contain some of the given characters";
27 | public static final String MOVE_DIRECTORY_INTO_FILE_ERROR =
28 | "Cannot move a directory into a file";
29 |
30 | // Returns a list of all exceptions
31 | public static ArrayList getErrors() {
32 | ArrayList errorMessages = new ArrayList();
33 | Field[] fields = Exceptions.class.getFields();
34 | for (Field field : fields) {
35 | try {
36 | String errorMessage = (String) field.get(Exceptions.class);
37 | errorMessages.add(errorMessage);
38 | } catch (Exception e) {
39 | // TODO Auto-generated catch block
40 | e.printStackTrace();
41 | }
42 | }
43 | return errorMessages;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/commands/Save.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.io.*;
4 | import java.util.List;
5 | import constants.Exceptions;
6 | import driver.IShellState;
7 | /**
8 | * This class is responsible for saving the current JShell session into a file
9 | */
10 | public class Save extends Command {
11 |
12 | public Save() {
13 | super(1, 1);
14 | }
15 |
16 | /**
17 | * This method will save the current JShell session into a file which will
18 | * created/ overwritten at the given path
19 | * @param shellState is the current state of JShell program
20 | * @param arguments list of arguments that were passed along with command
21 | * @throws Exception if any of the paths is invalid
22 | */
23 | public String executeCommand(IShellState shellState, List arguments)
24 | throws Exception {
25 | try {
26 | checkArgumentsNum(arguments);
27 | String path = arguments.get(0);
28 | if (!path.contains("/")) {
29 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
30 | }
31 |
32 | saveToFile2(shellState, path);
33 | return "";
34 | } catch (IOException e) {
35 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
36 | }
37 | }
38 |
39 | private void saveToFile2(IShellState shellState, String path) throws IOException {
40 |
41 | FileOutputStream fileOut =
42 | new FileOutputStream(path);
43 | ObjectOutputStream out = new ObjectOutputStream(fileOut);
44 | out.writeObject(shellState);
45 | out.close();
46 | fileOut.close();
47 | }
48 |
49 | private void saveToFile1(IShellState shellState, String path) throws IOException {
50 | FileWriter fileWriter = new FileWriter(path);
51 | BufferedWriter bw = new BufferedWriter(fileWriter);
52 | //add history
53 | for (String commandLine : shellState.getHistory()) {
54 | bw.write(commandLine);
55 | bw.newLine();
56 | }
57 | bw.write("*****");
58 | bw.newLine();
59 | // add content to file
60 | for (String commandLine : shellState.getCorrectHistory()) {
61 | bw.write(commandLine);
62 | bw.newLine();
63 | }
64 | bw.close();
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/file_system/File.java:
--------------------------------------------------------------------------------
1 | package file_system;
2 |
3 | import constants.Exceptions;
4 |
5 | /**
6 | * This class represents a virtual file that has content and is a child of a
7 | * directory
8 | */
9 | public class File extends FileSystemObject {
10 | private String content;
11 |
12 |
13 | /**
14 | * Constructs a file with given name and parent
15 | * @param name given name
16 | * @param parent given parent
17 | * @throws Exception if object with given name exists in given parent
18 | */
19 | public File(String name, Directory parent) throws Exception {
20 | this(name, parent, "");
21 | }
22 |
23 | /**
24 | * Constructs a file with given name and parent and content
25 | * @param name given name
26 | * @param parent given parent
27 | * @param content given content
28 | * @throws Exception if object with given name exists in given parent
29 | */
30 | public File(String name, Directory parent, String content) throws Exception {
31 | super(name, parent);
32 | parent.addChild(this);
33 | this.content = content;
34 | }
35 |
36 | /**
37 | * Return content of file
38 | */
39 | public String getContent() {
40 | return this.content;
41 | }
42 |
43 | /**
44 | * Set content of file
45 | * @param content is given content
46 | */
47 | public void setContent(String content) {
48 | this.content = content;
49 | }
50 |
51 | /**
52 | * Append content to the file
53 | * @param contentToAppend is content to append to the file
54 | */
55 | public void appendContent(String contentToAppend) {
56 | this.content += "\n" + contentToAppend;
57 | }
58 |
59 | @Override
60 | public void moveFsObjectIn(FileSystemObject fsObject) throws Exception {
61 | if (!(fsObject instanceof File)) {
62 | throw new Exception(Exceptions.MOVE_DIRECTORY_INTO_FILE_ERROR);
63 | }
64 | setContent(fsObject.getContent());
65 | }
66 |
67 | /**
68 | * Constructor for cloning purpose
69 | */
70 | private File(String name, String content) {
71 | this.name = name;
72 | this.content = content;
73 | this.parent = null;
74 | }
75 |
76 | @Override
77 | public FileSystemObject cloneObject() {
78 | return new File(name, content);
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/driver/JShellState.java:
--------------------------------------------------------------------------------
1 | package driver;
2 |
3 | import file_system.Directory;
4 | import file_system.VirtualFileSystem;
5 |
6 | import java.io.Serializable;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.Stack;
10 |
11 | /**
12 | * This class holds all the states of the Shell Program
13 | */
14 | public class JShellState implements IShellState, Serializable {
15 | private final VirtualFileSystem fs;
16 | private Directory currentDir;
17 | private boolean running;
18 | private final Stack directoryStack;
19 | private final List commandsHistory;
20 | private final List correctCommandsHistory;
21 |
22 | /**
23 | * Constructs an object that holds JShell's important states including
24 | * the root directory, current directory, directory stack and a boolean that
25 | * indicates JShell is running
26 | */
27 | public JShellState() {
28 | this.running = true;
29 | this.fs = VirtualFileSystem.createFileSystemInstance();
30 | this.currentDir = fs.getRoot();
31 | this.commandsHistory = new ArrayList<>();
32 | this.correctCommandsHistory = new ArrayList<>();
33 | this.directoryStack = new Stack<>();
34 | }
35 |
36 | public boolean isRunning() {
37 | return running;
38 | }
39 |
40 | public void stopRunning() {
41 | running = false;
42 | }
43 |
44 | public VirtualFileSystem getFileSystem() {
45 | return fs;
46 | }
47 |
48 | public Directory getRootDir() {
49 | return fs.getRoot();
50 | }
51 |
52 | public Directory getCurrentDir() {
53 | return currentDir;
54 | }
55 |
56 | public void setCurrentDir(Directory newCurrentDir) {
57 | currentDir = newCurrentDir;
58 | }
59 |
60 | public void addHistory(String inputLine) {
61 | commandsHistory.add(inputLine);
62 | }
63 |
64 | public void removeHistory(int index) {
65 | commandsHistory.remove(index);
66 | }
67 |
68 | public List getHistory() {
69 | return commandsHistory;
70 | }
71 |
72 | public void addCorrectHistory(String inputLine) {
73 | correctCommandsHistory.add(inputLine);
74 | }
75 |
76 | public List getCorrectHistory() {
77 | return correctCommandsHistory;
78 | }
79 |
80 | public Stack getDirectoryStack(){
81 | return directoryStack;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/commands/History.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import constants.Exceptions;
7 | import driver.IShellState;
8 |
9 | public class History extends Command {
10 |
11 | public History() {
12 | super(1, 0);
13 | }
14 |
15 | /**
16 | * print out recent commands, one command per line
17 | * @param shellState is the state of JShell program
18 | * @param arguments is list of arguments that were passed along with command
19 | * (includes the path of directory to be switched to)
20 | */
21 | public String executeCommand(IShellState shellState, List arguments)
22 | throws Exception {
23 | int numberOfCommand;
24 | checkArgumentsNum(arguments);
25 | /* if no argument is passed,
26 | * set numberOfCommand to print the all history
27 | */
28 | if (arguments.size() == 0) {
29 | numberOfCommand =shellState.getHistory().size();
30 | } else {
31 | numberOfCommand = Integer.parseInt(arguments.get(0));
32 | }
33 | return getHistory(shellState, numberOfCommand);
34 | }
35 |
36 | /**
37 | * print out recent commands, one command per line
38 | * @param shellState is the state of JShell program
39 | * @param numberOfCommand is the number of command in the history
40 | * the user want to see
41 | * @throws Exception if numberOfCommand < 0
42 | */
43 | private String getHistory(IShellState shellState, int numberOfCommand)
44 | throws Exception {
45 | List history = shellState.getHistory();
46 | int i = history.size() - 1 ;
47 | StringBuilder output = new StringBuilder();
48 | /*
49 | * if numberOfCommand exceed the number of history,
50 | * set it to print up to all history
51 | */
52 | if (numberOfCommand > history.size()) {
53 | numberOfCommand = history.size();
54 | } else if (numberOfCommand < 0) {
55 | throw new Exception(Exceptions.INVALID_ARGUMENT);
56 | }
57 | /*
58 | * loop and print the number of commands required
59 | * or until all history commands have been printed
60 | */
61 | while (numberOfCommand > 0 && i <= history.size()) {
62 | output.insert(0, i + 1 + ". " + history.get(i) + "\n");
63 | i--;
64 | numberOfCommand--;
65 | }
66 | return output.toString();
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/commands/Get.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.Directory;
7 |
8 | import java.net.*;
9 | import java.io.*;
10 |
11 | /**
12 | * This class create a new file with content from given url
13 | */
14 | public class Get extends Command{
15 | public Get() {
16 | super(1, 1);
17 | }
18 |
19 | /**
20 | * Retrieve file at given URL and add it to the current working directory
21 | * @param shellState is the current state of JShell program
22 | * @param arguments is the list of paths that indicate where new directories
23 | * should be created
24 | * @throws Exception if any of the paths is invalid
25 | */
26 | public String executeCommand(IShellState shellState, List arguments)
27 | throws Exception {
28 | checkArgumentsNum(arguments);
29 | Directory currentDir = shellState.getCurrentDir();
30 |
31 | //read through each line of the file and append to content
32 | StringBuilder content = new StringBuilder();
33 | URL url = new URL(arguments.get(0));
34 | BufferedReader in = new BufferedReader(
35 | new InputStreamReader(url.openStream()));
36 | String inputLine;
37 | while ((inputLine = in.readLine()) != null)
38 | content.append(inputLine).append("\n");
39 | in.close();
40 |
41 | //get the url to find the file name
42 | String urlLink = arguments.get(0);
43 |
44 | String fileName = extractName(urlLink);
45 | /*
46 | * create a file in current directory with founded file name
47 | * and content
48 | */
49 | new file_system.File(fileName, currentDir, content.toString());
50 |
51 | return "";
52 | }
53 |
54 | /**
55 | * Get the file name from a url
56 | * @param urlLink is a url link
57 | */
58 | public String extractName(String urlLink) {
59 | int start=0;
60 | int end=urlLink.length();
61 |
62 | boolean foundName = false;
63 | // loop from the end until find the first "/"
64 | int i = urlLink.length() - 1;
65 | while ( i >= 0 && !foundName) {
66 | char c = urlLink.charAt(i);
67 | // exclude the file type
68 | if (c == '.') {
69 | end = i;
70 | } else if (c == '/') {
71 | start = i+1;
72 | foundName = true;
73 | }
74 | i--;
75 | }
76 | return urlLink.substring(start, end);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/commands/Mkdir.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.Directory;
7 | import helper_classes.DirectoryFileNameTuple;
8 | import helper_classes.PathHandler;
9 |
10 | /**
11 | * Creates directories in the file system
12 | */
13 | public class Mkdir extends Command {
14 | private static final String startingErrorMsg = "cannot create directory";
15 |
16 | public Mkdir() {
17 | super(100, 1);
18 | }
19 |
20 | /**
21 | * Creates many directories according to each path
22 | * @param shellState is the current state of JShell program
23 | * @param arguments is the list of paths that indicate where new directories
24 | * should be created
25 | * @throws Exception if any of the paths is invalid
26 | */
27 | public String executeCommand
28 | (IShellState shellState, List arguments) throws Exception {
29 | checkArgumentsNum(arguments);
30 | StringBuilder allErrorMsg = new StringBuilder();
31 | for (String path: arguments) {
32 | try {
33 | createDir(shellState, path);
34 | }
35 | catch (Exception e) {
36 | String fullErrorMsg = constructFullErrorMsg(path, e.getMessage());
37 | allErrorMsg.append((allErrorMsg.toString().equals("")) ?
38 | fullErrorMsg : ("\n" + fullErrorMsg));
39 | }
40 | }
41 | if (!allErrorMsg.toString().equals("")) {
42 | throw new Exception(allErrorMsg.toString());
43 | }
44 | return "";
45 | }
46 |
47 | /**
48 | * Creates a single new directory according to the given path
49 | * @param shellState is the current state of JShell program
50 | * @param path indicates where the new directory should be created
51 | * @throws Exception if given path is invalid
52 | */
53 | private void createDir(IShellState shellState, String path)
54 | throws Exception {
55 | /*
56 | * get the directory from which new directory should be added from and
57 | * name of the new directory
58 | */
59 | DirectoryFileNameTuple wantedDirAndFileName =
60 | PathHandler.getDirectoryAndFileName(shellState, path);
61 | new Directory(wantedDirAndFileName.getFileName(),
62 | wantedDirAndFileName.getDirectory());
63 | }
64 |
65 | /**
66 | * Constructs a complete detailed error message for this command subclass
67 | * @param path is the path from which directory could not be created
68 | * @param detailedErrorMsg is the error message that was returned when
69 | * creating directory failed
70 | * @return string that represents the complete detailed error message
71 | */
72 | private String constructFullErrorMsg(String path, String detailedErrorMsg) {
73 | return startingErrorMsg + " '" + path + "': " + detailedErrorMsg;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/commands/Find.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import constants.Exceptions;
6 | import driver.IShellState;
7 | import file_system.Directory;
8 | import file_system.File;
9 | import file_system.FileSystemObject;
10 | import helper_classes.PathHandler;
11 |
12 |
13 | /**
14 | * This class searches for the file or directory in a given path
15 | *
16 | */
17 |
18 | public class Find extends Command{
19 |
20 | public Find() {
21 | super(100, 5);
22 | }
23 |
24 | /**
25 | * Searches for the file or directory in a given path
26 | * @param shellState is the current state of JShell program
27 | * @param arguments includes all of: [file_path], --type [f/d], --name [file_name]
28 | * @throws Exception if path, type or name is invalid
29 | *
30 | */
31 | public String executeCommand(IShellState shellState,
32 | List arguments) throws Exception {
33 |
34 | checkArgumentsNum(arguments);
35 | String output = "";
36 | String name = arguments.get(arguments.size()-1);
37 | String type = arguments.get(arguments.size()-3);
38 |
39 | if ((!arguments.get(arguments.size()-2).equals("-name"))||
40 | !arguments.get(arguments.size()-4).equals("-type")){
41 | throw new Exception(Exceptions.INVALID_ARGUMENT);
42 | }
43 | if (!type.equals("d") && !type.equals("f")){
44 | throw new Exception("Invalid type");
45 | }
46 |
47 |
48 | try {
49 | // get arguments excluding the type and expression
50 | List baseArgs = arguments.subList(0, arguments.
51 | size() - 4);
52 | // Search the given paths for the file/directory
53 | for (String paths:baseArgs) {
54 | FileSystemObject fsObject = PathHandler
55 | .getFileSystemObject(shellState, paths);
56 | // if path is a file, check if it matches type
57 | // and name
58 | if (fsObject.isEqualByClassAndName(File.class,name)){
59 | output = name + "found in " + paths;
60 | }
61 | // if path is a directory, check its contents to find
62 | // the file or the directory
63 | if (fsObject instanceof Directory) {
64 | // if it has a child that is of type directory
65 | if (((Directory) fsObject).
66 | hasChildWithTypeAndName(Directory.class,name)){
67 | output = "directory found in " + paths;}
68 | // if it has a child that is of type file
69 | else if (((Directory) fsObject).
70 | hasChildWithTypeAndName(File.class, name)){
71 | output = name + "found in " + paths;
72 | }
73 | else {
74 | output = "File or Directory not found";
75 | }
76 | }}}
77 | catch (Exception e) {
78 | output = "File/Directory not found";
79 | }
80 | return output;
81 | }}
82 |
83 |
--------------------------------------------------------------------------------
/src/main/java/helper_classes/PathHandler.java:
--------------------------------------------------------------------------------
1 | package helper_classes;
2 |
3 | import driver.IShellState;
4 | import file_system.Directory;
5 | import file_system.File;
6 | import file_system.VirtualFileSystem;
7 | import file_system.FileSystemObject;
8 |
9 | /**
10 | * This is class finds files and directories related to the shell given path
11 | */
12 | public class PathHandler {
13 |
14 | /**
15 | * This method is used when trying to create or access some file or directory
16 | * with the path. Gets the directory from which the file/directory is
17 | * attempted to be created/accessed from and its name
18 | * @param shellState holds state of the program including root directory and
19 | * current directory
20 | * @param path is the specified path that indicates which file/directory is
21 | * attempted to be created/accessed
22 | * @return a tuple that holds directory from which the file/directory is
23 | * attempted to be created/accessed from and its name
24 | * @throws Exception if the given path is invalid
25 | */
26 | public static DirectoryFileNameTuple getDirectoryAndFileName
27 | (IShellState shellState, String path) throws Exception {
28 | VirtualFileSystem fs = shellState.getFileSystem();
29 | return fs.getDirectoryAndFileName(shellState.getCurrentDir(), path);
30 | }
31 |
32 | /**
33 | * This method is used when trying to access some file system object such as
34 | * file or directory with the path.
35 | * @param shellState holds state of the program including root directory and
36 | * current directory
37 | * @param path is the specified path that indicates which file/directory is
38 | * attempted to be accessed
39 | * @return the file system object indicated by path
40 | * @throws Exception if the object does not exist at given path
41 | */
42 | public static FileSystemObject getFileSystemObject
43 | (IShellState shellState, String path) throws Exception {
44 | VirtualFileSystem fs = shellState.getFileSystem();
45 | return fs.getFileSystemObject(shellState.getCurrentDir(), path);
46 | }
47 |
48 | /**
49 | * Get the file specified by path
50 | * @param shellState holds state of the program including root directory and
51 | * current directory
52 | * @param path is the specified path(complete or relative)
53 | * @return path described by path
54 | * @throws Exception if the path specified object at this path is not a file
55 | */
56 | public static File getFileByPath
57 | (IShellState shellState, String path) throws Exception {
58 | VirtualFileSystem fs = shellState.getFileSystem();
59 | return fs.getFileByPath(shellState.getCurrentDir(), path);
60 | }
61 |
62 | /**
63 | * Get the directory specified by path
64 | * @param shellState holds state of the program including root directory and
65 | * current directory
66 | * @param path is the specified path(complete or relative)
67 | * @return directory described by path
68 | * @throws Exception if the path specified object at this path is not a
69 | * directory
70 | */
71 | public static Directory getDirectoryByPath
72 | (IShellState shellState, String path) throws Exception {
73 | VirtualFileSystem fs = shellState.getFileSystem();
74 | return fs.getDirectoryByPath(shellState.getCurrentDir(), path);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/commands/Load.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.io.*;
4 | import java.util.List;
5 |
6 | import constants.Exceptions;
7 | import driver.IShellState;
8 |
9 | /**
10 | * This class is responsible for loading up the previously saved JShell session
11 | */
12 | public class Load extends Command {
13 |
14 | public Load() {
15 | super(1, 1);
16 | }
17 |
18 | /**
19 | * This method will load the previous JShell session that was saved on the
20 | * file from the given path
21 | *
22 | * @param shellState is the current state of JShell program
23 | * @param arguments list of arguments that were passed along with command
24 | * @throws Exception if any of the paths is invalid
25 | */
26 | public String executeCommand(IShellState shellState, List arguments)
27 | throws Exception {
28 |
29 | try {
30 | checkArgumentsNum(arguments);
31 | // check if load was the first to be called in new session
32 | List his = shellState.getHistory();
33 | if (his.size() != 1) {
34 | throw new Exception("Load can only be called at the start of a session");
35 | }
36 | String path = arguments.get(0);
37 | if (!path.contains("/")) {
38 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
39 | }
40 |
41 | loadShellState1(shellState, path);
42 | return "";
43 | } catch (IOException e) {
44 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
45 | }
46 |
47 | }
48 |
49 | private void loadShellState2(IShellState shellState, String path) throws Exception {
50 | FileInputStream fileIn = new FileInputStream(path);
51 | ObjectInputStream in = new ObjectInputStream(fileIn);
52 | IShellState loadShellState = (IShellState) in.readObject();
53 | // what do we do with it now? We want to replace the ShellState
54 | // object in method main, but we don't have a way for this use
55 | // case to reach into that method. A design problem!
56 | System.out.println(shellState.getCorrectHistory());
57 | in.close();
58 | fileIn.close();
59 | }
60 |
61 | private void loadShellState1(IShellState shellState, String path) throws Exception {
62 | String line;
63 | FileReader fileReader = new FileReader(path);
64 | BufferedReader bufferedReader = new BufferedReader(fileReader);
65 |
66 | CommandController commandExecutor = new CommandController();
67 | boolean nextPart = false;
68 | int count = 0;
69 | String currentHistory = shellState.getHistory().get(0);
70 | shellState.removeHistory(0);
71 |
72 | // load the file system
73 | while ((line = bufferedReader.readLine()) != null) {
74 | if (line.equals("*****")) {
75 | nextPart = true;
76 | } else if (!nextPart) {
77 | shellState.addHistory(line);
78 |
79 | } else {
80 | // executeCommand correct command
81 | count++;
82 | commandExecutor.executeCommand(shellState, line);
83 | }
84 |
85 | }
86 |
87 | bufferedReader.close();
88 | // remove double history
89 | for (int i = 0; i < count; i++) {
90 | int currentSize = shellState.getHistory().size();
91 | shellState.removeHistory(currentSize - 1);
92 | }
93 | shellState.addHistory("exit");
94 | shellState.addHistory(currentHistory);
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/commands/CommandController.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.lang.reflect.Constructor;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import command_decorators.Redirection;
8 | import constants.CommandException;
9 | import constants.Constants;
10 | import constants.Exceptions;
11 | import driver.IShellState;
12 | import helper_classes.CmdArgTuple;
13 |
14 | /**
15 | * Decorates and executes command appropriately based on arguments provided
16 | */
17 | public class CommandController {
18 |
19 | /**
20 | * Executes the provided command line
21 | * @param shellState is the state of the program
22 | * @param commandLine is the given command line and arguments
23 | * @return string that is given back as command is executed
24 | * @throws Exception if any of the provided arguments is invalid
25 | */
26 | public String executeCommand(IShellState shellState, String commandLine)
27 | throws Exception {
28 | // TODO: clean this up.
29 | shellState.addHistory(commandLine);
30 | if (commandLine.equals("")) {
31 | return "";
32 | }
33 | // use command reader to separate command with arguments
34 | CmdArgTuple cmdArgTuple = CommandReader.parseCommandLine(commandLine);
35 | Command command = getCommand(cmdArgTuple);
36 | List arguments = cmdArgTuple.getArguments();
37 | List optParams = getOptionalParamsAndRemoveFrom(arguments);
38 |
39 | // decorate command appropriately
40 | command = decorateCommand(command, arguments, optParams);
41 | String result = command.executeCommand(shellState, arguments);
42 | // if command doesn't result in an error add it to STD OUPOUT history
43 | shellState.addCorrectHistory(commandLine);
44 | return result;
45 | }
46 |
47 | private List getOptionalParamsAndRemoveFrom(List arguments) {
48 | // remove optional parameters, make a new list
49 | List optParams = new ArrayList<>();
50 | for (String arg : arguments) {
51 | if (Constants.OPTIONAL_PARAM_DIC.containsKey(arg)) {
52 | optParams.add(arg);
53 | }
54 | }
55 | for (String optParam : optParams) {
56 | arguments.remove(optParam);
57 | }
58 | return optParams;
59 | }
60 |
61 | private Command getCommand(CmdArgTuple cmdArgTuple) throws CommandException {
62 | String command = cmdArgTuple.getCommand();
63 | if (!CommandReader.isValidCommand(command)) {
64 | throw new CommandException(Exceptions.COMMAND_NOT_FOUND);
65 | }
66 | return Constants.COMMAND_DIC.get(command);
67 | }
68 |
69 | /**
70 | * Decorates the command with optional parameter(if present) and
71 | * redirection (if present)
72 | * @param command is the command to decorate
73 | * @param arguments are base arguments provided
74 | * @param optParam is a list of optional parameters provided
75 | * @return command that is decorated
76 | * @throws Exception if there is more than one optional parameter
77 | */
78 | private Command decorateCommand
79 | (Command command, List arguments, List optParam)
80 | throws Exception {
81 | Command decoratedCommand = command;
82 | if (optParam.size() > 1) {
83 | throw new Exception("commands can only take 1 optional parameter");
84 | }
85 | // decorate with optional parameter if necessary
86 | if (optParam.size() == 1) {
87 | String aprropDecoratorName =
88 | Constants.OPTIONAL_PARAM_DIC.get(optParam.get(0));
89 | Class> appropDecoratorClass =
90 | Class.forName("commandDecorators." + aprropDecoratorName);
91 | Constructor> decConstructor =
92 | appropDecoratorClass.getConstructor(Command.class);
93 | decoratedCommand = (Command) decConstructor.newInstance(command);
94 | }
95 | // decorate with redirection if necessary
96 | int argLen = arguments.size();
97 | if (argLen >= 2) {
98 | if (arguments.get(argLen - 2).equals(Constants.REDIRECTION_APPEND) ||
99 | arguments.get(argLen - 2).equals(Constants.REDIRECTION_OVERWRITE)) {
100 | decoratedCommand = new Redirection(decoratedCommand);
101 | }
102 | }
103 | return decoratedCommand;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/command_decorators/Redirection.java:
--------------------------------------------------------------------------------
1 | package command_decorators;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import commands.Command;
7 | import constants.Constants;
8 | import constants.Exceptions;
9 | import driver.IShellState;
10 | import file_system.Directory;
11 | import file_system.File;
12 | import helper_classes.DirectoryFileNameTuple;
13 | import helper_classes.PathHandler;
14 |
15 | /**
16 | * This is a decorator that redirects output to a provided outfile
17 | */
18 | public class Redirection extends CommandDecorator {
19 |
20 | public Redirection(Command command) {
21 | super(command);
22 | }
23 |
24 | /**
25 | * Redirect result from the command to a file provided in the arguments
26 | * @param shellState is the state of the program
27 | * @param arguments are provided arguments, including redirection type and
28 | * path of file to execute redirection on (length >= 2)
29 | * @throws Exception if path of redirection file is invalid
30 | */
31 | @Override
32 | public String executeCommand(IShellState shellState, List arguments)
33 | throws Exception {
34 | // get arguments excluding the redirection part
35 | List baseArgs = arguments.subList(0, arguments.size() - 2);
36 | // get the output that the command executes with base arguments
37 | String contentToRedirect = command.executeCommand(shellState, baseArgs);
38 | contentToRedirect = removeErrors(contentToRedirect);
39 | // get the redirection type and path of file to redirect output to
40 | String redirectionType = arguments.get(arguments.size() - 2);
41 | String path = arguments.get(arguments.size() - 1);
42 | // get fileName and directory from which the outfile should be in
43 | DirectoryFileNameTuple wantedDirAndFileName =
44 | PathHandler.getDirectoryAndFileName(shellState, path);
45 | Directory dirToCreateFileFrom = wantedDirAndFileName.getDirectory();
46 | String fileName = wantedDirAndFileName.getFileName();
47 | // if file doesn't yet exist
48 | if (!dirToCreateFileFrom.hasChildWithTypeAndName(File.class, fileName)) {
49 | // create new file with String argument as its content
50 | new File(fileName, dirToCreateFileFrom, contentToRedirect);
51 | }
52 | else {
53 | // get the existing file
54 | File existingFile =
55 | Directory.findChildFile(dirToCreateFileFrom, fileName);
56 | // append or overwrite accordingly
57 | if (redirectionType.equals(Constants.REDIRECTION_OVERWRITE)) {
58 | existingFile.setContent(contentToRedirect);
59 | } else {
60 | existingFile.appendContent(contentToRedirect);
61 | }
62 | }
63 | return "";
64 | }
65 |
66 | /**
67 | * Removes the error messages from the given string
68 | * @param result is the given string
69 | * @return the given string without error messages
70 | */
71 | private String removeErrors(String result) {
72 | // get all the error messages
73 | ArrayList errorMessages = Exceptions.getErrors();
74 | // remove all the error messages
75 | for (String errorMessage : errorMessages) {
76 | result = removeError(result, errorMessage);
77 | }
78 | return result;
79 | }
80 |
81 | /**
82 | * Remove the specified error message from the given string
83 | * @param result is the given string
84 | * @param error is the specified error message
85 | * @return given string without specified error message
86 | */
87 | private String removeError(String result, String error) {
88 | // remove the error message until are none left
89 | while (result.contains(error)) {
90 | int firstIndex = result.indexOf(error);
91 | int startIndex = 0;
92 | for (int i = firstIndex; i >= 0; i--) {
93 | startIndex = i;
94 | if (result.charAt(i) == '\n') {
95 | break;
96 | }
97 | }
98 | int lastIndex = firstIndex + error.length();
99 | if (lastIndex < result.length()) {
100 | lastIndex ++;
101 | }
102 | result = result.substring(0, startIndex)
103 | + result.substring(lastIndex);
104 | }
105 | return result;
106 |
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/file_system/FileSystemObject.java:
--------------------------------------------------------------------------------
1 | package file_system;
2 |
3 | import constants.Constants;
4 | import constants.Exceptions;
5 | import helper_classes.StringHelper;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * This class represents an object in a file system (can be a directory of file)
11 | */
12 | public abstract class FileSystemObject implements Serializable {
13 | // this is object's name
14 | protected String name;
15 | // this is object's parent object
16 | protected Directory parent;
17 |
18 | /** Constructs an object that will be considered as root */
19 | public FileSystemObject() {
20 | // set name and create empty list of children
21 | this.name = Constants.SYSTEM_FILE_ROOT_NAME;
22 | this.parent = null;
23 | }
24 |
25 | /**
26 | * Constructs an object that has a name, and a parent object
27 | * @param name is a name of the object
28 | * @param parent is the parent object of the object
29 | * @throws Exception if name has invalid characters in it
30 | */
31 | public FileSystemObject
32 | (String name, Directory parent) throws Exception {
33 | // check if name is valid, throw error if not
34 | if (StringHelper.containsAny(name, Constants.INVALID_NAMING_CHAR)) {
35 | throw new Exception(this.getClass().getSimpleName() + " " +
36 | Exceptions.INVALID_NAME);
37 | }
38 | // set name and create empty list of children
39 | this.name = name;
40 | this.parent = parent;
41 | }
42 |
43 | /** Return name of this FileSystemObject */
44 | public String getName() {
45 | return name;
46 | }
47 |
48 |
49 | /** Set name of this FileSystemObject
50 | * @throws Exception if name contains invalid characters */
51 | public void setName(String name) throws Exception {
52 | // check if name is valid, throw error if not
53 | if (StringHelper.containsAny(name, Constants.INVALID_NAMING_CHAR)) {
54 | throw new Exception(this.getClass().getSimpleName() + " " +
55 | Exceptions.INVALID_NAME);
56 | }
57 | this.name = name;
58 | }
59 |
60 | /** Return parent of this FileSystemObject */
61 | public FileSystemObject getParent() {
62 | return parent;
63 | }
64 |
65 | /**
66 | * Set new parent to this object
67 | * @param newParent is the new parent (directory)
68 | * @throws Exception if newParent already has child with this object's name
69 | */
70 | public void setParent(Directory newParent) throws Exception {
71 | if (parent != null) {
72 | parent.removeChild(this);
73 | }
74 | newParent.addChild(this);
75 | parent = newParent;
76 | }
77 |
78 | /** Return the path of this FileSystemObject */
79 | public String getPath() {
80 | // initialize result path
81 | String result;
82 | // recursively get the result path
83 | if (parent == null) {
84 | result = name;
85 | } else if (parent.getParent() == null) {
86 | result = parent.getPath() + name;
87 | } else {
88 | result = parent.getPath() + Constants.SYSTEM_FILE_PATH_SEPERATOR + name;
89 | }
90 | // return the result path
91 | return result;
92 | }
93 |
94 | /**
95 | * Check if this fileSystemObject instance is of given type and name
96 | * @param classToComp given type
97 | * @param name given name
98 | * @return boolean
99 | */
100 | public boolean isEqualByClassAndName(Class> classToComp, String name) {
101 | return (classToComp.equals(this.getClass()) &&
102 | this.name.equals(name));
103 | }
104 |
105 | abstract public String getContent();
106 |
107 | /**
108 | * Check if current object has given fsObject as an ancestor
109 | * @param fsObject is given file system object
110 | * @return boolean
111 | */
112 | public boolean hasAncestor(FileSystemObject fsObject) {
113 | // if fsObject is a directory and this object isn't the fsObject directory
114 | if (fsObject instanceof Directory) {
115 | if (this.equals(fsObject)) {
116 | return true;
117 | }
118 | // get current object
119 | FileSystemObject currentObject = this;
120 | // loop until meet the root or until we find fsObject as ancestor
121 | while (currentObject.getParent() != null) {
122 | FileSystemObject curParent = currentObject.getParent();
123 | if (curParent.equals(fsObject)) {
124 | return true;
125 | }
126 | currentObject = currentObject.getParent();
127 | }
128 | }
129 | // return false if no ancestor found
130 | return false;
131 | }
132 |
133 | abstract public void moveFsObjectIn
134 | (FileSystemObject fsObject) throws Exception;
135 |
136 | abstract public FileSystemObject cloneObject();
137 | }
138 |
--------------------------------------------------------------------------------
/src/main/java/commands/CommandReader.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import constants.Constants;
7 | import constants.Exceptions;
8 | import helper_classes.CmdArgTuple;
9 |
10 | /**
11 | * Parses command line input, recognizes a string surrounded by quotes as one
12 | * argument
13 | */
14 | public class CommandReader {
15 |
16 | /**
17 | * Parses the input into a tuple that holds command as String and arguments
18 | * as List of Strings
19 | *
20 | * @param commandLine the input command line
21 | * @return CmdArgTuple the tuple that holds command and its arguments
22 | */
23 | public static CmdArgTuple parseCommandLine(String commandLine)
24 | throws Exception {
25 | // split up the command line by the spaces
26 | List splited = manuallySplit(commandLine);
27 | if (splited.size() == 0) {
28 | throw new Exception(Exceptions.COMMAND_NOT_FOUND);
29 | }
30 | String command = splited.get(0);
31 | List arguments = splited.subList(1, splited.size());
32 | return new CmdArgTuple(command, arguments);
33 | }
34 |
35 | /**
36 | * Split a string into 'arguments' where 'arguments' words surrounded by
37 | * white spaces. Anything surrounded by double quotes is considered as one
38 | * argument
39 | *
40 | * @param commandLine is the
41 | * @return the list of arguments
42 | * @throws Exception if STRING input is invalid (i.e STRING input has
43 | * quotation mark inside it"
44 | */
45 | private static List manuallySplit(String commandLine)
46 | throws Exception {
47 | // initialize list of split arguments and current index
48 | List splittedCommandLine = new ArrayList<>();
49 | int currI = 0;
50 | while (currI < commandLine.length()) {
51 | char currChar = commandLine.charAt(currI);
52 | if (currChar == ' ') {
53 | currI += 1;
54 | } else {
55 | /*
56 | * else, current character is the start of an argument that is needed
57 | * to be split. Get the end index of the argument and split it.
58 | */
59 | // int endSplitI = (currChar == '"') ?
60 | // getEndStringIndex(commandLine, currI) :
61 | // getEndNonStrIndex(commandLine, currI);
62 |
63 | int endSplitI;
64 | if (currChar == '"') {
65 | endSplitI = getEndStringIndex(commandLine, currI);
66 | } else {
67 | endSplitI = getEndNonStrIndex(commandLine, currI);
68 | }
69 |
70 | String splittedArgument = commandLine.substring(currI, endSplitI);
71 | // remove the quotes if the argument is the STRING argument
72 | if (currChar == '"') {
73 | splittedArgument =
74 | splittedArgument.substring(1, splittedArgument.length() - 1);
75 | }
76 | // add the argument to the list, move on
77 | splittedCommandLine.add(splittedArgument);
78 | currI = endSplitI;
79 | }
80 | }
81 | return splittedCommandLine;
82 | }
83 |
84 | /**
85 | * Get end of a STRING input inside given string that starts at given index
86 | *
87 | * @param str given string
88 | * @param startI given start index
89 | * @return index of the last character of the STRING input
90 | * @throws Exception if STRING input is invalid
91 | */
92 | private static int getEndStringIndex(String str, int startI)
93 | throws Exception {
94 | boolean foundEndI = false;
95 | int endI = 0;
96 | int currI = startI + 1;
97 | // make the current index the wanted end index of the string argument
98 | while (!foundEndI && currI < str.length()) {
99 | if (str.charAt(currI) == '"') {
100 | if (currI + 1 != str.length() && str.charAt(currI + 1) != ' ') {
101 | throw new Exception(Exceptions.INVALID_STRING_MSG);
102 | }
103 | endI = currI + 1;
104 | foundEndI = true;
105 | }
106 | currI++;
107 | }
108 | // throw error if no other quotation mark was found
109 | if (endI == 0) {
110 | throw new Exception(Exceptions.INVALID_STRING_MSG);
111 | }
112 | return endI;
113 | }
114 |
115 | /**
116 | * Get end of an input surrounded by spaces
117 | *
118 | * @param str given string
119 | * @param startI given start index
120 | * @return index of the last character of the input surrounded by spaces
121 | */
122 | private static int getEndNonStrIndex(String str, int startI) {
123 | boolean foundEndI = false;
124 | int endI = startI + 1;
125 | while (!foundEndI && endI < str.length()) {
126 | if (str.charAt(endI) == ' ') {
127 | foundEndI = true;
128 | } else {
129 | endI += 1;
130 | }
131 | }
132 | return endI;
133 | }
134 |
135 | /**
136 | * This method checks if the given command is valid
137 | *
138 | * @param command the input command
139 | * @return boolean that indicates if command is valid
140 | */
141 | public static boolean isValidCommand(String command) {
142 | return Constants.COMMAND_DIC.containsKey(command);
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/commands/Ls.java:
--------------------------------------------------------------------------------
1 | package commands;
2 |
3 | import java.util.List;
4 |
5 | import driver.IShellState;
6 | import file_system.Directory;
7 | import file_system.FileSystemObject;
8 | import helper_classes.PathHandler;
9 |
10 | /**
11 | * This class finds the content of some directory (recursively if specified)
12 | */
13 | public class Ls extends Command implements RecursiveInterface {
14 |
15 | public Ls() {
16 | super(100, 0);
17 | }
18 |
19 | /**
20 | * Returns the content of the current Directory if path not given
21 | * If path p specifies a file, print p
22 | * if path p specifies a directory, print the content of the directory
23 | * @param shellState is the current state of JShell program
24 | * @param arguments is the paths that indicates what should be printed
25 | * @throws Exception if path is invalid
26 | */
27 | public String executeCommand(IShellState shellState, List arguments)
28 | throws Exception {
29 | checkArgumentsNum(arguments);
30 | StringBuilder output = new StringBuilder();
31 | // if no path is given, get content of the current directory
32 | if (arguments.size() == 0) {
33 | output.append(shellState.getCurrentDir().getContent());
34 | }
35 | // go through all the paths and print content accordingly
36 | else {
37 | for (String path : arguments) {
38 | output.append(path).append(getContentOfObject(shellState, path)).append("\n");
39 | }
40 | }
41 | return output.toString().endsWith("\n")
42 | ? output.substring(0, output.length() - 1) : output.toString();
43 | }
44 |
45 | /**
46 | * Given the path of a FileSystem object, if path specifies a file,
47 | * return the path, else if path p specifies a directory, return the content
48 | * of the directory
49 | * @param shellState that holds root directory of file system
50 | * @param path is the given path
51 | * @return string as specified in the description
52 | */
53 | public String getContentOfObject
54 | (IShellState shellState, String path) {
55 | String output = "";
56 | try {
57 | FileSystemObject fsObject = PathHandler.getFileSystemObject(shellState, path);
58 | // if object is directory print out the path with the content
59 | if (fsObject instanceof Directory) {
60 | String objContent = fsObject.getContent();
61 | output += objContent.equals("")
62 | ? ": \n" : ": \n" + fsObject.getContent() + "\n";
63 | }
64 | }
65 | catch (Exception e) {
66 | output += ": " + e.getMessage() + "\n";
67 | }
68 | return output;
69 | }
70 |
71 | /**
72 | * Get content (recursively) of file or directory at specified path
73 | * @param state is the state of the program
74 | * @param path is the given path
75 | * @return content
76 | */
77 | public String getRecursiveContent (IShellState state, String path){
78 | String output = "";
79 | try {
80 | FileSystemObject fsObject = PathHandler.getFileSystemObject(state, path);
81 | // if object is directory print out the path with the content
82 | if (fsObject instanceof Directory) {
83 | output += recrusiveListing((Directory) fsObject, path);
84 | } else {
85 | output += path + "\n";
86 | }
87 | }
88 | catch (Exception e) {
89 | output += path + ": " + e.getMessage() + "\n\n";
90 | }
91 | return output;
92 | }
93 |
94 | /**
95 | * Lists content of current directory, and subdirectories
96 | * @param dir given directory
97 | * @param path path of parent directory
98 | * @return content of current directory, and subdirectories
99 | */
100 | public String recrusiveListing(Directory dir, String path) {
101 | // get current directories content
102 | String content = dir.getContent();
103 | StringBuilder output = new StringBuilder(path.equals("") ? content : path + ": \n" + content);
104 | output.append(content.equals("") ? "\n" : "\n\n");
105 | // get content of subdirectories recursively
106 | for (FileSystemObject child: dir) {
107 | if (child instanceof Directory) {
108 | String childPath = path + "/" + child.getName();
109 | output.append(recrusiveListing((Directory) child, childPath));
110 | }
111 | }
112 | return output.toString();
113 | }
114 |
115 | /**
116 | * Get content (recursively) of file or directory at specified paths
117 | * @param shellState is the state of the program
118 | * @param arguments is the list of given path
119 | * @return needed content
120 | */
121 | @Override
122 | public String executeRecursively
123 | (IShellState shellState, List arguments) {
124 | StringBuilder output = new StringBuilder();
125 | if (arguments.size() == 0) {
126 | output.append(recrusiveListing(shellState.getCurrentDir(), ""));
127 | } else {
128 | // for each path, recursively return content of that path
129 | for (String path: arguments) {
130 | output.append(getRecursiveContent(shellState, path));
131 | }
132 | }
133 | // return output (remove last line break if present
134 | return output.toString().endsWith("\n")
135 | ? output.substring(0, output.length() - 1) : output.toString();
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MSYS* | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/main/java/constants/Constants.java:
--------------------------------------------------------------------------------
1 | package constants;
2 |
3 | import java.util.Hashtable;
4 |
5 | import commands.Cat;
6 | import commands.Cd;
7 | import commands.Command;
8 | import commands.Cp;
9 | import commands.Echo;
10 | import commands.Exit;
11 | import commands.Find;
12 | import commands.Get;
13 | import commands.History;
14 | import commands.Load;
15 | import commands.Ls;
16 | import commands.Man;
17 | import commands.Mkdir;
18 | import commands.Mv;
19 | import commands.Popd;
20 | import commands.Pushd;
21 | import commands.Pwd;
22 | import commands.Save;
23 | import commands.Tree;
24 |
25 | /**
26 | * This class holds the constants variables in the program
27 | */
28 | public class Constants {
29 | // path related constants
30 | public static final String SYSTEM_FILE_PATH_SEPERATOR = "/";
31 | public static final String SYSTEM_FILE_ROOT_NAME = "/";
32 | public static final String PARENT_OF_SYSTEM_FILE_INDICATOR = "..";
33 | public static final String CURRENT_SYSTEM_FILE_INDICATOR = ".";
34 | // invalid file naming characters
35 | public static final char[] INVALID_NAMING_CHAR = {'/','.', '!', '@', '#',
36 | '$', '%', '^', '&', '*', '(', ')', '{', '}', '~', '|', '<', '>', '?'};
37 | public static final String REDIRECTION_OVERWRITE = ">";
38 | public static final String REDIRECTION_APPEND = ">>";
39 | // command dictionary
40 | public static final Hashtable COMMAND_DIC =
41 | new Hashtable();
42 |
43 | static {
44 | COMMAND_DIC.put("get", new Get());
45 | COMMAND_DIC.put("exit", new Exit());
46 | COMMAND_DIC.put("mkdir", new Mkdir());
47 | COMMAND_DIC.put("cd", new Cd());
48 | COMMAND_DIC.put("ls", new Ls());
49 | COMMAND_DIC.put("pwd", new Pwd());
50 | COMMAND_DIC.put("pushd", new Pushd());
51 | COMMAND_DIC.put("popd", new Popd());
52 | COMMAND_DIC.put("history", new History());
53 | COMMAND_DIC.put("cat", new Cat());
54 | COMMAND_DIC.put("echo", new Echo());
55 | COMMAND_DIC.put("man", new Man());
56 | COMMAND_DIC.put("mv", new Mv());
57 | COMMAND_DIC.put("cp", new Cp());
58 | COMMAND_DIC.put("tree", new Tree());
59 | COMMAND_DIC.put("save", new Save());
60 | COMMAND_DIC.put("load", new Load());
61 | COMMAND_DIC.put("find", new Find());
62 |
63 | }
64 |
65 | //optional parameters dictionary maps optional parameter to its decorator
66 | public static final Hashtable OPTIONAL_PARAM_DIC =
67 | new Hashtable();
68 |
69 | static {
70 | OPTIONAL_PARAM_DIC.put("-R", "RecursiveDecorator");
71 | }
72 |
73 | public static final Hashtable COMMAND_DOCUMENTATION =
74 | new Hashtable();
75 |
76 | static {
77 | COMMAND_DOCUMENTATION.put("exit","Quit the program");
78 | COMMAND_DOCUMENTATION.put("mkdir", "Create directories, each of which may"
79 | + " be relative to the current directory \n or may be a full path.");
80 | COMMAND_DOCUMENTATION.put("cd", "Change directory to DIR, which may be"
81 | + " relative to the current directory or \n may be a full path. As"
82 | + " with Unix, .. means a parent directory and a .means the current"
83 | + " directory.");
84 | COMMAND_DOCUMENTATION.put("ls", "If no paths are given, print the"
85 | + " contents (file or directory) of the current \n directory, with a"
86 | + " new line following each of the content (file or directory). \n"
87 | + " Otherwise, for each path p, the order listed: \n"
88 | + " •If p specifies a file, print p \n"
89 | + " •If p specifies a directory, print p, a colon, then"
90 | + " the contents of that directory, then an extra new line. \n"
91 | + " •If p does not exist, print a suitable message. ");
92 | COMMAND_DOCUMENTATION.put("pwd", "Print the current working directory"
93 | + " (including the whole path). ");
94 | COMMAND_DOCUMENTATION.put("cp"," Move item OLDPATH to NEWPATH, but don’t"
95 | + " remove OLDPATH. \n If OLDPATHis a directory, recursively copy the"
96 | + " contents.");
97 | COMMAND_DOCUMENTATION.put("mv"," Move item OLDPATH to NEWPATH. Both "
98 | + "OLDPATH and NEWPATH \n may be relative to the current directory"
99 | + "or may be full paths. If NEWPATH is a directory, move the item"
100 | + "into the directory.");
101 | COMMAND_DOCUMENTATION.put("pushd","Saves the current working directory by"
102 | + " pushing onto directory stack and \n then changes the new current"
103 | + " working directory to DIR. The push must be\nconsistent as per"
104 | + " the LIFO behavior of a stack. The pushd command \n saves the"
105 | + " old current working directory in directory stack so that it can"
106 | + " be \n returned to at any time (via the popd command). The size of"
107 | + " the directory \n stack is dynamic and dependent on the pushd and"
108 | + " the popd commands. ");
109 | COMMAND_DOCUMENTATION.put("popd", "Remove the top entry from the"
110 | + " directory stack, and cd into it. The removal \n must be"
111 | + " consistent as per the LIFO behavior of a stack. The popd \n"
112 | + "command removes the top most directory from the directory stack"
113 | + " and \n makes it the current working directory. If there is no"
114 | + " directory onto the \n stack, then give appropriate error message."
115 | + " ");
116 | COMMAND_DOCUMENTATION.put("history","This command will print out recent"
117 | + " commands, one command per line. \nHistory will also include"
118 | + "any syntactical errors typed by the user ");
119 | COMMAND_DOCUMENTATION.put("cat", "Display the contents of FILE1 and other"
120 | + " files (i.e. File2 ....) concatenated in the shell.");
121 | COMMAND_DOCUMENTATION.put("echo","•echo STRING: prints the provided " +
122 | "STRING argument.\nSTRING argument must be surrounded by double quotes"
123 | + "unless it consists of only one word");
124 | COMMAND_DOCUMENTATION.put("man", "Print documentation for command");
125 | COMMAND_DOCUMENTATION.put("get", "Retrieve the file at given URL and add" +
126 | " it to the current working directory");
127 | COMMAND_DOCUMENTATION.put("save", "Saves the session of the JShell"
128 | + " onto a file in the given path");
129 | COMMAND_DOCUMENTATION.put("load", "Loads the session of the JShell"
130 | + " from the file of the given path. Load must be called at the start"
131 | + "of the new session");
132 | COMMAND_DOCUMENTATION.put("find", "The syntax of thefindcommand is as"
133 | + "follows:find path ... -type [f|d] -name expression. \n So here are"
134 | + " some examples of how thefindcommand may be used:"
135 | + "\n •find /users/Desktop -type f -name \"xyz\". This command will"
136 | + " search the directoryDesktopand find all files (indicated by type"
137 | + " f) that have the name exactlyxyz. \n"
138 | + " •find /users/Desktop -type d -name \"abc\". This command will"
139 | + " search the directoryDesktopand find all directories (indicated by"
140 | + " type d) that have the name exactlyabc. \n"
141 | + " •find /users/Desktop. This command will result in an error"
142 | + " because it has missing arguments. \n"
143 | + " •find /users/Desktop /users/Desktop1 -type d -name \"abc\". "
144 | + " This command will searchthe directoryDesktopandDesktop1 and"
145 | + " find all directories (indicated bytype d) that have the name"
146 | + " exactly abc. \n "
147 | + "•find /users/Desktop /users/Desktop1 -type f -name \"abc\". "
148 | + " This command will searchthe directory Desktop and Desktop1 and"
149 | + " find all directories (indicated bytype f) that have the name"
150 | + " exactly abc.\n"
151 | + " •If at any point one of the path in this command is invalid,"
152 | + " shell will print out an error for that path,however, you must"
153 | + " continue searching for any other files or directories that may"
154 | + " exist in other valid paths. \n"
155 | + " •Thefindcommand must accept the path as relative or in absolute"
156 | + " path.");
157 | COMMAND_DOCUMENTATION.put("tree", "Tree will display the entire"
158 | + " filesystem as a tree starting from the root directory");
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/file_system/VirtualFileSystem.java:
--------------------------------------------------------------------------------
1 | package file_system;
2 |
3 | import java.io.Serializable;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | import constants.Constants;
8 | import constants.Exceptions;
9 | import helper_classes.DirectoryFileNameTuple;
10 | import helper_classes.StringHelper;
11 |
12 | /**
13 | * This class is a virtual file system that stores directories and files.
14 | */
15 | public class VirtualFileSystem implements Serializable {
16 | // this is a single reference to a File System
17 | private static VirtualFileSystem singleReference = null;
18 | // this is the root directory of file system
19 | private final Directory root;
20 |
21 | /**
22 | * This is a private constructor that creates a new file system
23 | */
24 | private VirtualFileSystem() {
25 | root = new Directory();
26 | }
27 |
28 | /**
29 | * If file system hasn't been created before, create a new file system; else
30 | * return the reference to the file system
31 | * @return the reference to a single file system
32 | */
33 | public static VirtualFileSystem createFileSystemInstance() {
34 | if (singleReference == null) {
35 | singleReference = new VirtualFileSystem();
36 | }
37 | return singleReference;
38 | }
39 |
40 | /**
41 | * This is a hack. Because sinceReference is static, we can't reset the
42 | * system when running unit tests.
43 | * This method was added to work around that.
44 | * TODO: need a better option, like make the file system non-static.
45 | */
46 | public static void resetFileSystemInstance() {
47 | singleReference = new VirtualFileSystem();
48 | }
49 |
50 | /**
51 | * Return root directory of the file system
52 | */
53 | public Directory getRoot() {
54 | return root;
55 | }
56 |
57 | /**
58 | * Get the directory from which the path starts (root directory if path is
59 | * full and current directory if path is relative)
60 | * @param path is the given path
61 | * @return directory from which the path starts
62 | */
63 | private Directory getStartingDirectoryToGoFrom
64 | (Directory curDir, String path) {
65 | return (path.startsWith(Constants.SYSTEM_FILE_ROOT_NAME) ?
66 | root : curDir);
67 | }
68 |
69 | /**
70 | * This method parses given path into a list of string names
71 | * (never including root)
72 | * @param path is a given string path
73 | * @return list of SystemFile names
74 | */
75 | private List parsePath(String path) {
76 | // split the path by system file separator (by default: /)
77 | return Arrays.asList(path.split(Constants.SYSTEM_FILE_PATH_SEPERATOR));
78 | }
79 |
80 | /**
81 | * This method is used when trying to create or access some file or directory
82 | * with the path. Gets the directory from which the file/directory is
83 | * attempted to be created/accessed from and its name
84 | * current directory
85 | * @param path is the specified path that indicates which file/directory is
86 | * attempted to be created/accessed
87 | * @return a tuple that holds directory from which the file/directory is
88 | * attempted to be created/accessed from and its name
89 | * @throws Exception if the given path is invalid
90 | */
91 | public DirectoryFileNameTuple getDirectoryAndFileName
92 | (Directory curDir, String path) throws Exception {
93 | List pathAsList = parsePath(path);
94 | List pathToDirToBeAddedFrom =
95 | pathAsList.subList(0, pathAsList.size() - 1);
96 | String nameOfFileToBeCreated = pathAsList.get(pathAsList.size() - 1);
97 | Directory startingDir = getStartingDirectoryToGoFrom(curDir, path);
98 | Directory dirToBeAddedFrom =
99 | Directory.findDirectory(startingDir, pathToDirToBeAddedFrom);
100 | return new DirectoryFileNameTuple(dirToBeAddedFrom, nameOfFileToBeCreated);
101 | }
102 |
103 | /**
104 | * This method is used when trying to access some file system object such as
105 | * file or directory with the path.
106 | * current directory
107 | * @param path is the specified path that indicates which file/directory is
108 | * attempted to be accessed
109 | * @return the file system object indicated by path
110 | * @throws Exception if the object does not exist at given path
111 | */
112 | public FileSystemObject getFileSystemObject
113 | (Directory curDir, String path) throws Exception {
114 | if (path.equals(Constants.SYSTEM_FILE_ROOT_NAME)) {
115 | return root;
116 | }
117 | DirectoryFileNameTuple dirAndFileName =
118 | getDirectoryAndFileName(curDir, path);
119 | return Directory.findChild
120 | (dirAndFileName.getDirectory(), dirAndFileName.getFileName());
121 | }
122 |
123 | /**
124 | * Get the file specified by path
125 | * current directory
126 | * @param path is the specified path(complete or relative)
127 | * @return path described by path
128 | * @throws Exception if the path specified object at this path is not a file
129 | */
130 | public File getFileByPath
131 | (Directory curDir, String path) throws Exception {
132 | FileSystemObject fsObject = getFileSystemObject(curDir, path);
133 | if (!(fsObject instanceof File)) {
134 | throw new Exception(Exceptions.NOT_A_FILE_ERROR);
135 | }
136 | return (File) fsObject;
137 | }
138 |
139 | /**
140 | * Get the directory specified by path
141 | * current directory
142 | * @param path is the specified path(complete or relative)
143 | * @return directory described by path
144 | * @throws Exception if the path specified object at this path is not a
145 | * directory
146 | */
147 | public Directory getDirectoryByPath
148 | (Directory curDir, String path) throws Exception {
149 | FileSystemObject fsObject = getFileSystemObject(curDir, path);
150 | if (!(fsObject instanceof Directory)) {
151 | throw new Exception(Exceptions.NOT_A_DIRECTORY_ERROR);
152 | }
153 | return (Directory) fsObject;
154 | }
155 |
156 | /**
157 | * Return tree representation of current file system
158 | */
159 | public String getTreeRepresentation() {
160 | return getTreeRepresentationHelper(root, 0);
161 | }
162 |
163 | /**
164 | * Make tree representation of file system rooted at given root; root is
165 | * indented by given number of spaces
166 | * @param root is given the root directory
167 | * @param numIndent is the number of spaces to indent root
168 | * @return tree representation
169 | */
170 | private String getTreeRepresentationHelper(Directory root, int numIndent) {
171 | // initialize output with root's name
172 | StringBuilder output = new StringBuilder(StringHelper.repeat(" ", numIndent) +
173 | root.getName() + "\n");
174 | for (FileSystemObject child: root) {
175 | if (child instanceof File) {
176 | output.append(StringHelper.repeat(" ", numIndent + 1)).append(child.getName()).append("\n");
177 | } else {
178 | output.append(getTreeRepresentationHelper((Directory) child, numIndent + 2));
179 | }
180 | }
181 | return output.toString();
182 | }
183 |
184 | /**
185 | * Move an object from one path to another (path can be absolute or relative
186 | * to given directory)
187 | * @param curDir given directory
188 | * @param oldPath is the path of object to be moved
189 | * @param newPath is the path of object to be moved into
190 | * @throws Exception if either of the paths are invalid or if trying to move
191 | * a directory inside one of its sub-directories
192 | */
193 | public void moveFsObject
194 | (Directory curDir, String oldPath, String newPath) throws Exception {
195 | FileSystemObject oldFsObject = getFileSystemObject(curDir, oldPath);
196 | DirectoryFileNameTuple newPathDirFileName =
197 | getDirectoryAndFileName(curDir, newPath);
198 | Directory dirWithNewObject = newPathDirFileName.getDirectory();
199 | String newFileName = newPathDirFileName.getFileName();
200 | // check if object at newPath is a subChild of object at oldPath
201 | if (dirWithNewObject.hasAncestor(oldFsObject)) {
202 | throw new Exception(Exceptions.MOVE_INTO_SUBCHILD_ERROR);
203 | }
204 | // if there is already an object at newPath, overwrite it
205 | try {
206 | FileSystemObject newFsObject =
207 | Directory.findChild(dirWithNewObject, newFileName);
208 | // if object at newPath and oldPath are the same do nothing
209 | if (!newFsObject.equals(oldFsObject)) {
210 | // else move accordingly
211 | newFsObject.moveFsObjectIn(oldFsObject);
212 | }
213 | }
214 | // else move oldFsObject into the directory with new object with new name
215 | catch (Exception e) {
216 | oldFsObject.setName(newFileName);
217 | oldFsObject.setParent(dirWithNewObject);
218 | }
219 | }
220 |
221 | /**
222 | * Copy an object from one path to another (path can be absolute or relative
223 | * to given directory)
224 | * @param curDir given directory
225 | * @param oldPath is the path of object to be moved
226 | * @param newPath is the path of object to be moved into
227 | * @throws Exception if either of the paths are invalid or if trying to move
228 | * a directory inside one of its sub-directories
229 | */
230 | public void copyFsObject
231 | (Directory curDir, String oldPath, String newPath) throws Exception {
232 | FileSystemObject oldFsObject = getFileSystemObject(curDir, oldPath);
233 | FileSystemObject parentOfOld = oldFsObject.getParent();
234 | FileSystemObject clonedOldFsObject = oldFsObject.cloneObject();
235 | moveFsObject(curDir, oldPath, newPath);
236 | clonedOldFsObject.setParent((Directory) parentOfOld);
237 | }
238 |
239 | }
240 |
--------------------------------------------------------------------------------
/src/main/java/file_system/Directory.java:
--------------------------------------------------------------------------------
1 | package file_system;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Iterator;
5 | import java.util.List;
6 |
7 | import constants.Constants;
8 | import constants.Exceptions;
9 |
10 | /**
11 | * This class represents a virtual directory that can hold other FileSystem
12 | * objects such as file or directory
13 | */
14 | public class Directory extends FileSystemObject
15 | implements Iterable {
16 | // this is a list that holds this directory's children
17 | private final ArrayList children;
18 |
19 | /**
20 | * This is an Directory Iterator
21 | */
22 | public class DirectoryIterator implements Iterator {
23 | // this is array of objects to loop through
24 | private final ArrayList childrenArr;
25 | // this is a counter
26 | int counter;
27 |
28 | /**
29 | * Create directory iterator with an array of objects to loop through
30 | * @param children array of children that can be a file or a directory
31 | */
32 | public DirectoryIterator(ArrayList children) {
33 | this.childrenArr = children;
34 | counter = 0;
35 | }
36 |
37 | @Override
38 | public boolean hasNext() {
39 | return counter < childrenArr.size() && childrenArr.get(counter) != null;
40 | }
41 |
42 | @Override
43 | public FileSystemObject next() {
44 | FileSystemObject fsObject = children.get(counter);
45 | counter ++;
46 | return fsObject;
47 | }
48 |
49 | }
50 |
51 | /** Constructs a directory without a parent (root directory) */
52 | public Directory() {
53 | // set name and create empty list of children
54 | super();
55 | children = new ArrayList<>();
56 | }
57 |
58 | /**
59 | * Constructs a Directory that has a name, and a parent directory
60 | * @param name is a name of the directory
61 | * @param parent is the parent directory of the directory
62 | * @throws Exception if name has invalid characters in it
63 | */
64 | public Directory(String name, Directory parent) throws Exception {
65 | // assign name, and parent directory, create list of children
66 | super(name, parent);
67 | children = new ArrayList<>();
68 | // add this directory as a child of parent directory
69 | if (parent != null) {
70 | parent.addChild(this);
71 | }
72 |
73 | }
74 |
75 | /** Return children of this directory */
76 | public ArrayList getChildren() {
77 | return children;
78 | }
79 |
80 | /** Add a child to this directory
81 | * @throws Exception if child with that type and name already exists
82 | */
83 | public void addChild(FileSystemObject child) throws Exception {
84 | if (this.hasChildWithName(child.name)) {
85 | throw new Exception(Exceptions.FILE_EXISTS);
86 | }
87 | children.add(child);
88 | }
89 |
90 | @Override
91 | public String getContent() {
92 | StringBuilder content = new StringBuilder();
93 | for (FileSystemObject child : this) {
94 | content.append(child.getName()).append("\n");
95 | }
96 | if (!content.toString().equals("")) {
97 | content = new StringBuilder(content.substring(0, content.length() - 1));
98 | }
99 | return content.toString();
100 | }
101 |
102 | /**
103 | * Checks if this directory has a child with given name and type
104 | * @param childClass is the type of the child
105 | * @param name is the given name of the child
106 | * @return boolean that indicates if directory has child with that name
107 | */
108 | public boolean hasChildWithTypeAndName(Class> childClass, String name) {
109 | boolean result = false;
110 | for (FileSystemObject currentChild : this.children) {
111 | if (currentChild.isEqualByClassAndName(childClass, name)) {
112 | result = true;
113 | }
114 | }
115 | return result;
116 | }
117 |
118 | /**
119 | * Checks if this directory has a child with given name
120 | * @param name is the given name of the child
121 | * @return boolean that indicates if directory has child with that name
122 | */
123 | public boolean hasChildWithName(String name) {
124 | boolean result = false;
125 | for (FileSystemObject currentChild : this.children) {
126 | if (name.equals(currentChild.getName())) {
127 | result = true;
128 | break;
129 | }
130 | }
131 | return result;
132 | }
133 |
134 | /**
135 | * Check if given directory has a child with given type and name
136 | * @param currentDir is given directory
137 | * @param classType is the given child type
138 | * @param name is the given child name
139 | * @return child with matching name and type
140 | * @throws Exception if currentDir directory has no such child
141 | */
142 | public static FileSystemObject findChild
143 | (Directory currentDir, Class> classType, String name) throws Exception {
144 | List curDirChildren = currentDir.getChildren();
145 | /*
146 | * loop through children to find and return child directory that
147 | * matches by name
148 | */
149 | for (FileSystemObject currentChild : curDirChildren) {
150 | if (currentChild.isEqualByClassAndName(classType, name)) {
151 | return currentChild;
152 | }
153 | }
154 | // throw exception because if method hasn't returned yet, no child matched
155 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
156 | }
157 |
158 | /**
159 | * Check if given directory has a child with given name; if name is '.' refer
160 | * to current directory, if name is '..' refer to parent directory
161 | * @param currentDir is given directory
162 | * @param childName is the given fileSystemObject name
163 | * @return child with matching name
164 | * @throws Exception if this directory has no such child
165 | */
166 | public static FileSystemObject findChild
167 | (Directory currentDir, String childName) throws Exception {
168 | List curDirChildren = currentDir.getChildren();
169 | /*
170 | * if name is '.' refer
171 | * to current directory, if name is '..' refer to parent directory
172 | */
173 | if (childName.equals(Constants.PARENT_OF_SYSTEM_FILE_INDICATOR)) {
174 | return (currentDir.getParent() != null)
175 | ? currentDir.getParent() : currentDir;
176 | } else if (childName.equals(Constants.CURRENT_SYSTEM_FILE_INDICATOR)) {
177 | return currentDir;
178 | }
179 | /*
180 | * else loop through children to find and return child directory
181 | * that matches by name
182 | */
183 | for (FileSystemObject currentChild : curDirChildren) {
184 | if (currentChild.getName().equals(childName)) {
185 | return currentChild;
186 | }
187 | }
188 | // throw exception because if method hasn't returned yet, no child matched
189 | throw new Exception(Exceptions.WRONG_PATH_INPUT_MSG);
190 | }
191 |
192 | /**
193 | * Removes directory's child with current name(if present)
194 | * @param fsObject reference child file object
195 | */
196 | public void removeChild(FileSystemObject fsObject) {
197 | children.remove(fsObject);
198 | }
199 |
200 | /**
201 | * Removes directory's child with current name(if present)
202 | * @param fsObjectName given child name
203 | */
204 | public void removeChildByName(String fsObjectName) {
205 | try {
206 | removeChild(findChild(this, fsObjectName));
207 | } catch (Exception e) {
208 | System.out.println(e.getMessage());
209 | }
210 | }
211 |
212 | /**
213 | * Check if given directory has a directory child with given name
214 | * @param currentDir is given directory
215 | * @param dirName is the given directory name
216 | * @return child with matching name
217 | * @throws Exception currentDir directory has no such child
218 | */
219 | public static Directory findChildDirectory
220 | (Directory currentDir, String dirName) throws Exception {
221 | return (Directory) findChild(currentDir, Directory.class, dirName);
222 | }
223 |
224 | /**
225 | * Check if given directory has a file child with given name
226 | * @param currentDir is given directory
227 | * @param fileName is the given directory name
228 | * @return file child with matching name
229 | * @throws Exception currentDir directory has no such child
230 | */
231 | public static File findChildFile
232 | (Directory currentDir, String fileName) throws Exception {
233 | return (File) findChild(currentDir, File.class, fileName);
234 | }
235 |
236 | /**
237 | * Find next directory by moving either backwards (to parent) or forward
238 | * (some child directory) from given directory according to the given string
239 | * @param currentDir is the given directory
240 | * @param nextDirectory is string that indicates which directory to move to
241 | * @return directory that matches nextDirectory
242 | * @throws Exception if cannot move from this directory to directory that
243 | * matches nextDirectory
244 | */
245 | public static Directory findDirectory
246 | (Directory currentDir, String nextDirectory) throws Exception{
247 | Directory wantedDirectory = currentDir;
248 | if (nextDirectory.equals(Constants.PARENT_OF_SYSTEM_FILE_INDICATOR)) {
249 | /*
250 | * if nextDirectory is the 'go to parent directory' indicator,
251 | * move to current directory parent; remain in the current directory if
252 | * it doesn't have a parent or if nextDirectory is an empty String
253 | */
254 | if (currentDir.getParent() != null) {
255 | wantedDirectory = (Directory) currentDir.getParent();
256 | }
257 | } else if (!nextDirectory.equals(Constants.CURRENT_SYSTEM_FILE_INDICATOR)
258 | && !nextDirectory.equals("")) {
259 | /*
260 | * else if nextDirectory isn't the 'current directory' indicator (do
261 | * nothing if it is), check to see any child directory of current one
262 | * matches the next directory name in the list by name
263 | */
264 | wantedDirectory = findChildDirectory(currentDir, nextDirectory);
265 | }
266 | return wantedDirectory;
267 | }
268 |
269 | /**
270 | * Find the directory starting from given directory, moving either backwards
271 | * (to its parent) or forward (to one of its children) according to the
272 | * given list of directory names
273 | * @param currentDir is the starting directory
274 | * @param listOfDirNames is list of directory names to move through
275 | * @return directory that is there after moved through the entire list
276 | * @throws Exception if at some point, next item on the list cannot be moved
277 | * to from current directory
278 | */
279 | public static Directory findDirectory
280 | (Directory currentDir, List listOfDirNames) throws Exception {
281 | // move in order through each directory in the list
282 | for (String nextDirectory: listOfDirNames) {
283 | currentDir = findDirectory(currentDir, nextDirectory);
284 | }
285 | return currentDir;
286 | }
287 |
288 | /**
289 | * Moves given file system object into the current directory, overwriting
290 | * existing file in current directory (if they have the same name)
291 | * @param fsObject the file object to be moved in this directory
292 | */
293 | public void moveFsObjectIn(FileSystemObject fsObject) {
294 | removeChildByName(fsObject.getName());
295 | try {
296 | fsObject.setParent(this);
297 | } catch (Exception e) {
298 | System.out.println(e.getMessage());
299 | }
300 | }
301 |
302 | @Override
303 | public Iterator iterator() {
304 | return new DirectoryIterator(children);
305 | }
306 |
307 | /**
308 | * Constructor for cloning purposes
309 | */
310 | @Override
311 | public FileSystemObject cloneObject(){
312 | Directory clonedDirectory = new Directory();
313 | try {
314 | clonedDirectory = new Directory(name, null);
315 | for (FileSystemObject child : this) {
316 | FileSystemObject childClone = child.cloneObject();
317 | childClone.setParent(clonedDirectory);
318 | }
319 | } catch (Exception e) {System.out.println(e.getMessage());}
320 | return clonedDirectory;
321 | }
322 | }
323 |
--------------------------------------------------------------------------------