diff --git a/src/main/java/com/acme/commands/Disk/BasicDiskStatusCmd.java b/src/main/java/com/acme/commands/Disk/DiskStatusCmd.java similarity index 70% rename from src/main/java/com/acme/commands/Disk/BasicDiskStatusCmd.java rename to src/main/java/com/acme/commands/Disk/DiskStatusCmd.java index ebe8e7c..cf2f042 100644 --- a/src/main/java/com/acme/commands/Disk/BasicDiskStatusCmd.java +++ b/src/main/java/com/acme/commands/Disk/DiskStatusCmd.java @@ -4,33 +4,38 @@ import com.acme.commands.StatusCommand; import com.acme.executors.ICommandExecutor; import com.acme.executors.SimpleCommandExecutor; -import org.springframework.beans.factory.annotation.Autowired; /** * Command for determining the basic disk status */ -public class BasicDiskStatusCmd implements StatusCommand { +public class DiskStatusCmd implements StatusCommand { private ICommandExecutor executor; private final long Id; private final String template; private final String name; + private final GenerateDiskStatusCmd cmd; private DiskStatus status; - public BasicDiskStatusCmd(long Id, String template, String name) { + public DiskStatusCmd(long Id, String template, String name, GenerateDiskStatusCmd cmd) { this.Id = Id; this.template = template; this.name = name; + this.cmd = cmd; + executor = new SimpleCommandExecutor(); } + public DiskStatusCmd(long Id, String template, String name) { + this(Id, template, name, new GenerateDiskStatusCmd()); + } + @Override public void execute() { - status = new DiskStatus(Id, String.format(template, name)); - GenerateDiskStatusCmd cmd = new GenerateDiskStatusCmd(); executor.executeCommand(cmd); + status = new DiskStatus(Id, String.format(template, name)); status.setStatusDesc(cmd.getResult()); } diff --git a/src/main/java/com/acme/commands/Disk/FastResponseDiskStatusCmd.java b/src/main/java/com/acme/commands/Disk/FastResponseDiskStatusCmd.java new file mode 100644 index 0000000..fff97ca --- /dev/null +++ b/src/main/java/com/acme/commands/Disk/FastResponseDiskStatusCmd.java @@ -0,0 +1,46 @@ +package com.acme.commands.Disk; + +import com.acme.beans.DiskStatus; + +public class FastResponseDiskStatusCmd extends DiskStatusCmd { + + private final long Id; + private final String template; + private final String name; + + private DiskStatusCmd cmd; + + public FastResponseDiskStatusCmd(long Id, String template, String name, DiskStatusCmd cmd) { + super(Id, template, name); + + this.Id = Id; + this.template = template; + this.name = name; + this.cmd = cmd; + } + + public FastResponseDiskStatusCmd(long Id, String template, String name) { + this(Id, template, name, new DiskStatusCmd(Id, template, name)); + } + + @Override + public void execute() { + Thread executionThread = new Thread( () -> cmd.execute() ); + executionThread.start(); + try { + Thread.sleep(2500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public DiskStatus getResult() { + DiskStatus result = cmd.getResult(); + if (result == null || result.getStatusDesc() == null){ + result = new DiskStatus(Id, String.format(template, name)); + result.setStatusDesc("Unknown"); + } + return result; + } +} diff --git a/src/main/java/com/acme/commands/Disk/ResourceEfficientDiskStatusGenerationCmd.java b/src/main/java/com/acme/commands/Disk/ResourceEfficientDiskStatusGenerationCmd.java new file mode 100644 index 0000000..8f776e8 --- /dev/null +++ b/src/main/java/com/acme/commands/Disk/ResourceEfficientDiskStatusGenerationCmd.java @@ -0,0 +1,53 @@ +package com.acme.commands.Disk; + +/** + * Singleton proxy for generating the disk status, so that only one instance of the command will be executed at once + */ +public class ResourceEfficientDiskStatusGenerationCmd extends GenerateDiskStatusCmd { + + private String statusDesc = "unknown"; + + private boolean isRunning; + private static ResourceEfficientDiskStatusGenerationCmd cmd = new ResourceEfficientDiskStatusGenerationCmd(); + + private ResourceEfficientDiskStatusGenerationCmd() { + } + + public static ResourceEfficientDiskStatusGenerationCmd getInstance(){ + return cmd; + } + + @Override + public void execute() { + + boolean willExecute; + synchronized (this){ + if (isRunning){ + willExecute = false; + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + isRunning = true; + willExecute = true; + } + } + + if (willExecute){ + statusDesc = super.createStatusDesc(); + synchronized (this){ + isRunning = false; + this.notifyAll(); + } + } + + } + + @Override + public String getResult() { + return statusDesc; + } + +} diff --git a/src/main/java/com/acme/commands/Disk/SecureDiskStatusCmd.java b/src/main/java/com/acme/commands/Disk/SecureDiskStatusCmd.java new file mode 100644 index 0000000..98d1982 --- /dev/null +++ b/src/main/java/com/acme/commands/Disk/SecureDiskStatusCmd.java @@ -0,0 +1,49 @@ +package com.acme.commands.Disk; + +import com.acme.beans.DiskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.invoke.MethodHandles; + +/** + * Proxy decorator for ensuring that only registered users can execute the disk status command + */ +public class SecureDiskStatusCmd extends DiskStatusCmd { + private final long Id; + private final String template; + private final String name; + + private DiskStatusCmd cmd; + + protected static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + public SecureDiskStatusCmd(long Id, String template, String name, DiskStatusCmd cmd) { + super(Id, template, name); + + this.Id = Id; + this.template = template; + this.name = name; + this.cmd = cmd; + } + + public SecureDiskStatusCmd(long Id, String template, String name) { + this(Id, template, name, new DiskStatusCmd(Id, template, name)); + } + + @Override + public void execute() { + if (name == null || name.equals("Anonymous")) { + return; + } + + LOGGER.info("User '{}' was allowed to access disk status information", name); + + cmd.execute(); + } + + @Override + public DiskStatus getResult() { + return cmd.getResult(); + } +} diff --git a/src/main/java/com/acme/statusmgr/StatusController.java b/src/main/java/com/acme/statusmgr/StatusController.java index fe6cbf9..99fab13 100644 --- a/src/main/java/com/acme/statusmgr/StatusController.java +++ b/src/main/java/com/acme/statusmgr/StatusController.java @@ -1,7 +1,10 @@ package com.acme.statusmgr; import com.acme.DecoratorFactory; -import com.acme.commands.Disk.BasicDiskStatusCmd; +import com.acme.commands.Disk.DiskStatusCmd; +import com.acme.commands.Disk.FastResponseDiskStatusCmd; +import com.acme.commands.Disk.ResourceEfficientDiskStatusGenerationCmd; +import com.acme.commands.Disk.SecureDiskStatusCmd; import com.acme.commands.Server.BasicServerStatusCmd; import com.acme.commands.Server.DetailedServerStatusCmd; import com.acme.executors.ICommandExecutor; @@ -74,7 +77,9 @@ public ServerStatus getCurrentDetailedServerStatus(@RequestParam(value = "name", @RequestMapping("/disk/status") public DiskStatus getCurrentDiskStatus(@RequestParam(value = "name", defaultValue = "Anonymous") String name) { - BasicDiskStatusCmd cmd = new BasicDiskStatusCmd(counter.incrementAndGet(), template, name); + long Id = counter.incrementAndGet(); + DiskStatusCmd cmd = new DiskStatusCmd(Id, template, name, ResourceEfficientDiskStatusGenerationCmd.getInstance()); + cmd = new SecureDiskStatusCmd(Id, template, name, new FastResponseDiskStatusCmd(Id, template, name, cmd)); executor.executeCommand(cmd); return cmd.getResult(); } diff --git a/src/test/java/com/acme/statusmgr/StatusCommandTests.java b/src/test/java/com/acme/statusmgr/StatusCommandTests.java index edf2622..8171276 100644 --- a/src/test/java/com/acme/statusmgr/StatusCommandTests.java +++ b/src/test/java/com/acme/statusmgr/StatusCommandTests.java @@ -3,7 +3,7 @@ import com.acme.beans.DiskStatus; import com.acme.beans.ServerStatus; import com.acme.beans.complex.ComplexDecoratorFactory; -import com.acme.commands.Disk.BasicDiskStatusCmd; +import com.acme.commands.Disk.DiskStatusCmd; import com.acme.commands.Server.BasicServerStatusCmd; import com.acme.commands.Server.DetailedServerStatusCmd; import com.acme.executors.ICommandExecutor; @@ -83,7 +83,7 @@ public void simplifiedDetailedServerStatusCommandShouldCreateSimplifiedStatus() @Test public void basicDiskStatusCommandShouldCreateBasicStatus() { - BasicDiskStatusCmd cmd = new BasicDiskStatusCmd(5, "Server Status requested by %s", "Anonymous"); + DiskStatusCmd cmd = new DiskStatusCmd(5, "Server Status requested by %s", "Anonymous"); executor.executeCommand(cmd); DiskStatus result = cmd.getResult();