From df77876206efe10119314d2d85213e2ff259e53d Mon Sep 17 00:00:00 2001 From: StevenJW Date: Sun, 7 Jun 2020 22:05:20 +0100 Subject: [PATCH] Upload project. --- .gitignore | 183 +++++++++++++++ build.xml | 73 ++++++ manifest.mf | 3 + src/middleware/Main.java | 30 +++ src/middleware/StressTest.java | 90 ++++++++ src/middleware/StressTestSendMsgServer.java | 48 ++++ src/middleware/agents/AgentAddress.java | 141 ++++++++++++ src/middleware/agents/MetaAgent.java | 209 ++++++++++++++++++ src/middleware/agents/MsgListener.java | 16 ++ src/middleware/agents/Portal.java | 110 +++++++++ src/middleware/agents/Router.java | 123 +++++++++++ src/middleware/agents/UserAgent.java | 76 +++++++ src/middleware/agents/package-info.java | 4 + src/middleware/components/main/MainUI.java | 51 +++++ .../main/nodelistener/NodeListener.java | 101 +++++++++ .../main/nodelistener/package-info.java | 4 + .../components/main/nodeview/NodeTree.java | 207 +++++++++++++++++ .../components/main/nodeview/NodeView.java | 41 ++++ .../main/nodeview/controls/ControlPane.java | 45 ++++ .../main/nodeview/controls/PortalButton.java | 47 ++++ .../main/nodeview/controls/RouterButton.java | 64 ++++++ .../nodeview/controls/UserAgentButton.java | 49 ++++ .../main/nodeview/controls/package-info.java | 4 + .../main/nodeview/package-info.java | 4 + .../components/main/package-info.java | 4 + .../components/useragents/UserAgentUI.java | 68 ++++++ .../useragents/messagefeed/MessageFeed.java | 83 +++++++ .../useragents/messagefeed/package-info.java | 4 + .../useragents/messagesending/MessageBox.java | 43 ++++ .../messagesending/MessageSender.java | 37 ++++ .../messagesending/RecipientBox.java | 23 ++ .../useragents/messagesending/SendButton.java | 74 +++++++ .../messagesending/package-info.java | 4 + .../components/useragents/package-info.java | 4 + src/middleware/message/Message.java | 49 ++++ src/middleware/message/MetaAgentMessage.java | 77 +++++++ .../message/SystemErrorMessage.java | 17 ++ src/middleware/message/SystemMessage.java | 32 +++ src/middleware/message/UserMessage.java | 70 ++++++ src/middleware/message/package-info.java | 4 + .../message/wrapper/MetaAgentWrapper.java | 31 +++ .../message/wrapper/UserAgentWrapper.java | 34 +++ .../message/wrapper/package-info.java | 4 + src/middleware/nodemonitor/NodeMonitor.java | 43 ++++ src/middleware/nodemonitor/package-info.java | 4 + src/middleware/observer/Observer.java | 19 ++ src/middleware/observer/Subject.java | 31 +++ src/middleware/observer/package-info.java | 4 + src/middleware/package-info.java | 4 + src/middleware/socket/Client.java | 81 +++++++ src/middleware/socket/ClientInstance.java | 53 +++++ src/middleware/socket/Server.java | 102 +++++++++ src/middleware/socket/ServerInstance.java | 26 +++ src/middleware/socket/ServerThread.java | 76 +++++++ src/middleware/socket/package-info.java | 4 + 55 files changed, 2832 insertions(+) create mode 100644 .gitignore create mode 100644 build.xml create mode 100644 manifest.mf create mode 100644 src/middleware/Main.java create mode 100644 src/middleware/StressTest.java create mode 100644 src/middleware/StressTestSendMsgServer.java create mode 100644 src/middleware/agents/AgentAddress.java create mode 100644 src/middleware/agents/MetaAgent.java create mode 100644 src/middleware/agents/MsgListener.java create mode 100644 src/middleware/agents/Portal.java create mode 100644 src/middleware/agents/Router.java create mode 100644 src/middleware/agents/UserAgent.java create mode 100644 src/middleware/agents/package-info.java create mode 100644 src/middleware/components/main/MainUI.java create mode 100644 src/middleware/components/main/nodelistener/NodeListener.java create mode 100644 src/middleware/components/main/nodelistener/package-info.java create mode 100644 src/middleware/components/main/nodeview/NodeTree.java create mode 100644 src/middleware/components/main/nodeview/NodeView.java create mode 100644 src/middleware/components/main/nodeview/controls/ControlPane.java create mode 100644 src/middleware/components/main/nodeview/controls/PortalButton.java create mode 100644 src/middleware/components/main/nodeview/controls/RouterButton.java create mode 100644 src/middleware/components/main/nodeview/controls/UserAgentButton.java create mode 100644 src/middleware/components/main/nodeview/controls/package-info.java create mode 100644 src/middleware/components/main/nodeview/package-info.java create mode 100644 src/middleware/components/main/package-info.java create mode 100644 src/middleware/components/useragents/UserAgentUI.java create mode 100644 src/middleware/components/useragents/messagefeed/MessageFeed.java create mode 100644 src/middleware/components/useragents/messagefeed/package-info.java create mode 100644 src/middleware/components/useragents/messagesending/MessageBox.java create mode 100644 src/middleware/components/useragents/messagesending/MessageSender.java create mode 100644 src/middleware/components/useragents/messagesending/RecipientBox.java create mode 100644 src/middleware/components/useragents/messagesending/SendButton.java create mode 100644 src/middleware/components/useragents/messagesending/package-info.java create mode 100644 src/middleware/components/useragents/package-info.java create mode 100644 src/middleware/message/Message.java create mode 100644 src/middleware/message/MetaAgentMessage.java create mode 100644 src/middleware/message/SystemErrorMessage.java create mode 100644 src/middleware/message/SystemMessage.java create mode 100644 src/middleware/message/UserMessage.java create mode 100644 src/middleware/message/package-info.java create mode 100644 src/middleware/message/wrapper/MetaAgentWrapper.java create mode 100644 src/middleware/message/wrapper/UserAgentWrapper.java create mode 100644 src/middleware/message/wrapper/package-info.java create mode 100644 src/middleware/nodemonitor/NodeMonitor.java create mode 100644 src/middleware/nodemonitor/package-info.java create mode 100644 src/middleware/observer/Observer.java create mode 100644 src/middleware/observer/Subject.java create mode 100644 src/middleware/observer/package-info.java create mode 100644 src/middleware/package-info.java create mode 100644 src/middleware/socket/Client.java create mode 100644 src/middleware/socket/ClientInstance.java create mode 100644 src/middleware/socket/Server.java create mode 100644 src/middleware/socket/ServerInstance.java create mode 100644 src/middleware/socket/ServerThread.java create mode 100644 src/middleware/socket/package-info.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba58a22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,183 @@ +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Annotation Processing +.apt_generated + +.sts4-cache/ + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# Sonarlint plugin +.idea/sonarlint \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..89c8962 --- /dev/null +++ b/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project Middleware. + + + diff --git a/manifest.mf b/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/src/middleware/Main.java b/src/middleware/Main.java new file mode 100644 index 0000000..0fdf3d5 --- /dev/null +++ b/src/middleware/Main.java @@ -0,0 +1,30 @@ +package middleware; + +import middleware.components.main.MainUI; + +/** + * Main + * + * @author JLScott1999 + */ +public class Main +{ + + /** + * @param args the command line arguments + */ + public static void main(String[] args) + { + MainUI main = new MainUI(); + +// UserAgent A = new UserAgent("A"); +// UserAgent B = new UserAgent("B"); +// Portal P = new Portal(10); +// P.addAgent(A); +// P.addAgent(B); +// P.start(); +// UserAgentUI Aform = new UserAgentUI(A); +// UserAgentUI Bform = new UserAgentUI(B); + } + +} diff --git a/src/middleware/StressTest.java b/src/middleware/StressTest.java new file mode 100644 index 0000000..e900510 --- /dev/null +++ b/src/middleware/StressTest.java @@ -0,0 +1,90 @@ +package middleware; + +import java.net.UnknownHostException; +import java.time.Duration; +import java.time.LocalDateTime; +import middleware.agents.MsgListener; +import middleware.agents.Portal; +import middleware.agents.Router; +import middleware.agents.UserAgent; + +/** + * + * @author JLScott1999 + */ +public class StressTest +{ + + public static void main(String[] args) throws UnknownHostException + { + Router r1 = new Router(10000, "1.0.0", 50); + Portal p1r1 = new Portal(10000, "1.1.0"); + Portal p2r1 = new Portal(10000, "1.2.0"); + UserAgent u1p1r1 = new UserAgent("1.1.1"); + UserAgent u2p1r1 = new UserAgent("1.1.2"); + UserAgent u1p2r1 = new UserAgent("1.2.1"); + r1.addAgent(p1r1); + r1.addAgent(p2r1); + r1.start(); + //p1r1.addAgent(p2r1); + p1r1.addAgent(u1p1r1); + p1r1.addAgent(u2p1r1); + p1r1.start(); + p2r1.addAgent(u1p2r1); + p2r1.start(); + u1p1r1.addListener(new MsgListener() { + @Override + public void UserAgentMsg(String sender, String msg) + { + LocalDateTime dateTimeMsg = LocalDateTime.parse(msg); + LocalDateTime dateTimeNow = LocalDateTime.now(); + System.out.println(dateTimeMsg + + " " + + dateTimeNow + + " " + + Duration.between(dateTimeMsg, dateTimeNow).toMillis()); + } + }); + + // 1 Portal 2 Useragents + + int SENDMSGCOUNT = 1000; + + new Thread(new Runnable() { + @Override + public void run() + { + for (int i = 0; i < SENDMSGCOUNT; i++) + { + u2p1r1.sendMsg(u2p1r1.getAddress(), "1.1.1", LocalDateTime.now().toString()); + } + } + }).start(); + + for (int i = 0; i < SENDMSGCOUNT; i++) + { + u2p1r1.sendMsg(u2p1r1.getAddress(), "1.1.1", LocalDateTime.now().toString()); + } + + + // 2 Portals 2 Useragents + +// new Thread(new Runnable() { +// @Override +// public void run() +// { +// for (int i = 0; i < SENDMSGCOUNT; i++) +// { +// u1p2r1.sendMsg(u1p2r1.getAddress(), "1.1.1", LocalDateTime.now().toString()); +// } +// } +// }).start(); +// +// for (int i = 0; i < SENDMSGCOUNT; i++) +// { +// u1p2r1.sendMsg(u1p2r1.getAddress(), "1.1.1", LocalDateTime.now().toString()); +// } +// + } + +} diff --git a/src/middleware/StressTestSendMsgServer.java b/src/middleware/StressTestSendMsgServer.java new file mode 100644 index 0000000..9ebc793 --- /dev/null +++ b/src/middleware/StressTestSendMsgServer.java @@ -0,0 +1,48 @@ +package middleware; + +import java.net.UnknownHostException; +import java.time.LocalDateTime; +import middleware.agents.Portal; +import middleware.agents.Router; +import middleware.agents.UserAgent; + +/** + * + * @author JLScott1999 + */ +public class StressTestSendMsgServer +{ + + public static void main(String[] args) throws UnknownHostException + { + Router r2 = new Router(10000, "2.0.0", 100); + Portal p1r2 = new Portal(10000, "2.1.0"); + UserAgent u1p1r2 = new UserAgent("2.1.1"); + r2.addAgent(p1r2); + r2.start(); + //p1r1.addAgent(p2r1); + p1r2.addAgent(u1p1r2); + p1r2.start(); + + r2.connect("1.0.0", "127.0.0.1", 50); + + int SENDMSGCOUNT = 1000; + + new Thread(new Runnable() { + @Override + public void run() + { + for (int i = 0; i < SENDMSGCOUNT; i++) + { + u1p1r2.sendMsg(u1p1r2.getAddress(), "1.1.1", LocalDateTime.now().toString()); + } + } + }).start(); + +// for (int i = 0; i < SENDMSGCOUNT; i++) +// { +// u2p1r1.sendMsg(u2p1r1.getAddress(), "1.1.1", LocalDateTime.now().toString()); +// } + } + +} diff --git a/src/middleware/agents/AgentAddress.java b/src/middleware/agents/AgentAddress.java new file mode 100644 index 0000000..4d44402 --- /dev/null +++ b/src/middleware/agents/AgentAddress.java @@ -0,0 +1,141 @@ +package middleware.agents; + +import java.io.Serializable; +import java.security.InvalidParameterException; + +/** + * Agent Address + * Addresses for metaAgents + * + * @author JLScott1999 + */ +public final class AgentAddress implements Serializable +{ + + private int[] address; + + /** + * Creates an instance of AgentAddress + * @param sections no. of sections in address + * @param addressString address + */ + public AgentAddress(int sections, String addressString) + { + address = new int[sections]; + setAddress(addressString); + } + + /** + * Creates a new instance of AgentAddress + * @param sections no. of sections in address + */ + public AgentAddress(int sections) + { + this(sections, null); + } + + /** + * Creates a new instance of AgentAddress + * Default of 3 sections + * @param addressString address string + */ + public AgentAddress(String addressString) + { + this(3, addressString); + } + + /** + * Creates instance of AgentAddress with a 3 section address + */ + public AgentAddress() + { + this(3); + } + + /** + * Sets valid address based off of given string + * @param addressString addressString + */ + public void setAddress(String addressString) + { + if (addressString != null) + { + int i = 0; + int section = 0; + while (i < addressString.length()) + { + int dot = addressString.indexOf('.', i); + if (dot != -1) + { + address[section++] = Integer.parseInt(addressString.substring(i, dot)); + i = dot + 1; + } + else + { + address[section] = Integer.parseInt(addressString.substring(i, addressString.length())); + i = addressString.length(); + } + } + } + } + + /** + * Gets Address + * @return address + */ + public String getAddress() + { + return toString(); + } + + /** + * Changes value of address at given section + * @param section specified section + * @param value new value + */ + public void setSection(int section, int value) + { + if (inSectionRange(section)) + { + address[section - 1] = value; + } + else + { + throw new InvalidParameterException(); + } + } + + private boolean inSectionRange(int section) + { + return (section > 0 && section <= address.length); + } + + /** + * + * @param section + * @return + */ + public int getSection(int section) + { + if (inSectionRange(section)) + { + return address[section - 1]; + } + else + { + throw new InvalidParameterException(); + } + } + + @Override + public String toString() + { + String result = ""; + for (int i = 0; i < address.length; i++) + { + result += address[i] + ((address.length == i + 1 ? "" : ".")); + } + return result; + } + +} \ No newline at end of file diff --git a/src/middleware/agents/MetaAgent.java b/src/middleware/agents/MetaAgent.java new file mode 100644 index 0000000..de2b1a9 --- /dev/null +++ b/src/middleware/agents/MetaAgent.java @@ -0,0 +1,209 @@ +package middleware.agents; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import middleware.message.MetaAgentMessage; +import middleware.message.SystemErrorMessage; +import middleware.message.wrapper.MetaAgentWrapper; +import middleware.observer.Observer; +import middleware.observer.Subject; + +/** + * MetaAgent + * + * @author JLScott1999 + */ +public abstract class MetaAgent extends LinkedBlockingQueue implements Runnable, Subject +{ + + private AgentAddress address; + private Thread thread; + private boolean running = true; + private ArrayList metaAgent = new ArrayList(); + private List listOfObservers = new ArrayList<>(); + + /** + * Creates a MetaAgent with specified properties + * @param queueSize the size of the blocking queue + * @param addressString address of the MetaAgent + */ + public MetaAgent(int queueSize, String addressString) + { + super(queueSize); + this.address = new AgentAddress(addressString); + } + + /** + * Runs the MessageHandler once thread is started + */ + @Override + public void run() + { + while (running) + { + try + { + msgHandler(super.take()); + } + catch (InterruptedException ex) + { + System.out.println("Exiting"); + } + } + } + + /** + * Starts thread + */ + public void start() + { + if (thread == null) + { + running = true; + thread = new Thread(this); + thread.start(); + } + } + + /** + * Stops thread + */ + public void stop() + { + if (thread != null) + { + running = false; + thread.interrupt(); + thread = null; + } + } + + /** + * Gets MetaAgent's address + * @return MetaAgent's Address + */ + public AgentAddress getAddress() + { + return address; + } + + /** + * Sets MetaAgent's address + * @param addressString MetaAgent's Address + */ + public void setAddress(String addressString) + { + this.address = new AgentAddress(addressString); + } + + /** + * Attaches an observer to the MetaAgent + * @param observer observer to be attached (e.g. NodeListener) + */ + @Override + public void attach(Observer observer) { + listOfObservers.add(observer); + } + + /** + * Detaches an observer from the MetaAgent (if it is attached) + * @param observer observer to be detached + */ + @Override + public void detach(Observer observer) { + if(listOfObservers.contains(observer)){ + listOfObservers.remove(observer); + } + } + + /** + * Updates attached observers with a message + * @param msg the message to be sent to the observers + * @return whether observers were successfully updated + */ + @Override + public boolean updateObservers(Object msg) { + boolean result = false; + for (Observer o : listOfObservers){ + result = o.update(msg); + } + return result; + } + + /** + * Allows for communication between MetaAgents + * Adds a MetaAgent + * @param agent + */ + public void addAgent(MetaAgent agent) + { + // TODO Generate random address + if (!metaAgent.contains(agent)) + { + metaAgent.add(agent); + agent.addAgent(this); + } + } + + /** + * Handles message objects passed to it + * @param data message + */ + public void msgHandler(Object data) + { + if (data instanceof MetaAgentMessage) + { + if (getAddress().getSection(1) != ((MetaAgentMessage) data).getMessage().getRecipient().getSection(1)) + { + boolean sent = false; + for (int i = 0; i < metaAgent.size() && !sent; i++) + { + if (metaAgent.get(i).getAddress().toString().equals(this.getAddress().getSection(1) + ".0.0")) + { + metaAgent.get(i).add(data); + sent = true; + } + } + if(!sent) + { + if (!((MetaAgentMessage) data).getMessage().getSender().getAddress().equals("0.0.0")) + { + add(MetaAgentWrapper.wrap(new SystemErrorMessage(((MetaAgentMessage) data).getMessage().getRecipient() + " Does not exist?", ((MetaAgentMessage) data).getMessage().getSender().getAddress()), 15)); + } + } + } + else + { + boolean sent = false; + for (int i = 0; i < metaAgent.size() && !sent; i++) + { + if (metaAgent.get(i).getAddress().getSection(2) == ((MetaAgentMessage) data).getMessage().getRecipient().getSection(2) && metaAgent.get(i).getAddress().getSection(1) == ((MetaAgentMessage) data).getMessage().getRecipient().getSection(1)) + { + metaAgent.get(i).add(data); + sent = true; + } + } + if(!sent) + { + for (int i = 0; i < metaAgent.size() && !sent; i++) + { + if (metaAgent.get(i).getAddress().getSection(1) == this.getAddress().getSection(1)) + { + metaAgent.get(i).add(data); + sent = true; + } + } + } + if(!sent) + { + if (!((MetaAgentMessage) data).getMessage().getSender().getAddress().equals("0.0.0")) + { + add(MetaAgentWrapper.wrap(new SystemErrorMessage(((MetaAgentMessage) data).getMessage().getRecipient() + " Does not exist?", ((MetaAgentMessage) data).getMessage().getSender().getAddress()), 15)); + } + } + } + } + } + +} diff --git a/src/middleware/agents/MsgListener.java b/src/middleware/agents/MsgListener.java new file mode 100644 index 0000000..57dacf7 --- /dev/null +++ b/src/middleware/agents/MsgListener.java @@ -0,0 +1,16 @@ +package middleware.agents; + +/** + * + * @author JLScott1999 + */ +public interface MsgListener +{ + /** + * + * @param sender + * @param msg + */ + void UserAgentMsg(String sender, String msg); + +} diff --git a/src/middleware/agents/Portal.java b/src/middleware/agents/Portal.java new file mode 100644 index 0000000..db9357c --- /dev/null +++ b/src/middleware/agents/Portal.java @@ -0,0 +1,110 @@ +package middleware.agents; + +import java.util.HashMap; +import middleware.message.MetaAgentMessage; +import middleware.message.SystemErrorMessage; +import middleware.message.UserMessage; +import middleware.message.wrapper.MetaAgentWrapper; + +/** + * MetaAgent Portal, for allowing connection between UserAgents and portals + * + * @author JLScott1999 + */ +public class Portal extends MetaAgent +{ + + private HashMap routingTable = new HashMap(); + + /** + * Creates instance of Portal with specified properties + * @param queueSize size of blocking queue + * @param address address of MetaAgent + */ + public Portal(int queueSize, String address) + { + super(queueSize, address); + } + + /** + * Adds a message to the queue + * @param e message + * @return success + */ + @Override + public boolean add(Object e) + { + if (e instanceof UserMessage) + { + return super.add(MetaAgentWrapper.wrap((UserMessage) e, 15)); + } + else if (e instanceof MetaAgentMessage) + { + return super.add(e); + } + return false; + } + + /** + * Message handler - handles messages passed to it + * @param data the passed message + */ + @Override + public void msgHandler(Object data) + { + if (data instanceof MetaAgentMessage) + { + MetaAgentMessage MAM = (MetaAgentMessage) data; + try + { + routingTable.get(MAM.getMessage().getRecipient().getAddress()).recieveMsg(MetaAgentWrapper.unwrap((MetaAgentMessage) data)); + super.updateObservers(data); + } + catch (Exception e) + { + if (MAM.timeToLive > 0) + { + MAM.decreaseTimeToLive(); + MAM.increaseHops(); + super.msgHandler(MAM); + } + else + { + if (!MAM.getMessage().getSender().getAddress().equals("0.0.0")) + { + super.msgHandler(MetaAgentWrapper.wrap(new SystemErrorMessage(MAM.getMessage().getRecipient().getAddress() + " Does not exist?", MAM.getMessage().getSender().getAddress()), 15)); + } + } + } + } + } + + /** + * Called when requested user agent is not found + * @param agent message without valid recipient + */ + private void NoUserAgentFound(MetaAgentMessage agent) + { + try + { + routingTable.get(agent.getMessage().getSender()).recieveMsg(new SystemErrorMessage(agent.getMessage().getRecipient() + " Does not exist?", agent.getMessage().getSender().getAddress())); + } + catch (Exception e2) + { + super.msgHandler(MetaAgentWrapper.wrap(new SystemErrorMessage(agent.getMessage().getRecipient() + " Does not exist?", agent.getMessage().getSender().getAddress()), Integer.MAX_VALUE)); + } + } + + /** + * Allows for communication between MetaAgents + * Adds a MetaAgent + * @param agent + */ + public void addAgent(UserAgent agent) + { + // TODO Generate random address + routingTable.put(agent.getAddress(), agent); + agent.setMetaAgent(this); + } + +} \ No newline at end of file diff --git a/src/middleware/agents/Router.java b/src/middleware/agents/Router.java new file mode 100644 index 0000000..373d203 --- /dev/null +++ b/src/middleware/agents/Router.java @@ -0,0 +1,123 @@ +package middleware.agents; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.HashMap; +import middleware.message.MetaAgentMessage; +import middleware.message.SystemErrorMessage; +import middleware.message.UserMessage; +import middleware.message.wrapper.MetaAgentWrapper; +import middleware.socket.Client; +import middleware.socket.Server; + +/** + * MetaAgent for Routers allowing for communication between different routers + * + */ +public class Router extends MetaAgent { + + int port; + Inet4Address ipAddress; + private Server listener; + private HashMap sender = new HashMap(); + + /** + * Creates a new instance of MetaAgent Router with given properties + * @param queueSize size of blocking queue + * @param address router address + * @param ipAddressIn ip address + * @param portIn port + * @throws java.net.UnknownHostException + */ + public Router(int queueSize, String address, int portIn) throws UnknownHostException { + super(queueSize, address); + ipAddress = (Inet4Address) Inet4Address.getByName(address); + port = portIn; + listener = new Server(portIn, this); + try + { + listener.create(); + listener.enableListening(); + } catch (IOException ex) + { + ex.printStackTrace(); + } + } + + /** + * Adds a message to the queue + * @param e message + * @return success + */ + @Override + public boolean add(Object e) + { + if (e instanceof UserMessage) + { + return super.add(MetaAgentWrapper.wrap((UserMessage) e, 15)); + } + else if (e instanceof MetaAgentMessage) + { + return super.add(e); + } + return false; + } + + /** + * Creates a connection using specified parameters + * @param addressString + * @param address + * @param port + */ + public void connect(String addressString, String address, int port) + { + Client client = new Client(address, port); + System.out.println(address + " + " + port); + sender.put(addressString, client); + try + { + client.connect(); + } catch (IOException ex) + { + ex.printStackTrace(); + } + + } + + /** + * Handles message objects passed to it + * @param data message + */ + @Override + public void msgHandler(Object data) + { + if (data instanceof MetaAgentMessage) + { + MetaAgentMessage MAM = (MetaAgentMessage) data; + try + { + sender.get(MAM.getMessage().getRecipient().getSection(1) + ".0.0").send((MetaAgentMessage) data); + super.updateObservers(data); + } + catch (Exception e) + { + if (MAM.timeToLive > 0) + { + MAM.decreaseTimeToLive(); + MAM.increaseHops(); + super.msgHandler(MAM); + } + else + { + if (!MAM.getMessage().getSender().getAddress().equals("0.0.0")) + { + super.msgHandler(MetaAgentWrapper.wrap(new SystemErrorMessage(MAM.getMessage().getRecipient().getAddress() + " Does not exist?", MAM.getMessage().getSender().getAddress()), 15)); + } + } + + } + } + } + +} diff --git a/src/middleware/agents/UserAgent.java b/src/middleware/agents/UserAgent.java new file mode 100644 index 0000000..2fe08ab --- /dev/null +++ b/src/middleware/agents/UserAgent.java @@ -0,0 +1,76 @@ +package middleware.agents; + +import java.util.ArrayList; +import middleware.message.Message; +import middleware.message.UserMessage; + +/** + * Agent for a user/node/endpoint + * @author JLScott1999 + */ +public class UserAgent +{ + private String address; + private MetaAgent metaAgent; + private ArrayList listeners = new ArrayList(); + + /** + * Creates an instance of UserAgent with a specified address + * @param address Specified address + */ + public UserAgent(String address) + { + this.address = address; + } + + /** + * Returns the UserAgent's address + * @return address + */ + public String getAddress() + { + return address; + } + + /** + * Used to wrap and send a message to a recipient + * @param sender the sender + * @param recipient the message recipient + * @param message the message content to be sent + */ + public void sendMsg(String sender, String recipient, String message) + { + metaAgent.add(new UserMessage(message, recipient, sender, false, "???", "0")); + } + + /** + * Set's the UserAgent's MetaAgent (e.g. the portal it belongs to) + * @param metaAgent metaAgent to be assigned + */ + public void setMetaAgent(MetaAgent metaAgent) + { + this.metaAgent = metaAgent; + } + + /** + * Used by msgHandler to receive message + * @param data message received + */ + public void recieveMsg(Message data) + { + for (MsgListener listener : listeners) + { + listener.UserAgentMsg(data.getSender().getAddress().toString(), data.getMessage().toString()); + } + } + + /** + * Adds a message listener to the UserAgent + * @param listener Message Listener + */ + public void addListener(MsgListener listener) + { + listeners.add(listener); + } + +} \ No newline at end of file diff --git a/src/middleware/agents/package-info.java b/src/middleware/agents/package-info.java new file mode 100644 index 0000000..f9d7b8e --- /dev/null +++ b/src/middleware/agents/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains classes for the Middleware agents + */ +package middleware.agents; diff --git a/src/middleware/components/main/MainUI.java b/src/middleware/components/main/MainUI.java new file mode 100644 index 0000000..6e67c3c --- /dev/null +++ b/src/middleware/components/main/MainUI.java @@ -0,0 +1,51 @@ +package middleware.components.main; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import middleware.components.main.nodelistener.NodeListener; +import middleware.components.main.nodeview.NodeView; + +/** + * The Main GUI form + * + * @author Dan Lawrence + */ +public class MainUI extends JFrame { + + NodeView nodeView; + + NodeListener nodeListener; + + /** + * Creates the Main UI + */ + public MainUI() { + setUpComponent(); + } + + /** + * Sets up all GUI components for the main GUI + */ + private void setUpComponent() { + nodeListener = new NodeListener(); + + nodeView = new NodeView(nodeListener); + add(nodeView, BorderLayout.WEST); + + JScrollPane nodeListenerScroller = new JScrollPane(nodeListener); + nodeListenerScroller.setPreferredSize(new Dimension(880,200)); + + add(nodeListenerScroller,BorderLayout.EAST); + + setTitle("Middleware"); + + setResizable(false); + + setDefaultCloseOperation(3); + setVisible(true); + + pack(); + } +} diff --git a/src/middleware/components/main/nodelistener/NodeListener.java b/src/middleware/components/main/nodelistener/NodeListener.java new file mode 100644 index 0000000..89a7b20 --- /dev/null +++ b/src/middleware/components/main/nodelistener/NodeListener.java @@ -0,0 +1,101 @@ + +package middleware.components.main.nodelistener; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +/** + * Used to display output from a NodeMonitor + * + * @author Dan Lawrence + */ +public class NodeListener extends JTable { + DefaultTableModel model; + + /** + * Sets up GUI components for NodeListener + */ + public NodeListener() { + setUpComponent(); + } + + private void setUpComponent() { + //TTL: Time to live + String[] headings = {"Time sent/received","Sender","Receiver","Message","TTL","Hops"}; + + model = new DefaultTableModel(headings,0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + + setModel(model); + + setFocusable(false); + setRowSelectionAllowed(false); + + getColumnModel().getColumn(0).setPreferredWidth(130); + getColumnModel().getColumn(0).setMaxWidth(130); + getColumnModel().getColumn(0).setMinWidth(130); + getColumnModel().getColumn(0).setResizable(false); + + getColumnModel().getColumn(1).setPreferredWidth(100); + getColumnModel().getColumn(1).setMaxWidth(100); + getColumnModel().getColumn(1).setMinWidth(100); + getColumnModel().getColumn(1).setResizable(false); + + getColumnModel().getColumn(2).setPreferredWidth(100); + getColumnModel().getColumn(2).setMaxWidth(100); + getColumnModel().getColumn(2).setMinWidth(100); + getColumnModel().getColumn(2).setResizable(false); + + getColumnModel().getColumn(3).setMinWidth(450); + getColumnModel().getColumn(3).setResizable(true); + + getColumnModel().getColumn(4).setPreferredWidth(50); + getColumnModel().getColumn(4).setMaxWidth(50); + getColumnModel().getColumn(4).setMinWidth(50); + getColumnModel().getColumn(4).setResizable(false); + + getColumnModel().getColumn(5).setPreferredWidth(50); + getColumnModel().getColumn(5).setMaxWidth(50); + getColumnModel().getColumn(5).setMinWidth(50); + getColumnModel().getColumn(5).setResizable(false); + + setRowHeight(20); + + setVisible(true); + setOpaque(true); + } + + /** + * Adds a row to the NodeListener Table, using unwrapped message parameters + * @param message message content + * @param sender sender + * @param recipient recipient + * @param ttl Time To Live (TTL) + * @param hops message hops + */ + public void addRow(String message, String sender, String recipient, int ttl, int hops) { + Object[] tableRow = new Object[6]; + + tableRow[0] = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()); + tableRow[1] = sender; + tableRow[2] = recipient; + tableRow[3] = message; + tableRow[4] = ttl; + tableRow[5] = hops; + + model.addRow(tableRow); + } + + /** + * Clears NodeListenerTable + */ + public void clear() { + model.setRowCount(0); + } +} diff --git a/src/middleware/components/main/nodelistener/package-info.java b/src/middleware/components/main/nodelistener/package-info.java new file mode 100644 index 0000000..6317e83 --- /dev/null +++ b/src/middleware/components/main/nodelistener/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the classes for the NodeListener + */ +package middleware.components.main.nodelistener; diff --git a/src/middleware/components/main/nodeview/NodeTree.java b/src/middleware/components/main/nodeview/NodeTree.java new file mode 100644 index 0000000..b6f469f --- /dev/null +++ b/src/middleware/components/main/nodeview/NodeTree.java @@ -0,0 +1,207 @@ + +package middleware.components.main.nodeview; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.net.UnknownHostException; +import java.util.HashMap; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import middleware.agents.MetaAgent; +import middleware.agents.Portal; +import middleware.agents.Router; +import middleware.agents.UserAgent; +import middleware.components.main.nodelistener.NodeListener; +import middleware.components.useragents.UserAgentUI; +import middleware.nodemonitor.NodeMonitor; + +/** + * GUI for NodeTrees + * + * @author Dan Lawrence + */ +public class NodeTree extends JTree implements MouseListener { + + DefaultTreeModel model; + DefaultMutableTreeNode rootNode; + NodeListener nodeListener; + + NodeMonitor nm; + MetaAgent nmMetaAgent; + + HashMap MetaAgentMap = new HashMap(); + HashMap UserAgentMap = new HashMap(); + + int id = 1; + Router router = null; + + /** + * Sets up a NodeTree GUI for given NodeListener + * @param nodeListenerIn NodeListener + */ + public NodeTree(NodeListener nodeListenerIn) { + nodeListener = nodeListenerIn; + + setUpComponent(); + } + + private void setUpComponent() { + rootNode = new DefaultMutableTreeNode("Agents"); + model = new DefaultTreeModel(rootNode); + + addPortal(); + + setModel(model); + + setVisible(true); + + this.addMouseListener(this); + } + + /** + * Adds a Router to the nodetree + * @param ipAddress ip address of router + * @param port router port + * @return index of new router + * @throws UnknownHostException + */ + public int addRouter(int id, String ipAddress, int port) throws UnknownHostException { + DefaultMutableTreeNode routerNode = new DefaultMutableTreeNode(); + rootNode.add(routerNode); + + if (router == null) + { + router = new Router(10, (rootNode.getIndex(routerNode) + id) + ".0.0", port); + router.start(); + MetaAgentMap.put(router.getAddress().getAddress(), router); + } + else + { + router.connect(id + ".0.0", ipAddress, port); + } + this.id = id; + routerNode.setUserObject("Router (" + id + ".0.0)"); + updateUI(); + + return rootNode.getIndex(routerNode) + 1; + } + + /** + * Adds a new portal to the NodeTree + * @return index of the new portal + */ + public int addPortal() { + if (getSelectionPath() == null) + return 0; + + DefaultMutableTreeNode selectedNode = + (DefaultMutableTreeNode) getSelectionPath().getLastPathComponent(); + + String nodeName = (String) selectedNode.getUserObject(); + + if (selectedNode.isRoot() || !nodeName.contains("Router")) + return 0; + + DefaultMutableTreeNode portalNode = new DefaultMutableTreeNode(); + selectedNode.add(portalNode); + + // Add Portals Here + Portal p = new Portal(10, id + "." + (selectedNode.getIndex(portalNode) + 1) + ".0"); + p.start(); + MetaAgentMap.get(String.valueOf(id + ".0.0")).addAgent(p); + MetaAgentMap.values().forEach((metaAgent) -> { + if (metaAgent instanceof Portal) + { + metaAgent.addAgent(p); + } + }); + MetaAgentMap.put(p.getAddress().getAddress(), p); + portalNode.setUserObject("Portal (" + p.getAddress() + ")"); + + updateUI(); + + return rootNode.getIndex(portalNode) + 1; + } + + /** + * Adds a new user agent to the NodeTree + * @return index of new UserAgent + */ + public int addUserAgent() { + if (getSelectionPath() == null) + return 0; + + DefaultMutableTreeNode selectedNode = + (DefaultMutableTreeNode) getSelectionPath().getLastPathComponent(); + + String nodeName = (String) selectedNode.getUserObject(); + + if (selectedNode.isRoot() || !nodeName.contains("Portal")) + return 0; + + DefaultMutableTreeNode userAgentNode = new DefaultMutableTreeNode(); + selectedNode.add(userAgentNode); + + UserAgent userAgent = new UserAgent((id) + "." + + (selectedNode.getParent().getIndex(selectedNode) + 1) + "." + + (selectedNode.getIndex(userAgentNode) + 1)); + ((Portal) MetaAgentMap.get(id + "." + + (selectedNode.getParent().getIndex(selectedNode)+ 1) + + ".0")).addAgent(userAgent); + UserAgentMap.put(userAgent.getAddress(), userAgent); + + userAgentNode.setUserObject("User Agent (" + userAgent.getAddress() + ")" ); + + updateUI(); + + return rootNode.getIndex(userAgentNode) + 1; + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount()==2 && getSelectionPath() != null) { + DefaultMutableTreeNode selectedNode = + (DefaultMutableTreeNode) getSelectionPath().getLastPathComponent(); + + String nodeName = (String) selectedNode.getUserObject(); + + if (nodeName.contains("Router") || nodeName.contains("Portal")) { + if (nm != null && nmMetaAgent != null) + { + nmMetaAgent.detach(nm); + } + + nodeListener.clear(); + //Get Portal + MetaAgent metaAgent = MetaAgentMap.get(nodeName.substring(nodeName.indexOf("(") + 1, nodeName.length() - 1)); + //Attach NodeMonitor + nm = new NodeMonitor(nodeListener); + metaAgent.attach(nm); + nmMetaAgent = metaAgent; + } else if (nodeName.contains("User Agent")) { + new UserAgentUI(UserAgentMap.get(nodeName.substring(nodeName.indexOf("(") + 1, nodeName.length()-1))); + } + } + } + + @Override + public void mousePressed(MouseEvent e) { + //Useless. + } + + @Override + public void mouseReleased(MouseEvent e) { + //Useless. + } + + @Override + public void mouseEntered(MouseEvent e) { + //Useless. + } + + @Override + public void mouseExited(MouseEvent e) { + //Useless. + } +} diff --git a/src/middleware/components/main/nodeview/NodeView.java b/src/middleware/components/main/nodeview/NodeView.java new file mode 100644 index 0000000..a3e86a3 --- /dev/null +++ b/src/middleware/components/main/nodeview/NodeView.java @@ -0,0 +1,41 @@ +package middleware.components.main.nodeview; + +import java.awt.Dimension; +import javax.swing.BoxLayout; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import middleware.components.main.nodelistener.NodeListener; +import middleware.components.main.nodeview.controls.ControlPane; + +/** + * NodeView + * Used to display the NodeTree + * + * @author Dan Lawrence + */ +public class NodeView extends JPanel { + + /** + * Creates an instance of NodeView, with an attached NodeListener + * @param nodeListenerIn nodelistener used to feed data to the view + */ + public NodeView(NodeListener nodeListenerIn) { + setUpComponent(nodeListenerIn); + } + + private void setUpComponent(NodeListener nodeListenerIn) { + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + + NodeTree nodeTree = new NodeTree(nodeListenerIn); + JScrollPane nodeTreePane = new JScrollPane (nodeTree); + nodeTreePane.setPreferredSize(new Dimension(200,400)); + + add(nodeTreePane); + + ControlPane controlPane = new ControlPane(nodeTree); + + add(controlPane); + + setVisible(true); + } +} diff --git a/src/middleware/components/main/nodeview/controls/ControlPane.java b/src/middleware/components/main/nodeview/controls/ControlPane.java new file mode 100644 index 0000000..75b3ad6 --- /dev/null +++ b/src/middleware/components/main/nodeview/controls/ControlPane.java @@ -0,0 +1,45 @@ +package middleware.components.main.nodeview.controls; + +import java.awt.Dimension; +import javax.swing.JPanel; +import middleware.components.main.nodeview.NodeTree; + +/** + * Control Pane + * Handles GUI components for controls of the Node Tree + * + * @author Dan Lawrence + */ +public class ControlPane extends JPanel { + + RouterButton routerButton; + + PortalButton portalButton; + + UserAgentButton userAgentButton; + + /** + * Creates an instance of ControlPane, attached to a NodeTree + * @param nodeTreeIn nodetree which the controls control + */ + public ControlPane(NodeTree nodeTreeIn) { + routerButton = new RouterButton(nodeTreeIn); + + portalButton = new PortalButton(nodeTreeIn); + + userAgentButton = new UserAgentButton(nodeTreeIn); + setUpComponent(); + } + + private void setUpComponent() { + add(routerButton); + + add(portalButton); + + add(userAgentButton); + + setPreferredSize(new Dimension(200,80)); + + setVisible(true); + } +} diff --git a/src/middleware/components/main/nodeview/controls/PortalButton.java b/src/middleware/components/main/nodeview/controls/PortalButton.java new file mode 100644 index 0000000..d52be16 --- /dev/null +++ b/src/middleware/components/main/nodeview/controls/PortalButton.java @@ -0,0 +1,47 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package middleware.components.main.nodeview.controls; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import middleware.components.main.nodeview.NodeTree; + +/** + * PortalButton + * Button used to create portals and add them to the NodeTree + */ +public class PortalButton extends JButton implements ActionListener { + + NodeTree nodeTree; + + /** + * Creates an instance of PortalButton and sets up its components + * @param nodeTreeIn attached nodeTree + */ + public PortalButton(NodeTree nodeTreeIn) { + nodeTree = nodeTreeIn; + + setUpComponent(); + } + + private void setUpComponent() { + setText("Add Portal"); + + setPreferredSize(new Dimension(190,20)); + + setVisible(true); + + addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == this) + nodeTree.addPortal(); + } +} diff --git a/src/middleware/components/main/nodeview/controls/RouterButton.java b/src/middleware/components/main/nodeview/controls/RouterButton.java new file mode 100644 index 0000000..c431e07 --- /dev/null +++ b/src/middleware/components/main/nodeview/controls/RouterButton.java @@ -0,0 +1,64 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package middleware.components.main.nodeview.controls; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.UnknownHostException; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import middleware.components.main.nodeview.NodeTree; + +/** + * RouterButton + * Button used to create and add routers to a NodeTree + * + */ +public class RouterButton extends JButton implements ActionListener { + + NodeTree nodeTree; + + /** + * Creates and sets up button, attached to specified NodeTree + * @param nodeTreeIn NodeTree + */ + public RouterButton(NodeTree nodeTreeIn) { + nodeTree = nodeTreeIn; + + setUpComponent(); + } + + private void setUpComponent() { + setText("Add Router"); + + setPreferredSize(new Dimension(190,20)); + + setVisible(true); + + addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == this) { + String id = (String) JOptionPane.showInputDialog(null, "Router ID", "Set Router ID", JOptionPane.PLAIN_MESSAGE, null, null, ""); + String ipAddress = (String) JOptionPane.showInputDialog(null, "IP Address", "Add Router", JOptionPane.PLAIN_MESSAGE, null, null, ""); + String port = (String) JOptionPane.showInputDialog(null, "Port", "Add Router", JOptionPane.PLAIN_MESSAGE, null, null, ""); + + try + { + nodeTree.addRouter(Integer.parseInt(id), ipAddress, Integer.parseInt(port)); + //nodeTree.addRouter(Integer.parseInt(id), ipAddress, Integer.parseInt(port)); + } + catch (UnknownHostException | NumberFormatException ex) + { + ex.printStackTrace(); + } + } + } + +} diff --git a/src/middleware/components/main/nodeview/controls/UserAgentButton.java b/src/middleware/components/main/nodeview/controls/UserAgentButton.java new file mode 100644 index 0000000..317d380 --- /dev/null +++ b/src/middleware/components/main/nodeview/controls/UserAgentButton.java @@ -0,0 +1,49 @@ + +package middleware.components.main.nodeview.controls; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import middleware.components.main.nodeview.NodeTree; + +/** + * UserAgentButton + * Creates and adds user agents to a node tree + * + * @author Dan Lawrence + */ +public class UserAgentButton extends JButton implements ActionListener{ + + NodeTree nodeTree; + + /** + * Creates button to add User Agents to a node tree + * @param nodeTreeIn + */ + public UserAgentButton(NodeTree nodeTreeIn) { + nodeTree = nodeTreeIn; + + setUpComponent(); + } + + private void setUpComponent() { + setText("Add User Agent"); + + setPreferredSize(new Dimension(190,20)); + + setVisible(true); + + addActionListener(this); + } + + /** + * When an action is performed, adds useragent to nodetree + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == this) + nodeTree.addUserAgent(); + } +} diff --git a/src/middleware/components/main/nodeview/controls/package-info.java b/src/middleware/components/main/nodeview/controls/package-info.java new file mode 100644 index 0000000..84d1ca7 --- /dev/null +++ b/src/middleware/components/main/nodeview/controls/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the controls for the nodeview GUI + */ +package middleware.components.main.nodeview.controls; diff --git a/src/middleware/components/main/nodeview/package-info.java b/src/middleware/components/main/nodeview/package-info.java new file mode 100644 index 0000000..7554650 --- /dev/null +++ b/src/middleware/components/main/nodeview/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the classes for the NodeView GUI + */ +package middleware.components.main.nodeview; diff --git a/src/middleware/components/main/package-info.java b/src/middleware/components/main/package-info.java new file mode 100644 index 0000000..1455b2b --- /dev/null +++ b/src/middleware/components/main/package-info.java @@ -0,0 +1,4 @@ +/** + * The main interface for the Middleware project + */ +package middleware.components.main; diff --git a/src/middleware/components/useragents/UserAgentUI.java b/src/middleware/components/useragents/UserAgentUI.java new file mode 100644 index 0000000..852db1c --- /dev/null +++ b/src/middleware/components/useragents/UserAgentUI.java @@ -0,0 +1,68 @@ + +package middleware.components.useragents; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import middleware.agents.MsgListener; +import middleware.agents.UserAgent; +import middleware.components.useragents.messagefeed.MessageFeed; +import middleware.components.useragents.messagesending.MessageSender; + +/** + * The GUI for UserAgents + * + * @author Dan Lawrence + */ +public class UserAgentUI extends JFrame implements MsgListener +{ + + private final MessageSender messageSender; + private final MessageFeed messageFeed; + private final UserAgent userAgent; + + /** + * Sets up GUI for a UserAgent + * @param userAgent specified UserAgent + */ + public UserAgentUI(UserAgent userAgent) { + messageFeed = new MessageFeed(); + this.userAgent = userAgent; + messageSender = new MessageSender(userAgent, messageFeed); + userAgent.addListener(this); + setUpComponent(); + } + + private void setUpComponent() { + setTitle("User Agent - " + userAgent.getAddress().toUpperCase()); + + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setVisible(true); + + JPanel padding1 = new JPanel(); + padding1.setPreferredSize(new Dimension(10,0)); + + JPanel padding2 = new JPanel(); + padding2.setPreferredSize(new Dimension(10,0)); + + add(padding1, BorderLayout.WEST); + add(padding2, BorderLayout.EAST); + + JScrollPane messageFeedScroller = new JScrollPane(messageFeed); + messageFeedScroller.setPreferredSize(new Dimension(780,200)); + + add(messageFeedScroller, BorderLayout.CENTER); + add(messageSender, BorderLayout.SOUTH); + + pack(); + setMinimumSize(getSize()); + } + + @Override + public void UserAgentMsg(String sender, String msg) + { + messageFeed.addRow(msg, sender.toUpperCase(), userAgent.getAddress().toUpperCase()); + } +} diff --git a/src/middleware/components/useragents/messagefeed/MessageFeed.java b/src/middleware/components/useragents/messagefeed/MessageFeed.java new file mode 100644 index 0000000..6763c53 --- /dev/null +++ b/src/middleware/components/useragents/messagefeed/MessageFeed.java @@ -0,0 +1,83 @@ +package middleware.components.useragents.messagefeed; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +/** + * MessageFeed for UserAgents + * + * @author Dan Lawrence + */ +public class MessageFeed extends JTable { + + DefaultTableModel model; + + /** + * Sets up GUI for MessageFeed + */ + public MessageFeed() { + setUpComponent(); + } + + private void setUpComponent() { + String[] headings = {"Time sent/received","Sender","Receiver","Message"}; + + model = new DefaultTableModel(headings,0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + + setModel(model); + + setFocusable(false); + setRowSelectionAllowed(false); + + getColumnModel().getColumn(0).setPreferredWidth(130); + getColumnModel().getColumn(0).setMaxWidth(130); + getColumnModel().getColumn(0).setMinWidth(130); + getColumnModel().getColumn(0).setResizable(false); + getColumnModel().getColumn(0).setHeaderValue("Time sent/received"); + + getColumnModel().getColumn(1).setPreferredWidth(100); + getColumnModel().getColumn(1).setMaxWidth(100); + getColumnModel().getColumn(1).setMinWidth(100); + getColumnModel().getColumn(1).setResizable(false); + getColumnModel().getColumn(1).setHeaderValue("Sender"); + + getColumnModel().getColumn(2).setPreferredWidth(100); + getColumnModel().getColumn(2).setMaxWidth(100); + getColumnModel().getColumn(2).setMinWidth(100); + getColumnModel().getColumn(2).setResizable(false); + getColumnModel().getColumn(2).setHeaderValue("Receiver"); + + getColumnModel().getColumn(3).setMinWidth(450); + getColumnModel().getColumn(3).setResizable(true); + getColumnModel().getColumn(3).setHeaderValue("Message"); + + setRowHeight(20); + + setVisible(true); + setOpaque(true); + } + + /** + * Adds a row to the table containing specified data + * @param message message content + * @param sender sender agent address + * @param recipient recipient agent address + */ + public void addRow(String message, String sender, String recipient) { + Object[] tableRow = new Object[4]; + + tableRow[0] = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()); + tableRow[1] = sender; + tableRow[2] = recipient; + tableRow[3] = message; + + model.addRow(tableRow); + } +} diff --git a/src/middleware/components/useragents/messagefeed/package-info.java b/src/middleware/components/useragents/messagefeed/package-info.java new file mode 100644 index 0000000..449c65b --- /dev/null +++ b/src/middleware/components/useragents/messagefeed/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the MessageFeed for the UserAgents GUI + */ +package middleware.components.useragents.messagefeed; diff --git a/src/middleware/components/useragents/messagesending/MessageBox.java b/src/middleware/components/useragents/messagesending/MessageBox.java new file mode 100644 index 0000000..9995bf9 --- /dev/null +++ b/src/middleware/components/useragents/messagesending/MessageBox.java @@ -0,0 +1,43 @@ + +package middleware.components.useragents.messagesending; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JTextField; + +/** + * MessageBox. A text field used to type a string message, with the intend to + * send that message to another user. + * + * @author Dan Lawrence + */ +public class MessageBox extends JTextField implements ActionListener { + + RecipientBox recipientBox; + + SendButton sendButton; + + /** + * Constructor. + */ + public MessageBox(RecipientBox recipientBoxIn) { + recipientBox = recipientBoxIn; + + setUpComponent(); + } + + private void setUpComponent() { + setPreferredSize(new Dimension(500,20)); + setVisible(true); + setOpaque(true); + + addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (!getText().equals("") && !recipientBox.getText().equals("")) + sendButton.sendMessage(); + } +} diff --git a/src/middleware/components/useragents/messagesending/MessageSender.java b/src/middleware/components/useragents/messagesending/MessageSender.java new file mode 100644 index 0000000..e6a80aa --- /dev/null +++ b/src/middleware/components/useragents/messagesending/MessageSender.java @@ -0,0 +1,37 @@ + +package middleware.components.useragents.messagesending; + +import javax.swing.JPanel; +import middleware.agents.UserAgent; +import middleware.components.useragents.messagefeed.MessageFeed; + +/** + * MessageSender. + * + * @author Dan Lawrence + */ +public class MessageSender extends JPanel { + + final RecipientBox recipientBox; + + final MessageBox messageBox; + + final SendButton sendButton; + + public MessageSender(UserAgent userAgent, MessageFeed messageFeedIn) { + recipientBox = new RecipientBox(); + messageBox = new MessageBox(recipientBox); + sendButton = new SendButton(userAgent, recipientBox,messageBox,messageFeedIn); + + setUpComponent(); + } + + private void setUpComponent() { + setVisible(true); + + add(recipientBox); + add(messageBox); + add(sendButton); + } + +} diff --git a/src/middleware/components/useragents/messagesending/RecipientBox.java b/src/middleware/components/useragents/messagesending/RecipientBox.java new file mode 100644 index 0000000..be1a066 --- /dev/null +++ b/src/middleware/components/useragents/messagesending/RecipientBox.java @@ -0,0 +1,23 @@ + +package middleware.components.useragents.messagesending; + +import java.awt.Dimension; +import javax.swing.JTextField; + +/** + * RecipientBox. + * + * @author Dan Lawrence + */ +public class RecipientBox extends JTextField { + + public RecipientBox() { + setUpComponent(); + } + + private void setUpComponent() { + setPreferredSize(new Dimension(170,20)); + setVisible(true); + setOpaque(true); + } +} diff --git a/src/middleware/components/useragents/messagesending/SendButton.java b/src/middleware/components/useragents/messagesending/SendButton.java new file mode 100644 index 0000000..0954483 --- /dev/null +++ b/src/middleware/components/useragents/messagesending/SendButton.java @@ -0,0 +1,74 @@ + +package middleware.components.useragents.messagesending; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import middleware.agents.UserAgent; +import middleware.components.useragents.messagefeed.MessageFeed; + +/** + * SendButton. + * + * @author Dan Lawrence + */ +public class SendButton extends JButton implements ActionListener +{ + + final RecipientBox recipientBox; + + final MessageBox messageBox; + + final MessageFeed messageFeed; + + private final UserAgent userAgent; + + /** + * + * @param userAgent + * @param recipientBoxIn + * @param messageBoxIn + * @param messageFeedIn + */ + public SendButton(UserAgent userAgent, RecipientBox recipientBoxIn, MessageBox messageBoxIn, MessageFeed messageFeedIn) { + this.userAgent = userAgent; + recipientBox = recipientBoxIn; + messageBox = messageBoxIn; + messageFeed = messageFeedIn; + + setUpComponent(); + } + + private void setUpComponent() { + messageBox.sendButton = this; + + setPreferredSize(new Dimension(100, 20)); + setVisible(true); + setOpaque(true); + setText("Send"); + + addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if ((e.getSource() == this) && !messageBox.getText().equals("") && !recipientBox.getText().equals("")) { + sendMessage(); + } + } + + void sendMessage() { + String sender = userAgent.getAddress(); + String recipient = recipientBox.getText(); + String message = messageBox.getText(); + + userAgent.sendMsg(sender, recipient, message); + + messageFeed.addRow(message,sender,recipient); + + recipientBox.setText(""); + messageBox.setText(""); + } + +} diff --git a/src/middleware/components/useragents/messagesending/package-info.java b/src/middleware/components/useragents/messagesending/package-info.java new file mode 100644 index 0000000..16a901b --- /dev/null +++ b/src/middleware/components/useragents/messagesending/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the MessageSending GUI classes for UserAgents GUI + */ +package middleware.components.useragents.messagesending; diff --git a/src/middleware/components/useragents/package-info.java b/src/middleware/components/useragents/package-info.java new file mode 100644 index 0000000..c3c29a4 --- /dev/null +++ b/src/middleware/components/useragents/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the GUI for the UserAgents + */ +package middleware.components.useragents; diff --git a/src/middleware/message/Message.java b/src/middleware/message/Message.java new file mode 100644 index 0000000..bc1b802 --- /dev/null +++ b/src/middleware/message/Message.java @@ -0,0 +1,49 @@ +package middleware.message; + +import java.io.Serializable; +import middleware.agents.AgentAddress; + +/** + * Message - sent between nodes + * Containing information + */ +public abstract class Message implements Serializable +{ + private final Object message; //These can be objects + private final AgentAddress recipient; + + /** + * Creates an instance of Message + * @param m Message Content + * @param r Recipient + */ + public Message(Object m, String r) + { + message = m; + recipient = new AgentAddress(r); + } + + /** + * Gets message content + * @return message content + */ + public Object getMessage() + { + return message; + } + + /** + * Gets message recipient + * @return recipient + */ + public AgentAddress getRecipient() + { + return recipient; + } + + /** + * Gets sender + * @return sender + */ + public abstract AgentAddress getSender(); +} diff --git a/src/middleware/message/MetaAgentMessage.java b/src/middleware/message/MetaAgentMessage.java new file mode 100644 index 0000000..762a762 --- /dev/null +++ b/src/middleware/message/MetaAgentMessage.java @@ -0,0 +1,77 @@ +package middleware.message; + +import java.io.Serializable; + +/** + * Type of message used for communications between MetaAgents + */ +public class MetaAgentMessage implements Serializable +{ + private final Message message; + + /** + * The maximum amount of hops a message can take before it is stopped + */ + public int timeToLive; + + /** + * The number of hops a message has taken + */ + public int hops; + + /** + * Creates an instance of MetaAgentMessage + * Wraps an already created message + * @param um message + * @param ttl time to live + */ + public MetaAgentMessage(Message um, int ttl) + { + hops = 0; + message = um; + timeToLive = ttl; + } + + /** + * Gets message + * @return message + */ + public Message getMessage() + { + return message; + } + + /** + * Gets message's TTL + * @return TimeToLive + */ + public int getTimeToLive() + { + return timeToLive; + } + + /** + * Gets no. of hops MetaAgentMessage has taken + * @return hops + */ + public int getHops() + { + return hops; + } + + /** + * Decrements TTL + */ + public void decreaseTimeToLive() + { + timeToLive -= 1; + } + + /** + * Increments TTL + */ + public void increaseHops() + { + hops += 1; + } +} diff --git a/src/middleware/message/SystemErrorMessage.java b/src/middleware/message/SystemErrorMessage.java new file mode 100644 index 0000000..c0100bf --- /dev/null +++ b/src/middleware/message/SystemErrorMessage.java @@ -0,0 +1,17 @@ +package middleware.message; + +/** + * A type of message for system error communication + */ +public class SystemErrorMessage extends SystemMessage +{ + /** + * Creates an instance of SystemErrorMessage + * @param message message content + * @param recipient recipient + */ + public SystemErrorMessage(String message, String recipient) + { + super(message, recipient); + } +} diff --git a/src/middleware/message/SystemMessage.java b/src/middleware/message/SystemMessage.java new file mode 100644 index 0000000..cd6b2b2 --- /dev/null +++ b/src/middleware/message/SystemMessage.java @@ -0,0 +1,32 @@ +package middleware.message; + +import middleware.agents.AgentAddress; + +/** + * A type of message for system communication + */ +public class SystemMessage extends Message +{ + + private final static AgentAddress SYSTEMADDRESS = new AgentAddress("0.0.0"); + + /** + * Creates an instance of System message + * @param m message content + * @param r recipient + */ + public SystemMessage(Object m, String r) + { + super(m, r); + } + + /** + * Gets sender + * @return always "System" + */ + @Override + public AgentAddress getSender() + { + return SYSTEMADDRESS; + } +} \ No newline at end of file diff --git a/src/middleware/message/UserMessage.java b/src/middleware/message/UserMessage.java new file mode 100644 index 0000000..c022e60 --- /dev/null +++ b/src/middleware/message/UserMessage.java @@ -0,0 +1,70 @@ +package middleware.message; + +import middleware.agents.AgentAddress; + +/** + * User message + * A type of message used between Portals (MetaAgent) and UserAgents + */ +public class UserMessage extends Message +{ + private final AgentAddress sender; //Can be object + private final boolean needsResponse; + private final String response; //Can be object + private final String messageID; + + /** + * Constructs an instance of UserMessage with specified properties + * @param m message content + * @param r recipient + * @param s sender + * @param n needs response? + * @param res response content + * @param id message ID + */ + public UserMessage(Object m, String r, String s, boolean n, String res, String id) + { + super(m,r); + sender = new AgentAddress(s); + needsResponse = n; + response = res; + messageID = id; + } + + /** + * Gets a UserMessage's sender + * @return + */ + @Override + public AgentAddress getSender() + { + return sender; + } + + /** + * Gets whether UserMessage requires response + * @return boolean, if needs response + */ + public boolean getNeedsResponse() + { + return needsResponse; + } + + /** + * Gets the response for a UserMessage + * @return Response + */ + public String getResponse() + { + return response; + } + + /** + * Gets the message ID + * @return message ID + */ + public String getMessageID() + { + return messageID; + } +} diff --git a/src/middleware/message/package-info.java b/src/middleware/message/package-info.java new file mode 100644 index 0000000..adecb59 --- /dev/null +++ b/src/middleware/message/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the message classes used for communication in the middleware + */ +package middleware.message; diff --git a/src/middleware/message/wrapper/MetaAgentWrapper.java b/src/middleware/message/wrapper/MetaAgentWrapper.java new file mode 100644 index 0000000..626040a --- /dev/null +++ b/src/middleware/message/wrapper/MetaAgentWrapper.java @@ -0,0 +1,31 @@ +package middleware.message.wrapper; + +import middleware.message.Message; +import middleware.message.MetaAgentMessage; + +/** + * Wraps given data into a MetaAgentMessage + */ +public class MetaAgentWrapper +{ + /** + * Creates a new MetaAgentMessage from given properties + * @param m message content + * @param ttl time to live (TTL) + * @return wrapped MetaAgentMessage + */ + public static MetaAgentMessage wrap(Message m, int ttl) + { + return new MetaAgentMessage(m, ttl); + } + + /** + * Unwraps a given message + * @param m MetaAgentMessage to be unwrapped + * @return message content + */ + public static Message unwrap(MetaAgentMessage m) + { + return m.getMessage(); + } +} diff --git a/src/middleware/message/wrapper/UserAgentWrapper.java b/src/middleware/message/wrapper/UserAgentWrapper.java new file mode 100644 index 0000000..f9bc08c --- /dev/null +++ b/src/middleware/message/wrapper/UserAgentWrapper.java @@ -0,0 +1,34 @@ +package middleware.message.wrapper; + +import middleware.message.UserMessage; + +/** + * Wraps given parameters into a UserMessage + */ +public class UserAgentWrapper +{ + /** + * Creates a new UserMessage with given properties + * @param m message content + * @param r recipient + * @param sender sender + * @param n requires response? + * @param res response content + * @param id message id + * @return Created UserMessage + */ + public static UserMessage wrap(Object m, String r, String sender, boolean n, String res, String id) + { + return new UserMessage(m, r, sender, n, res, id); + } + + /** + * Unwraps a specified user message + * @param m user message + * @return message content + */ + public static Object unwrap(UserMessage m) + { + return m.getMessage(); + } +} diff --git a/src/middleware/message/wrapper/package-info.java b/src/middleware/message/wrapper/package-info.java new file mode 100644 index 0000000..d314411 --- /dev/null +++ b/src/middleware/message/wrapper/package-info.java @@ -0,0 +1,4 @@ +/** + * The main interface for the Middleware project + */ +package middleware.message.wrapper; diff --git a/src/middleware/nodemonitor/NodeMonitor.java b/src/middleware/nodemonitor/NodeMonitor.java new file mode 100644 index 0000000..89ce668 --- /dev/null +++ b/src/middleware/nodemonitor/NodeMonitor.java @@ -0,0 +1,43 @@ +package middleware.nodemonitor; + +import middleware.components.main.nodelistener.NodeListener; +import middleware.message.MetaAgentMessage; +import middleware.observer.Observer; + +/** + * NodeMonitor created to read messages received by a node (e.g. meta agent, agent) and add them to the GUI + * + * @author Dylan Currey + * @since 12/12/18 + */ +public class NodeMonitor implements Observer{ + + + private NodeListener nodeListener; + + /** + * Creates an instance, using a passed GUI component + * @param nodeListener a GUI component, to be updated by NodeMonitor + */ + public NodeMonitor(NodeListener nodeListener) + { + this.nodeListener = nodeListener; + } + + /** + * Parses and updates GUI from received message + * @param msg the message object received by the attached subject + * @return whether operation was successful + */ + @Override + public boolean update(Object msg) { + if(msg instanceof MetaAgentMessage) + { + MetaAgentMessage MAM = (MetaAgentMessage) msg; + nodeListener.addRow(MAM.getMessage().getMessage().toString(), MAM.getMessage().getSender().getAddress(), MAM.getMessage().getRecipient().getAddress(), MAM.getTimeToLive(), MAM.getHops()); + return true; + } + return false; + } + +} diff --git a/src/middleware/nodemonitor/package-info.java b/src/middleware/nodemonitor/package-info.java new file mode 100644 index 0000000..b48c999 --- /dev/null +++ b/src/middleware/nodemonitor/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the NodeMonitor classes which can be attached to MetaAgents + */ +package middleware.nodemonitor; diff --git a/src/middleware/observer/Observer.java b/src/middleware/observer/Observer.java new file mode 100644 index 0000000..edb08c6 --- /dev/null +++ b/src/middleware/observer/Observer.java @@ -0,0 +1,19 @@ +package middleware.observer; + +/** + * An Observer interface created to facilitate the implementation of the Observer design pattern between UserAgents and NodeMonitors. + * + * @author Dylan Currey + * @since 12/12/18 + */ +public interface Observer { + + /** + * Updates the Observer with the specified command + * @param msg + * @return + */ + public boolean update(Object msg); + +} + diff --git a/src/middleware/observer/Subject.java b/src/middleware/observer/Subject.java new file mode 100644 index 0000000..b57846d --- /dev/null +++ b/src/middleware/observer/Subject.java @@ -0,0 +1,31 @@ +package middleware.observer; + +/** + * A Subject interface created to facilitate the implementation of the Observer design pattern between UserAgents and NodeMonitors + * + * @author Dylan Currey + * @since 12/12/18 + */ +public interface Subject +{ + + /** + * Attaches observers to the subject. + * @param observer the Observer object to be attached. + */ + public void attach(Observer observer); + + /** + * Detaches observers from the subject + * @param observer the Observer object to be detached + */ + public void detach (Observer observer); + + /** + * Updates all observers in listOfObservers with a command. + * @param msg + * @return + */ + public boolean updateObservers(Object msg); + +} \ No newline at end of file diff --git a/src/middleware/observer/package-info.java b/src/middleware/observer/package-info.java new file mode 100644 index 0000000..8c8f4ef --- /dev/null +++ b/src/middleware/observer/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains classes for implementing the Observer pattern + */ +package middleware.observer; diff --git a/src/middleware/package-info.java b/src/middleware/package-info.java new file mode 100644 index 0000000..645a094 --- /dev/null +++ b/src/middleware/package-info.java @@ -0,0 +1,4 @@ +/** + * The main interface for the Middleware project + */ +package middleware; diff --git a/src/middleware/socket/Client.java b/src/middleware/socket/Client.java new file mode 100644 index 0000000..0c68302 --- /dev/null +++ b/src/middleware/socket/Client.java @@ -0,0 +1,81 @@ +package middleware.socket; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import middleware.message.MetaAgentMessage; + +/** + * Client + * Acts as client in client-server relationship + */ +public class Client +{ + //Socket variables (for connection) + private Socket socket; + private String address; + private int port; + + //Socket input and output variables + private PrintWriter writer; + private ObjectOutputStream objOut; + + /** + * Creates an instance of Client + * @param a address + * @param p port + */ + public Client(String a, int p) + { + address = a; + port = p; + } + + /** + * Creates a connection with a socket and output stream + * @throws IOException + */ + public void connect() throws IOException + { + //Create new socket + socket = new Socket(address, port); + + //Declare the output stream + //writer = new PrintWriter(socket.getOutputStream()); + objOut = new ObjectOutputStream(socket.getOutputStream()); + } + + /** + * Sends a String to a socket, may be used when communicating with other languages + * @param s string to be sent + */ + public void sendString(String s) + { + //TODO maybe? + } + + /** + * Sends serialisable objects (e.g. messages, in this case) to a socket + * @param message message, serialisable to be sent + * @throws IOException + */ + public void send(MetaAgentMessage message) throws IOException + { + //Write the object/message to the stream + objOut.writeObject((MetaAgentMessage) message); + //Flush the stream, is nice to have + objOut.flush(); + } + + /** + * Closes all connections + * @throws IOException + */ + public void close() throws IOException + { + //Close all connections and writers + socket.close(); + writer.close(); + } +} diff --git a/src/middleware/socket/ClientInstance.java b/src/middleware/socket/ClientInstance.java new file mode 100644 index 0000000..f1aabff --- /dev/null +++ b/src/middleware/socket/ClientInstance.java @@ -0,0 +1,53 @@ +package middleware.socket; + +import java.io.IOException; +import java.util.Scanner; +import middleware.message.Message; +import middleware.message.MetaAgentMessage; +import middleware.message.UserMessage; + +/** + * Runs an instance of Client + */ +public class ClientInstance +{ + /** + * + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException + { + + + //Input message stuff + System.out.println("Client"); + + Scanner sc = new Scanner(System.in); + System.out.print("Please input the server IP: "); + String ip = sc.nextLine(); + System.out.print("Please input the port: "); + int port = sc.nextInt(); + + Client client = new Client(ip, port); + client.connect(); + + sc.nextLine(); + + + String message, target; + for(;;) + { + System.out.print("Please enter target address: "); + target = sc.nextLine(); + System.out.print("Please enter message: "); + message = sc.nextLine(); + + //Meta agent stuff + MetaAgentMessage metaAgentMessage = new MetaAgentMessage(new UserMessage(message, target, "3", false, "", "MID"), 1000); + + client.send(metaAgentMessage); + } + + } +} diff --git a/src/middleware/socket/Server.java b/src/middleware/socket/Server.java new file mode 100644 index 0000000..68070fa --- /dev/null +++ b/src/middleware/socket/Server.java @@ -0,0 +1,102 @@ +package middleware.socket; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import middleware.agents.Router; + +/** + * Server acts as server in Client-Server Communications + */ +public class Server +{ + private ServerSocket serverSocket; + private Socket socket; + private int port; + private InetAddress address; + + private Router router; + + private boolean listening; + + + + /** + * Creates an instance of Server with given properties + * @param p port + */ + public Server(int p, Router r) + { + //address = a; + port = p; + router = r; + + } + + /** + * Creates a new server socket on Server's port + * @throws IOException + */ + public void create() throws IOException + { + //serverSocket = new ServerSocket(port, 50, address); + serverSocket = new ServerSocket(port); + } + + /** + * Accepts input from socket + * @throws IOException + */ + private void listen() throws IOException + { + final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10); + + Runnable serverTask = new Runnable() + { + @Override + public void run() + { + try + { + for (;;) + { + socket = serverSocket.accept(); + new ServerThread(socket, router).start(); + System.out.println("Connected: " + socket.toString()); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + }; + + Thread serverThread = new Thread(serverTask); + serverThread.start(); + } + + /** + * Server starts listening to socket input + * @throws IOException + */ + public void enableListening() throws IOException + { + if (!listening) + { + listening = true; + listen(); + } + } + + /** + * Stops Server listening to socket + */ + public void disableListening() + { + listening = false; + } +} diff --git a/src/middleware/socket/ServerInstance.java b/src/middleware/socket/ServerInstance.java new file mode 100644 index 0000000..fa8a60a --- /dev/null +++ b/src/middleware/socket/ServerInstance.java @@ -0,0 +1,26 @@ +package middleware.socket; + +import java.io.IOException; +import java.util.Scanner; + +/** + * Runs an instance of Server + */ +public class ServerInstance +{ + /** + * + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException + { + System.out.println("Server"); + Scanner sc = new Scanner(System.in); + System.out.print("Please input a port: "); + int port = sc.nextInt(); + Server server = new Server(port, null); + server.create(); + server.enableListening(); + } +} diff --git a/src/middleware/socket/ServerThread.java b/src/middleware/socket/ServerThread.java new file mode 100644 index 0000000..57d8405 --- /dev/null +++ b/src/middleware/socket/ServerThread.java @@ -0,0 +1,76 @@ +package middleware.socket; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.net.Socket; +import middleware.agents.Router; +import middleware.message.MetaAgentMessage; + +/** + * A type of thread for running Server objects + */ +public class ServerThread extends Thread +{ + private Socket socket; + private Router router; + + /** + * Creates an instance of ServerThread with given property + * @param client client socket + */ + public ServerThread (Socket client, Router r) + { + socket = client; + router = r; + } + + /** + * Closes connection + * @throws IOException + */ + public void close() throws IOException + { + socket.close(); + } + + /** + * Runs thread + */ + @Override + public void run() + { + ObjectInputStream objIn = null; + + try + { + objIn = new ObjectInputStream(socket.getInputStream()); + } + catch (Exception e) + { + e.printStackTrace(); + } + + //Object input; + MetaAgentMessage input; + for(;;) + { + try + { + input = (MetaAgentMessage) objIn.readObject(); + //out.flush(); + System.out.println("Object is of type: " + input.getClass().getSimpleName()); + System.out.println(input); + + if (router != null) + router.add(input); + //INPUT IS THE MESSAGE HERE + //SHOULD STICK AT THE readLine CODE UNTIL A LINE IS DETECTED + //CAN USE RETURN TO BREAK OUT OF LOOP IF NEEDED + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } +} diff --git a/src/middleware/socket/package-info.java b/src/middleware/socket/package-info.java new file mode 100644 index 0000000..7b2d539 --- /dev/null +++ b/src/middleware/socket/package-info.java @@ -0,0 +1,4 @@ +/** + * + */ +package middleware.socket;