From 3a07a83a856fcc52b66b7511dae61c8cdea9456d Mon Sep 17 00:00:00 2001 From: Ben Goldsworthy Date: Wed, 24 Jun 2020 10:51:22 +0100 Subject: [PATCH] Initial commit (v2) --- bin/1. rmireg.bat | 1 + bin/2. compile.bat | 3 + bin/3. startServer.bat | 3 + bin/4. startClient.bat | 3 + bin/rmireg.bat | 1 - bin/startClient.bat | 1 - bin/startServer.bat | 1 - src/Auction.java | 116 +++++++--- src/AuctionClient.java | 285 +++++++++++++++++------- src/AuctionImpl.java | 481 +++++++++++++++++++++++++++++----------- src/AuctionServer.java | 39 +++- src/AuctionWrapper.java | 15 +- src/GenSig.java | 47 ---- src/Replica.java | 158 +++++++++++++ src/UserWrapper.java | 12 +- 15 files changed, 856 insertions(+), 310 deletions(-) create mode 100755 bin/1. rmireg.bat create mode 100755 bin/2. compile.bat create mode 100755 bin/3. startServer.bat create mode 100755 bin/4. startClient.bat delete mode 100755 bin/rmireg.bat delete mode 100755 bin/startClient.bat delete mode 100755 bin/startServer.bat delete mode 100755 src/GenSig.java create mode 100755 src/Replica.java diff --git a/bin/1. rmireg.bat b/bin/1. rmireg.bat new file mode 100755 index 0000000..7fe393f --- /dev/null +++ b/bin/1. rmireg.bat @@ -0,0 +1 @@ +start rmiregistry \ No newline at end of file diff --git a/bin/2. compile.bat b/bin/2. compile.bat new file mode 100755 index 0000000..f3cf4bf --- /dev/null +++ b/bin/2. compile.bat @@ -0,0 +1,3 @@ +set CLASSPATH=%CLASSPATH%;C:\JGroups\jgroups-3.6.0.Final.jar; +javac -Xlint:unchecked *.java +pause \ No newline at end of file diff --git a/bin/3. startServer.bat b/bin/3. startServer.bat new file mode 100755 index 0000000..f1cd408 --- /dev/null +++ b/bin/3. startServer.bat @@ -0,0 +1,3 @@ +set CLASSPATH=%CLASSPATH%;C:\JGroups\jgroups-3.6.0.Final.jar; +java -Djava.net.preferIPv4Stack=true AuctionServer +pause \ No newline at end of file diff --git a/bin/4. startClient.bat b/bin/4. startClient.bat new file mode 100755 index 0000000..78c8623 --- /dev/null +++ b/bin/4. startClient.bat @@ -0,0 +1,3 @@ +set /p id="Username (leave blank for new user): " +java -Djava.net.preferIPv4Stack=true AuctionClient %id% +pause \ No newline at end of file diff --git a/bin/rmireg.bat b/bin/rmireg.bat deleted file mode 100755 index 03b7af3..0000000 --- a/bin/rmireg.bat +++ /dev/null @@ -1 +0,0 @@ -javac *.java && start rmiregistry \ No newline at end of file diff --git a/bin/startClient.bat b/bin/startClient.bat deleted file mode 100755 index d14bb34..0000000 --- a/bin/startClient.bat +++ /dev/null @@ -1 +0,0 @@ -javac *.java && java AuctionClient \ No newline at end of file diff --git a/bin/startServer.bat b/bin/startServer.bat deleted file mode 100755 index c4d9c2a..0000000 --- a/bin/startServer.bat +++ /dev/null @@ -1 +0,0 @@ -javac *.java && java AuctionServer \ No newline at end of file diff --git a/src/Auction.java b/src/Auction.java index 4152cc2..6c2a0f9 100755 --- a/src/Auction.java +++ b/src/Auction.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -31,34 +31,37 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** - ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @author Ben Goldsworthy (rumps) + ** @version 2.0 **/ public interface Auction extends java.rmi.Remote { + /* + * Methods to validate operations and then remotely invoke methods + * using JGroups. + * + */ + /** - ** Creates an auction with the given details, generating a new ID for - ** it. + ** Invokes the creation of a new auction. ** - ** @param desc The auction description. - ** @param owner The auction owner/creator. - ** @param startingPrice The auction starting price. - ** @param reserve The auction reserve price. + ** @param newAuction The new auction to create. **/ - public void createAuction(String desc, UserWrapper owner, float startingPrice, float reserve) throws java.rmi.RemoteException; + public void openNewAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException; /** - ** Removes an auction, provided the user calling the method owns it. - ** If the reserve price was met, also returns the winning bidder. + ** Validates that the calling user owns the auction in question, and + ** if invokes the closing of the auction, returning the winning + ** bidder (if applicaable). ** - ** @param id The ID of the auction to remove. - ** @param currentUser The user calling the method. - ** @return The `UserWrapper` of the highest bidder, if applicable. + ** @param id The ID of the auction to bid on. + ** @param currentUser The user placing the bid. + ** @return The highest bidder, or `null`. **/ - public UserWrapper removeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException; + public void closeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException; /** - ** Bids on a given auction, provided the bid is more than the - ** current highest price. + ** Validates a bid is higher than the given auctions current price, + ** and if so invokes the setting the a new bid and bidder. ** ** @param id The ID of the auction in question. ** @param bidder The user bidding on the auction. @@ -67,30 +70,35 @@ public interface Auction extends java.rmi.Remote { public void bidOnAuction(int id, UserWrapper bidder, float price) throws java.rmi.RemoteException; /** - ** Accessor Method. Retrieves a list of all the auctions. + ** Invokes the returning of a list of all the current auctions. ** ** @return An `ArrayList` of `AuctionWrapper`s. **/ - public ArrayList getAuctions() throws java.rmi.RemoteException; + public ArrayList showAllAuctions() throws java.rmi.RemoteException; /** - ** Accessor Method. Gets a user, or creates a new one if non - ** exists with the given details. + ** Accessor Method. Invokes the retrieval of a preexisting user, + ** if it exists. ** - ** @param name The user's name. - ** @param email The user's email address. + ** @param username The user's username. ** @return The relevant `UserWrapper`. **/ public UserWrapper getUser(String username) throws java.rmi.RemoteException; - public UserWrapper registerUser(String name, String email, String username) throws java.rmi.RemoteException; - - public void close() throws java.rmi.RemoteException; - - public PublicKey getPublicKey() throws java.rmi.RemoteException; - public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException; - /** + ** Tests that the username entered is not already taken, and + ** invokes the creation of a new user with the given details if not. + ** + ** @param newUser The new user to validate and create. + ** @return The newly-created user. + **/ + public UserWrapper registerUser(UserWrapper newUser) throws java.rmi.RemoteException; + + /* + * Methods that are called by the `AuctionClient` program via RMI. + */ + + /** ** Accessor Method. Gets the status resulting from the last action ** attempted. ** @@ -98,9 +106,55 @@ public interface Auction extends java.rmi.Remote { **/ public String getStatusofLast() throws java.rmi.RemoteException; + /** + ** Accessor Method. Gets the server's public key. + ** + ** @return The public key. + **/ + public PublicKey getPublicKey() throws java.rmi.RemoteException; + + /** + ** Retrieves a user's public key and writes it to a file. + ** + ** @param key The user's public key. + ** @param usernam The user's username. + **/ + public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException; + + /** + ** Sends back a user's challenge, signed with the server's private + ** key. + ** + ** @param challenge The user's challenge. + ** @return The signature. + **/ public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException; + /** + ** Sends a user's a challenge. + ** + ** @return The challenge. + **/ public byte[] getChallenge() throws java.rmi.RemoteException; + + /** + ** Takes a returned challenge from the user and verifies the + ** signature. + ** + ** @param retChal The returned signature from the user. + ** @param username The user's username. + ** @return Whether the user has been verified or not. + **/ public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException; + + /** + ** Creates a new replica of the server. + **/ + public void replicate() throws java.rmi.RemoteException; + + /** + ** Closes the server and replicas. + **/ + public void close() throws java.rmi.RemoteException; } diff --git a/src/AuctionClient.java b/src/AuctionClient.java index 9186f7f..3e47e06 100755 --- a/src/AuctionClient.java +++ b/src/AuctionClient.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -37,85 +37,108 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** - ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @author Ben Goldsworthy (rumps) + ** @version 2.0 **/ public class AuctionClient { // This regex is used to ensure the email address entered is a valid - // email address format + // RFC 2822 email address format // (Source: http://stackoverflow.com/a/153751/4580273) private static final Pattern rfc2822 = Pattern.compile("^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$"); - + private static Auction a; + private static ArrayList options, debugOptions; + private static boolean debugMode; + /** - ** Displays the UI. + ** Sets up the program and runs the event loop. ** ** @param args Command-line arguments. **/ public static void main(String[] args) { + debugMode = true; + + displayIntro(); + + // Create the reference to the remote object through the + // remiregistry. This comes first because if it fails we can + // skip doing everything else. try { - // Create the reference to the remote object through the - // remiregistry. This comes first because if it fails we can - // skip doing everything else. - Auction a = (Auction) Naming.lookup("rmi://localhost/AuctionService"); - - // Declares some variables that'll be used later on. - Scanner in = new Scanner(System.in); - UserWrapper currentUser = null; - int id; - float price; + a = (Auction) Naming.lookup("rmi://localhost/AuctionService"); + + setOptions(); // Authenticates the user, if the program is run with a username // as an argument. Otherwise, prompts the user to create a new // user. - currentUser = login(a, (args.length > 0) ? args[0] : "server"); - - while(true) { - // Resets the variables after each run through. - price = 0.0f; - - printOptions(); - - switch(in.nextLine()) { - // This case takes auction details from the user and then - // creates a new auction with those. - case "1": - createNewAuction(a, currentUser); - break; - // This case removes the auction with the given ID, provided it - // is owned by the current user. - case "2": - deleteAuction(a, currentUser); - break; - // This case displays all the currently-available auctions. - case "3": - displayAuctions(a); - break; - // This case places a bid on an auction. - case "4": - placeBid(a, currentUser); - break; - // This case exits the program. - case "5": - System.exit(1); - break; - // The below cases are remote debug commands. - // This case remotely shuts down the server. - case "6": - a.close(); - break; - default: - break; - } - } + UserWrapper currentUser = login((args.length > 0) ? args[0] : "server"); + + eventLoop(currentUser); } catch (Exception e) { - System.out.println(); - System.out.println("Exception"); System.out.println(e); } - System.exit(-1); } - private static UserWrapper login(Auction a, String username) throws java.rmi.RemoteException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.SignatureException { + /* + * Loops indefinitely, taking user input for various options. + */ + private static void eventLoop(UserWrapper currentUser) throws Exception { + Scanner in = new Scanner(System.in); + + while(true) { + printOptions(); + try { + int enteredOption = Integer.parseInt(in.nextLine()); + System.out.println(); + + if(enteredOption < options.size()) { + switch(options.get(enteredOption)) { + // This case takes auction details from the user and then + // creates a new auction with those. + case "Create auction": + createNewAuction(currentUser); + break; + // This case removes the auction with the given ID, provided it + // is owned by the current user. + case "Close auction": + closeAuction(currentUser); + break; + // This case displays all the currently-available auctions. + case "View all auctions": + displayAuctions(); + break; + // This case places a bid on an auction. + case "Bid on auction": + placeBid(currentUser); + break; + case "Quit": + System.exit(1); + break; + default: break; + } + } else if(debugMode) { + switch(debugOptions.get(enteredOption-options.size())) { + case "Replicate server": + System.out.println("Server replicating..."); + a.replicate(); + System.out.println(a.getStatusofLast()); + break; + case "Close server": + a.close(); + break; + default: break; + } + } + } catch (NumberFormatException e) { + System.out.println("\nError: That is not a valid option.\n"); + } + } + } + + /* + * Logs a user in if they are preexisting (after authentication), or + * prompts a user to create a new user if not. + */ + private static UserWrapper login(String username) throws java.rmi.RemoteException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.SignatureException { UserWrapper user = null; // If the user has run the program with a username argument, @@ -169,8 +192,8 @@ public class AuctionClient { System.out.print("Enter name: "); name = in.nextLine(); - System.out.print("Enter email: "); while (!rfc2822.matcher(email).matches()) { + System.out.print("Enter email: "); email = in.nextLine(); if (!rfc2822.matcher(email).matches()) System.out.println("\nError: invalid email address\n"); } @@ -179,9 +202,14 @@ public class AuctionClient { System.out.print("Enter username ('server' is prohibited): "); username = in.nextLine(); } - - user = a.registerUser(name, email, username); - System.out.println(a.getStatusofLast()); + + try { + user = a.registerUser(new UserWrapper(name, email, username)); + System.out.println(a.getStatusofLast()); + } catch (NullPointerException e) { + System.out.println(a.getStatusofLast()); + System.exit(0); + } } // Upon a successful user creation, new keys are generated and @@ -198,12 +226,44 @@ public class AuctionClient { return user; } - private static void printOptions() { - System.out.println("1\tCreate auction\n2\tDelete auction\n3\tView auctions\n4\tBid on auction\n5\tQuit\n6\tClose server"); - System.out.print("Choose option: "); + /* + * Sets the suite of options to present to the user. + */ + private static void setOptions() { + options = new ArrayList(); + options.add("Create auction"); + options.add("Close auction"); + options.add("View all auctions"); + options.add("Bid on auction"); + options.add("Quit"); + + debugOptions = new ArrayList(); + debugOptions.add("Replicate server"); + debugOptions.add("Close server"); } - private static void createNewAuction(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException { + /* + * Prints the options for the user. + */ + private static void printOptions() { + for(String option: options) { + System.out.println(options.indexOf(option) +"\t"+option); + } + if (debugMode) { + System.out.println("DEBUG"); + int num = options.size(); + for(String option: debugOptions) { + System.out.println((num++)+"\t"+option); + } + } + System.out.print("Choose option: "); + } + + /* + * Prompts for auction details and then sends it off to be validated + * and created. + */ + private static void createNewAuction(UserWrapper currentUser) throws java.rmi.RemoteException { float startPrice = 0.0f; float reservePrice = 0.0f; Scanner in = new Scanner(System.in); @@ -220,38 +280,73 @@ public class AuctionClient { reservePrice = Float.parseFloat(in.nextLine()); } - a.createAuction(desc, currentUser, startPrice, reservePrice); + a.openNewAuction(new AuctionWrapper(0, desc, currentUser, startPrice, reservePrice)); System.out.println(a.getStatusofLast()); } catch(NumberFormatException ex){ System.out.println("\nError: not a valid price\n"); } } - private static void deleteAuction(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException { + /* + * Closes an auction (after sending the request off for validation). + */ + private static void closeAuction(UserWrapper currentUser) throws java.rmi.RemoteException { int id; UserWrapper winner; Scanner in = new Scanner(System.in); - if (!a.getAuctions().isEmpty()) { + if (!a.showAllAuctions().isEmpty()) { System.out.print("Enter auction number: "); id = Integer.parseInt(in.nextLine()); - try { - winner = a.removeAuction(id, currentUser); - System.out.println("\nAuction won by: "+winner.getName()+" <"+winner.getEmail()+">\n"); - } catch(NullPointerException e) { - System.out.println(a.getStatusofLast()); - } + a.closeAuction(id, currentUser); + System.out.println(a.getStatusofLast()); } else { System.out.println("\nNo auctions available\n"); } } - private static void displayAuctions(Auction a) throws java.rmi.RemoteException { - if (!a.getAuctions().isEmpty()) { + /* + * Displays the program intro preamble. + */ + private static void displayIntro() { + ArrayList lines = new ArrayList(); + lines.add(""); + lines.add("AuctionProg 1.0"); + lines.add("Copyright \u00a9 2016 Ben Goldsworthy (rumps)"); + lines.add(""); + lines.add("A program to facilitate a networked auction system"); + lines.add("This file is part of AuctionProg."); + lines.add(""); + lines.add("AuctionProg is free software: you can redistribute it and/or modify"); + lines.add("it under the terms of the GNU General Public License as published by"); + lines.add("the Free Software Foundation, either version 3 of the License, or"); + lines.add("(at your option) any later version."); + lines.add(""); + lines.add("AuctionProg is distributed in the hope that it will be useful,"); + lines.add("but WITHOUT ANY WARRANTY; without even the implied warranty of"); + lines.add("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); + lines.add("GNU General Public License for more details."); + lines.add(""); + lines.add("You should have received a copy of the GNU General Public License"); + lines.add("along with AuctionProg. If not, see ."); + lines.add(""); + + for(String line: lines){ + System.out.println(line); + } + } + + /* + * Displays all the available auctions. + */ + private static void displayAuctions() throws java.rmi.RemoteException { + if (!a.showAllAuctions().isEmpty()) { + System.out.println(); System.out.println("#\tOwner\tPrice\tDesc"); for (int i = 0; i < 80; i++) System.out.print("-"); - for(AuctionWrapper auction: a.getAuctions()){ + System.out.println(); + for(AuctionWrapper auction: a.showAllAuctions()){ System.out.println(auction.getID()+"\t"+auction.getOwner().getUsername()+"\t\u00A3"+String.format("%.2f", auction.getPrice())+"\t"+auction.getDesc()); } System.out.println(""); @@ -260,10 +355,13 @@ public class AuctionClient { } } - private static void placeBid(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException { + /* + * Takes bid details and sends the bid off. + */ + private static void placeBid(UserWrapper currentUser) throws java.rmi.RemoteException { Scanner in = new Scanner(System.in); - if (!a.getAuctions().isEmpty()) { + if (!a.showAllAuctions().isEmpty()) { try{ int id; float price; @@ -284,9 +382,12 @@ public class AuctionClient { } } + /* + * Reads a user's private key from a file. + */ private static PrivateKey readKey(String username) { try { - FileInputStream keyfis = new FileInputStream(username + "priv.key"); + FileInputStream keyfis = new FileInputStream("../key/client/"+username + "priv.key"); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); @@ -302,9 +403,12 @@ public class AuctionClient { return null; } } + /* + * Reads the server's public key from a file. + */ private static PublicKey readKey() { try { - FileInputStream keyfis = new FileInputStream("serverpub.key"); + FileInputStream keyfis = new FileInputStream("../key/client/serverpub.key"); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); @@ -321,16 +425,25 @@ public class AuctionClient { } } + /* + * Writes a private key to a file. + */ private static void writeKey(PrivateKey pKey, String username) { wK(pKey, username, "priv"); } + /* + * Writes a public key to a file. + */ private static void writeKey(PublicKey pKey, String username) { wK(pKey, username, "pub"); } + /* + * Actually writes a key to a file. + */ private static void wK(Key pKey, String username, String type) { try { byte[] key = pKey.getEncoded(); - FileOutputStream keyfos = new FileOutputStream(username+type+".key"); + FileOutputStream keyfos = new FileOutputStream("../key/client/"+username+type+".key"); keyfos.write(key); keyfos.close(); } catch (Exception e) { @@ -339,4 +452,4 @@ public class AuctionClient { System.out.println(e); } } -} \ No newline at end of file +} diff --git a/src/AuctionImpl.java b/src/AuctionImpl.java index 1896d28..7a00b86 100755 --- a/src/AuctionImpl.java +++ b/src/AuctionImpl.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -29,20 +29,31 @@ import java.util.*; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import org.jgroups.JChannel; +import org.jgroups.blocks.RpcDispatcher; +import org.jgroups.blocks.RequestOptions; +import org.jgroups.blocks.ResponseMode; +import org.jgroups.View; +import org.jgroups.util.*; +import java.lang.reflect.InvocationTargetException; /** ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @version 2.0 **/ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements Auction { private ArrayList auctions; private ArrayList users; String status; byte[] challenge = new byte[1024]; + static JChannel channel; + static RpcDispatcher disp; + static RequestOptions opts = new RequestOptions(ResponseMode.GET_ALL, 5000); /** ** Constructor Method. Required to declare the `RemoteException` - ** instance. + ** instance. Also sets up three replicas and creates a test suite of + ** three auctions. **/ public AuctionImpl() throws java.rmi.RemoteException { super(); @@ -54,9 +65,32 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements status = ""; generateKeys(); - System.out.println("Server start successful."); + System.out.println("Server initiliasation successful."); + + try { + channel=new JChannel(); + disp = new RpcDispatcher(channel, this); + channel.connect("AuctionProg"); + + System.out.println("Creating replicas..."); + new Replica().start(); + new Replica().start(); + new Replica().start(); + System.out.println("Replicas created."); + + UserWrapper testUser = new UserWrapper("Test", "test@test.com", "test"); + this.openNewAuction(new AuctionWrapper(1, "test1", testUser, 12.0f, 14.0f)); + this.openNewAuction(new AuctionWrapper(2, "test2", testUser, 12.0f, 14.0f)); + this.openNewAuction(new AuctionWrapper(3, "test3", testUser, 12.0f, 14.0f)); + } catch (Exception e) { + System.out.println(e); + } } + /* + * Generates the pair of keys for the server's authentication and + * writes them to files. + */ private void generateKeys() { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); @@ -73,108 +107,226 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /* + * Methods to validate operations and then remotely invoke methods + * using JGroups. + * + */ + /** - ** Creates an auction with the given details, generating a new ID for - ** it. + ** Invokes the creation of a new auction. ** - ** @param desc The auction description. - ** @param owner The auction owner/creator. - ** @param startingPrice The auction starting price. - ** @param reserve The auction reserve price. + ** @param newAuction The new auction to create. **/ - public void createAuction(String desc, UserWrapper owner, float startingPrice, float reserve) throws java.rmi.RemoteException { - int id = 0; - String preamble = "Create new auction: "; - - lines(); - System.out.println(preamble + "begin."); - - // Gives the new auction the lowest unclaimed ID. - for(AuctionWrapper item: auctions){ - if (id <= item.getID()) { - id = item.getID(); - } + public void openNewAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException { + System.out.println("Opening new auction..."); + try { + disp.callRemoteMethods(null, "createAuction", new Object[]{newAuction}, new Class[]{AuctionWrapper.class}, opts); + status = "Auction successfully opened."; + System.out.println("Auction successfully opened."); + return; + } catch (Exception e) { + System.out.println(e); } - - auctions.add(new AuctionWrapper(++id, desc, owner, startingPrice, reserve)); - System.out.println(preamble + "auction "+id+" successfully created."); - status = "Auction no. "+id+" successfully created."; - - System.out.println(preamble + "end."); - lines(); + status = "Auction could not be opened."; + System.out.println("Auction unsuccessfully opened."); } /** - ** Removes an auction, provided the user calling the method owns it. - ** If the reserve price was met, also returns the winning bidder. + ** Validates that the calling user owns the auction in question, and + ** if invokes the closing of the auction, returning the winning + ** bidder (if applicaable). ** - ** @param id The ID of the auction to remove. - ** @param currentUser The user calling the method. - ** @return The `UserWrapper` of the highest bidder, if applicable. + ** @param id The ID of the auction to bid on. + ** @param currentUser The user placing the bid. + ** @return The highest bidder, or `null`. **/ - public UserWrapper removeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException { + public void closeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException { + System.out.println("Closing auction #"+id+"..."); AuctionWrapper auction = this.getAuction(id); UserWrapper response = null; - String preamble = "Close auction "+id+": "; - - lines(); - System.out.println(preamble + "begin."); if (auction.getOwner().getUsername().equals(currentUser.getUsername())) { - System.out.println(preamble + "ownership rights confirmed."); - auctions.remove(auction); - System.out.println(preamble + "auction successfully closed."); - status = "Auction no. "+id+" successfully removed"; - if (auction.getPrice() >= auction.getReserve()) { - System.out.println(preamble + "auction closed with winner."); - status = "Auction closed - winner"; - response = auction.getHighestBidder(); - } else { - System.out.println(preamble + "auction closed with no winner."); - status = "Auction closed - no winner"; + System.out.println("Ownership rights confirmed."); + try { + RspList rsp_list = disp.callRemoteMethods(null, "removeAuction", new Object[]{auction}, new Class[]{AuctionWrapper.class}, opts); + System.out.println("Auction successfully closed."); + + response = (UserWrapper)rsp_list.getFirst(); + if (response.getUsername().equals("server")) { + status = "Auction closed with no winner"; + } else { + status = "Auction won by: "+response.getName()+" <"+response.getEmail()+">"; + } + return; + } catch (Exception e) { + System.out.println(e); } - } else { - System.out.println(preamble + "invalid ownership rights."); - status = "Auction no. "+id+" could not be removed - you do not own this auction"; } - - System.out.println(preamble + "end."); - lines(); - return response; + status = "You do not own this auction."; + System.out.println("Auction closing unsuccessful."); } /** - ** Bids on a given auction, provided the bid is more than the - ** current highest price. + ** Validates a bid is higher than the given auctions current price, + ** and if so invokes the setting the a new bid and bidder. ** ** @param id The ID of the auction in question. ** @param bidder The user bidding on the auction. ** @param price The amount bid. **/ - public void bidOnAuction(int id, UserWrapper bidder, float price) - throws java.rmi.RemoteException { + public void bidOnAuction(int id, UserWrapper bidder, float price) throws java.rmi.RemoteException { AuctionWrapper auction; - String preamble = "Bid on auction "+id+": "; + System.out.println("Placing bid on auction #"+id+"..."); - lines(); - System.out.println(preamble + "begin."); - - if ((auction = this.getAuction(id)) != null) { - if (price > auction.getPrice()) { - this.getAuction(id).setBid(bidder, price); - System.out.println(preamble + "bid successful."); - status = "Bid successful"; + try { + if ((auction = this.getAuction(id)) != null) { + if (price > auction.getPrice()) { + disp.callRemoteMethods(null, "setBid", new Object[]{auction, bidder, price}, new Class[]{AuctionWrapper.class, UserWrapper.class, float.class}, opts); + System.out.println("Bid successful."); + status = "Bid successful"; + } else { + System.out.println("Bid unsuccessful."); + status = "Price less than highest bid"; + } } else { - System.out.println(preamble + "bid less than current highest bid."); - status = "Price less than highest bid"; + System.out.println("Bid unsuccessful."); + status = "Invalid auction ID"; + } + } catch (Exception e) { + System.out.println(e); + } + } + + /** + ** Invokes the returning of a list of all the current auctions. + ** + ** @return An `ArrayList` of `AuctionWrapper`s. + **/ + public ArrayList showAllAuctions() throws java.rmi.RemoteException { + try { + RspList rsp_list=disp.callRemoteMethods(null, "getAllAuctions", null, null, opts); + return (ArrayList)rsp_list.getFirst(); + } catch (Exception e) { + System.out.println(e); + } + return null; + } + + /** + ** Accessor Method. Invokes the retrieval of a preexisting user, + ** if it exists. + ** + ** @param username The user's username. + ** @return The relevant `UserWrapper`. + **/ + public UserWrapper getUser(String username) throws java.rmi.RemoteException { + try { + RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts); + for(UserWrapper user: (ArrayList)rsp_list.getFirst()) { + if (user.getUsername().equals(username)) { + status = "Welcome back, "+user.getName()+"."; + return user; + } + } + } catch (Exception e) { + System.out.println(e); + } + status = "No such user."; + return null; + } + + /** + ** Tests that the username entered is not already taken, and + ** invokes the creation of a new user with the given details if not. + ** + ** @param newUser The new user to validate and create. + ** @return The newly-created user. + **/ + public UserWrapper registerUser(UserWrapper newUser) throws java.rmi.RemoteException { + try { + RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts); + + if (!rsp_list.isEmpty()) { + for(UserWrapper user: (ArrayList)rsp_list.getFirst()){ + if (user.getUsername().equals(newUser.getUsername())) { + status = "Username taken. Either choose a new username or, if trying to login to an existing account, rerun the program as 'AuctionClient '."; + return null; + } + } + } + + disp.callRemoteMethods(null, "createUser", new Object[]{newUser}, new Class[]{UserWrapper.class}, opts); + status = "New user created. Hello "+newUser.getName()+"."; + return newUser; + } catch (Exception e) { + System.out.println(e); + } + status = "Something went wrong"; + return null; + } + + /* + * Methods that are remotely invoked via RPC on both this and the + * `Replica`s due to multicasting. + */ + + /** + ** Creates an auction with the given details. + ** + ** @param newAuction An `AuctionWrapper` of the new auction. + **/ + private void createAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException { + int id = 0; + + // Gives the new auction the lowest unclaimed ID. + for(AuctionWrapper auction: auctions){ + if (id <= auction.getID()) { + id = auction.getID(); } - } else { - System.out.println(preamble + "auction ID not found."); - status = "Invalid auction ID"; } - System.out.println(preamble + "end."); - lines(); + newAuction.setID(++id); + auctions.add(newAuction); + status = "Auction no. "+id+" successfully created."; + } + + /** + ** Removes an auction. If the reserve price was met, also returns + ** the winning bidder, otherwise an indicative `UserWrapper` with + ** username of "server". + ** + ** @param auction The `AuctionWrapper` of the auction to remove. + ** @return The `UserWrapper` of the highest bidder, or `null`. + **/ + private UserWrapper removeAuction(AuctionWrapper auction) throws java.rmi.RemoteException { + auctions.remove(auction); + + if (auction.getPrice() >= auction.getReserve()) { + return auction.getHighestBidder(); + } else { + return new UserWrapper("err", "err", "server"); + } + } + + /** + ** Mutator Method. Sets the bid on an auction. + ** + ** @param auction The `AuctionWrapper` of the auction to bid on. + ** @param user The user bidding on the auction. + ** @param price The amount the user has bid. + **/ + private void setBid(AuctionWrapper auction, UserWrapper user, float price) { + this.getAuction(auction.getID()).setBid(user, price); + } + + /** + ** Accessor Method. Retrieves a list of all the auctions. + ** + ** @return An `ArrayList` of `AuctionWrapper`s. + **/ + private ArrayList getAllAuctions() { + return this.auctions; } /** @@ -184,56 +336,42 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements ** @return The `AuctionWrapper` indicated. **/ private AuctionWrapper getAuction(int id) { - for(AuctionWrapper auction: auctions){ - if (auction.getID() == id) { - return auction; + try { + RspList rsp_list=disp.callRemoteMethods(null, "getAllAuctions", null, null, opts); + for(AuctionWrapper auction: (ArrayList)rsp_list.getFirst()) { + if (auction.getID() == id) { + return auction; + } } + } catch (Exception e) { + System.out.println(e); } return null; } /** - ** Accessor Method. Retrieves a list of all the auctions. - ** - ** @return An `ArrayList` of `AuctionWrapper`s. + ** Creates a new user. + ** + ** @param newUser The new user to create. **/ - public ArrayList getAuctions() throws java.rmi.RemoteException { - return auctions; + private void createUser(UserWrapper newUser) { + System.out.println("doing it"); + this.users.add(newUser); } - + /** - ** Accessor Method. Gets a user, or creates a new one if non - ** exists with the given details. - ** - ** @param name The user's name. - ** @param email The user's email address. - ** @return The relevant `UserWrapper`. + ** Gets the list of all users. + ** + ** @return An `ArrayList` of users. **/ - public UserWrapper getUser(String username) throws java.rmi.RemoteException { - for(UserWrapper user: users){ - if (user.getUsername().equals(username)) { - status = "Welcome back, "+user.getName()+"."; - return user; - } - } - status = "No such user."; - return null; - } - - public UserWrapper registerUser(String name, String email, String username) throws java.rmi.RemoteException { - for(UserWrapper user: users){ - if (user.getUsername().equals(username)) { - status = "Username taken. Either choose a new username or, if trying to login to an existing account, rerun the program as 'AuctionClient '."; - return null; - } - } - - UserWrapper user = new UserWrapper(name, email, username); - users.add(user); - status = "New user created. Hello "+name+"."; - return user; + private ArrayList getAllUsers() { + return this.users; } + /* + * Methods that are called by the `AuctionClient` program via RMI. + */ + /** ** Accessor Method. Gets the status resulting from the last action ** attempted. @@ -244,18 +382,34 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements return "\n"+status+"\n"; } + /** + ** Accessor Method. Gets the server's public key. + ** + ** @return The public key. + **/ public PublicKey getPublicKey() throws java.rmi.RemoteException { return this.readKey("server"); } + /** + ** Retrieves a user's public key and writes it to a file. + ** + ** @param key The user's public key. + ** @param usernam The user's username. + **/ public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException { this.writeKey(key, username); } + /* + * Writes the server's private key to a file. + * + * @param The private key. + */ private static void writeKey(PrivateKey pKey) throws java.rmi.RemoteException { try { byte[] key = pKey.getEncoded(); - FileOutputStream keyfos = new FileOutputStream("../key/serverpriv.key"); + FileOutputStream keyfos = new FileOutputStream("../key/server/serverpriv.key"); keyfos.write(key); keyfos.close(); } catch (Exception e) { @@ -265,10 +419,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /* + * Writes the server's public key to a file. + * + * @param The public key. + */ private static void writeKey(PublicKey pKey) throws java.rmi.RemoteException { try { byte[] key = pKey.getEncoded(); - FileOutputStream keyfos = new FileOutputStream("../key/serverpub.key"); + FileOutputStream keyfos = new FileOutputStream("../key/server/serverpub.key"); keyfos.write(key); keyfos.close(); } catch (Exception e) { @@ -278,10 +437,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /* + * Writes a user's public key to a file. + * + * @param The public key. + */ private static void writeKey(PublicKey pKey, String username) throws java.rmi.RemoteException { try { byte[] key = pKey.getEncoded(); - FileOutputStream keyfos = new FileOutputStream("../key/"+username+"pub.key"); + FileOutputStream keyfos = new FileOutputStream("../key/server/"+username+"pub.key"); keyfos.write(key); keyfos.close(); } catch (Exception e) { @@ -291,9 +455,14 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /* + * Reads the server's private key from a file. + * + * @return The private key. + */ private static PrivateKey readKey() throws java.rmi.RemoteException { try { - FileInputStream keyfis = new FileInputStream("../key/serverpriv.key"); + FileInputStream keyfis = new FileInputStream("../key/server/serverpriv.key"); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); @@ -310,9 +479,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /* + * Reads a user's public key from a file. + * + * @param username The user's username. + * @return The public key. + */ private static PublicKey readKey(String username) throws java.rmi.RemoteException { try { - FileInputStream keyfis = new FileInputStream("../key/"+username+"pub.key"); + FileInputStream keyfis = new FileInputStream("../key/server/"+username+"pub.key"); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); @@ -330,7 +505,13 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } - + /** + ** Sends back a user's challenge, signed with the server's private + ** key. + ** + ** @param challenge The user's challenge. + ** @return The signature. + **/ public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException { try { Signature dsa = Signature.getInstance("SHA1withDSA"); @@ -347,17 +528,32 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements } } + /** + ** Sends a user's a challenge. + ** + ** @return The challenge. + **/ public byte[] getChallenge() throws java.rmi.RemoteException { challenge = new byte[1024]; new Random().nextBytes(this.challenge); return this.challenge; } + /** + ** Takes a returned challenge from the user and verifies the + ** signature. + ** + ** @param retChal The returned signature from the user. + ** @param username The user's username. + ** @return Whether the user has been verified or not. + **/ public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException { System.out.println("Authenticating user '"+username+"'..."); - for(UserWrapper user: users){ - if (user.getUsername().equals(username)) { - try { + System.out.println(users); + try { + RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts); + for(UserWrapper user: (ArrayList)rsp_list.getFirst()) { + if (user.getUsername().equals(username)) { Signature sig = Signature.getInstance("SHA1withDSA"); sig.initVerify(this.readKey(username)); @@ -366,24 +562,41 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements boolean verifies = sig.verify(retChal); System.out.println(username+" signature verifies: " + verifies); return verifies; - } catch (Exception e) { - System.out.println(); - System.out.println("Exception"); - System.out.println(e); } } + } catch (Exception e) { + System.out.println(e); } + System.out.println("User '"+username+"' not found."); return false; } - public void close() throws java.rmi.RemoteException { - System.exit(-1); + /** + ** Creates a new replica of the server. + **/ + public void replicate() throws java.rmi.RemoteException { + try { + new Replica().start(); + status = "Server replication successful."; + } catch (Exception e) { + System.out.println(e); + status = "Server replication failed."; + } } - private void lines() { - for (int i = 0; i < 80; i++) System.out.print("-"); - System.out.print("\n"); + /** + ** Closes the server and replicas. + **/ + public void close() throws java.rmi.RemoteException { + System.out.println("Stopping replicas"); + try { + disp.callRemoteMethods(null, "stop", null, null, opts); + } catch (Exception e) { + System.out.println(e); + } + channel.close(); + disp.stop(); + System.exit(-1); } } - diff --git a/src/AuctionServer.java b/src/AuctionServer.java index 23edf4b..324eda6 100755 --- a/src/AuctionServer.java +++ b/src/AuctionServer.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -25,16 +25,18 @@ **/ import java.rmi.Naming; +import java.util.*; /** ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @version 2.0 **/ public class AuctionServer { /** ** Constructor Method. **/ public AuctionServer() { + try { Auction a = new AuctionImpl(); Naming.rebind("rmi://localhost/AuctionService", a); @@ -49,6 +51,39 @@ public class AuctionServer { ** @param args Command-line arguments. **/ public static void main(String args[]) { + displayIntro(); + new AuctionServer(); } + + /* + * Displays the intro preamble to the user. + */ + private static void displayIntro() { + ArrayList lines = new ArrayList(); + lines.add(""); + lines.add("AuctionProg 1.0"); + lines.add("Copyright \u00a9 2016 Ben Goldsworthy (rumps)"); + lines.add(""); + lines.add("A program to facilitate a networked auction system"); + lines.add("This file is part of AuctionProg."); + lines.add(""); + lines.add("AuctionProg is free software: you can redistribute it and/or modify"); + lines.add("it under the terms of the GNU General Public License as published by"); + lines.add("the Free Software Foundation, either version 3 of the License, or"); + lines.add("(at your option) any later version."); + lines.add(""); + lines.add("AuctionProg is distributed in the hope that it will be useful,"); + lines.add("but WITHOUT ANY WARRANTY; without even the implied warranty of"); + lines.add("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); + lines.add("GNU General Public License for more details."); + lines.add(""); + lines.add("You should have received a copy of the GNU General Public License"); + lines.add("along with AuctionProg. If not, see ."); + lines.add(""); + + for(String line: lines){ + System.out.println(line); + } + } } diff --git a/src/AuctionWrapper.java b/src/AuctionWrapper.java index 0fa9816..8d496a8 100755 --- a/src/AuctionWrapper.java +++ b/src/AuctionWrapper.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -28,7 +28,7 @@ import java.io.*; /** ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @version 2.0 **/ public class AuctionWrapper implements Serializable { private int id; @@ -46,7 +46,7 @@ public class AuctionWrapper implements Serializable { ** @param startingPrice The starting price of the auction. ** @param reserve The reserve price of the auction. **/ - public AuctionWrapper(int id, String desc, UserWrapper owner, float startingPrice, float reserve){ + public AuctionWrapper(int id, String desc, UserWrapper owner, float startingPrice, float reserve) { this.id = id; this.desc = desc; this.owner = owner; @@ -120,4 +120,13 @@ public class AuctionWrapper implements Serializable { public float getReserve() { return this.reserve; } + + + /** + ** Mutator Method. Sets the auction ID. + ** @param id The new auction ID. + **/ + public void setID(int id) { + this.id = id; + } } diff --git a/src/GenSig.java b/src/GenSig.java deleted file mode 100755 index e367f03..0000000 --- a/src/GenSig.java +++ /dev/null @@ -1,47 +0,0 @@ -import java.io.*; -import java.security.*; - -class GenSig { - public static void main(String[] args) { - /* Generate a DSA signature */ - - if (args.length != 1) { - System.out.println("Usage: GenSig nameOfFileToSign"); - } else try { - KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN"); - SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); - keyGen.initialize(1024, random); - - KeyPair pair = keyGen.generateKeyPair(); - PrivateKey priv = pair.getPrivate(); - PublicKey pub = pair.getPublic(); - - Signature dsa = Signature.getInstance("SHA1withDSA", "SUN"); - dsa.initSign(priv); - - FileInputStream fis = new FileInputStream(args[0]); - BufferedInputStream bufin = new BufferedInputStream(fis); - byte[] buffer = new byte[1024]; - int len; - while ((len = bufin.read(buffer)) >= 0) { - dsa.update(buffer, 0, len); - }; - bufin.close(); - - byte[] realSig = dsa.sign(); - - /* save the signature in a file */ - FileOutputStream sigfos = new FileOutputStream("sig"); - sigfos.write(realSig); - sigfos.close(); - - /* save the public key in a file */ - byte[] key = pub.getEncoded(); - FileOutputStream keyfos = new FileOutputStream("suepk"); - keyfos.write(key); - keyfos.close(); - } catch (Exception e) { - System.err.println("Caught exception " + e.toString()); - } - } -} \ No newline at end of file diff --git a/src/Replica.java b/src/Replica.java new file mode 100755 index 0000000..6e77ba9 --- /dev/null +++ b/src/Replica.java @@ -0,0 +1,158 @@ +/* + * AuctionProg 2.0 + * Copyright © 2016 Ben Goldsworthy (rumps) + * + * A program to facilitate a networked auction system. + * + * This file is part of AuctionProg. + * + * AuctionProg is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AuctionProg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AuctionProg. If not, see . + */ + +/** + ** This class represents a User. + **/ + +import java.io.*; +import java.util.*; +import org.jgroups.JChannel; +import org.jgroups.blocks.RpcDispatcher; +import org.jgroups.blocks.RequestOptions; +import org.jgroups.blocks.ResponseMode; +import org.jgroups.util.*; + +/** + ** @author Ben Goldsworthy (rumps) + ** @version 2.0 + **/ +public class Replica { + JChannel channel; + RpcDispatcher disp; + RequestOptions opts=new RequestOptions(ResponseMode.GET_ALL, 5000); + + private ArrayList auctions; + private ArrayList users; + + /** + ** Connects to the channel and sets itself up. + **/ + public void start() { + try { + channel = new JChannel(); + disp = new RpcDispatcher(channel, this); + channel.connect("AuctionProg"); + + auctions = new ArrayList(); + users = new ArrayList(); + } catch (Exception e) { + System.out.println(e); + } + } + + /** + ** Shuts down the replica. + **/ + public void stop() { + channel.close(); + disp.stop(); + } + + /** + ** Creates a new auction. + ** + ** @param newAuction The new auction to create. + **/ + public void createAuction(AuctionWrapper newAuction) { + int id = 0; + + // Gives the new auction the lowest unclaimed ID. + for(AuctionWrapper auction: auctions){ + if (id <= auction.getID()) { + id = auction.getID(); + } + } + + newAuction.setID(++id); + auctions.add(newAuction); + } + + /** + ** Removes an auction from the list. + ** + ** @param auction The auction to remove. + ** @return The highest-bidding user (if applicable). + **/ + public UserWrapper removeAuction(AuctionWrapper auction) { + auctions.remove(auction); + + if (auction.getPrice() >= auction.getReserve()) { + return auction.getHighestBidder(); + } else { + return new UserWrapper("err", "err", "server"); + } + } + + /** + ** Mutator Method. Sets a new bid on an auction. + ** + ** @param auction The auction to bid on. + ** @param user The user bidding. + ** @param price The user's bid. + **/ + public void setBid(AuctionWrapper auction, UserWrapper user, float price) { + this.getAuction(auction.getID()).setBid(user, price); + } + + /** + ** Accessor Method. Gets all the auctions. + ** + ** @return The list of auctions. + **/ + public ArrayList getAllAuctions() { + return this.auctions; + } + + /** + ** Gets an auction by ID. + ** + ** @param id The auction ID. + ** @return The auction requested, or `null`. + **/ + private AuctionWrapper getAuction(int id) { + for(AuctionWrapper auction: auctions) { + if (auction.getID() == id) { + return auction; + } + } + return null; + } + + /** + ** Accessor Method. Gets the list of all users. + ** + ** @return The list of users. + **/ + public ArrayList getAllUsers() { + return this.users; + } + + /** + ** Creates a new user. + ** + ** @param The new user to create. + **/ + public void createUser(UserWrapper newUser) { + this.users.add(newUser); + } +} diff --git a/src/UserWrapper.java b/src/UserWrapper.java index 495cf1f..97ebf61 100755 --- a/src/UserWrapper.java +++ b/src/UserWrapper.java @@ -1,5 +1,5 @@ /* - * AuctionProg 1.0 + * AuctionProg 2.0 * Copyright © 2016 Ben Goldsworthy (rumps) * * A program to facilitate a networked auction system. @@ -28,7 +28,7 @@ import java.io.*; /** ** @author Ben Goldsworthy (rumps) - ** @version 1.0 + ** @version 2.0 **/ public class UserWrapper implements Serializable { private String name; @@ -49,19 +49,23 @@ public class UserWrapper implements Serializable { /** ** Accessor Method. Returns the user's name. - ** @param The user's name. + ** @return The user's name. **/ public String getName() { return this.name; } + /** + ** Accessor Method. Returns the user's username. + ** @return The user's username. + **/ public String getUsername() { return this.username; } /** ** Accessor Method. Returns the user's email address. - ** @param The user's email address. + ** @return The user's email address. **/ public String getEmail() { return this.email;