DS_project

=========================================Client.java=========================================== package EZShare; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashMap; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import com.google.gson.Gson; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; public class Client { private static String ip = "localhost"; // 127.0.0.1 private static int port = 8080; private static boolean debugon = false; // DEBUG public static void main(String[] args) { Options options = new Options(); // client command line arguments options.addOption("channel",true,"channel"); options.addOption("debug",false,"print debug information"); options.addOption("description",true,"resource description"); options.addOption("exchange",false,"exchange server list with server"); options.addOption("fetch",false,"fetch resources from server"); options.addOption("host",true,"server host, a domain name or IP address"); options.addOption("name",true,"resource name"); options.addOption("owner",true,"owner"); options.addOption("port",true,"server port, an integer"); options.addOption("publish",false,"publish resource on server"); options.addOption("query",false,"query for resources from server"); options.addOption("remove",false,"remove resource from server"); options.addOption("secret",true,"secret"); options.addOption("servers",true,"server list, host1:port1,host2:port2,..."); options.addOption("share",false,"share resource on server"); options.addOption("tags",true,"resource tags, tag1,tag2,tag3,..."); options.addOption("uri",true,"resource URI"); CommandLineParser parser = new DefaultParser(); CommandLine cmd = null; try { cmd = parser.parse(options,args); } catch (org.apache.commons.cli.ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } // change HOST if(cmd.hasOption("host")) { ip = cmd.getOptionValue("host"); } // change PORT if(cmd.hasOption("port")) { port = Integer.parseInt(cmd.getOptionValue("port")); } try(Socket socket = new Socket(ip,port)) { DataInputStream input = new DataInputStream(socket.getInputStream()); DataOutputStream output = new DataOutputStream(socket.getOutputStream()); /* output.writeUTF("Hello server"); output.flush(); */ if(debugon == true) { System.out.println("setting debug on"); } JSONObject command = new JSONObject(); Resource resource = new Resource(); JSONObject send = new JSONObject(); // put resource in //JSONObject secret = new JSONObject(); // change the ezserver resource.ezserver = ip + ":" + port; // DEBUG command-------------------------------------------- if (cmd.hasOption("debug")) { debugon = true; } // PUBLISH command------------------------------------------ if(cmd.hasOption("publish")){ if(cmd.hasOption("remove") ||cmd.hasOption("share") ||cmd.hasOption("query") ||cmd.hasOption("exchange") ||cmd.hasOption("fetch")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("publishing to " + ip + ":" + port); } if(cmd.hasOption("name")) { resource.name = cmd.getOptionValue("name"); } if(cmd.hasOption("description")) { resource.description = cmd.getOptionValue("description"); } if(cmd.hasOption("tags")) { resource.tags = cmd.getOptionValue("tags").split(","); } if(cmd.hasOption("channel")) { resource.changeChannel(cmd.getOptionValue("channel")); } if(cmd.hasOption("owner")) { resource.owner = cmd.getOptionValue("owner"); } // MANDANTORY URI if(cmd.hasOption("uri")) { resource.uri = URI.create((cmd.getOptionValue("uri"))); } send.put("name", resource.name); send.put("description",resource.description); JSONArray arr = new JSONArray(); for(String tag: resource.tags) { arr.add(tag); } send.put("tags", arr); send.put("channel", resource.getChannel()); send.put("owner", resource.owner); if(resource.uri == null) { send.put("uri", ""); } else { send.put("uri", resource.uri.toString()); } send.put("ezserver", resource.ezserver); command.put("resource", send); command.put("command", "PUBLISH"); } } // REMOVE command------------------------------------------- if (cmd.hasOption("remove")) { if(cmd.hasOption("publish") ||cmd.hasOption("share") ||cmd.hasOption("query") ||cmd.hasOption("exchange") ||cmd.hasOption("fetch")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("removing to " + ip + ":" + port); } if (cmd.hasOption("channel")) { resource.changeChannel(cmd.getOptionValue("channel")); } if (cmd.hasOption("owner")) { resource.owner = cmd.getOptionValue("owner"); } if (cmd.hasOption("uri")) { resource.uri = resource.uri = URI.create((cmd.getOptionValue("uri"))); } send.put("channel", resource.getChannel()); send.put("owner", resource.owner); if(resource.uri == null) { send.put("uri", ""); } else { send.put("uri", resource.uri.toString()); } command.put("resource", send); command.put("command", "REMOVE"); } } // SHARE command--------------------------------------------- if(cmd.hasOption("share")){ if(cmd.hasOption("remove") ||cmd.hasOption("publish") ||cmd.hasOption("query") ||cmd.hasOption("exchange") ||cmd.hasOption("fetch")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("sharing to " + ip + ":" + port); } if(cmd.hasOption("name")) { resource.name = cmd.getOptionValue("name"); } if(cmd.hasOption("description")) { resource.description = cmd.getOptionValue("description"); } if(cmd.hasOption("tags")) { resource.tags = cmd.getOptionValue("tags").split(","); } if(cmd.hasOption("channel")) { resource.changeChannel(cmd.getOptionValue("channel")); } if(cmd.hasOption("owner")) { resource.owner = cmd.getOptionValue("owner"); } // MANDANTORY URI if(cmd.hasOption("uri")) { resource.uri = URI.create((cmd.getOptionValue("uri"))); } // MANDANTORY secret if(cmd.hasOption("secret")) { command.put("secret", cmd.getOptionValue("secret")); } send.put("name", resource.name); send.put("description",resource.description); JSONArray arr = new JSONArray(); for(String tag: resource.tags) { arr.add(tag); } send.put("tags", arr); send.put("channel", resource.getChannel()); send.put("owner", resource.owner); if(resource.uri == null) { send.put("uri", ""); } else { send.put("uri", resource.uri.toString()); } send.put("ezserver", resource.ezserver); command.put("resource", send); command.put("command", "SHARE"); } } // QUERY command------------------------------------------------ if(cmd.hasOption("query")){ if(cmd.hasOption("remove") ||cmd.hasOption("share") ||cmd.hasOption("publish") ||cmd.hasOption("exchange") ||cmd.hasOption("fetch")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("quering to " + ip + ":" + port); } if(cmd.hasOption("name")) { resource.name = cmd.getOptionValue("name"); } if(cmd.hasOption("description")) { resource.description = cmd.getOptionValue("description"); } if(cmd.hasOption("tags")) { resource.tags = cmd.getOptionValue("tags").split(","); } if(cmd.hasOption("channel")) { resource.changeChannel(cmd.getOptionValue("channel")); } if(cmd.hasOption("owner")) { resource.owner = cmd.getOptionValue("owner"); } if(cmd.hasOption("uri")) { resource.uri = URI.create((cmd.getOptionValue("uri"))); } if(resource.uri == null) { send.put("uri", ""); //URI is not null!!!!!!!! } else { send.put("uri", resource.uri.toString()); } send.put("name", resource.name); send.put("description",resource.description); //send.put("tags", Arrays.toString(resource.tags)); JSONArray arr = new JSONArray(); for(String tag: resource.tags) { arr.add(tag); } send.put("tags", arr); send.put("channel", resource.getChannel()); send.put("owner", resource.owner); send.put("ezserver", null); command.put("resourceTemplate", send); command.put("command", "QUERY"); command.put("relay", true); //relay field } } // FETCH command--------------------------------------------- if(cmd.hasOption("fetch")){ if(cmd.hasOption("remove") ||cmd.hasOption("share") ||cmd.hasOption("query") ||cmd.hasOption("exchange") ||cmd.hasOption("publish")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("fetching to " + ip + ":" + port); } // should have channel if(cmd.hasOption("channel")) { resource.changeChannel(cmd.getOptionValue("channel")); } // should have uri if(cmd.hasOption("uri")) { resource.uri = URI.create((cmd.getOptionValue("uri"))); } if(resource.uri == null) { send.put("uri", "");// URI is not null!!!!!!!!!!!!! } else { send.put("uri", resource.uri.toString()); } send.put("name", resource.name); send.put("description",resource.description); JSONArray arr = new JSONArray(); send.put("tags", arr); send.put("channel", resource.getChannel()); send.put("owner", resource.owner); send.put("ezserver", null); command.put("resourceTemplate", send); command.put("command", "FETCH"); } } // EXCHANGE command--------------------------------------------- if(cmd.hasOption("exchange")){ if(cmd.hasOption("remove") ||cmd.hasOption("share") ||cmd.hasOption("query") ||cmd.hasOption("fetch") ||cmd.hasOption("publish")) { command.put("command", "REDUNDANT"); } else { if(debugon == true) { System.out.println("exchanging to " + ip + ":" + port); } JSONArray servers = new JSONArray(); // should have servers if(cmd.hasOption("servers")) { String[] serverlist = cmd.getOptionValue("servers").split(","); for(String s :serverlist) { String[] separate = s.split(":"); JSONObject server = new JSONObject(); if(separate.length>1) { server.put("hostname", separate[0]); server.put("port", Integer.parseInt(separate[1])); } else { server = null; } servers.add(server); } } command.put("serverList", servers); command.put("command", "EXCHANGE"); } } if (debugon == true) { System.out.println("SENT: " + command); } //WRITE the command to Server output.writeUTF(command.toJSONString()); //CREATE a JSONPareser JSONParser js_parser = new JSONParser(); //String message = input.readUTF(); while(true){// handle with the socket from server if(input.available() > 0) { // if FETCH, // DOWNLOAD-------------------------------------------- if (cmd.hasOption("fetch")) { String response = input.readUTF(); String result = input.readUTF(); if (debugon == true) { System.out.println("Received from server: " + response); } JSONObject status = (JSONObject) js_parser.parse(response); if (status.get("response").equals("success")) { JSONObject fetched = (JSONObject) js_parser.parse(result); // The file location File f = new File((URI.create((String) fetched.get("uri"))).getPath()); String fileName = "C:/Users/frankie/workspace/DS_project1/client_files/" + f.getName(); // Create a RandomAccessFile to read and write the // output file. RandomAccessFile downloadingFile = new RandomAccessFile(fileName, "rw"); // Find out how much size is remaining to get from // the // server. long fileSizeRemaining = (Long) fetched.get("resourceSize"); int chunkSize = setChunkSize(fileSizeRemaining); // Represents the receiving buffer byte[] receiveBuffer = new byte[chunkSize]; // Variable used to read if there are remaining size // left to read. int num; if (debugon == true) { System.out.println("Downloading " + fileName + " of size " + fileSizeRemaining); } while ((num = input.read(receiveBuffer)) > 0) { // Write the received bytes into the // RandomAccessFile downloadingFile.write(Arrays.copyOf(receiveBuffer, num)); // Reduce the file size left to read.. fileSizeRemaining -= num; // Set the chunkSize again chunkSize = setChunkSize(fileSizeRemaining); receiveBuffer = new byte[chunkSize]; System.out.println(fileSizeRemaining); // If you're done then break if (fileSizeRemaining == 0) { break; } } if (debugon == true) { System.out.println("File received!"); } downloadingFile.close(); } } // Regular----------------------------------------------------------------- JSONObject result = (JSONObject) js_parser.parse(input.readUTF()); if (debugon == true) { System.out.println(result); } /* // extract the first and last [ ] JSONArray array = (JSONArray) result.get("results"); if (debugon == true) { System.out.println("RECEIVED: "); for (Object message: array) { //if(((JSONObject) message).containsKey("command_name")) //fetched = (JSONObject) message; System.out.println(message); } } */ // result.get("results").toString().substring(1, // result.get("results").toString().length()-1)); } } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static int setChunkSize(long fileSizeRemaining){ // Determine the chunkSize int chunkSize=512*512; // If the file size remaining is less than the chunk size // then set the chunk size to be equal to the file size. if(fileSizeRemaining<chunkSize){ chunkSize=(int) fileSizeRemaining; } return chunkSize; } } ==========================================Server.java================================= package EZShare; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Random; import javax.net.ServerSocketFactory; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.JSONArray; public class Server { private static int port = 8080; private static String advertisedhostname = "localhost"; private static String secret = "whoami";// "5uv1ii7ec362me7hkch3s7l5c4"; private static int exchangeinterval = 600; // seconds private static int connectionintervallimit = 1; // seconds // Identifies the user number connected private static int counter = 0; private static List<Resource> resourcelist = new ArrayList<Resource>(); private static List<JSONObject> serverrecords = new ArrayList<JSONObject>(); private static boolean debugon = false; // DEBUG private static long mainTime; public static void main(String[] args) { mainTime = System.currentTimeMillis();// initialize the start time Options options = new Options(); // Server command line arguments options.addOption("advertisedhostname", true, "advertised host name"); options.addOption("connectionintervallimit", true, "connection interval limit in seconds"); options.addOption("exchangeinterval", true, "exchange interval in seconds"); options.addOption("port", true, "server port, an integer"); options.addOption("secret", true, "secret"); options.addOption("debug", false, "print debug information"); CommandLineParser parser = new DefaultParser(); CommandLine cmd = null; try { cmd = parser.parse(options, args); } catch (org.apache.commons.cli.ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } // change HOST if (cmd.hasOption("advertisedhostname")) { advertisedhostname = cmd.getOptionValue("advertisedhostname"); } // change PORT if (cmd.hasOption("port")) { port = Integer.parseInt(cmd.getOptionValue("port")); } if (cmd.hasOption("connectionintervallimit")) { connectionintervallimit = Integer.parseInt(cmd.getOptionValue("connectionintervallimit")); } if (cmd.hasOption("exchangeinterval")) { exchangeinterval = Integer.parseInt(cmd.getOptionValue("exchangeinterval")); } // DEBUG command-------------------------------------------- if (cmd.hasOption("debug")) { debugon = true; } // SECRET command-------------------------------------------- if (cmd.hasOption("secret")) { secret = cmd.getOptionValue("secret"); } System.out.println("Starting the EZShare Server"); System.out.println("using secret: " + secret); System.out.println("using advertised hostname: " + advertisedhostname); System.out.println("bound to port: " + port); // System.out.println("started"); ServerSocketFactory factory = ServerSocketFactory.getDefault(); try (ServerSocket server = factory.createServerSocket(port)) { System.out.println("started"); if (debugon == true) { System.out.println("setting debug on"); } boolean isActive = true; // options.addOption("email",true, "input email address"); // for a THREAD TEST-------------------------------!!!!!!!!!!!!!!!!! Thread t = new Thread(() -> test()); t.start(); while (isActive) { // Connection Interval Limit Socket Client = server.accept(); Client.setSoTimeout(connectionintervallimit * 1000); counter++; System.out.println("Client " + counter + ": Applying for connection!"); Thread r = new Thread(() -> serverClient(Client)); r.start(); } } catch (IOException e) { e.printStackTrace(); } } private static void test() { // TODO Auto-generated method stub while (true) { //System.out.println("test start"); // =========================Every X // minutes========================== if ((System.currentTimeMillis() - mainTime) % (exchangeinterval*1000) == 0) { // print current time /* System.out.println("Current server time is: " + getTime()); */ // ------------------------------------------------------------------ // Randomly selected server from the Server Records JSONObject send = new JSONObject(); Random randomizer = new Random(); if (!serverrecords.isEmpty()) { JSONObject random = serverrecords.get(randomizer.nextInt(serverrecords.size())); String hostname = (String) random.get("hostname"); int port = Integer.parseInt(random.get("port").toString()); try (Socket socket = new Socket(hostname, port)) { DataInputStream Input = new DataInputStream(socket.getInputStream()); DataOutputStream Output = new DataOutputStream(socket.getOutputStream()); // Initiates an EXCHANGE command with it. // It provides the selected server with a copy of its // entire Server Records list. if (socket.isConnected()) { if (debugon == true) { System.out.println("exchanging to " + hostname + ":" + port); } JSONArray servers = new JSONArray(); for (JSONObject record : serverrecords) { servers.add(record); } send.put("serverList", servers); send.put("command", "EXCHANGE"); Output.writeUTF(send.toJSONString()); if (debugon == true) { System.out.println("SENT in Server Interactions: " + send); System.out.println("RECEIVED in Server Interactions: " + Input.readUTF()); } } else { serverrecords.remove(random); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } } public static String getTime() { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); String stringTime = sdf.format(date); return stringTime; } private static JSONArray parseCommand(JSONObject command, DataOutputStream output) { int result = 0; //Resource resource = new Resource(); JSONArray seq = new JSONArray(); JSONObject receive = new JSONObject(); JSONObject message = new JSONObject(); Resource resource = new Resource(); if(command.containsKey("command")) { // PUBLISH------------------------------------------------------------------- if(command.get("command").equals("PUBLISH")) { boolean publisherror = false; receive = (JSONObject) command.get("resource"); resource.name = (String) receive.get("name"); if(receive.get("uri").equals("")) { resource.uri = null; } else { resource.uri = URI.create(((String)receive.get("uri"))); } resource.description = (String) receive.get("description"); resource.changeChannel((String) receive.get("channel")); resource.owner = (String) receive.get("owner"); resource.tags = new String[((JSONArray) receive.get("tags")).size()]; resource.ezserver = (String) receive.get("ezserver"); for(int i = 0, count = resource.tags.length; i< count; i++) { resource.tags[i] = (String) ((JSONArray) receive.get("tags")).get(i); } // Publishing a resource with the same channel and URI but different owner is not allowed. for (Resource r: resourcelist) { if(resource.getChannel().equals(r.getChannel())&&resource.uri.equals(r.uri) && resource.owner.equals(r.owner)) { publisherror = true; } } if (resource.uri == null) { message.put("response", "error"); message.put("errorMessage", "missing resource"); } else if (!resource.uri.isAbsolute() || resource.uri.getScheme().equals("file")) { //The URI must be present, must be absolute and cannot be a file scheme. message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.name.startsWith(" ") || resource.name.endsWith(" ") || resource.name.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.description.startsWith(" ") || resource.description.endsWith(" ") || resource.description.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.getChannel().startsWith(" ") || resource.getChannel().endsWith(" ") || resource.getChannel().contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.owner.startsWith(" ") || resource.owner.endsWith(" ") || resource.owner.contains("\0") || resource.owner.equals("*")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (publisherror == true) { message.put("response", "error"); message.put("errorMessage", "cannot publish resource"); } else { // check if the primary key is same with exists // if yes, overwrite for (Resource r: resourcelist) { if (r.owner.equals(resource.owner)&&r.getChannel().equals(resource.getChannel()) &&r.uri.equals(resource.uri)) { resourcelist.remove(r); } } resourcelist.add(resource); message.put("response", "success"); } //seq.add(message); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //REMOVE--------------------------------------------------------- else if (command.get("command").equals("REMOVE")) {// code written by // chin , remove // method receive = (JSONObject) command.get("resource"); resource.name = (String) receive.get("name"); if(receive.get("uri").equals("")) { resource.uri = null; } else { resource.uri = URI.create(((String)receive.get("uri"))); } resource.changeChannel((String) receive.get("channel")); resource.owner = (String) receive.get("owner"); if (resource.uri == null) { message.put("response", "error"); message.put("errorMessage", "missing resource"); } else if (!resource.uri.isAbsolute()) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else { Iterator<Resource> iter = resourcelist.iterator(); while(iter.hasNext()) { Resource r = iter.next(); if (r.owner.equals(resource.owner) && r.getChannel().equals(resource.getChannel()) && r.uri.equals(resource.uri)) { iter.remove(); message.put("response", "success"); } else { message.put("response", "cannot remove resource"); } } } //seq.add(message); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if(command.get("command").equals("SHARE")) { // SHARE-------------------------------------------------------------------------- boolean shareerror = false; receive = (JSONObject) command.get("resource"); resource.name = (String) receive.get("name"); if(receive.get("uri").equals("")) { resource.uri = null; } else { resource.uri = URI.create(((String)receive.get("uri"))); } resource.description = (String) receive.get("description"); resource.changeChannel((String) receive.get("channel")); resource.owner = (String) receive.get("owner"); resource.tags = new String[((JSONArray) receive.get("tags")).size()]; resource.ezserver = (String) receive.get("ezserver"); for(int i = 0, count = resource.tags.length; i< count; i++) { resource.tags[i] = (String) ((JSONArray) receive.get("tags")).get(i); } File file = new File(resource.uri.getPath()); // Sharing a resource with the same channel and URI but different owner is not allowed. for (Resource r: resourcelist) { if(resource.getChannel().equals(r.getChannel())&&resource.uri.equals(r.uri) && resource.owner.equals(r.owner)) { shareerror = true; } } if (resource.uri == null) { message.put("response", "error"); message.put("errorMessage", "missing resource"); } else if (!resource.uri.isAbsolute() || !resource.uri.getScheme().equals("file") || !file.exists()) { //The URI must be present, must be absolute, non-authoritative and must be a file scheme. It must point //to a file on the local file system that the server can read as a file. message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (command.get("secret") == null) { //If the resource or secret field was not given or not of the correct type message.put("response", "error"); message.put("errorMessage", "missing resource and/or secret"); } else if (!command.get("secret").getClass().equals(String.class)) { //If the resource or secret field was not given or not of the correct type message.put("response", "error"); message.put("errorMessage", "missing resource and/or secret"); } else if (!command.get("secret").equals(secret)) { message.put("response", "error"); message.put("errorMessage", "incorrect secret"); } else if (resource.name.startsWith(" ") || resource.name.endsWith(" ") || resource.name.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.description.startsWith(" ") || resource.description.endsWith(" ") || resource.description.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.getChannel().startsWith(" ") || resource.getChannel().endsWith(" ") || resource.getChannel().contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (resource.owner.startsWith(" ") || resource.owner.endsWith(" ") || resource.owner.contains("\0") || resource.owner.equals("*")) { message.put("response", "error"); message.put("errorMessage", "invalid resource"); } else if (shareerror == true) { message.put("response", "error"); message.put("errorMessage", "cannot share resource"); } else { // check if the primary key is same with exists // if yes, overwrite for (Resource r: resourcelist) { if (r.owner.equals(resource.owner)&&r.getChannel().equals(resource.getChannel()) &&r.uri.equals(resource.uri)) { resourcelist.remove(r); } } resourcelist.add(resource); message.put("response", "success"); } //seq.add(message); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if(command.get("command").equals("QUERY")) { // QUERY-------------------------------------------------------------------------- boolean relay = (boolean) command.get("relay"); receive = (JSONObject) command.get("resourceTemplate"); resource.name = (String) receive.get("name"); if(receive.get("uri").equals("")) { resource.uri = null; } else { resource.uri = URI.create(((String)receive.get("uri"))); } resource.description = (String) receive.get("description"); resource.changeChannel((String) receive.get("channel")); resource.owner = (String) receive.get("owner"); resource.tags = new String[((JSONArray) receive.get("tags")).size()]; for(int i = 0, count = resource.tags.length; i< count; i++) { resource.tags[i] = (String) ((JSONArray) receive.get("tags")).get(i); } if (!(resource.uri == null)&&!resource.uri.isAbsolute()) { message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); } else if (resource.name.startsWith(" ") || resource.name.endsWith(" ") || resource.name.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); } else if (resource.description.startsWith(" ") || resource.description.endsWith(" ") || resource.description.contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); } else if (resource.getChannel().startsWith(" ") || resource.getChannel().endsWith(" ") || resource.getChannel().contains("\0")) { message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); } else if (resource.owner.startsWith(" ") || resource.owner.endsWith(" ") || resource.owner.contains("\0") || resource.owner.equals("*")) { message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); } else if (command.get("relay") == null) { // if the relay field is not given message.put("response", "error"); message.put("errorMessage", "missing resourceTemplate"); } else { int sum = 0; // sum of the sizes in other servers // create a JSONObject List List<JSONObject> jslist = new ArrayList<JSONObject>(); // if RELAY is true------------------------------------------------------------------ //=================================================================================== if (relay == true) { for (JSONObject record:serverrecords) { String hostname = (String) record.get("hostname"); int port = Integer.parseInt(record.get("port").toString()); try(Socket socket = new Socket(hostname,port)) { DataInputStream in = new DataInputStream(socket.getInputStream()); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); /* out.writeUTF("Hello server"); out.flush(); */ // ----------------------send query to a new server--------------------------- if (debugon == true) { System.out.println("quering to " + hostname + ":" + port); } JSONObject com = new JSONObject(); // put resource in JSONObject send = new JSONObject(); send.put("name", resource.name); send.put("description",resource.description); if(resource.uri == null) { send.put("uri", ""); //URI is not null } else { send.put("uri", resource.uri.toString()); } JSONArray arr = new JSONArray(); for(String tag: resource.tags) { arr.add(tag); } send.put("tags", arr); send.put("channel", ""); // channel changed!!! send.put("owner", ""); // owner changed!!! send.put("ezserver", null); com.put("resourceTemplate", send); com.put("command", "QUERY"); com.put("relay", false); //relay field changed!!! //WRITE the command to Server out.writeUTF(com.toJSONString()); if (debugon == true) { System.out.println("SENT: " + com); } //----------------------read from other servers------------------ while(true){ if(in.available() > 0) { //CREATE a JSONPareser JSONParser js_parser = new JSONParser(); JSONObject returned = (JSONObject) js_parser.parse(in.readUTF()); if (returned.containsKey("response")) { if(returned.get("response").equals("error")){ break; //do nothing } } if (returned.containsKey("name")) {// or any attribute else jslist.add(returned); //add to the list System.out.println("receive from other servers: " + returned); } if (returned.containsKey("resultSize")) { break; //break the while loop } } } //---------------------------------------------------------------------- } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (org.json.simple.parser.ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // check QUERY rules enforced by the server List<Resource> rslist = new ArrayList<Resource>(); //boolean tagpresent = true; for (Resource c : resourcelist) { // The template channel equals (case sensitive) the // resource channel if (c.getChannel().equals(resource.getChannel())) { // 1. ALL exists-------------------------------------------------------------- // Any tags present in the template also are present // in the candidate (case insensitive) if (resource.tags.length > 0 && Arrays.asList(c).containsAll(Arrays.asList(resource.tags))) { // If the template contains an owner that is not // "", then the candidate owner must equal it // (case sensitive) if (!resource.owner.equals("") && resource.owner.equals(c.owner)) { // If the template contains a URI then the // candidate URI matches (case sensitive) if (!(resource.uri == null) && resource.uri.equals(c.uri)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } } // 2----------------------------------------------------------------------------- // only if owner is "" if (resource.owner.equals("")) { // Any tags present in the template also are // present // in the candidate (case insensitive) if (resource.tags.length > 0 && Arrays.asList(c).containsAll(Arrays.asList(resource.tags))) { // If the template contains a URI then the // candidate URI matches (case sensitive) if (!(resource.uri == null) && resource.uri.equals(c.uri)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } } // 3------------------------------------------------------------------------ // only if tags is [] if (resource.tags.length == 0) { // If the template contains an owner that is not // "", then the candidate owner must equal it // (case sensitive) if (!resource.owner.equals("") && resource.owner.equals(c.owner)) { // If the template contains a URI then the // candidate URI matches (case sensitive) if (!(resource.uri == null) && resource.uri.equals(c.uri)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } } // 4-------------------------------------------------------------------------------- // only if URI is "" if (resource.uri == null) { if (resource.tags.length > 0 && Arrays.asList(c).containsAll(Arrays.asList(resource.tags))) { // If the template contains an owner that is // not // "", then the candidate owner must equal // it // (case sensitive) if (!resource.owner.equals("") && resource.owner.equals(c.owner)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } } // 5---------------------------------------------------------------------------------- // only if owner is "" and tag is [] if (resource.owner.equals("") && resource.tags.length == 0) { // If the template contains a URI then the // candidate URI matches (case sensitive) if (!(resource.uri == null) && resource.uri.equals(c.uri)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } // 6--------------------------------------------------------------------------------------- // only if owner is "" and URI is "" if (resource.owner.equals("") && (resource.uri == null)) { // Any tags present in the template also are // present // in the candidate (case insensitive) if (resource.tags.length > 0 && Arrays.asList(c).containsAll(Arrays.asList(resource.tags))) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } // 7------------------------------------------------------------------------------- // only if tag is [] and URI is "" if ((resource.uri == null) && resource.tags.length == 0) { // If the template contains an owner that is not // "", then the candidate owner must equal it // (case sensitive) if (!resource.owner.equals("") && resource.owner.equals(c.owner)) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); } } } // 8--------------------------------------------------------------------------------- // if owner is "" and tag is [] and URI is "" if (resource.owner.equals("") && (resource.uri == null) && resource.tags.length == 0) { if ((!resource.name.equals("") && c.name.contains(resource.name)) || (!resource.description.equals("") && c.name.contains(resource.name)) || (resource.description.equals("")) && (resource.name.equals(""))) { rslist.add(c); System.out.println("test query!"); } } } } // query succeed message.put("response", "success"); JSONObject size = new JSONObject(); for(Resource r: rslist) { JSONObject o = new JSONObject(); o.put("name", r.name); o.put("description", r.description); o.put("channel",r.getChannel()); o.put("uri", r.uri.toString()); if(!r.owner.equals("")) o.put("owner", "*");//The server will never reveal the owner of a resource in a response. If a resource has an owner then it will be //replaced with the "*" character else o.put("owner",""); o.put("ezserver", r.ezserver); JSONArray arr = new JSONArray(); for(String tag: r.tags) { arr.add(tag); } o.put("tags", arr); //seq.add(o); jslist.add(o); } size.put("resultSize", jslist.size()); //seq.add(size); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } Iterator<JSONObject> iter = jslist.iterator(); while(iter.hasNext()) { JSONObject js = iter.next(); output.writeUTF(js.toJSONString()); if (debugon == true) { System.out.println(js); } } output.writeUTF(size.toJSONString()); if (debugon == true) { System.out.println(size); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //seq.add(message); } else if(command.get("command").equals("FETCH")) { // FETCH-------------------------------------------------------------------------- receive = (JSONObject) command.get("resourceTemplate"); resource.name = (String) receive.get("name"); if(receive.get("uri").equals("")) { resource.uri = null; } else { resource.uri = URI.create(((String)receive.get("uri"))); } resource.description = (String) receive.get("description"); resource.changeChannel((String) receive.get("channel")); resource.owner = (String) receive.get("owner"); resource.tags = new String[((JSONArray) receive.get("tags")).size()]; for(int i = 0, count = resource.tags.length; i< count; i++) { resource.tags[i] = (String) ((JSONArray) receive.get("tags")).get(i); } //File file = new File(resource.uri.getPath()); if (resource.uri == null) { message.put("response", "error"); message.put("errorMessage", "missing resource"); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // response:error } else if (!resource.uri.isAbsolute() || !resource.uri.getScheme().equals("file")) { //The URI must be present, must be absolute, non-authoritative and must be a file scheme. It must point //to a file on the local file system that the server can read as a file. message.put("response", "error"); message.put("errorMessage", "invalid resourceTemplate"); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // response:error } else { File f = null; JSONObject j = new JSONObject(); for (Resource r: resourcelist) { if (r.getChannel().equals(resource.getChannel()) &&r.uri.equals(resource.uri)) { f = new File(resource.uri.getPath()); // Create a new resource JSONObject j.put("name", r.name); j.put("channel", r.getChannel()); JSONArray arr = new JSONArray(); for(String tag: r.tags) { arr.add(tag); } j.put("tags", arr); j.put("uri", r.uri.toString()); j.put("owner", r.owner); j.put("description", r.description); j.put("resourceSize", f.length()); j.put("ezserver", r.ezserver); } } // Check if file exists //File f = new File("server_files/"+fileName); String fileName = f.getName(); if(f.exists()){ // Send this back to client so that they know what the file is. //JSONObject trigger = new JSONObject(); JSONObject resultsize = new JSONObject(); //trigger.put("command_name", "SENDING_FILE"); //trigger.put("file_name",fileName); //trigger.put("file_size",f.length()); //seq.add(trigger); try { message.put("response", "success"); output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } output.writeUTF(j.toJSONString()); if (debugon == true) { System.out.println(j); } // Start sending file RandomAccessFile byteFile = new RandomAccessFile(f,"r"); byte[] sendingBuffer = new byte[1024*1024]; int num; // While there are still bytes to send.. while((num = byteFile.read(sendingBuffer)) > 0){ System.out.println(num); output.write(Arrays.copyOf(sendingBuffer, num)); System.out.println("test!"); } byteFile.close(); //JSONObject resultsize = new JSONObject(); resultsize.put("resultSize", 1); //seq.add(resultsize); output.writeUTF(resultsize.toJSONString()); if (debugon == true) { System.out.println(resultsize); } } catch (IOException e) { e.printStackTrace(); } } else{ // Throw an error here.. message.put("errorMessage", "file does not exist"); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //seq.add(message); } else if(command.get("command").equals("EXCHANGE")) { //EXCHANGE------------------------------------------------------- JSONArray record = (JSONArray) command.get("serverList"); if(record.isEmpty()) { message.put("response", "error"); message.put("errorMessage", "missing serverList"); } else {//adding the servers to its list. for(Object server:record) { serverrecords.add((JSONObject) server); } message.put("response", "success"); } try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }//----------------------------------finished-------------------------------- else { // there are other commands rather than "publish", "remove", ... message.put("response", "error"); message.put("errorMessage", "invalid command"); //seq.add(message); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // there is no command } else { message.put("response", "error"); message.put("errorMessage", "missing or incorrect type for command"); try { output.writeUTF(message.toJSONString()); if (debugon == true) { System.out.println("SENT: " + message); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return seq; } private static void serverClient(Socket client) { try(Socket clientSocket = client) { JSONParser parser = new JSONParser(); DataInputStream input = new DataInputStream(clientSocket.getInputStream()); DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream()); /* if (debugon == true) { System.out.println("Client: " + input.readUTF()); } */ //output.writeUTF("Message received."); while(true) { if(input.available() > 0) { JSONObject command = (JSONObject)parser.parse(input.readUTF()); if (debugon == true) { System.out.println("RECEIVED: " + command); } JSONArray message = parseCommand(command, output); /*delete these stuff if (debugon == true) { System.out.println("SENT: "); for (Object o: message) { System.out.println(o); } } JSONObject results = new JSONObject(); results.put("results", message); output.writeUTF(results.toJSONString());*/ } } } catch (IOException e) { e.printStackTrace(); } catch (org.json.simple.parser.ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
4.25 updates:
revise "read from other servers" in QUERY
revise arguments in every X minutes EXCHANGE
------------------------------------------------------------------------------------------------
This may be the final version of the DS_project 1, during these 2 weeks, we've solved lots of interesting problems through this project.

I will mention some tough points:
1. For the QUERY command, we need to get serveral JSONObjects from the server, instead of a single JSON like PUBLISH, REMOVE and SHARE. At the beginning, I just use a tricker way, JSONArray to handle this stuff, but when I tried to QUERY from Aaron's server, the problem happens. I realized that Aaron used a for loop to send a series of JSONObjects. The logic of the command is really really confusing, I thought of a complicated if...if...if...so many IF statements to solve it, and don't forget to reveal the owner with "*"!
2. For the FETCH command, in the previous version, I put the filename and size in two separate JSONObjects and give them keys named by myself. The problem also occurs when FETCHING with Aaron's server, because we nerver know if the keys' names are the same. The only way here is getting relevant informations from the Resource, and that is why a new Attribute resultSize needed here.
3. For the EXCHANGE, it is not difficult to send a serverlist to another server, but the hard question is how to EXCHANGE with records every X minutes. We need a new THREAD here, to timing and control the behaviors. Every X minutes, we can regard the existed Server as a new Client, and send a new EXCHANGE to the recorded server.
4. RELAY, when the RELAY is true, we have to get all query results from a recorded server with original server. The thing is just the same as EXCHANGE, we use the queried server as a new Client, and then QUERY to a random Server in the list, returning all results to the original client.


Server command:

java -cp ezshare.jar;C:\Users\frankie\workspace\EZShare\lib\commo

Be the first to comment

You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.