diff options
20 files changed, 1307 insertions, 23 deletions
diff --git a/src/main/java/derms/ReplicaManager.java b/src/main/java/derms/ReplicaManager.java index 414cdf0..85cdbe8 100644 --- a/src/main/java/derms/ReplicaManager.java +++ b/src/main/java/derms/ReplicaManager.java @@ -54,7 +54,7 @@ public class ReplicaManager { replica = new derms.replica2.Replica2(new derms.replica2.City(), this); break; case 3: - replica = new derms.replica2.Replica2(new derms.replica2.City(), this); + replica = new derms.replica3.Replica3(new derms.replica3.City(), this); break; case 4: replica = new derms.replica2.Replica2(new derms.replica2.City(), this); @@ -151,4 +151,6 @@ public class ReplicaManager { e.printStackTrace(); } } + + public int getReplicaId() { return replicaId; } }
\ No newline at end of file diff --git a/src/main/java/derms/Request.java b/src/main/java/derms/Request.java index 80c7d5a..3b75db3 100644 --- a/src/main/java/derms/Request.java +++ b/src/main/java/derms/Request.java @@ -14,6 +14,7 @@ public class Request implements MessagePayload { private int sequenceNumber = 0; private String MessageType = "00"; private int retryCount = 1; + private int reqId; public Request(String function, String clientID) { setFunction(function); @@ -123,6 +124,10 @@ public class Request implements MessagePayload { retryCount--; } + public int getId() { return reqId; } + + public void setId(int id) { reqId = id; } + //Message Format: Sequence_id;FrontIpAddress;Message_Type;function(addResource,...);userID; newEventID;newEventType; oldEventID; oldEventType;bookingCapacity @Override public String toString() { diff --git a/src/main/java/derms/Response.java b/src/main/java/derms/Response.java index c9787f8..28a2bbd 100644 --- a/src/main/java/derms/Response.java +++ b/src/main/java/derms/Response.java @@ -15,6 +15,7 @@ public class Response implements MessagePayload { private int duration = 0; private String udpMessage = ""; private boolean isSuccess = false; + private int requestId; public Response(String udpMessage) { setUdpMessage(udpMessage.trim()); @@ -44,6 +45,15 @@ public class Response implements MessagePayload { setDuration(1); } + public Response(Request req, int rmNumber, String response, boolean isSuccess) { + this.sequenceID = req.getSequenceNumber(); + this.response = response; + this.rmNumber = rmNumber; + this.function = req.getFunction(); + this.isSuccess = isSuccess; + this.requestId = req.getId(); + } + @Override public int hash() { return sequenceID + response.hashCode() + rmNumber + function.hashCode() @@ -153,6 +163,10 @@ public class Response implements MessagePayload { return isSuccess; } + public int getRequestId() { return requestId; } + + public void setRequestId(int id) { requestId = id; } + @Override public boolean equals(Object obj) { if (obj != null) { @@ -167,4 +181,10 @@ public class Response implements MessagePayload { } return false; } + + //Message Format: Sequence_id;FrontIpAddress;Message_Type;function(addResource,...);userID; newEventID;newEventType; oldEventID; oldEventType;bookingCapacity + @Override + public String toString() { + return getResponse(); + } } diff --git a/src/main/java/derms/client/CLI.java b/src/main/java/derms/client/CLI.java new file mode 100644 index 0000000..05f4e35 --- /dev/null +++ b/src/main/java/derms/client/CLI.java @@ -0,0 +1,86 @@ +package derms.client; + +import java.util.*; + +abstract class CLI implements Runnable { + protected Map<String, Command> commands = new HashMap<String, Command>(); + protected List<Description> cmdDescriptions = new ArrayList<Description>(); + protected List<Description> argDescriptions = new ArrayList<Description>(); + + protected CLI() { + commands.put("quit", new Quit()); + cmdDescriptions.add(new Description("quit", "Exit the program")); + + commands.put("help", new Help()); + cmdDescriptions.add(new Description("help", "List commands")); + } + + @Override + public void run() { + Scanner scanner = new Scanner(System.in); + System.out.println("Type 'help' for a list of commands."); + for (;;) { + System.out.print("Command: "); + String input = scanner.nextLine(); + String[] fields = input.split(" "); + if (fields.length < 1 || fields[0] == "") { + continue; + } + Command cmd = commands.get(fields[0]); + if (cmd == null) { + System.out.println("Invalid command '"+fields[0]+"'"); + System.out.println("Type 'help' for a list of commands."); + continue; + } + String[] args = null; + if (fields.length < 2) { + args = new String[0]; + } else { + args = Arrays.copyOfRange(fields, 1, fields.length); + } + cmd.exec(args); + } + } + + protected interface Command { + public void exec(String[] args); + } + + protected class Quit implements Command { + @Override + public void exec(String[] args) { + System.out.println("Shutting down..."); + System.exit(1); + } + } + + protected class Help implements Command { + @Override + public void exec(String[] args) { + System.out.println("\nCommands:"); + for (Description d : cmdDescriptions) { + System.out.println(d); + } + System.out.println("\nArguments:"); + for (Description d : argDescriptions) { + System.out.println(d); + } + System.out.println(); + } + } + + protected class Description { + String object; /// The thing being described + String description; + + protected Description(String object, String description) { + this.object = object; + this.description = description; + } + + @Override + public String toString() { + return object+"\n\t"+description; + } + } +} diff --git a/src/main/java/derms/client/Client.java b/src/main/java/derms/client/Client.java index 11e863f..7069f54 100644 --- a/src/main/java/derms/client/Client.java +++ b/src/main/java/derms/client/Client.java @@ -9,14 +9,12 @@ import javax.xml.ws.Service; import java.net.MalformedURLException; import java.net.URL; -public abstract class Client { +class Client { public static final String namespace = "frontend.derms"; public static final QName qname = new QName("http://"+namespace+"/", DERMSServerImpl.class.getSimpleName()+"Service"); - protected final DERMSInterface server; - - protected Client(String FEhost) throws MalformedURLException { + static DERMSInterface connectToServer(String FEhost) throws MalformedURLException { URL url = new URL(FE.endpointURL(FEhost) + "?wsdl"); - this.server = Service.create(url, qname).getPort(DERMSInterface.class); + return Service.create(url, qname).getPort(DERMSInterface.class); } } diff --git a/src/main/java/derms/client/ResponderClient.java b/src/main/java/derms/client/ResponderClient.java index af5dc3d..57bb132 100644 --- a/src/main/java/derms/client/ResponderClient.java +++ b/src/main/java/derms/client/ResponderClient.java @@ -1,36 +1,103 @@ package derms.client; +import derms.frontend.DERMSInterface; + import java.net.MalformedURLException; -public class ResponderClient extends Client { - public static final String usage = "Usage: java derms.client.ResponderClienet <FE host>"; +public class ResponderClient extends CLI { + public static final String usage = "Usage: java derms.client.ResponderClientCLI <FE host>"; + + private final DERMSInterface server; + + private ResponderClient(String FEhost) throws MalformedURLException { + server = Client.connectToServer(FEhost); + + commands.put("add", new Add()); + cmdDescriptions.add(new Description( + "add <resource ID> <resource type> <duration>", + "Add ad resource to the server")); + + commands.put("remove", new Remove()); + cmdDescriptions.add(new Description( + "remove <resource ID> <duration>", + "Decrease the duration of a resource. If duration is negative, the resource is removed entirely.")); - public ResponderClient(String FEhost) throws MalformedURLException { - super(FEhost); + commands.put("list", new List()); + cmdDescriptions.add(new Description( + "list <resource name>", + "List available resources")); } public static void main(String[] args) { if (args.length < 1) { - System.err.println("Missing argument 'FE host'"); + System.err.println(usage); System.exit(1); } String FEhost = args[0]; - ResponderClient client = null; try { - client = new ResponderClient(FEhost); + (new ResponderClient(FEhost)).run(); } catch (MalformedURLException e) { - System.err.println(e.getMessage()); - System.exit(1); + e.printStackTrace(); + } + } + + private class Add implements Command { + @Override + public void exec(String[] args) { + if (args.length < 3) + System.out.println("invalid arguments for 'add'"); + else + add(args[0], args[1], args[2]); } - System.out.println("Adding resource..."); - String response = client.addResource("MTL1234", "AMBULANCE", 100); - System.out.println("Response: " + response); + private void add(String resourceID, String resourceName, String durationStr) { + try { + int duration = Integer.parseInt(durationStr); + if (duration < 0) { + throw new NumberFormatException("duration less than 0"); + } + String response = server.addResource(resourceID, resourceName, duration); + System.out.println(response); + } catch (NumberFormatException e) { + System.out.println("invalid duration: " + durationStr); + } + } } - public String addResource(String resourceID, String resourceName, int duration) { - return server.addResource(resourceID, resourceName, duration); + private class Remove implements Command { + @Override + public void exec(String[] args) { + if (args.length < 2) + System.out.println("invalid arguments for 'remove'"); + else + remove(args[0], args[1]); + } + + private void remove(String resourceID, String durationStr) { + try { + int duration = Integer.parseInt(durationStr); + String response = server.removeResource(resourceID, duration); + System.out.println(response); + } catch (NumberFormatException e) { + System.out.println("invalid duration: " + durationStr); + } + } + } + + private class List implements Command { + @Override + public void exec(String[] args) { + if (args.length < 1) + System.out.println("invalid arguments for 'list'"); + else + list(args[0]); + } + + private void list(String resourceName) { + String response = server.listResourceAvailability(resourceName); + System.out.println(response); + } } } diff --git a/src/main/java/derms/frontend/DERMSServerImpl.java b/src/main/java/derms/frontend/DERMSServerImpl.java index 663bc47..fda6717 100644 --- a/src/main/java/derms/frontend/DERMSServerImpl.java +++ b/src/main/java/derms/frontend/DERMSServerImpl.java @@ -171,7 +171,11 @@ public class DERMSServerImpl implements DERMSInterface { Response res3 = null; Response res4 = null; for (Response response :responses) { - if (response.getSequenceID() == request.getSequenceNumber()) { + System.out.println("Response: " + response.getResponse()); + System.out.println("Response ID: " + response.getRequestId()); + System.out.println("Request ID: " + request.getId()); + System.out.println("Response RM number: " + response.getRmNumber()); + if (response.getRequestId() == request.getId()) { switch (response.getRmNumber()) { case 1: res1 = response; diff --git a/src/main/java/derms/frontend/FE.java b/src/main/java/derms/frontend/FE.java index 2665116..8d6fc59 100644 --- a/src/main/java/derms/frontend/FE.java +++ b/src/main/java/derms/frontend/FE.java @@ -100,6 +100,7 @@ public class FE { private static int sendUnicastToSequencer(Request requestFromClient) { int sequenceID = sequenceIDGenerator.incrementAndGet(); + requestFromClient.setId(sequenceID); try { sequencerSock.send(requestFromClient); } catch (IOException e) { diff --git a/src/main/java/derms/net/rmulticast/Heartbeat.java b/src/main/java/derms/net/rmulticast/Heartbeat.java index 5dac49d..30e8d42 100644 --- a/src/main/java/derms/net/rmulticast/Heartbeat.java +++ b/src/main/java/derms/net/rmulticast/Heartbeat.java @@ -57,6 +57,7 @@ class Heartbeat implements Runnable { nacks.toArray(new MessageID[0])); ByteBuffer buf = Serial.encode(msg); sock.send(buf, group); + log.info("Sent " + msg); acks.clear(); } } diff --git a/src/main/java/derms/net/rmulticast/MessageID.java b/src/main/java/derms/net/rmulticast/MessageID.java index 70680b2..c760b53 100644 --- a/src/main/java/derms/net/rmulticast/MessageID.java +++ b/src/main/java/derms/net/rmulticast/MessageID.java @@ -1,6 +1,8 @@ package derms.net.rmulticast; -class MessageID { +import java.io.Serializable; + +class MessageID implements Serializable { int id; MessageID(int id) { diff --git a/src/main/java/derms/replica2/Replica2.java b/src/main/java/derms/replica2/Replica2.java index e004fe6..251754d 100644 --- a/src/main/java/derms/replica2/Replica2.java +++ b/src/main/java/derms/replica2/Replica2.java @@ -144,7 +144,7 @@ public class Replica2 implements Replica { status = "Failure: " + request.getFunction() + ": " + e.getMessage(); } - Response response = new Response(request.getSequenceNumber(), status); + Response response = new Response(request, replicaManager.getReplicaId(), status, false); // TODO: isSuccess flag log.info("Processed request " + request + "; response: " + response); replicaManager.sendResponseToFE(response); } diff --git a/src/main/java/derms/replica3/City.java b/src/main/java/derms/replica3/City.java new file mode 100644 index 0000000..89fd8ce --- /dev/null +++ b/src/main/java/derms/replica3/City.java @@ -0,0 +1,40 @@ +package derms.replica3; + +import java.io.Serializable; + +public class City implements Serializable { + static final int codeLen = 3; + + private String code; + + City(String code) throws IllegalArgumentException { + if (code.length() != codeLen) + throw new IllegalArgumentException("Invalid city: "+code+"; must be "+codeLen+" letters"); + this.code = code; + } + + public City() { + this("XXX"); + } + public String getCode(){ + return code; + } + @Override + public String toString() { + return code; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || this.getClass() != obj.getClass()) { + return false; + } + City other = (City) obj; + return this.code.equals(other.code); + } + + @Override + public int hashCode() { + return code.hashCode(); + } +} diff --git a/src/main/java/derms/replica3/Constants.java b/src/main/java/derms/replica3/Constants.java new file mode 100644 index 0000000..f142a4f --- /dev/null +++ b/src/main/java/derms/replica3/Constants.java @@ -0,0 +1,17 @@ +package derms.replica3; + +public class Constants { + public static final String MONTREAL = "MTL"; + public static final String QUEBEC = "QUE"; + public static final String SHERBROOKE = "SHE"; + + //Address for Servers +// public static final String MONTREAL_ADDRESS = "http://localhost:8085/service/" + Constants.MONTREAL; +// public static final String QUEBEC_ADDRESS = "http://localhost:8090/service/" + Constants.QUEBEC; +// public static final String SHERBROOKE_ADDRESS = "http://localhost:8091/service/" + Constants.SHERBROOKE; +// +// //WSDL URLS +// public static final String MONTREAL_WSDL_URL = Constants.MONTREAL_ADDRESS + "?wsdl"; +// public static final String QUEBEC_WSDL_URL = Constants.QUEBEC_ADDRESS + "?wsdl"; +// public static final String SHERBROOKE_WSDL_URL = Constants.SHERBROOKE_ADDRESS + "?wsdl"; +} diff --git a/src/main/java/derms/replica3/Logger.java b/src/main/java/derms/replica3/Logger.java new file mode 100644 index 0000000..15124c5 --- /dev/null +++ b/src/main/java/derms/replica3/Logger.java @@ -0,0 +1,60 @@ +package derms.replica3; + + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.text.DateFormat; +import java.util.Date; + +public class Logger { + private FileWriter fileWriter = null; + private BufferedWriter bufferedWriter = null; + private PrintWriter printWriter = null; + + public Logger(final String activityLoggerFile) throws IOException { + fileWriter = new FileWriter(activityLoggerFile, true); + bufferedWriter = new BufferedWriter(fileWriter); + printWriter = new PrintWriter(bufferedWriter); + } + + public synchronized void log( String action, String status, String res) { + try { + final String dataLog = DateFormat.getDateTimeInstance().format(new Date()) + " [" + + action + "] : [" + status + "] - " + res; + + printWriter.println(dataLog); + System.out.println(dataLog); + bufferedWriter.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public synchronized void clientLog(final String userId, final String action, final String message) { + try { + final String dataLog = DateFormat.getDateTimeInstance().format(new Date()) + " [" + userId + "] [" + + action + "] - " + message; + printWriter.println(dataLog); + System.out.println(dataLog); + bufferedWriter.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public synchronized void clientLog(final String userId, final String action) { + try { + final String dataLog = DateFormat.getDateTimeInstance().format(new Date()) + " [" + userId + "] " + " [" + + action + "] "; + printWriter.println(dataLog); + System.out.println(dataLog); + bufferedWriter.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/derms/replica3/MTLServer.java b/src/main/java/derms/replica3/MTLServer.java new file mode 100644 index 0000000..9e7ea5c --- /dev/null +++ b/src/main/java/derms/replica3/MTLServer.java @@ -0,0 +1,113 @@ +package derms.replica3; + +//import logger.Logger; + + +import javax.xml.ws.Endpoint; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; +import java.nio.charset.StandardCharsets; + +import derms.replica3.Constants; +import derms.replica3.Constants; + +public class MTLServer { + public static void main(String[] args) { + + try{ + final Logger activityLogger = new Logger("MTLServer.log"); + int udpPort = PortConstants.getUdpPort("MTL"); + City ct = new City("MTL"); + final Replica3 ServerImpl = new Replica3(ct, null); +// Endpoint endpoint = Endpoint.publish(Constants.MONTREAL_ADDRESS, ServerImpl); + + /*Start UDP server for MTL*/ + new Thread(() -> { + startUdpServer(activityLogger, ServerImpl, udpPort); + }).start(); + + System.out.println("#=== MTL Server is started ===#"); + + } catch (Exception e) { + System.err.println("ERROR: " + e); + e.printStackTrace(System.out); + } + } + + private static void startUdpServer(final Logger activityLogger, final Replica3 server, int udpPort) { + DatagramSocket socket = null; + try { + socket = new DatagramSocket(udpPort); +// activityLogger.log(MessageTypeConstants.INFO, String.format(UdpServerMessages.UDP_SERVER_STARTED, server.getServerName())); + while (true) { + try { + final byte[] data = new byte[1000]; + final DatagramPacket packet = new DatagramPacket(data, data.length); + socket.receive(packet); + System.out.println("request received" + udpPort); + new Thread(() -> { + processRequest(activityLogger, server, packet); + }).start(); + } catch (IOException e) { +// activityLogger.log("MessageTypeConstants.ERROR", e.getMessage()); + } + } + } catch (SocketException e1) { +// activityLogger.log(MessageTypeConstants.ERROR, e1.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static void processRequest(final Logger activityLogger, final Replica3 server, final DatagramPacket packet) { + byte[] response; + DatagramSocket socket = null; + final String request = new String(packet.getData(), StandardCharsets.UTF_8).trim(); + final String[] packetData = request.split("-"); + final String sourceServer = packetData[0].trim(); + final String action = packetData[1].trim(); + final String resourceName = packetData[2].trim(); + String resourceID = ""; + int duration = 0; + + System.out.println("action:" + action); + + if(packetData.length == 4) { + resourceID = packetData[2].trim(); + duration = Integer.parseInt(packetData[3]); + } + + try { + socket = new DatagramSocket(); + if("GET_AVAILABLE_RESOURCES".equalsIgnoreCase(action)) { + response = sanitizeXml(server.getAvailableResources(resourceName).toString()).getBytes(StandardCharsets.UTF_8); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + }else if("GET_RESOURCE".equalsIgnoreCase(action)) { + response = server.getRequestedResource(resourceID, duration).toString().getBytes(); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + } + +// activityLogger.log("", action, "Response sent"); + } catch (IOException e) { +// activityLogger.log("", "EXCEPTION", e.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static String sanitizeXml(String input) { + if (input == null) { + return ""; // or handle as needed + } + + return input.replaceAll("[\\x00]", ""); + } + +} diff --git a/src/main/java/derms/replica3/PortConstants.java b/src/main/java/derms/replica3/PortConstants.java new file mode 100644 index 0000000..e8ce489 --- /dev/null +++ b/src/main/java/derms/replica3/PortConstants.java @@ -0,0 +1,24 @@ +package derms.replica3; + +public class PortConstants { + + public static final int MTL_PORT = 12012; + public static final int QUE_PORT = 12013; + public static final int SHE_PORT = 12014; + + public static final int MTL_UDP_PORT = 13013; + public static final int QUE_UDP_PORT = 13014; + public static final int SHE_UDP_PORT = 13015; + + public static int getUdpPort(final String serverLocation) { + if(Constants.MONTREAL.equalsIgnoreCase(serverLocation)) { + return MTL_UDP_PORT; + } else if(Constants.QUEBEC.equalsIgnoreCase(serverLocation)) { + return QUE_UDP_PORT; + } else if(Constants.SHERBROOKE.equalsIgnoreCase(serverLocation)) { + return SHE_UDP_PORT; + } + return 0; + } + +} diff --git a/src/main/java/derms/replica3/QUEServer.java b/src/main/java/derms/replica3/QUEServer.java new file mode 100644 index 0000000..c03d329 --- /dev/null +++ b/src/main/java/derms/replica3/QUEServer.java @@ -0,0 +1,111 @@ +package derms.replica3; + +//import logger.Logger; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; +import java.nio.charset.StandardCharsets; + +import javax.xml.ws.Endpoint; +// +//import constants.Constants; +//import constants.PortConstants; +public class QUEServer { + public static void main(String[] args) { + + try{ + final Logger activityLogger = new Logger("QUEServer.log"); + int udpPort = PortConstants.getUdpPort("QUE"); + City ct = new City("QUE"); + /* Create servant and register it with the ORB */ + final Replica3 ServerImpl = new Replica3(ct, null); +// Endpoint endpoint = Endpoint.publish(Constants.QUEBEC_ADDRESS, ServerImpl); + + /*Start UDP server for QUE*/ + new Thread(() -> { + startUdpServer(activityLogger, ServerImpl, udpPort); + }).start(); + + System.out.println("#=== QUE Server is started ===#"); + + } catch (Exception e) { + System.err.println("ERROR: " + e); + e.printStackTrace(System.out); + } + } + + private static void startUdpServer(final Logger activityLogger, final Replica3 server, int udpPort) { + DatagramSocket socket = null; + try { + socket = new DatagramSocket(udpPort); + while (true) { + try { + final byte[] data = new byte[1000]; + final DatagramPacket packet = new DatagramPacket(data, data.length); + socket.receive(packet); + System.out.println("request received" + udpPort); + + new Thread(() -> { + processRequest(activityLogger, server, packet); + }).start(); + } catch (IOException e) { + activityLogger.log("", "EXCEPTION", e.getMessage()); + } + } + } catch (SocketException e1) { + activityLogger.log("", "EXCEPTION", e1.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static void processRequest(final Logger activityLogger, final Replica3 server, final DatagramPacket packet) { + byte[] response; + DatagramSocket socket = null; + final String request = new String(packet.getData(), StandardCharsets.UTF_8).trim(); + final String[] packetData = request.split("-"); + final String sourceServer = packetData[0].trim(); + final String action = packetData[1].trim(); + final String resourceName = packetData[2].trim(); + String resourceID = ""; + int duration = 0; + + if(packetData.length == 4) { + resourceID = packetData[2].trim(); + duration = Integer.parseInt(packetData[3]); + } + + try { + socket = new DatagramSocket(); + + if("GET_AVAILABLE_RESOURCES".equalsIgnoreCase(action)) { + response = sanitizeXml(server.getAvailableResources(resourceName).toString()).getBytes(StandardCharsets.UTF_8); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + }else if("GET_RESOURCE".equalsIgnoreCase(action)) { + response = server.getRequestedResource(resourceID, duration).toString().getBytes(); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + } + + activityLogger.log("", action, "Response sent"); + } catch (IOException e) { + activityLogger.log("", "EXCEPTION", e.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static String sanitizeXml(String input) { + if (input == null) { + return ""; // or handle as needed + } + + return input.replaceAll("[\\x00]", ""); + } + +} diff --git a/src/main/java/derms/replica3/Replica3.java b/src/main/java/derms/replica3/Replica3.java new file mode 100644 index 0000000..34891f7 --- /dev/null +++ b/src/main/java/derms/replica3/Replica3.java @@ -0,0 +1,589 @@ +package derms.replica3; + +import derms.Replica; +import derms.ReplicaManager; +import derms.Request; +import derms.Response; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import derms.replica3.Logger; + +public class Replica3 implements Replica{ + static final InetSocketAddress announceGroup = new InetSocketAddress("225.5.5.5", 5555); + + private String serverID; + private HashMap<String, HashMap<String, Resource>> resources; + private HashMap<String, List<Resource>> coordinatorResources ; + private HashMap<String, List<String>> resourceWaitingQueues; + private List<String> serverList = Arrays.asList(Constants.MONTREAL, Constants.QUEBEC, Constants.SHERBROOKE); + private Logger activityLogger; +// final InetAddress localAddr; +// private final Logger log; + + private boolean alive; + private final ReplicaManager replicaManager; + + public Replica3(City city, ReplicaManager replicaManager) throws IOException { + this.serverID = city.getCode(); + this.resources = new HashMap<>(); + coordinatorResources = new HashMap<>(); + resourceWaitingQueues = new HashMap<>(); +// this.log = DermsLogger.getLogger(getClass()); + this.replicaManager = replicaManager; + this.activityLogger = new Logger( serverID + "Server.log"); + +// log.info("Running"); +// log.config("Local address is "+localAddr.toString()); + + this.alive = true; + } + + @Override + public boolean isAlive() { return alive; } + + @Override + public void startProcess() { + // TODO +// log.info(getClass().getSimpleName() + " started."); + System.out.println("process started"); + } + + @Override + public void processRequest(Request request) { +// log.info(request.toString()); + System.out.println("process request and good"); + String status = ""; + try { + switch (request.getFunction()) { + case "addResource": + status = addResource(request.getResourceID(), request.getResourceType(), request.getDuration()); + break; + case "removeResource": + status = removeResource(request.getResourceID(), request.getDuration()); + break; + case "listResourceAvailability": + status = listResourceAvailability(request.getResourceType()); + break; + case "requestResource": + status = requestResource(request.getClientID(), request.getResourceID(), request.getDuration()); + break; + case "findResource": + status = findResource(request.getClientID(), request.getResourceType()); + break; + case "returnResource": + status = returnResource(request.getClientID(), request.getResourceID()); + break; + case "swapResource": + status = swapResource(request.getClientID(),request.getOldResourceID(), request.getOldResourceType(), request.getResourceID(), request.getResourceType()); + break; + default: + status = "Failure: unknown function '" + request.getFunction() + "'"; + } + } catch (Exception e) { +// log.warning(e.getMessage()); + status = "Failure: " + request.getFunction() + ": " + e.getMessage(); + } + + Response response = new Response(request, replicaManager.getReplicaId(), status, false); // TODO +// log.info("Processed request " + request + "; response: " + response); + replicaManager.sendResponseToFE(response); + } + + + @Override + public void restart() { + // TODO + shutdown(); + startProcess(); + } + + @Override + public int getId() { return 3; } + + private void shutdown() { + // TODO + } + + public synchronized String addResource(String resourceID, String resourceName, int duration) { + // Check if the resource name already exists + String message = ""; +// boolean isIdValid = ValidationService.isResourceIDValid(resourceID); +// boolean isNameValid = ValidationService.isResourceNameValid(resourceName); +// +// if(!(isIdValid && isNameValid)) { +// message = "Input is not valid for ID: " + resourceID + " " + resourceName + " " + duration; +// activityLogger.log(" ADD RESOURCE (" + resourceID + ", " + resourceName + ", " + duration + ") " , " FAILED ", message); +// return message; +// } + + HashMap<String, Resource> resourceMap = resources.get(resourceName); + if (resourceMap == null) { + resourceMap = new HashMap<>(); // Create a new inner HashMap if it doesn't exist + resources.put(resourceName, resourceMap); + } + + Resource resource = resourceMap.get(resourceID); + if (resource != null) { + // If the resource already exists, update its duration + if (duration > resource.getDuration()) { + resource.setDuration(duration); + } + message = "Resource already exist! So duration is updated: " + resourceID + " : " + resourceName + " : " + duration; + } else { + // Add the new resource + resource = new Resource(resourceID, resourceName, duration); + resourceMap.put(resourceID, resource); + message = "New Resource of " + resourceName +" is added: " + resourceID + " : " + resourceName + " : " + duration; + } + +// if(resourceWaitingQueues.containsKey(resourceID)) { +// List<String> coordinators = resourceWaitingQueues.get(resourceID); +// for(int i=0; i<coordinators.size(); i++) { +// if(coordinators.get(i).split("-").length > 1) { +// String crID = coordinators.get(i).split("-")[0]; +// int dur = Integer.parseInt(coordinators.get(i).split("-")[1]); +// Resource res = resourceMap.get(resourceID); +// +// if(res.getDuration() >= dur) { +//// activityLogger.log(" ADD RESOURCE - Resource allocation to waiting coordinator", " COMPLETED ", "Resource " + +//// resourceID + " is allocated to waiting coordinator " + crID); +// res.setDuration(res.getDuration() - dur); +// resourceMap.put(resourceID, res); +// coordinators.remove(i); +// break; +// } +// } +// +// } +// } +// activityLogger.log(" ADD RESOURCE (" + resourceID + ", " + resourceName + ", " + duration + ") " , " COMPLETED ", message); + + return message; + } + + public synchronized String removeResource(String resourceID, int duration) { + String message = ""; + +// boolean isIdValid = ValidationService.isResourceIDValid(resourceID); +// +// if(!isIdValid ) { +// message = "Input is not valid for ID: " + resourceID + " " + duration; +// activityLogger.log(" ADD RESOURCE (" + resourceID + ", " + duration + ") " , " FAILED ", message); +// return message; +// } + + for (HashMap<String, Resource> resourceMap : resources.values()) { + Resource resource = resourceMap.get(resourceID); + + if (resource != null) { + if (duration >= resource.getDuration()) { + resourceMap.remove(resourceID); // Remove if duration is fully used + message = "Resource of ID: " + resourceID + " with duration " + resource.getDuration() + " is successfully removed."; + activityLogger.log(" REMOVE RESOURCE (" + resourceID + ", " + duration + ") " , " COMPLETED ", message); + return message; + } else { + resource.setDuration(resource.getDuration() - duration); // Reduce the duration + message = "Duration of the Resource of ID: " + resourceID + " with duration " + duration + " is successfully reduced."; + activityLogger.log(" REMOVE RESOURCE (" + resourceID + ", " + duration + ") " , " COMPLETED ", message); + return message; + } + } + } + message = "Resource with ID " + resourceID + " is not found!"; + activityLogger.log(" REMOVE RESOURCE (" + resourceID + ", " + duration + ") " , " FAILED ", message); + + return "Resource not found"; + } + + public synchronized String listResourceAvailability(String resourceName) { + String message = ""; + +// boolean isNameValid = ValidationService.isResourceNameValid(resourceName); +// +// if(!isNameValid ) { +// message = "Input is not valid for name: " + resourceName; +// activityLogger.log(" LIST RESOURCE AVAILABILITY (" + resourceName + ") " , " FAILED ", message); +// return message; +// } + + final StringBuilder result = new StringBuilder(); + + result.append(resourceName.toUpperCase()); + CountDownLatch latch = new CountDownLatch(serverList.size() - 1); + + for(String server: serverList) { + System.out.println(serverID + " " + server); + + if(serverID.equalsIgnoreCase(server)) { + result.append(getAvailableResources(resourceName)); + System.out.println("listResourceAvailability same server:" + result); + }else { + System.out.println("listResourceAvailability request region:" + result); + new Thread(() -> { + System.out.println("listResourceAvailability Thread:" + result); + final String count = sendResourceAvailabilityRequest(server, resourceName); + System.out.println(count); + if(count != null) + synchronized(result) { + result.append(count); + } + latch.countDown(); + }).start(); + } + } + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + activityLogger.log(" LIST RESOURCE AVAILABILITY (" + resourceName + ") " , " COMPLETED ", result.toString()); + System.out.println("printing: " + result.toString()); + return result.toString().trim(); + } + + public String getAvailableResources(String resourceName) { + String result = ""; + + HashMap<String, Resource> resourceMap = resources.get(resourceName); + if (resourceMap == null) { + return result; + } + + for (Resource resource : resourceMap.values()) { + result += " " + resource.getResourceID() + "-" + resource.getDuration(); + } + + return result; + } + + private String sendResourceAvailabilityRequest(final String location, String resourceName) { + System.out.println("sendResourceAvailabilityRequest:"); + String recordCount = ""; + try { + final InetAddress inetAddress = InetAddress.getByName("localhost"); + activityLogger.log(location, " UPD MESSAGE SENT ", "UPD Message sent for Resource Availability"); + + final DatagramSocket socket = new DatagramSocket(); + byte[] data = (serverID + "-GET_AVAILABLE_RESOURCES" + "-" + resourceName ).toString().getBytes(); + + final DatagramPacket packet = new DatagramPacket(data, data.length, inetAddress, PortConstants.getUdpPort(location)) ; + socket.send(packet); + data = new byte[1000]; + DatagramPacket responsePacket = new DatagramPacket(data, data.length); + socket.receive(responsePacket); + recordCount = " " + new String(responsePacket.getData(), 0, responsePacket.getLength()).trim(); + socket.close(); + } catch (Exception e) { + activityLogger.log("", "EXCEPTION", e.getMessage()); + } + return recordCount; + } + + public synchronized String requestResource(String coordinatorID, String resourceID, int duration) { + // Iterate through the outer HashMap to find the resource by its ID + String message = ""; + final StringBuilder result = new StringBuilder(); + +// boolean isUserIdValid = ValidationService.isUserIDValid(coordinatorID); +// boolean isIdValid = ValidationService.isResourceIDValid(resourceID); +// +// if(!(isIdValid && isUserIdValid)) { +// message = "Input is not valid for ID: " + resourceID + " " + resourceID + " " + duration; +// activityLogger.log(" ADD RESOURCE (" + resourceID + ", " + resourceID + ", " + duration + ") " , " FAILED ", message); +// return message; +// } + + CountDownLatch latch = new CountDownLatch(1); + + for (HashMap<String, Resource> resourceMap : resources.values()) { + Resource resource = resourceMap.get(resourceID); + if (resource != null && resource.getDuration() >= duration) { + // If resource is found and has sufficient duration, reduce it + + resource.setDuration(resource.getDuration() - duration); + if(coordinatorResources.containsKey(coordinatorID)) { + Resource rs = new Resource(resourceID, resource.getResourceName(), duration); + coordinatorResources.get(coordinatorID).add(rs); + }else { + Resource rs = new Resource(resourceID, resource.getResourceName(), duration); + List<Resource> lst = new ArrayList<Resource>(); + lst.add(rs); + System.out.println(lst); + coordinatorResources.put(coordinatorID, lst); + System.out.println(coordinatorResources.keySet()); + } + message = "Coordinator of ID " + coordinatorID + " borrowed resource of ID " + resourceID + " " + "from same server"; + + activityLogger.log(" REQUEST RESOURCE (" + coordinatorID + ", " + resourceID + ", " + duration + ") " , " COMPLETED ", message); + return message; + } else if (resource != null) { + message = "Insufficient resource duration for resource of ID " + resourceID + " " + " in the same server" ; + activityLogger.log(" REQUEST RESOURCE (" + coordinatorID + ", " + resourceID + ", " + duration + ") " , " FAILED ", message); + if(resourceWaitingQueues.containsKey(resourceID)) { + resourceWaitingQueues.get(resourceID).add(coordinatorID + "-" + duration); + }else { + List<String> lst = new ArrayList<String>(); + lst.add(coordinatorID + "-" + duration); + resourceWaitingQueues.put(resourceID, lst); + } + return message; + } + } + + for(String server: serverList) { + if(!server.equalsIgnoreCase(serverID) && resourceID.substring(0,3).equalsIgnoreCase(server)) { + new Thread(() -> { + final String count = sendResourceRequest(server, resourceID, duration); + if(count != null) { + if(count.trim().length() > 0) { + if(coordinatorResources.containsKey(coordinatorID)) { + Resource rs = new Resource(resourceID, "", duration); + coordinatorResources.get(coordinatorID).add(rs); + }else { + List<Resource> lst = new ArrayList<Resource>(); + Resource rs = new Resource(resourceID, "", duration); + lst.add(rs); + coordinatorResources.put(coordinatorID, lst); + } + }else { + if(resourceWaitingQueues.containsKey(resourceID)) { + resourceWaitingQueues.get(resourceID).add(coordinatorID); + }else { + List<String> lst = new ArrayList<String>(); + lst.add(coordinatorID); + resourceWaitingQueues.put(resourceID, lst); + } + + } + synchronized(result) { + result.append(count); + } + } + latch.countDown(); + }).start(); + + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + System.out.println(coordinatorResources.toString()); + + // Request to other servers for getting specified resource + if(result.toString().trim().length() == 0) { + message = "Requested Resource of ID " + resourceID + " by coordinator " + coordinatorID + " is not found! so Coordinator is added to waiting queue!"; + activityLogger.log(" REQUEST RESOURCE (" + coordinatorID + ", " + resourceID + ", " + duration + ") " , " COMPLETED ", message); + return message; + } + + activityLogger.log(" REQUEST RESOURCE (" + coordinatorID + ", " + resourceID + ", " + duration + ") " , " COMPLETED ", message); + return result.toString(); + + } + + private String sendResourceRequest(final String location, String resourceID, int duration) { + + String recordCount = ""; + try { + final InetAddress inetAddress = InetAddress.getByName("localhost"); +// activityLogger.log(location, " UPD MESSAGE SENT ", "UPD Message sent for Request Resource"); + final DatagramSocket socket = new DatagramSocket(); + byte[] data = (serverID + "-GET_RESOURCE" + "-" + resourceID + "-" + duration).toString().getBytes(); + + final DatagramPacket packet = new DatagramPacket(data, data.length, inetAddress, PortConstants.getUdpPort(location)) ; + socket.send(packet); + System.out.println("inside the request udp: "+ location + " "+ data.toString()); + data = new byte[1000]; + + DatagramPacket responsePacket = new DatagramPacket(data, data.length); + socket.receive(responsePacket); + recordCount = " " + new String(responsePacket.getData(), 0, responsePacket.getLength()).trim(); + System.out.println("after received the request udp: "+ location + " "+ data.toString()); + + socket.close(); + } catch (Exception e) { + } + return recordCount; + } + + public String getRequestedResource(String id, int duration) { + String message = ""; + for (HashMap<String, Resource> resourceMap : resources.values()) { + Resource resource = resourceMap.get(id); + + if (resource != null) { + if(resource.getDuration() >= duration) { + resource.setDuration(resource.getDuration() - duration); + message = "Resource of ID: " + id + " is borrowed successfully and duration is updated to " + resource.getDuration() + " in " + serverID + "server" ; + activityLogger.log("REQUEST RESOURCE", " COMPLETED " , message); + return message; + } + } + } + message = "Resource of ID: " + id + " is not available to borrow!"; + activityLogger.log("REQUEST RESOURCE", " FAILED " , message); + return ""; + + } + + public String findResource(String coordinatorID, String resourceName){ + // Retrieve the inner HashMap for the resource name (e.g., "AMBULANCE") + final StringBuilder result = new StringBuilder(); + String message = ""; + +// boolean isUserIdValid = ValidationService.isUserIDValid(coordinatorID); +// boolean isNameValid = ValidationService.isResourceNameValid(resourceName); +// +// if(!(isNameValid && isUserIdValid)) { +// message = "Input is not valid for : " + coordinatorID + " " + resourceName; +// activityLogger.log(" FIND RESOURCE (" + coordinatorID + ", " + resourceName + ") " , " FAILED ", message); +// return message; +// } + + result.append(resourceName.toUpperCase()); + int startLen = result.length(); + + HashMap<String, Resource> specifiedResources = resources.get(resourceName); + if(specifiedResources != null) { + if(coordinatorResources.containsKey(coordinatorID)) { + for(Resource res: coordinatorResources.get(coordinatorID)) { + System.out.println("resID: " + res.getResourceID()); + if(specifiedResources.containsKey(res.getResourceID())) { + result.append(" " + res.getResourceID() + "-" + res.getDuration()); + } + } + } + } + + + CountDownLatch latch = new CountDownLatch(serverList.size() - 1); + final StringBuilder response = new StringBuilder(); + for(String server: serverList) { + + if(!serverID.equalsIgnoreCase(server)) { + new Thread(() -> { + final String count = sendResourceAvailabilityRequest(server, resourceName); + if(count != null) + synchronized(result) { + response.append(count); + } + latch.countDown(); + }).start(); + } + } + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + String responseString = response.toString().trim(); + String[] resources = responseString.split(" "); + if (resources != null) { + for (String resource : resources) { + // Split each resource by '-' + String[] parts = resource.split("-"); + + if (parts.length == 2) { + String resourceID = parts[0]; + String count = parts[1]; + + if(coordinatorResources.containsKey(coordinatorID)) { + for(Resource res: coordinatorResources.get(coordinatorID)) { + if(resourceID.equalsIgnoreCase(res.getResourceID())) { + result.append(" " + resourceID + "-" + res.getDuration()); + } + } + } + + } + } + } + if(startLen == result.length()) { + message = "Resources of " + resourceName+ " occupied by coordinator " + coordinatorID + " are not found!"; + activityLogger.log(" FIND RESOURCE (" + coordinatorID + ") " , " COMPLETED ", message); + return message; + } + + message = "Resources of " + resourceName+ " occupied by coordinator " + coordinatorID + " are returned successfully!"; + activityLogger.log(" FIND RESOURCE (" + coordinatorID + ") " , " COMPLETED ", message); + System.out.println(result); + + return result.toString(); + } + + public synchronized String returnResource(String coordinatorID, String resourceID){ + // Iterate through the outer HashMap to find the resource by its ID + String message = ""; +// boolean isUserIdValid = ValidationService.isUserIDValid(coordinatorID); +// boolean isIDValid = ValidationService.isResourceIDValid(resourceID); +// +// if(!(isIDValid && isUserIdValid)) { +// message = "Input is not valid for : " + coordinatorID + " " + resourceID; +// activityLogger.log(" RETURN RESOURCE (" + coordinatorID + ", " + resourceID + ") " , " FAILED ", message); +// return message; +// } + +// for (HashMap<String, Resource> resourceMap : resources.values()) { +// Resource resource = resourceMap.get(resourceID); +// if (resource != null) { + // Perform any logic to return the resource + if(coordinatorResources.containsKey(coordinatorID)) { + for(Resource res: coordinatorResources.get(coordinatorID)) { + if(res.getResourceID().equalsIgnoreCase(resourceID)) { + message = "Resource " + resourceID + "-" + res.getDuration() + " returned successfully to coordinator " + coordinatorID; + activityLogger.log(" RETURN RESOURCE (" + coordinatorID + ", " + resourceID + ") " , " COMPLETED ", message); + return message; + } + } + } +// } +// } + message = "Resource of ID: " + resourceID + " not found."; + activityLogger.log(" RETURN RESOURCE (" + coordinatorID + ", " + resourceID + ") " , " FAILED ", message); + return message; + } + + public synchronized String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType) { + String message = ""; + int durationRequest = 0; + String returnedResource = returnResource(coordinatorID, oldResourceID); + if(returnedResource.contains("not found")) { + message = "Coordinator of ID: " + coordinatorID + " didn't acquired Resource of ID: " + oldResourceID + "."; +// activityLogger.log(" SWAP RESOURCE (" + coordinatorID + ", " + oldResourceID + ") " , " FAILED ", message); + return message; + } + if(coordinatorResources.containsKey(coordinatorID)) { + for(Resource res: coordinatorResources.get(coordinatorID)) { + if(res.getResourceID().equals(oldResourceID)) { + durationRequest = res.getDuration(); + coordinatorResources.get(coordinatorID).remove(res); + break; + } + } + } + + String requestedResource = requestResource(coordinatorID, newResourceID, durationRequest); + if(requestedResource.contains("not found")) { + message = "Coordinator of ID: " + coordinatorID + " couldn't acquire Resource of ID: " + newResourceID + "."; + activityLogger.log(" SWAP RESOURCE (" + coordinatorID + ", " + oldResourceID + ") " , " FAILED ", message); + return message; + } + message = "Coordinator of ID: " + coordinatorID + " Successfully swapped old resource " + oldResourceID + " with new resource " + newResourceID; +// activityLogger.log(" SWAP RESOURCE (" + coordinatorID + ", " + oldResourceID + ", " + oldResourceType + ", " + newResourceID + ", " + newResourceType + ", "+ ") ", +// " COMPLETED ", message); + + return message; + } + +} diff --git a/src/main/java/derms/replica3/Resource.java b/src/main/java/derms/replica3/Resource.java new file mode 100644 index 0000000..d4fc424 --- /dev/null +++ b/src/main/java/derms/replica3/Resource.java @@ -0,0 +1,32 @@ +package derms.replica3; + +import java.io.Serializable; + +public class Resource implements Serializable { + private String resourceID; + private String resourceName; + private int duration; + + public Resource(String resourceID, String resourceName, int duration) { + this.resourceID = resourceID; + this.resourceName = resourceName; + this.duration = duration; + } + + public String getResourceID() { + return resourceID; + } + + public String getResourceName() { + return resourceName; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } +} + diff --git a/src/main/java/derms/replica3/SHEServer.java b/src/main/java/derms/replica3/SHEServer.java new file mode 100644 index 0000000..9d29a70 --- /dev/null +++ b/src/main/java/derms/replica3/SHEServer.java @@ -0,0 +1,112 @@ +package derms.replica3; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; +import java.nio.charset.StandardCharsets; + +import javax.xml.ws.Endpoint; + +//import constants.Constants; +//import constants.PortConstants; + +public class SHEServer { + public static void main(String[] args) { + + try{ +// final ActivityLoggerService activityLogger = new ActivityLoggerService(FileConstants.SERVER_LOG_FILE_PATH + LocationConstants.DOLLARD + "/" + FileConstants.ACTIVITY_LOG); + + final Logger activityLogger = new Logger("SHEServer.log"); + int udpPort = PortConstants.getUdpPort("SHE"); + City ct = new City("SHE"); + + final Replica3 ServerImpl = new Replica3(ct, null); +// Endpoint endpoint = Endpoint.publish(Constants.SHERBROOKE_ADDRESS, ServerImpl); + + /*Start UDP server for SHE*/ + new Thread(() -> { + startUdpServer(activityLogger, ServerImpl, udpPort); + }).start(); + + System.out.println("#=== SHE Server is started ===#"); + + + } catch (Exception e) { + System.err.println("ERROR: " + e); + e.printStackTrace(System.out); + } + } + + private static void startUdpServer(final Logger activityLogger, final Replica3 server, int udpPort) { + DatagramSocket socket = null; + try { + socket = new DatagramSocket(udpPort); + while (true) { + try { + final byte[] data = new byte[1000]; + final DatagramPacket packet = new DatagramPacket(data, data.length); + socket.receive(packet); + System.out.println("inside the received packet she"); + new Thread(() -> { + processRequest(activityLogger, server, packet); + }).start(); + } catch (IOException e) { + activityLogger.log("", "EXCEPTION", e.getMessage()); + } + } + } catch (SocketException e1) { + activityLogger.log("", "EXCEPTION", e1.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static void processRequest(final Logger activityLogger, final Replica3 server, final DatagramPacket packet) { + byte[] response; + DatagramSocket socket = null; + final String request = new String(packet.getData(), StandardCharsets.UTF_8).trim(); + final String[] packetData = request.split("-"); + final String sourceServer = packetData[0].trim(); + final String action = packetData[1].trim(); + final String resourceName = packetData[2].trim(); + String resourceID = ""; + int duration = 0; + System.out.println(" action:" + action); + if(packetData.length == 4) { + resourceID = packetData[2].trim(); + duration = Integer.parseInt(packetData[3]); + } + + try { + socket = new DatagramSocket(); + + if("GET_AVAILABLE_RESOURCES".equalsIgnoreCase(action)) { + response = sanitizeXml(server.getAvailableResources(resourceName).toString()).getBytes(StandardCharsets.UTF_8); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + }else if("GET_RESOURCE".equalsIgnoreCase(action)) { + System.out.println("inside action:" + action); + response = server.getRequestedResource(resourceID, duration).toString().getBytes(); + socket.send(new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort())); + } + + } catch (IOException e) { + activityLogger.log("", "EXCEPTION", e.getMessage()); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + private static String sanitizeXml(String input) { + if (input == null) { + return ""; // or handle as needed + } + + return input.replaceAll("[\\x00]", ""); + } + +} |